| author | |
| committer | |
| log | 01b4bf34ea4f37d8b778bb2413ac1fc445f8bead |
| tree | 6075a5f6e35448ab1899b34a559d5c1ce9e27bd2 |
| parent | cf57e8223f06f6b305e7274445cf935b1ed312d2 |
* AstGen: represent compile errors in ZIR rather than returning
`error.AnalysisFail`.
* ZIR: remove decl_ref and decl_val instructions. These are replaced by
`decl_ref_named` and `decl_val_named`, respectively, which will
probably get renamed in the future to the instructions that were just
deleted.
* AstGen: implement `@This()`, `@fence()`, `@returnAddress()`, and
`@src()`.
* AstGen: struct_decl improved to support fields_len=0 but have decls.
* AstGen: fix missing null bytes after compile error messages.
* SrcLoc: no longer depend on `Decl`. Instead have an explicit field
`parent_decl_node` which is an absolute AST Node index.
* Module: `failed_files` table can have null value, in which case the
key, which is a `*Scope.File`, will have ZIR errors in it.
* ZIR: implement text rendering of struct decls.
* CLI: introduce debug_usage and `zig astgen` command which is enabled
when the compiler is built in debug mode.7 files changed, 457 insertions(+), 263 deletions(-)
BRANCH_TODO+11| ... | ... | @@ -1,3 +1,14 @@ |
| 1 | * AstGen decls into blocks so we can evaluate them independently | |
| 2 | * look for cached zir code | |
| 3 | * save zir code to cache | |
| 4 | * store list of imported strings | |
| 5 | * use list of imported strings to queue up more astgen tasks | |
| 6 | * keep track of file dependencies/dependants | |
| 7 | * unload files from memory when a dependency is dropped | |
| 8 | * implement zir error notes | |
| 9 | ||
| 10 | * implement the new AstGen compile errors | |
| 11 | ||
| 1 | 12 | * get rid of failed_root_src_file |
| 2 | 13 | * get rid of Scope.DeclRef |
| 3 | 14 | * handle decl collision with usingnamespace |
src/AstGen.zig+36-24| ... | ... | @@ -96,14 +96,18 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { |
| 96 | 96 | .arg = 0, |
| 97 | 97 | }, |
| 98 | 98 | }; |
| 99 | const struct_decl_ref = try AstGen.structDeclInner( | |
| 99 | if (AstGen.structDeclInner( | |
| 100 | 100 | &gen_scope, |
| 101 | 101 | &gen_scope.base, |
| 102 | 102 | 0, |
| 103 | 103 | container_decl, |
| 104 | 104 | .struct_decl, |
| 105 | ); | |
| 106 | astgen.extra.items[0] = @enumToInt(struct_decl_ref); | |
| 105 | )) |struct_decl_ref| { | |
| 106 | astgen.extra.items[0] = @enumToInt(struct_decl_ref); | |
| 107 | } else |err| switch (err) { | |
| 108 | error.OutOfMemory => return error.OutOfMemory, | |
| 109 | error.AnalysisFail => {}, // Handled via compile_errors below. | |
| 110 | } | |
| 107 | 111 | |
| 108 | 112 | if (astgen.compile_errors.items.len == 0) { |
| 109 | 113 | astgen.extra.items[1] = 0; |
| ... | ... | @@ -1272,8 +1276,6 @@ fn blockExprStmts( |
| 1272 | 1276 | .cmp_gt, |
| 1273 | 1277 | .cmp_neq, |
| 1274 | 1278 | .coerce_result_ptr, |
| 1275 | .decl_ref, | |
| 1276 | .decl_val, | |
| 1277 | 1279 | .decl_ref_named, |
| 1278 | 1280 | .decl_val_named, |
| 1279 | 1281 | .load, |
| ... | ... | @@ -1381,6 +1383,10 @@ fn blockExprStmts( |
| 1381 | 1383 | .type_info, |
| 1382 | 1384 | .size_of, |
| 1383 | 1385 | .bit_size_of, |
| 1386 | .this, | |
| 1387 | .fence, | |
| 1388 | .ret_addr, | |
| 1389 | .builtin_src, | |
| 1384 | 1390 | => break :b false, |
| 1385 | 1391 | |
| 1386 | 1392 | // ZIR instructions that are always either `noreturn` or `void`. |
| ... | ... | @@ -2385,13 +2391,16 @@ fn structDeclInner( |
| 2385 | 2391 | |
| 2386 | 2392 | const decl_inst = try gz.addBlock(tag, node); |
| 2387 | 2393 | try gz.instructions.append(gpa, decl_inst); |
| 2388 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | |
| 2394 | if (field_index != 0) { | |
| 2395 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | |
| 2396 | } | |
| 2389 | 2397 | |
| 2390 | 2398 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + |
| 2391 | 2399 | @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + |
| 2392 | bit_bag.items.len + 1 + fields_data.items.len + | |
| 2400 | bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len + | |
| 2393 | 2401 | block_scope.instructions.items.len + |
| 2394 | wip_decls.bit_bag.items.len + 1 + wip_decls.name_and_value.items.len); | |
| 2402 | wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) + | |
| 2403 | wip_decls.name_and_value.items.len); | |
| 2395 | 2404 | const zir_datas = astgen.instructions.items(.data); |
| 2396 | 2405 | zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 2397 | 2406 | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| ... | ... | @@ -2401,11 +2410,15 @@ fn structDeclInner( |
| 2401 | 2410 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); |
| 2402 | 2411 | |
| 2403 | 2412 | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. |
| 2404 | astgen.extra.appendAssumeCapacity(cur_bit_bag); | |
| 2413 | if (field_index != 0) { | |
| 2414 | astgen.extra.appendAssumeCapacity(cur_bit_bag); | |
| 2415 | } | |
| 2405 | 2416 | astgen.extra.appendSliceAssumeCapacity(fields_data.items); |
| 2406 | 2417 | |
| 2407 | 2418 | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. |
| 2408 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | |
| 2419 | if (wip_decls.decl_index != 0) { | |
| 2420 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | |
| 2421 | } | |
| 2409 | 2422 | astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items); |
| 2410 | 2423 | |
| 2411 | 2424 | return gz.indexToRef(decl_inst); |
| ... | ... | @@ -4750,6 +4763,11 @@ fn builtinCall( |
| 4750 | 4763 | return rvalue(gz, scope, rl, result, node); |
| 4751 | 4764 | }, |
| 4752 | 4765 | |
| 4766 | .This => return rvalue(gz, scope, rl, try gz.addNode(.this, node), node), | |
| 4767 | .fence => return rvalue(gz, scope, rl, try gz.addNode(.fence, node), node), | |
| 4768 | .return_address => return rvalue(gz, scope, rl, try gz.addNode(.ret_addr, node), node), | |
| 4769 | .src => return rvalue(gz, scope, rl, try gz.addNode(.builtin_src, node), node), | |
| 4770 | ||
| 4753 | 4771 | .add_with_overflow, |
| 4754 | 4772 | .align_cast, |
| 4755 | 4773 | .align_of, |
| ... | ... | @@ -4778,7 +4796,6 @@ fn builtinCall( |
| 4778 | 4796 | .error_name, |
| 4779 | 4797 | .error_return_trace, |
| 4780 | 4798 | .err_set_cast, |
| 4781 | .fence, | |
| 4782 | 4799 | .field_parent_ptr, |
| 4783 | 4800 | .float_to_int, |
| 4784 | 4801 | .has_field, |
| ... | ... | @@ -4794,7 +4811,6 @@ fn builtinCall( |
| 4794 | 4811 | .pop_count, |
| 4795 | 4812 | .ptr_cast, |
| 4796 | 4813 | .rem, |
| 4797 | .return_address, | |
| 4798 | 4814 | .set_align_stack, |
| 4799 | 4815 | .set_cold, |
| 4800 | 4816 | .set_float_mode, |
| ... | ... | @@ -4805,7 +4821,6 @@ fn builtinCall( |
| 4805 | 4821 | .shuffle, |
| 4806 | 4822 | .splat, |
| 4807 | 4823 | .reduce, |
| 4808 | .src, | |
| 4809 | 4824 | .sqrt, |
| 4810 | 4825 | .sin, |
| 4811 | 4826 | .cos, |
| ... | ... | @@ -4821,21 +4836,18 @@ fn builtinCall( |
| 4821 | 4836 | .round, |
| 4822 | 4837 | .sub_with_overflow, |
| 4823 | 4838 | .tag_name, |
| 4824 | .This, | |
| 4825 | 4839 | .truncate, |
| 4826 | 4840 | .Type, |
| 4827 | 4841 | .type_name, |
| 4828 | 4842 | .union_init, |
| 4829 | => return astgen.failNode(node, "TODO: implement builtin function {s}", .{ | |
| 4830 | builtin_name, | |
| 4831 | }), | |
| 4832 | ||
| 4833 | 4843 | .async_call, |
| 4834 | 4844 | .frame, |
| 4835 | 4845 | .Frame, |
| 4836 | 4846 | .frame_address, |
| 4837 | 4847 | .frame_size, |
| 4838 | => return astgen.failNode(node, "async and related features are not yet supported", .{}), | |
| 4848 | => return astgen.failNode(node, "TODO: implement builtin function {s}", .{ | |
| 4849 | builtin_name, | |
| 4850 | }), | |
| 4839 | 4851 | } |
| 4840 | 4852 | } |
| 4841 | 4853 | |
| ... | ... | @@ -5376,7 +5388,7 @@ pub fn failNodeNotes( |
| 5376 | 5388 | { |
| 5377 | 5389 | var managed = string_bytes.toManaged(astgen.gpa); |
| 5378 | 5390 | defer string_bytes.* = managed.toUnmanaged(); |
| 5379 | try managed.writer().print(format, args); | |
| 5391 | try managed.writer().print(format ++ "\x00", args); | |
| 5380 | 5392 | } |
| 5381 | 5393 | const notes_index: u32 = if (notes.len != 0) blk: { |
| 5382 | 5394 | const notes_start = astgen.extra.items.len; |
| ... | ... | @@ -5417,7 +5429,7 @@ pub fn failTokNotes( |
| 5417 | 5429 | { |
| 5418 | 5430 | var managed = string_bytes.toManaged(astgen.gpa); |
| 5419 | 5431 | defer string_bytes.* = managed.toUnmanaged(); |
| 5420 | try managed.writer().print(format, args); | |
| 5432 | try managed.writer().print(format ++ "\x00", args); | |
| 5421 | 5433 | } |
| 5422 | 5434 | const notes_index: u32 = if (notes.len != 0) blk: { |
| 5423 | 5435 | const notes_start = astgen.extra.items.len; |
| ... | ... | @@ -5451,7 +5463,7 @@ pub fn failOff( |
| 5451 | 5463 | { |
| 5452 | 5464 | var managed = string_bytes.toManaged(astgen.gpa); |
| 5453 | 5465 | defer string_bytes.* = managed.toUnmanaged(); |
| 5454 | try managed.writer().print(format, args); | |
| 5466 | try managed.writer().print(format ++ "\x00", args); | |
| 5455 | 5467 | } |
| 5456 | 5468 | try astgen.compile_errors.append(astgen.gpa, .{ |
| 5457 | 5469 | .msg = msg, |
| ... | ... | @@ -5475,7 +5487,7 @@ pub fn errNoteTok( |
| 5475 | 5487 | { |
| 5476 | 5488 | var managed = string_bytes.toManaged(astgen.gpa); |
| 5477 | 5489 | defer string_bytes.* = managed.toUnmanaged(); |
| 5478 | try managed.writer().print(format, args); | |
| 5490 | try managed.writer().print(format ++ "\x00", args); | |
| 5479 | 5491 | } |
| 5480 | 5492 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 5481 | 5493 | .msg = msg, |
| ... | ... | @@ -5498,7 +5510,7 @@ pub fn errNoteNode( |
| 5498 | 5510 | { |
| 5499 | 5511 | var managed = string_bytes.toManaged(astgen.gpa); |
| 5500 | 5512 | defer string_bytes.* = managed.toUnmanaged(); |
| 5501 | try managed.writer().print(format, args); | |
| 5513 | try managed.writer().print(format ++ "\x00", args); | |
| 5502 | 5514 | } |
| 5503 | 5515 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 5504 | 5516 | .msg = msg, |
src/Compilation.zig+63-6| ... | ... | @@ -391,10 +391,10 @@ pub const AllErrors = struct { |
| 391 | 391 | const notes = try arena.allocator.alloc(Message, module_err_msg.notes.len); |
| 392 | 392 | for (notes) |*note, i| { |
| 393 | 393 | const module_note = module_err_msg.notes[i]; |
| 394 | const source = try module_note.src_loc.fileScope().getSource(module.gpa); | |
| 394 | const source = try module_note.src_loc.file_scope.getSource(module.gpa); | |
| 395 | 395 | const byte_offset = try module_note.src_loc.byteOffset(); |
| 396 | 396 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 397 | const sub_file_path = module_note.src_loc.fileScope().sub_file_path; | |
| 397 | const sub_file_path = module_note.src_loc.file_scope.sub_file_path; | |
| 398 | 398 | note.* = .{ |
| 399 | 399 | .src = .{ |
| 400 | 400 | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| ... | ... | @@ -406,10 +406,10 @@ pub const AllErrors = struct { |
| 406 | 406 | }, |
| 407 | 407 | }; |
| 408 | 408 | } |
| 409 | const source = try module_err_msg.src_loc.fileScope().getSource(module.gpa); | |
| 409 | const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa); | |
| 410 | 410 | const byte_offset = try module_err_msg.src_loc.byteOffset(); |
| 411 | 411 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 412 | const sub_file_path = module_err_msg.src_loc.fileScope().sub_file_path; | |
| 412 | const sub_file_path = module_err_msg.src_loc.file_scope.sub_file_path; | |
| 413 | 413 | try errors.append(.{ |
| 414 | 414 | .src = .{ |
| 415 | 415 | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| ... | ... | @@ -423,6 +423,56 @@ pub const AllErrors = struct { |
| 423 | 423 | }); |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | pub fn addZir( | |
| 427 | arena: *Allocator, | |
| 428 | errors: *std.ArrayList(Message), | |
| 429 | file: *Module.Scope.File, | |
| 430 | source: []const u8, | |
| 431 | ) !void { | |
| 432 | assert(file.zir_loaded); | |
| 433 | assert(file.tree_loaded); | |
| 434 | const Zir = @import("Zir.zig"); | |
| 435 | const payload_index = file.zir.extra[Zir.compile_error_extra_index]; | |
| 436 | assert(payload_index != 0); | |
| 437 | ||
| 438 | const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index); | |
| 439 | const items_len = header.data.items_len; | |
| 440 | var extra_index = header.end; | |
| 441 | var item_i: usize = 0; | |
| 442 | while (item_i < items_len) : (item_i += 1) { | |
| 443 | const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); | |
| 444 | extra_index = item.end; | |
| 445 | ||
| 446 | if (item.data.notes != 0) { | |
| 447 | @panic("TODO implement AllErrors for Zir notes"); | |
| 448 | } | |
| 449 | ||
| 450 | const msg = file.zir.nullTerminatedString(item.data.msg); | |
| 451 | const byte_offset = blk: { | |
| 452 | const token_starts = file.tree.tokens.items(.start); | |
| 453 | if (item.data.node != 0) { | |
| 454 | const main_tokens = file.tree.nodes.items(.main_token); | |
| 455 | const main_token = main_tokens[item.data.node]; | |
| 456 | break :blk token_starts[main_token]; | |
| 457 | } | |
| 458 | break :blk token_starts[item.data.token] + item.data.byte_offset; | |
| 459 | }; | |
| 460 | const loc = std.zig.findLineColumn(source, byte_offset); | |
| 461 | ||
| 462 | try errors.append(.{ | |
| 463 | .src = .{ | |
| 464 | .src_path = try arena.dupe(u8, file.sub_file_path), | |
| 465 | .msg = try arena.dupe(u8, msg), | |
| 466 | .byte_offset = byte_offset, | |
| 467 | .line = @intCast(u32, loc.line), | |
| 468 | .column = @intCast(u32, loc.column), | |
| 469 | .notes = &.{}, // TODO | |
| 470 | .source_line = try arena.dupe(u8, loc.source_line), | |
| 471 | }, | |
| 472 | }); | |
| 473 | } | |
| 474 | } | |
| 475 | ||
| 426 | 476 | fn addPlain( |
| 427 | 477 | arena: *std.heap.ArenaAllocator, |
| 428 | 478 | errors: *std.ArrayList(Message), |
| ... | ... | @@ -1624,7 +1674,13 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 1624 | 1674 | } |
| 1625 | 1675 | if (self.bin_file.options.module) |module| { |
| 1626 | 1676 | for (module.failed_files.items()) |entry| { |
| 1627 | try AllErrors.add(module, &arena, &errors, entry.value.*); | |
| 1677 | if (entry.value) |msg| { | |
| 1678 | try AllErrors.add(module, &arena, &errors, msg.*); | |
| 1679 | } else { | |
| 1680 | // Must be ZIR errors. | |
| 1681 | const source = try entry.key.getSource(module.gpa); | |
| 1682 | try AllErrors.addZir(&arena.allocator, &errors, entry.key, source); | |
| 1683 | } | |
| 1628 | 1684 | } |
| 1629 | 1685 | for (module.failed_decls.items()) |entry| { |
| 1630 | 1686 | if (entry.key.namespace.file_scope.status == .parse_failure) { |
| ... | ... | @@ -2276,7 +2332,8 @@ fn reportRetryableAstGenError( |
| 2276 | 2332 | file.status = .retryable_failure; |
| 2277 | 2333 | |
| 2278 | 2334 | const err_msg = try Module.ErrorMsg.create(gpa, .{ |
| 2279 | .container = .{ .file_scope = file }, | |
| 2335 | .file_scope = file, | |
| 2336 | .parent_decl_node = 0, | |
| 2280 | 2337 | .lazy = .entire_file, |
| 2281 | 2338 | }, "unable to load {s}: {s}", .{ |
| 2282 | 2339 | file.sub_file_path, @errorName(err), |
src/Module.zig+91-129| ... | ... | @@ -70,7 +70,7 @@ emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{}, |
| 70 | 70 | compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, SrcLoc) = .{}, |
| 71 | 71 | /// Using a map here for consistency with the other fields here. |
| 72 | 72 | /// The ErrorMsg memory is owned by the `Scope.File`, using Module's general purpose allocator. |
| 73 | failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, *ErrorMsg) = .{}, | |
| 73 | failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{}, | |
| 74 | 74 | /// Using a map here for consistency with the other fields here. |
| 75 | 75 | /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator. |
| 76 | 76 | failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, |
| ... | ... | @@ -267,9 +267,10 @@ pub const Decl = struct { |
| 267 | 267 | return .{ .node_offset = decl.nodeIndexToRelative(node_index) }; |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | pub fn srcLoc(decl: *Decl) SrcLoc { | |
| 270 | pub fn srcLoc(decl: Decl) SrcLoc { | |
| 271 | 271 | return .{ |
| 272 | .container = .{ .decl = decl }, | |
| 272 | .file_scope = decl.getFileScope(), | |
| 273 | .parent_decl_node = decl.src_node, | |
| 273 | 274 | .lazy = .{ .node_offset = 0 }, |
| 274 | 275 | }; |
| 275 | 276 | } |
| ... | ... | @@ -367,7 +368,8 @@ pub const ErrorSet = struct { |
| 367 | 368 | |
| 368 | 369 | pub fn srcLoc(self: ErrorSet) SrcLoc { |
| 369 | 370 | return .{ |
| 370 | .container = .{ .decl = self.owner_decl }, | |
| 371 | .file_scope = self.owner_decl.getFileScope(), | |
| 372 | .parent_decl_node = self.owner_decl.src_node, | |
| 371 | 373 | .lazy = .{ .node_offset = self.node_offset }, |
| 372 | 374 | }; |
| 373 | 375 | } |
| ... | ... | @@ -397,7 +399,8 @@ pub const Struct = struct { |
| 397 | 399 | |
| 398 | 400 | pub fn srcLoc(s: Struct) SrcLoc { |
| 399 | 401 | return .{ |
| 400 | .container = .{ .decl = s.owner_decl }, | |
| 402 | .file_scope = s.owner_decl.getFileScope(), | |
| 403 | .parent_decl_node = s.owner_decl.src_node, | |
| 401 | 404 | .lazy = .{ .node_offset = s.node_offset }, |
| 402 | 405 | }; |
| 403 | 406 | } |
| ... | ... | @@ -416,7 +419,8 @@ pub const EnumSimple = struct { |
| 416 | 419 | |
| 417 | 420 | pub fn srcLoc(self: EnumSimple) SrcLoc { |
| 418 | 421 | return .{ |
| 419 | .container = .{ .decl = self.owner_decl }, | |
| 422 | .file_scope = self.owner_decl.getFileScope(), | |
| 423 | .parent_decl_node = self.owner_decl.src_node, | |
| 420 | 424 | .lazy = .{ .node_offset = self.node_offset }, |
| 421 | 425 | }; |
| 422 | 426 | } |
| ... | ... | @@ -444,7 +448,8 @@ pub const EnumFull = struct { |
| 444 | 448 | |
| 445 | 449 | pub fn srcLoc(self: EnumFull) SrcLoc { |
| 446 | 450 | return .{ |
| 447 | .container = .{ .decl = self.owner_decl }, | |
| 451 | .file_scope = self.owner_decl.getFileScope(), | |
| 452 | .parent_decl_node = self.owner_decl.src_node, | |
| 448 | 453 | .lazy = .{ .node_offset = self.node_offset }, |
| 449 | 454 | }; |
| 450 | 455 | } |
| ... | ... | @@ -1710,51 +1715,19 @@ pub const ErrorMsg = struct { |
| 1710 | 1715 | |
| 1711 | 1716 | /// Canonical reference to a position within a source file. |
| 1712 | 1717 | pub const SrcLoc = struct { |
| 1713 | /// The active field is determined by tag of `lazy`. | |
| 1714 | container: union { | |
| 1715 | /// The containing `Decl` according to the source code. | |
| 1716 | decl: *Decl, | |
| 1717 | file_scope: *Scope.File, | |
| 1718 | }, | |
| 1719 | /// Relative to `decl`. | |
| 1718 | file_scope: *Scope.File, | |
| 1719 | /// Might be 0 depending on tag of `lazy`. | |
| 1720 | parent_decl_node: ast.Node.Index, | |
| 1721 | /// Relative to `parent_decl_node`. | |
| 1720 | 1722 | lazy: LazySrcLoc, |
| 1721 | 1723 | |
| 1722 | pub fn fileScope(src_loc: SrcLoc) *Scope.File { | |
| 1723 | return switch (src_loc.lazy) { | |
| 1724 | .unneeded => unreachable, | |
| 1725 | ||
| 1726 | .byte_abs, | |
| 1727 | .token_abs, | |
| 1728 | .node_abs, | |
| 1729 | .entire_file, | |
| 1730 | => src_loc.container.file_scope, | |
| 1724 | pub fn declSrcToken(src_loc: SrcLoc) ast.TokenIndex { | |
| 1725 | const tree = src_loc.file_scope.tree; | |
| 1726 | return tree.firstToken(src_loc.parent_decl_node); | |
| 1727 | } | |
| 1731 | 1728 | |
| 1732 | .byte_offset, | |
| 1733 | .token_offset, | |
| 1734 | .node_offset, | |
| 1735 | .node_offset_back2tok, | |
| 1736 | .node_offset_var_decl_ty, | |
| 1737 | .node_offset_for_cond, | |
| 1738 | .node_offset_builtin_call_arg0, | |
| 1739 | .node_offset_builtin_call_arg1, | |
| 1740 | .node_offset_array_access_index, | |
| 1741 | .node_offset_slice_sentinel, | |
| 1742 | .node_offset_call_func, | |
| 1743 | .node_offset_field_name, | |
| 1744 | .node_offset_deref_ptr, | |
| 1745 | .node_offset_asm_source, | |
| 1746 | .node_offset_asm_ret_ty, | |
| 1747 | .node_offset_if_cond, | |
| 1748 | .node_offset_bin_op, | |
| 1749 | .node_offset_bin_lhs, | |
| 1750 | .node_offset_bin_rhs, | |
| 1751 | .node_offset_switch_operand, | |
| 1752 | .node_offset_switch_special_prong, | |
| 1753 | .node_offset_switch_range, | |
| 1754 | .node_offset_fn_type_cc, | |
| 1755 | .node_offset_fn_type_ret_ty, | |
| 1756 | => src_loc.container.decl.namespace.file_scope, | |
| 1757 | }; | |
| 1729 | pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) ast.TokenIndex { | |
| 1730 | return @bitCast(ast.Node.Index, offset + @bitCast(i32, src_loc.parent_decl_node)); | |
| 1758 | 1731 | } |
| 1759 | 1732 | |
| 1760 | 1733 | pub fn byteOffset(src_loc: SrcLoc) !u32 { |
| ... | ... | @@ -1765,48 +1738,45 @@ pub const SrcLoc = struct { |
| 1765 | 1738 | .byte_abs => |byte_index| return byte_index, |
| 1766 | 1739 | |
| 1767 | 1740 | .token_abs => |tok_index| { |
| 1768 | const tree = src_loc.container.file_scope.tree; | |
| 1741 | const tree = src_loc.file_scope.tree; | |
| 1769 | 1742 | const token_starts = tree.tokens.items(.start); |
| 1770 | 1743 | return token_starts[tok_index]; |
| 1771 | 1744 | }, |
| 1772 | 1745 | .node_abs => |node| { |
| 1773 | const tree = src_loc.container.file_scope.tree; | |
| 1746 | const tree = src_loc.file_scope.tree; | |
| 1774 | 1747 | const token_starts = tree.tokens.items(.start); |
| 1775 | 1748 | const tok_index = tree.firstToken(node); |
| 1776 | 1749 | return token_starts[tok_index]; |
| 1777 | 1750 | }, |
| 1778 | 1751 | .byte_offset => |byte_off| { |
| 1779 | const decl = src_loc.container.decl; | |
| 1780 | return decl.srcByteOffset() + byte_off; | |
| 1752 | const tree = src_loc.file_scope.tree; | |
| 1753 | const token_starts = tree.tokens.items(.start); | |
| 1754 | return token_starts[src_loc.declSrcToken()] + byte_off; | |
| 1781 | 1755 | }, |
| 1782 | 1756 | .token_offset => |tok_off| { |
| 1783 | const decl = src_loc.container.decl; | |
| 1784 | const tok_index = decl.srcToken() + tok_off; | |
| 1785 | const tree = decl.namespace.file_scope.tree; | |
| 1757 | const tok_index = src_loc.declSrcToken() + tok_off; | |
| 1758 | const tree = src_loc.file_scope.tree; | |
| 1786 | 1759 | const token_starts = tree.tokens.items(.start); |
| 1787 | 1760 | return token_starts[tok_index]; |
| 1788 | 1761 | }, |
| 1789 | 1762 | .node_offset, .node_offset_bin_op => |node_off| { |
| 1790 | const decl = src_loc.container.decl; | |
| 1791 | const node = decl.relativeToNodeIndex(node_off); | |
| 1792 | const tree = decl.namespace.file_scope.tree; | |
| 1763 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1764 | const tree = src_loc.file_scope.tree; | |
| 1793 | 1765 | const main_tokens = tree.nodes.items(.main_token); |
| 1794 | 1766 | const tok_index = main_tokens[node]; |
| 1795 | 1767 | const token_starts = tree.tokens.items(.start); |
| 1796 | 1768 | return token_starts[tok_index]; |
| 1797 | 1769 | }, |
| 1798 | 1770 | .node_offset_back2tok => |node_off| { |
| 1799 | const decl = src_loc.container.decl; | |
| 1800 | const node = decl.relativeToNodeIndex(node_off); | |
| 1801 | const tree = decl.namespace.file_scope.tree; | |
| 1771 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1772 | const tree = src_loc.file_scope.tree; | |
| 1802 | 1773 | const tok_index = tree.firstToken(node) - 2; |
| 1803 | 1774 | const token_starts = tree.tokens.items(.start); |
| 1804 | 1775 | return token_starts[tok_index]; |
| 1805 | 1776 | }, |
| 1806 | 1777 | .node_offset_var_decl_ty => |node_off| { |
| 1807 | const decl = src_loc.container.decl; | |
| 1808 | const node = decl.relativeToNodeIndex(node_off); | |
| 1809 | const tree = decl.namespace.file_scope.tree; | |
| 1778 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1779 | const tree = src_loc.file_scope.tree; | |
| 1810 | 1780 | const node_tags = tree.nodes.items(.tag); |
| 1811 | 1781 | const full = switch (node_tags[node]) { |
| 1812 | 1782 | .global_var_decl => tree.globalVarDecl(node), |
| ... | ... | @@ -1825,11 +1795,10 @@ pub const SrcLoc = struct { |
| 1825 | 1795 | return token_starts[tok_index]; |
| 1826 | 1796 | }, |
| 1827 | 1797 | .node_offset_builtin_call_arg0 => |node_off| { |
| 1828 | const decl = src_loc.container.decl; | |
| 1829 | const tree = decl.namespace.file_scope.tree; | |
| 1798 | const tree = src_loc.file_scope.tree; | |
| 1830 | 1799 | const node_datas = tree.nodes.items(.data); |
| 1831 | 1800 | const node_tags = tree.nodes.items(.tag); |
| 1832 | const node = decl.relativeToNodeIndex(node_off); | |
| 1801 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1833 | 1802 | const param = switch (node_tags[node]) { |
| 1834 | 1803 | .builtin_call_two, .builtin_call_two_comma => node_datas[node].lhs, |
| 1835 | 1804 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs], |
| ... | ... | @@ -1841,11 +1810,10 @@ pub const SrcLoc = struct { |
| 1841 | 1810 | return token_starts[tok_index]; |
| 1842 | 1811 | }, |
| 1843 | 1812 | .node_offset_builtin_call_arg1 => |node_off| { |
| 1844 | const decl = src_loc.container.decl; | |
| 1845 | const tree = decl.namespace.file_scope.tree; | |
| 1813 | const tree = src_loc.file_scope.tree; | |
| 1846 | 1814 | const node_datas = tree.nodes.items(.data); |
| 1847 | 1815 | const node_tags = tree.nodes.items(.tag); |
| 1848 | const node = decl.relativeToNodeIndex(node_off); | |
| 1816 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1849 | 1817 | const param = switch (node_tags[node]) { |
| 1850 | 1818 | .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs, |
| 1851 | 1819 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1], |
| ... | ... | @@ -1857,22 +1825,20 @@ pub const SrcLoc = struct { |
| 1857 | 1825 | return token_starts[tok_index]; |
| 1858 | 1826 | }, |
| 1859 | 1827 | .node_offset_array_access_index => |node_off| { |
| 1860 | const decl = src_loc.container.decl; | |
| 1861 | const tree = decl.namespace.file_scope.tree; | |
| 1828 | const tree = src_loc.file_scope.tree; | |
| 1862 | 1829 | const node_datas = tree.nodes.items(.data); |
| 1863 | 1830 | const node_tags = tree.nodes.items(.tag); |
| 1864 | const node = decl.relativeToNodeIndex(node_off); | |
| 1831 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1865 | 1832 | const main_tokens = tree.nodes.items(.main_token); |
| 1866 | 1833 | const tok_index = main_tokens[node_datas[node].rhs]; |
| 1867 | 1834 | const token_starts = tree.tokens.items(.start); |
| 1868 | 1835 | return token_starts[tok_index]; |
| 1869 | 1836 | }, |
| 1870 | 1837 | .node_offset_slice_sentinel => |node_off| { |
| 1871 | const decl = src_loc.container.decl; | |
| 1872 | const tree = decl.namespace.file_scope.tree; | |
| 1838 | const tree = src_loc.file_scope.tree; | |
| 1873 | 1839 | const node_datas = tree.nodes.items(.data); |
| 1874 | 1840 | const node_tags = tree.nodes.items(.tag); |
| 1875 | const node = decl.relativeToNodeIndex(node_off); | |
| 1841 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1876 | 1842 | const full = switch (node_tags[node]) { |
| 1877 | 1843 | .slice_open => tree.sliceOpen(node), |
| 1878 | 1844 | .slice => tree.slice(node), |
| ... | ... | @@ -1885,11 +1851,10 @@ pub const SrcLoc = struct { |
| 1885 | 1851 | return token_starts[tok_index]; |
| 1886 | 1852 | }, |
| 1887 | 1853 | .node_offset_call_func => |node_off| { |
| 1888 | const decl = src_loc.container.decl; | |
| 1889 | const tree = decl.namespace.file_scope.tree; | |
| 1854 | const tree = src_loc.file_scope.tree; | |
| 1890 | 1855 | const node_datas = tree.nodes.items(.data); |
| 1891 | 1856 | const node_tags = tree.nodes.items(.tag); |
| 1892 | const node = decl.relativeToNodeIndex(node_off); | |
| 1857 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1893 | 1858 | var params: [1]ast.Node.Index = undefined; |
| 1894 | 1859 | const full = switch (node_tags[node]) { |
| 1895 | 1860 | .call_one, |
| ... | ... | @@ -1912,11 +1877,10 @@ pub const SrcLoc = struct { |
| 1912 | 1877 | return token_starts[tok_index]; |
| 1913 | 1878 | }, |
| 1914 | 1879 | .node_offset_field_name => |node_off| { |
| 1915 | const decl = src_loc.container.decl; | |
| 1916 | const tree = decl.namespace.file_scope.tree; | |
| 1880 | const tree = src_loc.file_scope.tree; | |
| 1917 | 1881 | const node_datas = tree.nodes.items(.data); |
| 1918 | 1882 | const node_tags = tree.nodes.items(.tag); |
| 1919 | const node = decl.relativeToNodeIndex(node_off); | |
| 1883 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1920 | 1884 | const tok_index = switch (node_tags[node]) { |
| 1921 | 1885 | .field_access => node_datas[node].rhs, |
| 1922 | 1886 | else => tree.firstToken(node) - 2, |
| ... | ... | @@ -1925,21 +1889,19 @@ pub const SrcLoc = struct { |
| 1925 | 1889 | return token_starts[tok_index]; |
| 1926 | 1890 | }, |
| 1927 | 1891 | .node_offset_deref_ptr => |node_off| { |
| 1928 | const decl = src_loc.container.decl; | |
| 1929 | const tree = decl.namespace.file_scope.tree; | |
| 1892 | const tree = src_loc.file_scope.tree; | |
| 1930 | 1893 | const node_datas = tree.nodes.items(.data); |
| 1931 | 1894 | const node_tags = tree.nodes.items(.tag); |
| 1932 | const node = decl.relativeToNodeIndex(node_off); | |
| 1895 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1933 | 1896 | const tok_index = node_datas[node].lhs; |
| 1934 | 1897 | const token_starts = tree.tokens.items(.start); |
| 1935 | 1898 | return token_starts[tok_index]; |
| 1936 | 1899 | }, |
| 1937 | 1900 | .node_offset_asm_source => |node_off| { |
| 1938 | const decl = src_loc.container.decl; | |
| 1939 | const tree = decl.namespace.file_scope.tree; | |
| 1901 | const tree = src_loc.file_scope.tree; | |
| 1940 | 1902 | const node_datas = tree.nodes.items(.data); |
| 1941 | 1903 | const node_tags = tree.nodes.items(.tag); |
| 1942 | const node = decl.relativeToNodeIndex(node_off); | |
| 1904 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1943 | 1905 | const full = switch (node_tags[node]) { |
| 1944 | 1906 | .asm_simple => tree.asmSimple(node), |
| 1945 | 1907 | .@"asm" => tree.asmFull(node), |
| ... | ... | @@ -1951,11 +1913,10 @@ pub const SrcLoc = struct { |
| 1951 | 1913 | return token_starts[tok_index]; |
| 1952 | 1914 | }, |
| 1953 | 1915 | .node_offset_asm_ret_ty => |node_off| { |
| 1954 | const decl = src_loc.container.decl; | |
| 1955 | const tree = decl.namespace.file_scope.tree; | |
| 1916 | const tree = src_loc.file_scope.tree; | |
| 1956 | 1917 | const node_datas = tree.nodes.items(.data); |
| 1957 | 1918 | const node_tags = tree.nodes.items(.tag); |
| 1958 | const node = decl.relativeToNodeIndex(node_off); | |
| 1919 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1959 | 1920 | const full = switch (node_tags[node]) { |
| 1960 | 1921 | .asm_simple => tree.asmSimple(node), |
| 1961 | 1922 | .@"asm" => tree.asmFull(node), |
| ... | ... | @@ -1968,9 +1929,8 @@ pub const SrcLoc = struct { |
| 1968 | 1929 | }, |
| 1969 | 1930 | |
| 1970 | 1931 | .node_offset_for_cond, .node_offset_if_cond => |node_off| { |
| 1971 | const decl = src_loc.container.decl; | |
| 1972 | const node = decl.relativeToNodeIndex(node_off); | |
| 1973 | const tree = decl.namespace.file_scope.tree; | |
| 1932 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1933 | const tree = src_loc.file_scope.tree; | |
| 1974 | 1934 | const node_tags = tree.nodes.items(.tag); |
| 1975 | 1935 | const src_node = switch (node_tags[node]) { |
| 1976 | 1936 | .if_simple => tree.ifSimple(node).ast.cond_expr, |
| ... | ... | @@ -1988,9 +1948,8 @@ pub const SrcLoc = struct { |
| 1988 | 1948 | return token_starts[tok_index]; |
| 1989 | 1949 | }, |
| 1990 | 1950 | .node_offset_bin_lhs => |node_off| { |
| 1991 | const decl = src_loc.container.decl; | |
| 1992 | const node = decl.relativeToNodeIndex(node_off); | |
| 1993 | const tree = decl.namespace.file_scope.tree; | |
| 1951 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1952 | const tree = src_loc.file_scope.tree; | |
| 1994 | 1953 | const node_datas = tree.nodes.items(.data); |
| 1995 | 1954 | const src_node = node_datas[node].lhs; |
| 1996 | 1955 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -1999,9 +1958,8 @@ pub const SrcLoc = struct { |
| 1999 | 1958 | return token_starts[tok_index]; |
| 2000 | 1959 | }, |
| 2001 | 1960 | .node_offset_bin_rhs => |node_off| { |
| 2002 | const decl = src_loc.container.decl; | |
| 2003 | const node = decl.relativeToNodeIndex(node_off); | |
| 2004 | const tree = decl.namespace.file_scope.tree; | |
| 1961 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1962 | const tree = src_loc.file_scope.tree; | |
| 2005 | 1963 | const node_datas = tree.nodes.items(.data); |
| 2006 | 1964 | const src_node = node_datas[node].rhs; |
| 2007 | 1965 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2011,9 +1969,8 @@ pub const SrcLoc = struct { |
| 2011 | 1969 | }, |
| 2012 | 1970 | |
| 2013 | 1971 | .node_offset_switch_operand => |node_off| { |
| 2014 | const decl = src_loc.container.decl; | |
| 2015 | const node = decl.relativeToNodeIndex(node_off); | |
| 2016 | const tree = decl.namespace.file_scope.tree; | |
| 1972 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1973 | const tree = src_loc.file_scope.tree; | |
| 2017 | 1974 | const node_datas = tree.nodes.items(.data); |
| 2018 | 1975 | const src_node = node_datas[node].lhs; |
| 2019 | 1976 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2023,9 +1980,8 @@ pub const SrcLoc = struct { |
| 2023 | 1980 | }, |
| 2024 | 1981 | |
| 2025 | 1982 | .node_offset_switch_special_prong => |node_off| { |
| 2026 | const decl = src_loc.container.decl; | |
| 2027 | const switch_node = decl.relativeToNodeIndex(node_off); | |
| 2028 | const tree = decl.namespace.file_scope.tree; | |
| 1983 | const switch_node = src_loc.declRelativeToNodeIndex(node_off); | |
| 1984 | const tree = src_loc.file_scope.tree; | |
| 2029 | 1985 | const node_datas = tree.nodes.items(.data); |
| 2030 | 1986 | const node_tags = tree.nodes.items(.tag); |
| 2031 | 1987 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2050,9 +2006,8 @@ pub const SrcLoc = struct { |
| 2050 | 2006 | }, |
| 2051 | 2007 | |
| 2052 | 2008 | .node_offset_switch_range => |node_off| { |
| 2053 | const decl = src_loc.container.decl; | |
| 2054 | const switch_node = decl.relativeToNodeIndex(node_off); | |
| 2055 | const tree = decl.namespace.file_scope.tree; | |
| 2009 | const switch_node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2010 | const tree = src_loc.file_scope.tree; | |
| 2056 | 2011 | const node_datas = tree.nodes.items(.data); |
| 2057 | 2012 | const node_tags = tree.nodes.items(.tag); |
| 2058 | 2013 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2081,11 +2036,10 @@ pub const SrcLoc = struct { |
| 2081 | 2036 | }, |
| 2082 | 2037 | |
| 2083 | 2038 | .node_offset_fn_type_cc => |node_off| { |
| 2084 | const decl = src_loc.container.decl; | |
| 2085 | const tree = decl.namespace.file_scope.tree; | |
| 2039 | const tree = src_loc.file_scope.tree; | |
| 2086 | 2040 | const node_datas = tree.nodes.items(.data); |
| 2087 | 2041 | const node_tags = tree.nodes.items(.tag); |
| 2088 | const node = decl.relativeToNodeIndex(node_off); | |
| 2042 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2089 | 2043 | var params: [1]ast.Node.Index = undefined; |
| 2090 | 2044 | const full = switch (node_tags[node]) { |
| 2091 | 2045 | .fn_proto_simple => tree.fnProtoSimple(&params, node), |
| ... | ... | @@ -2101,11 +2055,10 @@ pub const SrcLoc = struct { |
| 2101 | 2055 | }, |
| 2102 | 2056 | |
| 2103 | 2057 | .node_offset_fn_type_ret_ty => |node_off| { |
| 2104 | const decl = src_loc.container.decl; | |
| 2105 | const tree = decl.namespace.file_scope.tree; | |
| 2058 | const tree = src_loc.file_scope.tree; | |
| 2106 | 2059 | const node_datas = tree.nodes.items(.data); |
| 2107 | 2060 | const node_tags = tree.nodes.items(.tag); |
| 2108 | const node = decl.relativeToNodeIndex(node_off); | |
| 2061 | const node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2109 | 2062 | var params: [1]ast.Node.Index = undefined; |
| 2110 | 2063 | const full = switch (node_tags[node]) { |
| 2111 | 2064 | .fn_proto_simple => tree.fnProtoSimple(&params, node), |
| ... | ... | @@ -2288,7 +2241,8 @@ pub const LazySrcLoc = union(enum) { |
| 2288 | 2241 | .token_abs, |
| 2289 | 2242 | .node_abs, |
| 2290 | 2243 | => .{ |
| 2291 | .container = .{ .file_scope = scope.getFileScope() }, | |
| 2244 | .file_scope = scope.getFileScope(), | |
| 2245 | .parent_decl_node = 0, | |
| 2292 | 2246 | .lazy = lazy, |
| 2293 | 2247 | }, |
| 2294 | 2248 | |
| ... | ... | @@ -2317,7 +2271,8 @@ pub const LazySrcLoc = union(enum) { |
| 2317 | 2271 | .node_offset_fn_type_cc, |
| 2318 | 2272 | .node_offset_fn_type_ret_ty, |
| 2319 | 2273 | => .{ |
| 2320 | .container = .{ .decl = scope.srcDecl().? }, | |
| 2274 | .file_scope = scope.getFileScope(), | |
| 2275 | .parent_decl_node = scope.srcDecl().?.src_node, | |
| 2321 | 2276 | .lazy = lazy, |
| 2322 | 2277 | }, |
| 2323 | 2278 | }; |
| ... | ... | @@ -2332,7 +2287,8 @@ pub const LazySrcLoc = union(enum) { |
| 2332 | 2287 | .token_abs, |
| 2333 | 2288 | .node_abs, |
| 2334 | 2289 | => .{ |
| 2335 | .container = .{ .file_scope = decl.getFileScope() }, | |
| 2290 | .file_scope = decl.getFileScope(), | |
| 2291 | .parent_decl_node = 0, | |
| 2336 | 2292 | .lazy = lazy, |
| 2337 | 2293 | }, |
| 2338 | 2294 | |
| ... | ... | @@ -2361,7 +2317,8 @@ pub const LazySrcLoc = union(enum) { |
| 2361 | 2317 | .node_offset_fn_type_cc, |
| 2362 | 2318 | .node_offset_fn_type_ret_ty, |
| 2363 | 2319 | => .{ |
| 2364 | .container = .{ .decl = decl }, | |
| 2320 | .file_scope = decl.getFileScope(), | |
| 2321 | .parent_decl_node = decl.src_node, | |
| 2365 | 2322 | .lazy = lazy, |
| 2366 | 2323 | }, |
| 2367 | 2324 | }; |
| ... | ... | @@ -2409,7 +2366,7 @@ pub fn deinit(mod: *Module) void { |
| 2409 | 2366 | mod.emit_h_failed_decls.deinit(gpa); |
| 2410 | 2367 | |
| 2411 | 2368 | for (mod.failed_files.items()) |entry| { |
| 2412 | entry.value.destroy(gpa); | |
| 2369 | if (entry.value) |msg| msg.destroy(gpa); | |
| 2413 | 2370 | } |
| 2414 | 2371 | mod.failed_files.deinit(gpa); |
| 2415 | 2372 | |
| ... | ... | @@ -2495,7 +2452,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node |
| 2495 | 2452 | const lock = comp.mutex.acquire(); |
| 2496 | 2453 | defer lock.release(); |
| 2497 | 2454 | if (mod.failed_files.swapRemove(file)) |entry| { |
| 2498 | entry.value.destroy(gpa); // Delete previous error message. | |
| 2455 | if (entry.value) |msg| msg.destroy(gpa); // Delete previous error message. | |
| 2499 | 2456 | } |
| 2500 | 2457 | }, |
| 2501 | 2458 | } |
| ... | ... | @@ -2531,7 +2488,8 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node |
| 2531 | 2488 | const err_msg = try gpa.create(ErrorMsg); |
| 2532 | 2489 | err_msg.* = .{ |
| 2533 | 2490 | .src_loc = .{ |
| 2534 | .container = .{ .file_scope = file }, | |
| 2491 | .file_scope = file, | |
| 2492 | .parent_decl_node = 0, | |
| 2535 | 2493 | .lazy = .{ .byte_abs = token_starts[parse_err.token] }, |
| 2536 | 2494 | }, |
| 2537 | 2495 | .msg = msg.toOwnedSlice(), |
| ... | ... | @@ -2550,11 +2508,11 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node |
| 2550 | 2508 | file.zir = try AstGen.generate(gpa, file); |
| 2551 | 2509 | file.zir_loaded = true; |
| 2552 | 2510 | |
| 2553 | if (file.zir.extra[1] != 0) { | |
| 2511 | if (file.zir.hasCompileErrors()) { | |
| 2554 | 2512 | { |
| 2555 | 2513 | const lock = comp.mutex.acquire(); |
| 2556 | 2514 | defer lock.release(); |
| 2557 | try mod.failed_files.putNoClobber(gpa, file, undefined); | |
| 2515 | try mod.failed_files.putNoClobber(gpa, file, null); | |
| 2558 | 2516 | } |
| 2559 | 2517 | file.status = .astgen_failure; |
| 2560 | 2518 | return error.AnalysisFail; |
| ... | ... | @@ -2972,12 +2930,14 @@ fn semaContainerFn( |
| 2972 | 2930 | if (deleted_decls.swapRemove(decl) == null) { |
| 2973 | 2931 | decl.analysis = .sema_failure; |
| 2974 | 2932 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 2975 | .container = .{ .file_scope = namespace.file_scope }, | |
| 2933 | .file_scope = namespace.file_scope, | |
| 2934 | .parent_decl_node = 0, | |
| 2976 | 2935 | .lazy = .{ .token_abs = name_token }, |
| 2977 | 2936 | }, "redeclaration of '{s}'", .{decl.name}); |
| 2978 | 2937 | errdefer msg.destroy(mod.gpa); |
| 2979 | 2938 | const other_src_loc: SrcLoc = .{ |
| 2980 | .container = .{ .file_scope = decl.namespace.file_scope }, | |
| 2939 | .file_scope = namespace.file_scope, | |
| 2940 | .parent_decl_node = 0, | |
| 2981 | 2941 | .lazy = .{ .node_abs = prev_src_node }, |
| 2982 | 2942 | }; |
| 2983 | 2943 | try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{}); |
| ... | ... | @@ -3040,12 +3000,14 @@ fn semaContainerVar( |
| 3040 | 3000 | if (deleted_decls.swapRemove(decl) == null) { |
| 3041 | 3001 | decl.analysis = .sema_failure; |
| 3042 | 3002 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3043 | .container = .{ .file_scope = namespace.file_scope }, | |
| 3003 | .file_scope = namespace.file_scope, | |
| 3004 | .parent_decl_node = 0, | |
| 3044 | 3005 | .lazy = .{ .token_abs = name_token }, |
| 3045 | 3006 | }, "redeclaration of '{s}'", .{decl.name}); |
| 3046 | 3007 | errdefer msg.destroy(mod.gpa); |
| 3047 | 3008 | const other_src_loc: SrcLoc = .{ |
| 3048 | .container = .{ .file_scope = decl.namespace.file_scope }, | |
| 3009 | .file_scope = decl.namespace.file_scope, | |
| 3010 | .parent_decl_node = 0, | |
| 3049 | 3011 | .lazy = .{ .node_abs = prev_src_node }, |
| 3050 | 3012 | }; |
| 3051 | 3013 | try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{}); |
src/Sema.zig+25-16| ... | ... | @@ -170,9 +170,7 @@ pub fn analyzeBody( |
| 170 | 170 | .cmp_lte => try sema.zirCmp(block, inst, .lte), |
| 171 | 171 | .cmp_neq => try sema.zirCmp(block, inst, .neq), |
| 172 | 172 | .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst), |
| 173 | .decl_ref => try sema.zirDeclRef(block, inst), | |
| 174 | 173 | .decl_ref_named => try sema.zirDeclRefNamed(block, inst), |
| 175 | .decl_val => try sema.zirDeclVal(block, inst), | |
| 176 | 174 | .decl_val_named => try sema.zirDeclValNamed(block, inst), |
| 177 | 175 | .load => try sema.zirLoad(block, inst), |
| 178 | 176 | .div => try sema.zirArithmetic(block, inst), |
| ... | ... | @@ -266,6 +264,10 @@ pub fn analyzeBody( |
| 266 | 264 | .type_info => try sema.zirTypeInfo(block, inst), |
| 267 | 265 | .size_of => try sema.zirSizeOf(block, inst), |
| 268 | 266 | .bit_size_of => try sema.zirBitSizeOf(block, inst), |
| 267 | .this => try sema.zirThis(block, inst), | |
| 268 | .fence => try sema.zirFence(block, inst), | |
| 269 | .ret_addr => try sema.zirRetAddr(block, inst), | |
| 270 | .builtin_src => try sema.zirBuiltinSrc(block, inst), | |
| 269 | 271 | .typeof => try sema.zirTypeof(block, inst), |
| 270 | 272 | .typeof_elem => try sema.zirTypeofElem(block, inst), |
| 271 | 273 | .typeof_peer => try sema.zirTypeofPeer(block, inst), |
| ... | ... | @@ -1656,20 +1658,6 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE |
| 1656 | 1658 | _ = try block.addDbgStmt(src, abs_byte_off); |
| 1657 | 1659 | } |
| 1658 | 1660 | |
| 1659 | fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 1660 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | |
| 1661 | const src = inst_data.src(); | |
| 1662 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; | |
| 1663 | return sema.analyzeDeclRef(block, src, decl); | |
| 1664 | } | |
| 1665 | ||
| 1666 | fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 1667 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | |
| 1668 | const src = inst_data.src(); | |
| 1669 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; | |
| 1670 | return sema.analyzeDeclVal(block, src, decl); | |
| 1671 | } | |
| 1672 | ||
| 1673 | 1661 | fn zirDeclRefNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 1674 | 1662 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| 1675 | 1663 | const src = inst_data.src(); |
| ... | ... | @@ -4373,6 +4361,27 @@ fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr |
| 4373 | 4361 | return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), bit_size); |
| 4374 | 4362 | } |
| 4375 | 4363 | |
| 4364 | fn zirThis(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 4365 | const src_node = sema.code.instructions.items(.data)[inst].node; | |
| 4366 | const src: LazySrcLoc = .{ .node_offset = src_node }; | |
| 4367 | return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirThis", .{}); | |
| 4368 | } | |
| 4369 | fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 4370 | const src_node = sema.code.instructions.items(.data)[inst].node; | |
| 4371 | const src: LazySrcLoc = .{ .node_offset = src_node }; | |
| 4372 | return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirFence", .{}); | |
| 4373 | } | |
| 4374 | fn zirRetAddr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 4375 | const src_node = sema.code.instructions.items(.data)[inst].node; | |
| 4376 | const src: LazySrcLoc = .{ .node_offset = src_node }; | |
| 4377 | return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirRetAddr", .{}); | |
| 4378 | } | |
| 4379 | fn zirBuiltinSrc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 4380 | const src_node = sema.code.instructions.items(.data)[inst].node; | |
| 4381 | const src: LazySrcLoc = .{ .node_offset = src_node }; | |
| 4382 | return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinSrc", .{}); | |
| 4383 | } | |
| 4384 | ||
| 4376 | 4385 | fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 4377 | 4386 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4378 | 4387 | const src = inst_data.src(); |
src/Zir.zig+138-82| ... | ... | @@ -42,6 +42,9 @@ string_bytes: []u8, |
| 42 | 42 | /// payload at this index. |
| 43 | 43 | extra: []u32, |
| 44 | 44 | |
| 45 | pub const main_struct_extra_index = 0; | |
| 46 | pub const compile_error_extra_index = 1; | |
| 47 | ||
| 45 | 48 | /// Returns the requested data, as well as the new index which is at the start of the |
| 46 | 49 | /// trailers for the object. |
| 47 | 50 | pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } { |
| ... | ... | @@ -76,6 +79,10 @@ pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref { |
| 76 | 79 | return @bitCast([]Inst.Ref, raw_slice); |
| 77 | 80 | } |
| 78 | 81 | |
| 82 | pub fn hasCompileErrors(code: Zir) bool { | |
| 83 | return code.extra[compile_error_extra_index] != 0; | |
| 84 | } | |
| 85 | ||
| 79 | 86 | pub fn deinit(code: *Zir, gpa: *Allocator) void { |
| 80 | 87 | code.instructions.deinit(gpa); |
| 81 | 88 | gpa.free(code.string_bytes); |
| ... | ... | @@ -83,13 +90,11 @@ pub fn deinit(code: *Zir, gpa: *Allocator) void { |
| 83 | 90 | code.* = undefined; |
| 84 | 91 | } |
| 85 | 92 | |
| 86 | /// For debugging purposes, like dumpFn but for unanalyzed zir blocks | |
| 87 | pub fn dump( | |
| 88 | code: Zir, | |
| 93 | /// Write human-readable, debug formatted ZIR code to a file. | |
| 94 | pub fn renderAsTextToFile( | |
| 89 | 95 | gpa: *Allocator, |
| 90 | kind: []const u8, | |
| 91 | scope: *Module.Scope, | |
| 92 | param_count: usize, | |
| 96 | scope_file: *Module.Scope.File, | |
| 97 | fs_file: std.fs.File, | |
| 93 | 98 | ) !void { |
| 94 | 99 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 95 | 100 | defer arena.deinit(); |
| ... | ... | @@ -97,17 +102,17 @@ pub fn dump( |
| 97 | 102 | var writer: Writer = .{ |
| 98 | 103 | .gpa = gpa, |
| 99 | 104 | .arena = &arena.allocator, |
| 100 | .scope = scope, | |
| 101 | .code = code, | |
| 105 | .file = scope_file, | |
| 106 | .code = scope_file.zir, | |
| 102 | 107 | .indent = 0, |
| 103 | .param_count = param_count, | |
| 108 | .parent_decl_node = 0, | |
| 109 | .param_count = 0, | |
| 104 | 110 | }; |
| 105 | 111 | |
| 106 | const decl_name = scope.srcDecl().?.name; | |
| 107 | const stderr = std.io.getStdErr().writer(); | |
| 108 | try stderr.print("ZIR {s} {s} %0 ", .{ kind, decl_name }); | |
| 109 | try writer.writeInstToStream(stderr, 0); | |
| 110 | try stderr.print(" // end ZIR {s} {s}\n\n", .{ kind, decl_name }); | |
| 112 | const main_struct_inst = scope_file.zir.extra[0] - @intCast(u32, Inst.Ref.typed_value_map.len); | |
| 113 | try fs_file.writer().print("%{d} ", .{main_struct_inst}); | |
| 114 | try writer.writeInstToStream(fs_file.writer(), main_struct_inst); | |
| 115 | try fs_file.writeAll("\n"); | |
| 111 | 116 | } |
| 112 | 117 | |
| 113 | 118 | /// These are untyped instructions generated from an Abstract Syntax Tree. |
| ... | ... | @@ -291,12 +296,6 @@ pub const Inst = struct { |
| 291 | 296 | /// Declares the beginning of a statement. Used for debug info. |
| 292 | 297 | /// Uses the `node` union field. |
| 293 | 298 | dbg_stmt_node, |
| 294 | /// Represents a pointer to a global decl. | |
| 295 | /// Uses the `pl_node` union field. `payload_index` is into `decls`. | |
| 296 | decl_ref, | |
| 297 | /// Equivalent to a decl_ref followed by load. | |
| 298 | /// Uses the `pl_node` union field. `payload_index` is into `decls`. | |
| 299 | decl_val, | |
| 300 | 299 | /// Same as `decl_ref` except instead of indexing into decls, uses |
| 301 | 300 | /// a name to identify the Decl. Uses the `str_tok` union field. |
| 302 | 301 | decl_ref_named, |
| ... | ... | @@ -705,6 +704,14 @@ pub const Inst = struct { |
| 705 | 704 | size_of, |
| 706 | 705 | /// Implements the `@bitSizeOf` builtin. Uses `un_node`. |
| 707 | 706 | bit_size_of, |
| 707 | /// Implements the `@This` builtin. Uses `node`. | |
| 708 | this, | |
| 709 | /// Implements the `@fence` builtin. Uses `un_node`. | |
| 710 | fence, | |
| 711 | /// Implements the `@returnAddress` builtin. Uses `un_node`. | |
| 712 | ret_addr, | |
| 713 | /// Implements the `@src` builtin. Uses `un_node`. | |
| 714 | builtin_src, | |
| 708 | 715 | |
| 709 | 716 | /// Returns whether the instruction is one of the control flow "noreturn" types. |
| 710 | 717 | /// Function calls do not count. |
| ... | ... | @@ -758,8 +765,6 @@ pub const Inst = struct { |
| 758 | 765 | .enum_decl_nonexhaustive, |
| 759 | 766 | .opaque_decl, |
| 760 | 767 | .dbg_stmt_node, |
| 761 | .decl_ref, | |
| 762 | .decl_val, | |
| 763 | 768 | .decl_ref_named, |
| 764 | 769 | .decl_val_named, |
| 765 | 770 | .load, |
| ... | ... | @@ -873,6 +878,10 @@ pub const Inst = struct { |
| 873 | 878 | .type_info, |
| 874 | 879 | .size_of, |
| 875 | 880 | .bit_size_of, |
| 881 | .this, | |
| 882 | .fence, | |
| 883 | .ret_addr, | |
| 884 | .builtin_src, | |
| 876 | 885 | => false, |
| 877 | 886 | |
| 878 | 887 | .@"break", |
| ... | ... | @@ -1647,11 +1656,16 @@ pub const SpecialProng = enum { none, @"else", under }; |
| 1647 | 1656 | const Writer = struct { |
| 1648 | 1657 | gpa: *Allocator, |
| 1649 | 1658 | arena: *Allocator, |
| 1650 | scope: *Module.Scope, | |
| 1659 | file: *Module.Scope.File, | |
| 1651 | 1660 | code: Zir, |
| 1652 | indent: usize, | |
| 1661 | indent: u32, | |
| 1662 | parent_decl_node: u32, | |
| 1653 | 1663 | param_count: usize, |
| 1654 | 1664 | |
| 1665 | fn relativeToNodeIndex(self: *Writer, offset: i32) ast.Node.Index { | |
| 1666 | return @bitCast(ast.Node.Index, offset + @bitCast(i32, self.parent_decl_node)); | |
| 1667 | } | |
| 1668 | ||
| 1655 | 1669 | fn writeInstToStream( |
| 1656 | 1670 | self: *Writer, |
| 1657 | 1671 | stream: anytype, |
| ... | ... | @@ -1832,10 +1846,6 @@ const Writer = struct { |
| 1832 | 1846 | .typeof_peer, |
| 1833 | 1847 | => try self.writePlNodeMultiOp(stream, inst), |
| 1834 | 1848 | |
| 1835 | .decl_ref, | |
| 1836 | .decl_val, | |
| 1837 | => try self.writePlNodeDecl(stream, inst), | |
| 1838 | ||
| 1839 | 1849 | .field_ptr, |
| 1840 | 1850 | .field_val, |
| 1841 | 1851 | => try self.writePlNodeField(stream, inst), |
| ... | ... | @@ -1851,6 +1861,10 @@ const Writer = struct { |
| 1851 | 1861 | .repeat_inline, |
| 1852 | 1862 | .alloc_inferred, |
| 1853 | 1863 | .alloc_inferred_mut, |
| 1864 | .this, | |
| 1865 | .fence, | |
| 1866 | .ret_addr, | |
| 1867 | .builtin_src, | |
| 1854 | 1868 | => try self.writeNode(stream, inst), |
| 1855 | 1869 | |
| 1856 | 1870 | .error_value, |
| ... | ... | @@ -2067,68 +2081,114 @@ const Writer = struct { |
| 2067 | 2081 | const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index); |
| 2068 | 2082 | const body = self.code.extra[extra.end..][0..extra.data.body_len]; |
| 2069 | 2083 | const fields_len = extra.data.fields_len; |
| 2084 | const decls_len = extra.data.decls_len; | |
| 2085 | ||
| 2086 | const prev_parent_decl_node = self.parent_decl_node; | |
| 2087 | self.parent_decl_node = self.relativeToNodeIndex(inst_data.src_node); | |
| 2088 | ||
| 2089 | var extra_index: usize = undefined; | |
| 2070 | 2090 | |
| 2071 | 2091 | if (fields_len == 0) { |
| 2072 | 2092 | assert(body.len == 0); |
| 2073 | try stream.writeAll("{}, {}) "); | |
| 2074 | try self.writeSrc(stream, inst_data.src()); | |
| 2075 | return; | |
| 2076 | } | |
| 2093 | try stream.writeAll("{}, {}, {"); | |
| 2094 | extra_index = extra.end; | |
| 2095 | } else { | |
| 2096 | try stream.writeAll("{\n"); | |
| 2097 | self.indent += 2; | |
| 2098 | try self.writeBody(stream, body); | |
| 2099 | ||
| 2100 | try stream.writeByteNTimes(' ', self.indent - 2); | |
| 2101 | try stream.writeAll("}, {\n"); | |
| 2102 | ||
| 2103 | const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable; | |
| 2104 | const body_end = extra.end + body.len; | |
| 2105 | extra_index = body_end + bit_bags_count; | |
| 2106 | var bit_bag_index: usize = body_end; | |
| 2107 | var cur_bit_bag: u32 = undefined; | |
| 2108 | var field_i: u32 = 0; | |
| 2109 | while (field_i < fields_len) : (field_i += 1) { | |
| 2110 | if (field_i % 16 == 0) { | |
| 2111 | cur_bit_bag = self.code.extra[bit_bag_index]; | |
| 2112 | bit_bag_index += 1; | |
| 2113 | } | |
| 2114 | const has_align = @truncate(u1, cur_bit_bag) != 0; | |
| 2115 | cur_bit_bag >>= 1; | |
| 2116 | const has_default = @truncate(u1, cur_bit_bag) != 0; | |
| 2117 | cur_bit_bag >>= 1; | |
| 2077 | 2118 | |
| 2078 | try stream.writeAll("{\n"); | |
| 2079 | self.indent += 2; | |
| 2080 | try self.writeBody(stream, body); | |
| 2119 | const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]); | |
| 2120 | extra_index += 1; | |
| 2121 | const field_type = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2122 | extra_index += 1; | |
| 2081 | 2123 | |
| 2082 | try stream.writeByteNTimes(' ', self.indent - 2); | |
| 2083 | try stream.writeAll("}, {\n"); | |
| 2124 | try stream.writeByteNTimes(' ', self.indent); | |
| 2125 | try stream.print("{}: ", .{std.zig.fmtId(field_name)}); | |
| 2126 | try self.writeInstRef(stream, field_type); | |
| 2084 | 2127 | |
| 2085 | const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable; | |
| 2086 | const body_end = extra.end + body.len; | |
| 2087 | var extra_index: usize = body_end + bit_bags_count; | |
| 2088 | var bit_bag_index: usize = body_end; | |
| 2128 | if (has_align) { | |
| 2129 | const align_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2130 | extra_index += 1; | |
| 2131 | ||
| 2132 | try stream.writeAll(" align("); | |
| 2133 | try self.writeInstRef(stream, align_ref); | |
| 2134 | try stream.writeAll(")"); | |
| 2135 | } | |
| 2136 | if (has_default) { | |
| 2137 | const default_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2138 | extra_index += 1; | |
| 2139 | ||
| 2140 | try stream.writeAll(" = "); | |
| 2141 | try self.writeInstRef(stream, default_ref); | |
| 2142 | } | |
| 2143 | try stream.writeAll(",\n"); | |
| 2144 | } | |
| 2145 | ||
| 2146 | self.indent -= 2; | |
| 2147 | try stream.writeByteNTimes(' ', self.indent); | |
| 2148 | try stream.writeAll("}, {"); | |
| 2149 | } | |
| 2150 | if (decls_len == 0) { | |
| 2151 | try stream.writeAll("}) "); | |
| 2152 | } else { | |
| 2153 | try stream.writeAll("\n"); | |
| 2154 | self.indent += 2; | |
| 2155 | try self.writeDecls(stream, decls_len, extra_index); | |
| 2156 | self.indent -= 2; | |
| 2157 | try stream.writeByteNTimes(' ', self.indent); | |
| 2158 | try stream.writeAll("}) "); | |
| 2159 | } | |
| 2160 | self.parent_decl_node = prev_parent_decl_node; | |
| 2161 | try self.writeSrc(stream, inst_data.src()); | |
| 2162 | } | |
| 2163 | ||
| 2164 | fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !void { | |
| 2165 | const bit_bags_count = std.math.divCeil(usize, decls_len, 16) catch unreachable; | |
| 2166 | var extra_index = extra_start + bit_bags_count; | |
| 2167 | var bit_bag_index: usize = extra_start; | |
| 2089 | 2168 | var cur_bit_bag: u32 = undefined; |
| 2090 | var field_i: u32 = 0; | |
| 2091 | while (field_i < fields_len) : (field_i += 1) { | |
| 2092 | if (field_i % 16 == 0) { | |
| 2169 | var decl_i: u32 = 0; | |
| 2170 | while (decl_i < decls_len) : (decl_i += 1) { | |
| 2171 | if (decl_i % 16 == 0) { | |
| 2093 | 2172 | cur_bit_bag = self.code.extra[bit_bag_index]; |
| 2094 | 2173 | bit_bag_index += 1; |
| 2095 | 2174 | } |
| 2096 | const has_align = @truncate(u1, cur_bit_bag) != 0; | |
| 2175 | const is_pub = @truncate(u1, cur_bit_bag) != 0; | |
| 2097 | 2176 | cur_bit_bag >>= 1; |
| 2098 | const has_default = @truncate(u1, cur_bit_bag) != 0; | |
| 2177 | const is_exported = @truncate(u1, cur_bit_bag) != 0; | |
| 2099 | 2178 | cur_bit_bag >>= 1; |
| 2100 | 2179 | |
| 2101 | const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]); | |
| 2180 | const decl_name = self.code.nullTerminatedString(self.code.extra[extra_index]); | |
| 2102 | 2181 | extra_index += 1; |
| 2103 | const field_type = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2182 | const decl_value = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2104 | 2183 | extra_index += 1; |
| 2105 | 2184 | |
| 2185 | const pub_str = if (is_pub) "pub " else ""; | |
| 2186 | const export_str = if (is_exported) "export " else ""; | |
| 2106 | 2187 | try stream.writeByteNTimes(' ', self.indent); |
| 2107 | try stream.print("{}: ", .{std.zig.fmtId(field_name)}); | |
| 2108 | try self.writeInstRef(stream, field_type); | |
| 2109 | ||
| 2110 | if (has_align) { | |
| 2111 | const align_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2112 | extra_index += 1; | |
| 2113 | ||
| 2114 | try stream.writeAll(" align("); | |
| 2115 | try self.writeInstRef(stream, align_ref); | |
| 2116 | try stream.writeAll(")"); | |
| 2117 | } | |
| 2118 | if (has_default) { | |
| 2119 | const default_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]); | |
| 2120 | extra_index += 1; | |
| 2121 | ||
| 2122 | try stream.writeAll(" = "); | |
| 2123 | try self.writeInstRef(stream, default_ref); | |
| 2124 | } | |
| 2125 | try stream.writeAll(",\n"); | |
| 2188 | try stream.print("{s}{s}{} = ", .{ pub_str, export_str, std.zig.fmtId(decl_name) }); | |
| 2189 | try self.writeInstRef(stream, decl_value); | |
| 2190 | try stream.writeAll("\n"); | |
| 2126 | 2191 | } |
| 2127 | ||
| 2128 | self.indent -= 2; | |
| 2129 | try stream.writeByteNTimes(' ', self.indent); | |
| 2130 | try stream.writeAll("}) "); | |
| 2131 | try self.writeSrc(stream, inst_data.src()); | |
| 2132 | 2192 | } |
| 2133 | 2193 | |
| 2134 | 2194 | fn writeEnumDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| ... | ... | @@ -2374,14 +2434,6 @@ const Writer = struct { |
| 2374 | 2434 | try self.writeSrc(stream, inst_data.src()); |
| 2375 | 2435 | } |
| 2376 | 2436 | |
| 2377 | fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void { | |
| 2378 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 2379 | const owner_decl = self.scope.ownerDecl().?; | |
| 2380 | const decl = owner_decl.dependencies.entries.items[inst_data.payload_index].key; | |
| 2381 | try stream.print("{s}) ", .{decl.name}); | |
| 2382 | try self.writeSrc(stream, inst_data.src()); | |
| 2383 | } | |
| 2384 | ||
| 2385 | 2437 | fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 2386 | 2438 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 2387 | 2439 | const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data; |
| ... | ... | @@ -2593,8 +2645,12 @@ const Writer = struct { |
| 2593 | 2645 | } |
| 2594 | 2646 | |
| 2595 | 2647 | fn writeSrc(self: *Writer, stream: anytype, src: LazySrcLoc) !void { |
| 2596 | const tree = self.scope.tree(); | |
| 2597 | const src_loc = src.toSrcLoc(self.scope); | |
| 2648 | const tree = self.file.tree; | |
| 2649 | const src_loc: Module.SrcLoc = .{ | |
| 2650 | .file_scope = self.file, | |
| 2651 | .parent_decl_node = self.parent_decl_node, | |
| 2652 | .lazy = src, | |
| 2653 | }; | |
| 2598 | 2654 | const abs_byte_off = try src_loc.byteOffset(); |
| 2599 | 2655 | const delta_line = std.zig.findLineColumn(tree.source, abs_byte_off); |
| 2600 | 2656 | try stream.print("{s}:{d}:{d}", .{ |
src/main.zig+93-6| ... | ... | @@ -25,7 +25,11 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn { |
| 25 | 25 | process.exit(1); |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB | |
| 28 | /// There are many assumptions in the entire codebase that Zig source files can | |
| 29 | /// be byte-indexed with a u32 integer. | |
| 30 | pub const max_src_size = std.math.maxInt(u32); | |
| 31 | ||
| 32 | pub const debug_extensions_enabled = std.builtin.mode == .Debug; | |
| 29 | 33 | |
| 30 | 34 | pub const Color = enum { |
| 31 | 35 | auto, |
| ... | ... | @@ -33,7 +37,7 @@ pub const Color = enum { |
| 33 | 37 | on, |
| 34 | 38 | }; |
| 35 | 39 | |
| 36 | const usage = | |
| 40 | const normal_usage = | |
| 37 | 41 | \\Usage: zig [command] [options] |
| 38 | 42 | \\ |
| 39 | 43 | \\Commands: |
| ... | ... | @@ -63,6 +67,16 @@ const usage = |
| 63 | 67 | \\ |
| 64 | 68 | ; |
| 65 | 69 | |
| 70 | const debug_usage = normal_usage ++ | |
| 71 | \\ | |
| 72 | \\Debug Commands: | |
| 73 | \\ | |
| 74 | \\ astgen Print ZIR code for a .zig source file | |
| 75 | \\ | |
| 76 | ; | |
| 77 | ||
| 78 | const usage = if (debug_extensions_enabled) debug_usage else normal_usage; | |
| 79 | ||
| 66 | 80 | pub const log_level: std.log.Level = switch (std.builtin.mode) { |
| 67 | 81 | .Debug => .debug, |
| 68 | 82 | .ReleaseSafe, .ReleaseFast => .info, |
| ... | ... | @@ -206,13 +220,15 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 206 | 220 | const stdout = io.getStdOut().writer(); |
| 207 | 221 | return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, info.target); |
| 208 | 222 | } else if (mem.eql(u8, cmd, "version")) { |
| 209 | try std.io.getStdOut().writeAll(build_options.version ++ "\n"); | |
| 223 | return std.io.getStdOut().writeAll(build_options.version ++ "\n"); | |
| 210 | 224 | } else if (mem.eql(u8, cmd, "env")) { |
| 211 | try @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer()); | |
| 225 | return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer()); | |
| 212 | 226 | } else if (mem.eql(u8, cmd, "zen")) { |
| 213 | try io.getStdOut().writeAll(info_zen); | |
| 227 | return io.getStdOut().writeAll(info_zen); | |
| 214 | 228 | } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) { |
| 215 | try io.getStdOut().writeAll(usage); | |
| 229 | return io.getStdOut().writeAll(usage); | |
| 230 | } else if (debug_extensions_enabled and mem.eql(u8, cmd, "astgen")) { | |
| 231 | return cmdAstgen(gpa, arena, cmd_args); | |
| 216 | 232 | } else { |
| 217 | 233 | std.log.info("{s}", .{usage}); |
| 218 | 234 | fatal("unknown command: {s}", .{args[1]}); |
| ... | ... | @@ -3485,3 +3501,74 @@ pub fn cleanExit() void { |
| 3485 | 3501 | process.exit(0); |
| 3486 | 3502 | } |
| 3487 | 3503 | } |
| 3504 | ||
| 3505 | /// This is only enabled for debug builds. | |
| 3506 | pub fn cmdAstgen( | |
| 3507 | gpa: *Allocator, | |
| 3508 | arena: *Allocator, | |
| 3509 | args: []const []const u8, | |
| 3510 | ) !void { | |
| 3511 | const Module = @import("Module.zig"); | |
| 3512 | const AstGen = @import("AstGen.zig"); | |
| 3513 | const Zir = @import("Zir.zig"); | |
| 3514 | ||
| 3515 | const zig_source_file = args[0]; | |
| 3516 | ||
| 3517 | var f = try fs.cwd().openFile(zig_source_file, .{}); | |
| 3518 | defer f.close(); | |
| 3519 | ||
| 3520 | const stat = try f.stat(); | |
| 3521 | ||
| 3522 | if (stat.size > max_src_size) | |
| 3523 | return error.FileTooBig; | |
| 3524 | ||
| 3525 | var file: Module.Scope.File = .{ | |
| 3526 | .status = .never_loaded, | |
| 3527 | .source_loaded = false, | |
| 3528 | .tree_loaded = false, | |
| 3529 | .zir_loaded = false, | |
| 3530 | .sub_file_path = zig_source_file, | |
| 3531 | .source = undefined, | |
| 3532 | .stat_size = stat.size, | |
| 3533 | .stat_inode = stat.inode, | |
| 3534 | .stat_mtime = stat.mtime, | |
| 3535 | .tree = undefined, | |
| 3536 | .zir = undefined, | |
| 3537 | .pkg = undefined, | |
| 3538 | .namespace = undefined, | |
| 3539 | }; | |
| 3540 | ||
| 3541 | const source = try arena.allocSentinel(u8, stat.size, 0); | |
| 3542 | const amt = try f.readAll(source); | |
| 3543 | if (amt != stat.size) | |
| 3544 | return error.UnexpectedEndOfFile; | |
| 3545 | file.source = source; | |
| 3546 | file.source_loaded = true; | |
| 3547 | ||
| 3548 | file.tree = try std.zig.parse(gpa, file.source); | |
| 3549 | file.tree_loaded = true; | |
| 3550 | defer file.tree.deinit(gpa); | |
| 3551 | ||
| 3552 | for (file.tree.errors) |parse_error| { | |
| 3553 | try printErrMsgToFile(gpa, parse_error, file.tree, zig_source_file, io.getStdErr(), .auto); | |
| 3554 | } | |
| 3555 | if (file.tree.errors.len != 0) { | |
| 3556 | process.exit(1); | |
| 3557 | } | |
| 3558 | ||
| 3559 | file.zir = try AstGen.generate(gpa, &file); | |
| 3560 | file.zir_loaded = true; | |
| 3561 | defer file.zir.deinit(gpa); | |
| 3562 | ||
| 3563 | if (file.zir.hasCompileErrors()) { | |
| 3564 | var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); | |
| 3565 | try Compilation.AllErrors.addZir(arena, &errors, &file, source); | |
| 3566 | const ttyconf = std.debug.detectTTYConfig(); | |
| 3567 | for (errors.items) |full_err_msg| { | |
| 3568 | full_err_msg.renderToStdErr(ttyconf); | |
| 3569 | } | |
| 3570 | process.exit(1); | |
| 3571 | } | |
| 3572 | ||
| 3573 | return Zir.renderAsTextToFile(gpa, &file, io.getStdOut()); | |
| 3574 | } |