| ... | @@ -60,10 +60,10 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -60,10 +60,10 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 60 | try self.types.append(self.arena, .{ | 60 | try self.types.append(self.arena, .{ |
| 61 | .name = tmpbuf.toOwnedSlice(), | 61 | .name = tmpbuf.toOwnedSlice(), |
| 62 | .kind = switch (@intToEnum(Ref, i)) { | 62 | .kind = switch (@intToEnum(Ref, i)) { |
| 63 | else => |t| blk: { | 63 | else => blk: { |
| 64 | std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{ | 64 | //std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{ |
| 65 | @tagName(t), | 65 | // @tagName(t), |
| 66 | }); | 66 | //}); |
| 67 | break :blk 7; | 67 | break :blk 7; |
| 68 | }, | 68 | }, |
| 69 | .u1_type, | 69 | .u1_type, |
| ... | @@ -302,7 +302,7 @@ const DocData = struct { | ... | @@ -302,7 +302,7 @@ const DocData = struct { |
| 302 | .int => |v| { | 302 | .int => |v| { |
| 303 | const neg = if (v.negated) "-" else ""; | 303 | const neg = if (v.negated) "-" else ""; |
| 304 | try w.print( | 304 | try w.print( |
| 305 | \\{{ "int": {{ "typeRef": | 305 | \\{{ "int": {{ "typeRef": |
| 306 | , .{}); | 306 | , .{}); |
| 307 | try v.typeRef.jsonStringify(options, w); | 307 | try v.typeRef.jsonStringify(options, w); |
| 308 | try w.print( | 308 | try w.print( |
| ... | @@ -312,7 +312,7 @@ const DocData = struct { | ... | @@ -312,7 +312,7 @@ const DocData = struct { |
| 312 | .float => |v| { | 312 | .float => |v| { |
| 313 | const neg = if (v.negated) "-" else ""; | 313 | const neg = if (v.negated) "-" else ""; |
| 314 | try w.print( | 314 | try w.print( |
| 315 | \\{{ "float": {{ "typeRef": | 315 | \\{{ "float": {{ "typeRef": |
| 316 | , .{}); | 316 | , .{}); |
| 317 | try v.typeRef.jsonStringify(options, w); | 317 | try v.typeRef.jsonStringify(options, w); |
| 318 | try w.print( | 318 | try w.print( |
| ... | @@ -429,13 +429,6 @@ fn walkInstruction( | ... | @@ -429,13 +429,6 @@ fn walkInstruction( |
| 429 | const pl_node = data[inst_index].pl_node; | 429 | const pl_node = data[inst_index].pl_node; |
| 430 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); | 430 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 431 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; | 431 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; |
| 432 | | | |
| 433 | std.debug.print("[instr: {}] body len: {} last instr idx: {}\n", .{ | | |
| 434 | inst_index, | | |
| 435 | extra.data.body_len, | | |
| 436 | break_index, | | |
| 437 | }); | | |
| 438 | | | |
| 439 | const break_operand = data[break_index].@"break".operand; | 432 | const break_operand = data[break_index].@"break".operand; |
| 440 | return self.walkRef(zir, parent_scope, break_operand); | 433 | return self.walkRef(zir, parent_scope, break_operand); |
| 441 | }, | 434 | }, |
| ... | @@ -444,10 +437,227 @@ fn walkInstruction( | ... | @@ -444,10 +437,227 @@ fn walkInstruction( |
| 444 | switch (extended.opcode) { | 437 | switch (extended.opcode) { |
| 445 | else => { | 438 | else => { |
| 446 | std.debug.panic( | 439 | std.debug.panic( |
| 447 | "TODO: implement `walkInstruction` (inside .extended case) for {s}\n\n", | 440 | "TODO: implement `walkInstruction.extended` for {s}\n\n", |
| 448 | .{@tagName(extended.opcode)}, | 441 | .{@tagName(extended.opcode)}, |
| 449 | ); | 442 | ); |
| 450 | }, | 443 | }, |
| | 444 | .union_decl => { |
| | 445 | var scope: Scope = .{ .parent = parent_scope }; |
| | 446 | |
| | 447 | const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small); |
| | 448 | var extra_index: usize = extended.operand; |
| | 449 | |
| | 450 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| | 451 | const src_node = @bitCast(i32, zir.extra[extra_index]); |
| | 452 | extra_index += 1; |
| | 453 | break :blk src_node; |
| | 454 | } else null; |
| | 455 | _ = src_node; |
| | 456 | |
| | 457 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| | 458 | const tag_type = zir.extra[extra_index]; |
| | 459 | extra_index += 1; |
| | 460 | break :blk @intToEnum(Ref, tag_type); |
| | 461 | } else null; |
| | 462 | _ = tag_type; |
| | 463 | |
| | 464 | const body_len = if (small.has_body_len) blk: { |
| | 465 | const body_len = zir.extra[extra_index]; |
| | 466 | extra_index += 1; |
| | 467 | break :blk body_len; |
| | 468 | } else 0; |
| | 469 | |
| | 470 | const fields_len = if (small.has_fields_len) blk: { |
| | 471 | const fields_len = zir.extra[extra_index]; |
| | 472 | extra_index += 1; |
| | 473 | break :blk fields_len; |
| | 474 | } else 0; |
| | 475 | _ = fields_len; |
| | 476 | |
| | 477 | const decls_len = if (small.has_decls_len) blk: { |
| | 478 | const decls_len = zir.extra[extra_index]; |
| | 479 | extra_index += 1; |
| | 480 | break :blk decls_len; |
| | 481 | } else 0; |
| | 482 | |
| | 483 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 484 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 485 | |
| | 486 | const decls_first_index = self.decls.items.len; |
| | 487 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| | 488 | // Done to make sure that all decl refs can be resolved correctly, |
| | 489 | // even if we haven't fully analyzed the decl yet. |
| | 490 | { |
| | 491 | var it = zir.declIterator(@intCast(u32, inst_index)); |
| | 492 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| | 493 | var decls_slot_index = decls_first_index; |
| | 494 | while (it.next()) |d| : (decls_slot_index += 1) { |
| | 495 | const decl_name_index = zir.extra[d.sub_index + 5]; |
| | 496 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| | 497 | } |
| | 498 | } |
| | 499 | |
| | 500 | extra_index = try self.walkDecls( |
| | 501 | zir, |
| | 502 | &scope, |
| | 503 | decls_first_index, |
| | 504 | decls_len, |
| | 505 | &decl_indexes, |
| | 506 | &priv_decl_indexes, |
| | 507 | extra_index, |
| | 508 | ); |
| | 509 | |
| | 510 | // const body = zir.extra[extra_index..][0..body_len]; |
| | 511 | extra_index += body_len; |
| | 512 | |
| | 513 | var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| | 514 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 515 | try self.collectUnionFieldInfo( |
| | 516 | zir, |
| | 517 | &scope, |
| | 518 | fields_len, |
| | 519 | &field_type_indexes, |
| | 520 | &field_name_indexes, |
| | 521 | extra_index, |
| | 522 | ); |
| | 523 | |
| | 524 | self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items; |
| | 525 | |
| | 526 | try self.types.append(self.arena, .{ |
| | 527 | .kind = @enumToInt(std.builtin.TypeId.Union), |
| | 528 | .name = "todo_name", |
| | 529 | .src = self_ast_node_index, |
| | 530 | .privDecls = priv_decl_indexes.items, |
| | 531 | .pubDecls = decl_indexes.items, |
| | 532 | .fields = field_type_indexes.items, |
| | 533 | }); |
| | 534 | |
| | 535 | return DocData.WalkResult{ .type = self.types.items.len - 1 }; |
| | 536 | }, |
| | 537 | .enum_decl => { |
| | 538 | var scope: Scope = .{ .parent = parent_scope }; |
| | 539 | |
| | 540 | const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small); |
| | 541 | var extra_index: usize = extended.operand; |
| | 542 | |
| | 543 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| | 544 | const src_node = @bitCast(i32, zir.extra[extra_index]); |
| | 545 | extra_index += 1; |
| | 546 | break :blk src_node; |
| | 547 | } else null; |
| | 548 | _ = src_node; |
| | 549 | |
| | 550 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| | 551 | const tag_type = zir.extra[extra_index]; |
| | 552 | extra_index += 1; |
| | 553 | break :blk @intToEnum(Ref, tag_type); |
| | 554 | } else null; |
| | 555 | _ = tag_type; |
| | 556 | |
| | 557 | const body_len = if (small.has_body_len) blk: { |
| | 558 | const body_len = zir.extra[extra_index]; |
| | 559 | extra_index += 1; |
| | 560 | break :blk body_len; |
| | 561 | } else 0; |
| | 562 | |
| | 563 | const fields_len = if (small.has_fields_len) blk: { |
| | 564 | const fields_len = zir.extra[extra_index]; |
| | 565 | extra_index += 1; |
| | 566 | break :blk fields_len; |
| | 567 | } else 0; |
| | 568 | _ = fields_len; |
| | 569 | |
| | 570 | const decls_len = if (small.has_decls_len) blk: { |
| | 571 | const decls_len = zir.extra[extra_index]; |
| | 572 | extra_index += 1; |
| | 573 | break :blk decls_len; |
| | 574 | } else 0; |
| | 575 | |
| | 576 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 577 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 578 | |
| | 579 | const decls_first_index = self.decls.items.len; |
| | 580 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| | 581 | // Done to make sure that all decl refs can be resolved correctly, |
| | 582 | // even if we haven't fully analyzed the decl yet. |
| | 583 | { |
| | 584 | var it = zir.declIterator(@intCast(u32, inst_index)); |
| | 585 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| | 586 | var decls_slot_index = decls_first_index; |
| | 587 | while (it.next()) |d| : (decls_slot_index += 1) { |
| | 588 | const decl_name_index = zir.extra[d.sub_index + 5]; |
| | 589 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| | 590 | } |
| | 591 | } |
| | 592 | |
| | 593 | extra_index = try self.walkDecls( |
| | 594 | zir, |
| | 595 | &scope, |
| | 596 | decls_first_index, |
| | 597 | decls_len, |
| | 598 | &decl_indexes, |
| | 599 | &priv_decl_indexes, |
| | 600 | extra_index, |
| | 601 | ); |
| | 602 | |
| | 603 | // const body = zir.extra[extra_index..][0..body_len]; |
| | 604 | extra_index += body_len; |
| | 605 | |
| | 606 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| | 607 | { |
| | 608 | var bit_bag_idx = extra_index; |
| | 609 | var cur_bit_bag: u32 = undefined; |
| | 610 | extra_index += std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| | 611 | |
| | 612 | var idx: usize = 0; |
| | 613 | while (idx < fields_len) : (idx += 1) { |
| | 614 | if (idx % 32 == 0) { |
| | 615 | cur_bit_bag = zir.extra[bit_bag_idx]; |
| | 616 | bit_bag_idx += 1; |
| | 617 | } |
| | 618 | |
| | 619 | const has_value = @truncate(u1, cur_bit_bag) != 0; |
| | 620 | cur_bit_bag >>= 1; |
| | 621 | |
| | 622 | const field_name_index = zir.extra[extra_index]; |
| | 623 | extra_index += 1; |
| | 624 | |
| | 625 | const doc_comment_index = zir.extra[extra_index]; |
| | 626 | extra_index += 1; |
| | 627 | |
| | 628 | const value_ref: ?Ref = if (has_value) blk: { |
| | 629 | const value_ref = zir.extra[extra_index]; |
| | 630 | extra_index += 1; |
| | 631 | break :blk @intToEnum(Ref, value_ref); |
| | 632 | } else null; |
| | 633 | _ = value_ref; |
| | 634 | |
| | 635 | const field_name = zir.nullTerminatedString(field_name_index); |
| | 636 | |
| | 637 | try field_name_indexes.append(self.arena, self.ast_nodes.items.len); |
| | 638 | const doc_comment: ?[]const u8 = if (doc_comment_index != 0) |
| | 639 | zir.nullTerminatedString(doc_comment_index) |
| | 640 | else |
| | 641 | null; |
| | 642 | try self.ast_nodes.append(self.arena, .{ |
| | 643 | .name = field_name, |
| | 644 | .docs = doc_comment, |
| | 645 | }); |
| | 646 | } |
| | 647 | } |
| | 648 | |
| | 649 | self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items; |
| | 650 | |
| | 651 | try self.types.append(self.arena, .{ |
| | 652 | .kind = @enumToInt(std.builtin.TypeId.Enum), |
| | 653 | .name = "todo_name", |
| | 654 | .src = self_ast_node_index, |
| | 655 | .privDecls = priv_decl_indexes.items, |
| | 656 | .pubDecls = decl_indexes.items, |
| | 657 | }); |
| | 658 | |
| | 659 | return DocData.WalkResult{ .type = self.types.items.len - 1 }; |
| | 660 | }, |
| 451 | .struct_decl => { | 661 | .struct_decl => { |
| 452 | var scope: Scope = .{ .parent = parent_scope }; | 662 | var scope: Scope = .{ .parent = parent_scope }; |
| 453 | | 663 | |
| ... | @@ -512,7 +722,7 @@ fn walkInstruction( | ... | @@ -512,7 +722,7 @@ fn walkInstruction( |
| 512 | | 722 | |
| 513 | var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; | 723 | var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| 514 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; | 724 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 515 | try self.collectFieldInfo( | 725 | try self.collectStructFieldInfo( |
| 516 | zir, | 726 | zir, |
| 517 | &scope, | 727 | &scope, |
| 518 | fields_len, | 728 | fields_len, |
| ... | @@ -539,12 +749,12 @@ fn walkInstruction( | ... | @@ -539,12 +749,12 @@ fn walkInstruction( |
| 539 | } | 749 | } |
| 540 | } | 750 | } |
| 541 | | 751 | |
| 542 | /// Called by `walkInstruction` when encountering a container type, | 752 | /// Called by `walkInstruction` when encountering a container type, |
| 543 | /// iterates over all decl definitions in its body. | 753 | /// iterates over all decl definitions in its body. |
| 544 | /// It also analyzes each decl's body recursively. | 754 | /// It also analyzes each decl's body recursively. |
| 545 | /// | 755 | /// |
| 546 | /// Does not append to `self.decls` directly because `walkInstruction` | 756 | /// Does not append to `self.decls` directly because `walkInstruction` |
| 547 | /// is expected to (look-ahead) scan all decls and reserve `body_len` | 757 | /// is expected to (look-ahead) scan all decls and reserve `body_len` |
| 548 | /// slots in `self.decls`, which are then filled out by `walkDecls`. | 758 | /// slots in `self.decls`, which are then filled out by `walkDecls`. |
| 549 | fn walkDecls( | 759 | fn walkDecls( |
| 550 | self: *Autodoc, | 760 | self: *Autodoc, |
| ... | @@ -678,7 +888,7 @@ fn walkDecls( | ... | @@ -678,7 +888,7 @@ fn walkDecls( |
| 678 | return extra_index; | 888 | return extra_index; |
| 679 | } | 889 | } |
| 680 | | 890 | |
| 681 | fn collectFieldInfo( | 891 | fn collectUnionFieldInfo( |
| 682 | self: *Autodoc, | 892 | self: *Autodoc, |
| 683 | zir: Zir, | 893 | zir: Zir, |
| 684 | scope: *Scope, | 894 | scope: *Scope, |
| ... | @@ -703,9 +913,78 @@ fn collectFieldInfo( | ... | @@ -703,9 +913,78 @@ fn collectFieldInfo( |
| 703 | cur_bit_bag = zir.extra[bit_bag_index]; | 913 | cur_bit_bag = zir.extra[bit_bag_index]; |
| 704 | bit_bag_index += 1; | 914 | bit_bag_index += 1; |
| 705 | } | 915 | } |
| 706 | // const has_align = @truncate(u1, cur_bit_bag) != 0; | 916 | const has_type = @truncate(u1, cur_bit_bag) != 0; |
| | 917 | cur_bit_bag >>= 1; |
| | 918 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| | 919 | cur_bit_bag >>= 1; |
| | 920 | const has_tag = @truncate(u1, cur_bit_bag) != 0; |
| | 921 | cur_bit_bag >>= 1; |
| | 922 | const unused = @truncate(u1, cur_bit_bag) != 0; |
| 707 | cur_bit_bag >>= 1; | 923 | cur_bit_bag >>= 1; |
| 708 | // const has_default = @truncate(u1, cur_bit_bag) != 0; | 924 | _ = unused; |
| | 925 | |
| | 926 | const field_name = zir.nullTerminatedString(zir.extra[extra_index]); |
| | 927 | extra_index += 1; |
| | 928 | const doc_comment_index = zir.extra[extra_index]; |
| | 929 | extra_index += 1; |
| | 930 | const field_type = if (has_type) |
| | 931 | @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]) |
| | 932 | else |
| | 933 | .void_type; |
| | 934 | extra_index += 1; |
| | 935 | |
| | 936 | if (has_align) extra_index += 1; |
| | 937 | if (has_tag) extra_index += 1; |
| | 938 | |
| | 939 | // type |
| | 940 | { |
| | 941 | const walk_result = try self.walkRef(zir, scope, field_type); |
| | 942 | try field_type_indexes.append(self.arena, walk_result); |
| | 943 | } |
| | 944 | |
| | 945 | // ast node |
| | 946 | { |
| | 947 | try field_name_indexes.append(self.arena, self.ast_nodes.items.len); |
| | 948 | const doc_comment: ?[]const u8 = if (doc_comment_index != 0) |
| | 949 | zir.nullTerminatedString(doc_comment_index) |
| | 950 | else |
| | 951 | null; |
| | 952 | try self.ast_nodes.append(self.arena, .{ |
| | 953 | .name = field_name, |
| | 954 | .docs = doc_comment, |
| | 955 | }); |
| | 956 | } |
| | 957 | } |
| | 958 | } |
| | 959 | |
| | 960 | fn collectStructFieldInfo( |
| | 961 | self: *Autodoc, |
| | 962 | zir: Zir, |
| | 963 | scope: *Scope, |
| | 964 | fields_len: usize, |
| | 965 | field_type_indexes: *std.ArrayListUnmanaged(DocData.WalkResult), |
| | 966 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| | 967 | ei: usize, |
| | 968 | ) !void { |
| | 969 | if (fields_len == 0) return; |
| | 970 | var extra_index = ei; |
| | 971 | |
| | 972 | const bits_per_field = 4; |
| | 973 | const fields_per_u32 = 32 / bits_per_field; |
| | 974 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; |
| | 975 | var bit_bag_index: usize = extra_index; |
| | 976 | extra_index += bit_bags_count; |
| | 977 | |
| | 978 | var cur_bit_bag: u32 = undefined; |
| | 979 | var field_i: u32 = 0; |
| | 980 | while (field_i < fields_len) : (field_i += 1) { |
| | 981 | if (field_i % fields_per_u32 == 0) { |
| | 982 | cur_bit_bag = zir.extra[bit_bag_index]; |
| | 983 | bit_bag_index += 1; |
| | 984 | } |
| | 985 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| | 986 | cur_bit_bag >>= 1; |
| | 987 | const has_default = @truncate(u1, cur_bit_bag) != 0; |
| 709 | cur_bit_bag >>= 1; | 988 | cur_bit_bag >>= 1; |
| 710 | // const is_comptime = @truncate(u1, cur_bit_bag) != 0; | 989 | // const is_comptime = @truncate(u1, cur_bit_bag) != 0; |
| 711 | cur_bit_bag >>= 1; | 990 | cur_bit_bag >>= 1; |
| ... | @@ -720,6 +999,9 @@ fn collectFieldInfo( | ... | @@ -720,6 +999,9 @@ fn collectFieldInfo( |
| 720 | const doc_comment_index = zir.extra[extra_index]; | 999 | const doc_comment_index = zir.extra[extra_index]; |
| 721 | extra_index += 1; | 1000 | extra_index += 1; |
| 722 | | 1001 | |
| | 1002 | if (has_align) extra_index += 1; |
| | 1003 | if (has_default) extra_index += 1; |
| | 1004 | |
| 723 | // type | 1005 | // type |
| 724 | { | 1006 | { |
| 725 | const walk_result = try self.walkRef(zir, scope, field_type); | 1007 | const walk_result = try self.walkRef(zir, scope, field_type); |