authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2023-10-31 13:12:15+03:30
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-08 16:33:33-08:00
log0e856da224d05816385550e292d97bc50985c2ff
tree5b9254e5b6626a4f4f4f44bec6528935bccdb823
parentdeed19496a98a22ed39025721d448ce2f47642ea

add type safety to ZIR for null terminated strings


6 files changed, 248 insertions(+), 240 deletions(-)

src/AstGen.zig+94-92
......@@ -46,7 +46,7 @@ fn_block: ?*GenZir = null,
4646fn_var_args: bool = false,
4747/// Maps string table indexes to the first `@import` ZIR instruction
4848/// that uses this string as the operand.
49imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},
49imports: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .{},
5050/// Used for temporary storage when building payloads.
5151scratch: std.ArrayListUnmanaged(u32) = .{},
5252/// Whenever a `ref` instruction is needed, it is created and saved in this
......@@ -86,6 +86,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
8686
8787 Zir.Inst.Ref,
8888 Zir.Inst.Index,
89 Zir.NullTerminatedString,
8990 => @intFromEnum(@field(extra, field.name)),
9091
9192 i32,
......@@ -1301,12 +1302,12 @@ fn fnProtoExpr(
13011302 }
13021303 } else false;
13031304
1304 const param_name: u32 = if (param.name_token) |name_token| blk: {
1305 const param_name = if (param.name_token) |name_token| blk: {
13051306 if (mem.eql(u8, "_", tree.tokenSlice(name_token)))
1306 break :blk 0;
1307 break :blk .empty;
13071308
13081309 break :blk try astgen.identAsString(name_token);
1309 } else 0;
1310 } else .empty;
13101311
13111312 if (is_anytype) {
13121313 const name_token = param.name_token orelse param.anytype_ellipsis3.?;
......@@ -1379,7 +1380,7 @@ fn fnProtoExpr(
13791380
13801381 .param_block = block_inst,
13811382 .body_gz = null,
1382 .lib_name = 0,
1383 .lib_name = .empty,
13831384 .is_var_args = is_var_args,
13841385 .is_inferred_error = false,
13851386 .is_test = false,
......@@ -1725,7 +1726,7 @@ fn structInitExpr(
17251726 var sfba = std.heap.stackFallback(256, astgen.arena);
17261727 const sfba_allocator = sfba.get();
17271728
1728 var duplicate_names = std.AutoArrayHashMap(u32, ArrayListUnmanaged(Ast.TokenIndex)).init(sfba_allocator);
1729 var duplicate_names = std.AutoArrayHashMap(Zir.NullTerminatedString, ArrayListUnmanaged(Ast.TokenIndex)).init(sfba_allocator);
17291730 defer duplicate_names.deinit();
17301731 try duplicate_names.ensureTotalCapacity(@intCast(struct_init.ast.fields.len));
17311732
......@@ -4068,10 +4069,10 @@ fn fnDecl(
40684069 }
40694070 } else false;
40704071
4071 const param_name: u32 = if (param.name_token) |name_token| blk: {
4072 const param_name: Zir.NullTerminatedString = if (param.name_token) |name_token| blk: {
40724073 const name_bytes = tree.tokenSlice(name_token);
40734074 if (mem.eql(u8, "_", name_bytes))
4074 break :blk 0;
4075 break :blk .empty;
40754076
40764077 const param_name = try astgen.identAsString(name_token);
40774078 if (!is_extern) {
......@@ -4107,7 +4108,7 @@ fn fnDecl(
41074108 }
41084109 return astgen.failNode(param.type_expr, "missing parameter name", .{});
41094110 }
4110 } else 0;
4111 } else .empty;
41114112
41124113 const param_inst = if (is_anytype) param: {
41134114 const name_token = param.name_token orelse param.anytype_ellipsis3.?;
......@@ -4133,7 +4134,7 @@ fn fnDecl(
41334134 break :param param_inst.toRef();
41344135 };
41354136
4136 if (param_name == 0 or is_extern) continue;
4137 if (param_name == .empty or is_extern) continue;
41374138
41384139 const sub_scope = try astgen.arena.create(Scope.LocalVal);
41394140 sub_scope.* = .{
......@@ -4149,16 +4150,16 @@ fn fnDecl(
41494150 break :is_var_args false;
41504151 };
41514152
4152 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
4153 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
41534154 const lib_name_str = try astgen.strLitAsString(lib_name_token);
4154 const lib_name_slice = astgen.string_bytes.items[lib_name_str.index..][0..lib_name_str.len];
4155 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
41554156 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
41564157 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
41574158 } else if (lib_name_str.len == 0) {
41584159 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
41594160 }
41604161 break :blk lib_name_str.index;
4161 } else 0;
4162 } else .empty;
41624163
41634164 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
41644165 const is_inferred_error = token_tags[maybe_bang] == .bang;
......@@ -4343,9 +4344,9 @@ fn fnDecl(
43434344 const line_delta = decl_gz.decl_line - gz.decl_line;
43444345 wip_members.appendToDecl(line_delta);
43454346 }
4346 wip_members.appendToDecl(fn_name_str_index);
4347 wip_members.appendToDecl(@intFromEnum(fn_name_str_index));
43474348 wip_members.appendToDecl(@intFromEnum(block_inst));
4348 wip_members.appendToDecl(doc_comment_index);
4349 wip_members.appendToDecl(@intFromEnum(doc_comment_index));
43494350}
43504351
43514352fn globalVarDecl(
......@@ -4408,16 +4409,16 @@ fn globalVarDecl(
44084409 break :blk true;
44094410 } else false;
44104411
4411 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {
4412 const lib_name = if (var_decl.lib_name) |lib_name_token| blk: {
44124413 const lib_name_str = try astgen.strLitAsString(lib_name_token);
4413 const lib_name_slice = astgen.string_bytes.items[lib_name_str.index..][0..lib_name_str.len];
4414 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
44144415 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
44154416 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
44164417 } else if (lib_name_str.len == 0) {
44174418 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
44184419 }
44194420 break :blk lib_name_str.index;
4420 } else 0;
4421 } else .empty;
44214422
44224423 const doc_comment_index = try astgen.docCommentAsString(var_decl.firstToken());
44234424
......@@ -4452,7 +4453,7 @@ fn globalVarDecl(
44524453 if (is_mutable) {
44534454 const var_inst = try block_scope.addVar(.{
44544455 .var_type = type_inst,
4455 .lib_name = 0,
4456 .lib_name = .empty,
44564457 .align_inst = .none, // passed via the decls data
44574458 .init = init_inst,
44584459 .is_extern = false,
......@@ -4495,9 +4496,9 @@ fn globalVarDecl(
44954496 const line_delta = block_scope.decl_line - gz.decl_line;
44964497 wip_members.appendToDecl(line_delta);
44974498 }
4498 wip_members.appendToDecl(name_str_index);
4499 wip_members.appendToDecl(@intFromEnum(name_str_index));
44994500 wip_members.appendToDecl(@intFromEnum(block_inst));
4500 wip_members.appendToDecl(doc_comment_index); // doc_comment wip
4501 wip_members.appendToDecl(@intFromEnum(doc_comment_index)); // doc_comment wip
45014502 if (align_inst != .none) {
45024503 wip_members.appendToDecl(@intFromEnum(align_inst));
45034504 }
......@@ -4640,7 +4641,7 @@ fn testDecl(
46404641 const test_name_token = test_token + 1;
46414642 const test_name_token_tag = token_tags[test_name_token];
46424643 const is_decltest = test_name_token_tag == .identifier;
4643 const test_name: u32 = blk: {
4644 const test_name: Zir.NullTerminatedString = blk: {
46444645 if (test_name_token_tag == .string_literal) {
46454646 break :blk try astgen.testNameString(test_name_token);
46464647 } else if (test_name_token_tag == .identifier) {
......@@ -4716,7 +4717,7 @@ fn testDecl(
47164717 break :blk name_str_index;
47174718 }
47184719 // String table index 1 has a special meaning here of test decl with no name.
4719 break :blk 1;
4720 break :blk .unnamed_test_decl;
47204721 };
47214722
47224723 var fn_block: GenZir = .{
......@@ -4766,7 +4767,7 @@ fn testDecl(
47664767 .lbrace_column = lbrace_column,
47674768 .param_block = block_inst,
47684769 .body_gz = &fn_block,
4769 .lib_name = 0,
4770 .lib_name = .empty,
47704771 .is_var_args = false,
47714772 .is_inferred_error = false,
47724773 .is_test = true,
......@@ -4789,10 +4790,10 @@ fn testDecl(
47894790 if (is_decltest)
47904791 wip_members.appendToDecl(2) // 2 here means that it is a decltest, look at doc comment for name
47914792 else
4792 wip_members.appendToDecl(test_name);
4793 wip_members.appendToDecl(@intFromEnum(test_name));
47934794 wip_members.appendToDecl(@intFromEnum(block_inst));
47944795 if (is_decltest)
4795 wip_members.appendToDecl(test_name) // the doc comment on a decltest represents it's name
4796 wip_members.appendToDecl(@intFromEnum(test_name)) // the doc comment on a decltest represents it's name
47964797 else
47974798 wip_members.appendToDecl(0); // no doc comments on test decls
47984799}
......@@ -4945,7 +4946,7 @@ fn structDeclInner(
49454946 var sfba = std.heap.stackFallback(256, astgen.arena);
49464947 const sfba_allocator = sfba.get();
49474948
4948 var duplicate_names = std.AutoArrayHashMap(u32, std.ArrayListUnmanaged(Ast.TokenIndex)).init(sfba_allocator);
4949 var duplicate_names = std.AutoArrayHashMap(Zir.NullTerminatedString, std.ArrayListUnmanaged(Ast.TokenIndex)).init(sfba_allocator);
49494950 try duplicate_names.ensureTotalCapacity(field_count);
49504951
49514952 // When there aren't errors, use this to avoid a second iteration.
......@@ -4968,7 +4969,7 @@ fn structDeclInner(
49684969 member.convertToNonTupleLike(astgen.tree.nodes);
49694970 assert(!member.ast.tuple_like);
49704971
4971 wip_members.appendToField(field_name);
4972 wip_members.appendToField(@intFromEnum(field_name));
49724973
49734974 const gop = try duplicate_names.getOrPut(field_name);
49744975
......@@ -4984,7 +4985,7 @@ fn structDeclInner(
49844985 }
49854986
49864987 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
4987 wip_members.appendToField(doc_comment_index);
4988 wip_members.appendToField(@intFromEnum(doc_comment_index));
49884989
49894990 if (member.ast.type_expr == 0) {
49904991 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
......@@ -5196,10 +5197,10 @@ fn unionDeclInner(
51965197 }
51975198
51985199 const field_name = try astgen.identAsString(member.ast.main_token);
5199 wip_members.appendToField(field_name);
5200 wip_members.appendToField(@intFromEnum(field_name));
52005201
52015202 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
5202 wip_members.appendToField(doc_comment_index);
5203 wip_members.appendToField(@intFromEnum(doc_comment_index));
52035204
52045205 const have_type = member.ast.type_expr != 0;
52055206 const have_align = member.ast.align_expr != 0;
......@@ -5475,10 +5476,10 @@ fn containerDecl(
54755476 assert(member.ast.align_expr == 0);
54765477
54775478 const field_name = try astgen.identAsString(member.ast.main_token);
5478 wip_members.appendToField(field_name);
5479 wip_members.appendToField(@intFromEnum(field_name));
54795480
54805481 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
5481 wip_members.appendToField(doc_comment_index);
5482 wip_members.appendToField(@intFromEnum(doc_comment_index));
54825483
54835484 const have_value = member.ast.value_expr != 0;
54845485 wip_members.nextField(bits_per_field, .{have_value});
......@@ -5665,7 +5666,7 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
56655666 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len);
56665667 var fields_len: usize = 0;
56675668 {
5668 var idents: std.AutoHashMapUnmanaged(u32, Ast.TokenIndex) = .{};
5669 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .{};
56695670 defer idents.deinit(gpa);
56705671
56715672 const error_token = main_tokens[node];
......@@ -5695,9 +5696,9 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
56955696 gop.value_ptr.* = tok_i;
56965697
56975698 try astgen.extra.ensureUnusedCapacity(gpa, 2);
5698 astgen.extra.appendAssumeCapacity(str_index);
5699 astgen.extra.appendAssumeCapacity(@intFromEnum(str_index));
56995700 const doc_comment_index = try astgen.docCommentAsString(tok_i);
5700 astgen.extra.appendAssumeCapacity(doc_comment_index);
5701 astgen.extra.appendAssumeCapacity(@intFromEnum(doc_comment_index));
57015702 fields_len += 1;
57025703 },
57035704 .r_brace => break,
......@@ -6372,7 +6373,7 @@ fn whileExpr(
63726373 then_scope.instructions_top = GenZir.unstacked_top;
63736374 defer then_scope.unstack();
63746375
6375 var dbg_var_name: ?u32 = null;
6376 var dbg_var_name: Zir.NullTerminatedString = .empty;
63766377 var dbg_var_inst: Zir.Inst.Ref = undefined;
63776378 var opt_payload_inst: Zir.Inst.OptionalIndex = .none;
63786379 var payload_val_scope: Scope.LocalVal = undefined;
......@@ -6464,7 +6465,7 @@ fn whileExpr(
64646465 if (opt_payload_inst.unwrap()) |payload_inst| {
64656466 try then_scope.instructions.append(astgen.gpa, payload_inst);
64666467 }
6467 if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst);
6468 if (dbg_var_name != .empty) try then_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);
64686469 try then_scope.instructions.append(astgen.gpa, continue_block);
64696470 // This code could be improved to avoid emitting the continue expr when there
64706471 // are no jumps to it. This happens when the last statement of a while body is noreturn
......@@ -7069,9 +7070,9 @@ fn switchExpr(
70697070 const is_multi_case = case.ast.values.len > 1 or
70707071 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
70717072
7072 var dbg_var_name: ?u32 = null;
7073 var dbg_var_name: Zir.NullTerminatedString = .empty;
70737074 var dbg_var_inst: Zir.Inst.Ref = undefined;
7074 var dbg_var_tag_name: ?u32 = null;
7075 var dbg_var_tag_name: Zir.NullTerminatedString = .empty;
70757076 var dbg_var_tag_inst: Zir.Inst.Ref = undefined;
70767077 var has_tag_capture = false;
70777078 var capture_val_scope: Scope.LocalVal = undefined;
......@@ -7193,11 +7194,11 @@ fn switchExpr(
71937194 defer case_scope.unstack();
71947195
71957196 try case_scope.addDbgBlockBegin();
7196 if (dbg_var_name) |some| {
7197 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
7197 if (dbg_var_name != .empty) {
7198 try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);
71987199 }
7199 if (dbg_var_tag_name) |some| {
7200 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst);
7200 if (dbg_var_tag_name != .empty) {
7201 try case_scope.addDbgVar(.dbg_var_val, dbg_var_tag_name, dbg_var_tag_inst);
72017202 }
72027203 const target_expr_node = case.ast.target_expr;
72037204 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
......@@ -7858,7 +7859,7 @@ fn asmExpr(
78587859 const node_tags = tree.nodes.items(.tag);
78597860 const token_tags = tree.tokens.items(.tag);
78607861
7861 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: u32 };
7862 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };
78627863 const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) {
78637864 .string_literal => .{
78647865 .tag = .@"asm",
......@@ -7870,7 +7871,7 @@ fn asmExpr(
78707871 },
78717872 else => .{
78727873 .tag = .asm_expr,
7873 .tmpl = @intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template)),
7874 .tmpl = @enumFromInt(@intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template))),
78747875 },
78757876 };
78767877
......@@ -7956,7 +7957,7 @@ fn asmExpr(
79567957 if (clobber_i >= clobbers_buffer.len) {
79577958 return astgen.failTok(tok_i, "too many asm clobbers", .{});
79587959 }
7959 clobbers_buffer[clobber_i] = (try astgen.strLitAsString(tok_i)).index;
7960 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);
79607961 clobber_i += 1;
79617962 tok_i += 1;
79627963 switch (token_tags[tok_i]) {
......@@ -8290,7 +8291,7 @@ fn builtinCall(
82908291 }
82918292 const str_lit_token = main_tokens[operand_node];
82928293 const str = try astgen.strLitAsString(str_lit_token);
8293 const str_slice = astgen.string_bytes.items[str.index..][0..str.len];
8294 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];
82948295 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
82958296 return astgen.failTok(str_lit_token, "import path cannot contain null bytes", .{});
82968297 } else if (str.len == 0) {
......@@ -8346,7 +8347,7 @@ fn builtinCall(
83468347 // This function causes a Decl to be exported. The first parameter is not an expression,
83478348 // but an identifier of the Decl to be exported.
83488349 var namespace: Zir.Inst.Ref = .none;
8349 var decl_name: u32 = 0;
8350 var decl_name: Zir.NullTerminatedString = .empty;
83508351 switch (node_tags[params[0]]) {
83518352 .identifier => {
83528353 const ident_token = main_tokens[params[0]];
......@@ -9263,7 +9264,7 @@ const Callee = union(enum) {
92639264 /// promote the lvalue to an address if the first parameter requires it.
92649265 obj_ptr: Zir.Inst.Ref,
92659266 /// Offset into `string_bytes`.
9266 field_name_start: u32,
9267 field_name_start: Zir.NullTerminatedString,
92679268 },
92689269 direct: Zir.Inst.Ref,
92699270};
......@@ -10529,7 +10530,7 @@ fn appendErrorNodeNotes(
1052910530) Allocator.Error!void {
1053010531 @setCold(true);
1053110532 const string_bytes = &astgen.string_bytes;
10532 const msg: u32 = @intCast(string_bytes.items.len);
10533 const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
1053310534 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1053410535 const notes_index: u32 = if (notes.len != 0) blk: {
1053510536 const notes_start = astgen.extra.items.len;
......@@ -10621,7 +10622,7 @@ fn appendErrorTokNotesOff(
1062110622 @setCold(true);
1062210623 const gpa = astgen.gpa;
1062310624 const string_bytes = &astgen.string_bytes;
10624 const msg: u32 = @intCast(string_bytes.items.len);
10625 const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
1062510626 try string_bytes.writer(gpa).print(format ++ "\x00", args);
1062610627 const notes_index: u32 = if (notes.len != 0) blk: {
1062710628 const notes_start = astgen.extra.items.len;
......@@ -10657,7 +10658,7 @@ fn errNoteTokOff(
1065710658) Allocator.Error!u32 {
1065810659 @setCold(true);
1065910660 const string_bytes = &astgen.string_bytes;
10660 const msg: u32 = @intCast(string_bytes.items.len);
10661 const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
1066110662 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1066210663 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1066310664 .msg = msg,
......@@ -10676,7 +10677,7 @@ fn errNoteNode(
1067610677) Allocator.Error!u32 {
1067710678 @setCold(true);
1067810679 const string_bytes = &astgen.string_bytes;
10679 const msg: u32 = @intCast(string_bytes.items.len);
10680 const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
1068010681 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1068110682 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1068210683 .msg = msg,
......@@ -10687,7 +10688,7 @@ fn errNoteNode(
1068710688 });
1068810689}
1068910690
10690fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
10691fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !Zir.NullTerminatedString {
1069110692 const gpa = astgen.gpa;
1069210693 const string_bytes = &astgen.string_bytes;
1069310694 const str_index: u32 = @intCast(string_bytes.items.len);
......@@ -10700,19 +10701,19 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
1070010701 });
1070110702 if (gop.found_existing) {
1070210703 string_bytes.shrinkRetainingCapacity(str_index);
10703 return gop.key_ptr.*;
10704 return @enumFromInt(gop.key_ptr.*);
1070410705 } else {
1070510706 gop.key_ptr.* = str_index;
1070610707 try string_bytes.append(gpa, 0);
10707 return str_index;
10708 return @enumFromInt(str_index);
1070810709 }
1070910710}
1071010711
1071110712/// Adds a doc comment block to `string_bytes` by walking backwards from `end_token`.
1071210713/// `end_token` must point at the first token after the last doc coment line.
1071310714/// Returns 0 if no doc comment is present.
10714fn docCommentAsString(astgen: *AstGen, end_token: Ast.TokenIndex) !u32 {
10715 if (end_token == 0) return 0;
10715fn docCommentAsString(astgen: *AstGen, end_token: Ast.TokenIndex) !Zir.NullTerminatedString {
10716 if (end_token == 0) return .empty;
1071610717
1071710718 const token_tags = astgen.tree.tokens.items(.tag);
1071810719
......@@ -10723,6 +10724,7 @@ fn docCommentAsString(astgen: *AstGen, end_token: Ast.TokenIndex) !u32 {
1072310724 } else {
1072410725 tok += 1;
1072510726 }
10727
1072610728 return docCommentAsStringFromFirst(astgen, end_token, tok);
1072710729}
1072810730
......@@ -10731,8 +10733,8 @@ fn docCommentAsStringFromFirst(
1073110733 astgen: *AstGen,
1073210734 end_token: Ast.TokenIndex,
1073310735 start_token: Ast.TokenIndex,
10734) !u32 {
10735 if (start_token == end_token) return 0;
10736) !Zir.NullTerminatedString {
10737 if (start_token == end_token) return .empty;
1073610738
1073710739 const gpa = astgen.gpa;
1073810740 const string_bytes = &astgen.string_bytes;
......@@ -10766,15 +10768,15 @@ fn docCommentAsStringFromFirst(
1076610768
1076710769 if (gop.found_existing) {
1076810770 string_bytes.shrinkRetainingCapacity(str_index);
10769 return gop.key_ptr.*;
10771 return @enumFromInt(gop.key_ptr.*);
1077010772 } else {
1077110773 gop.key_ptr.* = str_index;
1077210774 try string_bytes.append(gpa, 0);
10773 return str_index;
10775 return @enumFromInt(str_index);
1077410776 }
1077510777}
1077610778
10777const IndexSlice = struct { index: u32, len: u32 };
10779const IndexSlice = struct { index: Zir.NullTerminatedString, len: u32 };
1077810780
1077910781fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1078010782 const gpa = astgen.gpa;
......@@ -10791,7 +10793,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1079110793 if (gop.found_existing) {
1079210794 string_bytes.shrinkRetainingCapacity(str_index);
1079310795 return IndexSlice{
10794 .index = gop.key_ptr.*,
10796 .index = @enumFromInt(gop.key_ptr.*),
1079510797 .len = @intCast(key.len),
1079610798 };
1079710799 } else {
......@@ -10801,7 +10803,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1080110803 // be null terminated for that to work.
1080210804 try string_bytes.append(gpa, 0);
1080310805 return IndexSlice{
10804 .index = str_index,
10806 .index = @enumFromInt(str_index),
1080510807 .len = @intCast(key.len),
1080610808 };
1080710809 }
......@@ -10839,12 +10841,12 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
1083910841 const len = string_bytes.items.len - str_index;
1084010842 try string_bytes.append(gpa, 0);
1084110843 return IndexSlice{
10842 .index = @intCast(str_index),
10844 .index = @enumFromInt(str_index),
1084310845 .len = @intCast(len),
1084410846 };
1084510847}
1084610848
10847fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !u32 {
10849fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !Zir.NullTerminatedString {
1084810850 const gpa = astgen.gpa;
1084910851 const string_bytes = &astgen.string_bytes;
1085010852 const str_index: u32 = @intCast(string_bytes.items.len);
......@@ -10858,7 +10860,7 @@ fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !u32 {
1085810860 return astgen.failTok(str_lit_token, "empty test name must be omitted", .{});
1085910861 }
1086010862 try string_bytes.append(gpa, 0);
10861 return str_index;
10863 return @enumFromInt(str_index);
1086210864}
1086310865
1086410866const Scope = struct {
......@@ -10933,7 +10935,7 @@ const Scope = struct {
1093310935 /// 0 means never discarded.
1093410936 discarded: Ast.TokenIndex = 0,
1093510937 /// String table index.
10936 name: u32,
10938 name: Zir.NullTerminatedString,
1093710939 id_cat: IdCat,
1093810940 };
1093910941
......@@ -10959,7 +10961,7 @@ const Scope = struct {
1095910961 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.
1096010962 used_as_lvalue: bool = false,
1096110963 /// String table index.
10962 name: u32,
10964 name: Zir.NullTerminatedString,
1096310965 id_cat: IdCat,
1096410966 /// true means we find out during Sema whether the value is comptime.
1096510967 /// false means it is already known at AstGen the value is runtime-known.
......@@ -10985,7 +10987,7 @@ const Scope = struct {
1098510987 parent: *Scope,
1098610988 /// Maps string table index to the source location of declaration,
1098710989 /// for the purposes of reporting name shadowing compile errors.
10988 decls: std.AutoHashMapUnmanaged(u32, Ast.Node.Index) = .{},
10990 decls: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.Node.Index) = .{},
1098910991 node: Ast.Node.Index,
1099010992 inst: Zir.Inst.Index,
1099110993
......@@ -11250,7 +11252,7 @@ const GenZir = struct {
1125011252 cc_ref: Zir.Inst.Ref,
1125111253 ret_ref: Zir.Inst.Ref,
1125211254
11253 lib_name: u32,
11255 lib_name: Zir.NullTerminatedString,
1125411256 noalias_bits: u32,
1125511257 is_var_args: bool,
1125611258 is_inferred_error: bool,
......@@ -11298,7 +11300,7 @@ const GenZir = struct {
1129811300 }
1129911301 const body_len = astgen.countBodyLenAfterFixups(body);
1130011302
11301 if (args.cc_ref != .none or args.lib_name != 0 or args.is_var_args or args.is_test or
11303 if (args.cc_ref != .none or args.lib_name != .empty or args.is_var_args or args.is_test or
1130211304 args.is_extern or args.align_ref != .none or args.section_ref != .none or
1130311305 args.addrspace_ref != .none or args.noalias_bits != 0 or args.is_noinline)
1130411306 {
......@@ -11322,7 +11324,7 @@ const GenZir = struct {
1132211324 fancyFnExprExtraLen(astgen, cc_body, args.cc_ref) +
1132311325 fancyFnExprExtraLen(astgen, ret_body, ret_ref) +
1132411326 body_len + src_locs.len +
11325 @intFromBool(args.lib_name != 0) +
11327 @intFromBool(args.lib_name != .empty) +
1132611328 @intFromBool(args.noalias_bits != 0),
1132711329 );
1132811330 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
......@@ -11334,7 +11336,7 @@ const GenZir = struct {
1133411336 .is_test = args.is_test,
1133511337 .is_extern = args.is_extern,
1133611338 .is_noinline = args.is_noinline,
11337 .has_lib_name = args.lib_name != 0,
11339 .has_lib_name = args.lib_name != .empty,
1133811340 .has_any_noalias = args.noalias_bits != 0,
1133911341
1134011342 .has_align_ref = args.align_ref != .none,
......@@ -11350,8 +11352,8 @@ const GenZir = struct {
1135011352 .has_ret_ty_body = ret_body.len != 0,
1135111353 },
1135211354 });
11353 if (args.lib_name != 0) {
11354 astgen.extra.appendAssumeCapacity(args.lib_name);
11355 if (args.lib_name != .empty) {
11356 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
1135511357 }
1135611358
1135711359 const zir_datas = astgen.instructions.items(.data);
......@@ -11493,7 +11495,7 @@ const GenZir = struct {
1149311495
1149411496 fn addVar(gz: *GenZir, args: struct {
1149511497 align_inst: Zir.Inst.Ref,
11496 lib_name: u32,
11498 lib_name: Zir.NullTerminatedString,
1149711499 var_type: Zir.Inst.Ref,
1149811500 init: Zir.Inst.Ref,
1149911501 is_extern: bool,
......@@ -11509,15 +11511,15 @@ const GenZir = struct {
1150911511 try astgen.extra.ensureUnusedCapacity(
1151011512 gpa,
1151111513 @typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
11512 @intFromBool(args.lib_name != 0) +
11514 @intFromBool(args.lib_name != .empty) +
1151311515 @intFromBool(args.align_inst != .none) +
1151411516 @intFromBool(args.init != .none),
1151511517 );
1151611518 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
1151711519 .var_type = args.var_type,
1151811520 });
11519 if (args.lib_name != 0) {
11520 astgen.extra.appendAssumeCapacity(args.lib_name);
11521 if (args.lib_name != .empty) {
11522 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
1152111523 }
1152211524 if (args.align_inst != .none) {
1152311525 astgen.extra.appendAssumeCapacity(@intFromEnum(args.align_inst));
......@@ -11532,7 +11534,7 @@ const GenZir = struct {
1153211534 .data = .{ .extended = .{
1153311535 .opcode = .variable,
1153411536 .small = @bitCast(Zir.Inst.ExtendedVar.Small{
11535 .has_lib_name = args.lib_name != 0,
11537 .has_lib_name = args.lib_name != .empty,
1153611538 .has_align = args.align_inst != .none,
1153711539 .has_init = args.init != .none,
1153811540 .is_extern = args.is_extern,
......@@ -11588,7 +11590,7 @@ const GenZir = struct {
1158811590 astgen.instructions.appendAssumeCapacity(.{
1158911591 .tag = .int_big,
1159011592 .data = .{ .str = .{
11591 .start = @intCast(astgen.string_bytes.items.len),
11593 .start = @enumFromInt(astgen.string_bytes.items.len),
1159211594 .len = @intCast(limbs.len),
1159311595 } },
1159411596 });
......@@ -11687,7 +11689,7 @@ const GenZir = struct {
1168711689 tag: Zir.Inst.Tag,
1168811690 /// Absolute token index. This function does the conversion to Decl offset.
1168911691 abs_tok_index: Ast.TokenIndex,
11690 name: u32,
11692 name: Zir.NullTerminatedString,
1169111693 first_doc_comment: ?Ast.TokenIndex,
1169211694 ) !Zir.Inst.Index {
1169311695 const gpa = gz.astgen.gpa;
......@@ -11699,7 +11701,7 @@ const GenZir = struct {
1169911701 const doc_comment_index = if (first_doc_comment) |first|
1170011702 try gz.astgen.docCommentAsStringFromFirst(abs_tok_index, first)
1170111703 else
11702 0;
11704 .empty;
1170311705
1170411706 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
1170511707 .name = name,
......@@ -11847,7 +11849,7 @@ const GenZir = struct {
1184711849 fn addStrTok(
1184811850 gz: *GenZir,
1184911851 tag: Zir.Inst.Tag,
11850 str_index: u32,
11852 str_index: Zir.NullTerminatedString,
1185111853 /// Absolute token index. This function does the conversion to Decl offset.
1185211854 abs_tok_index: Ast.TokenIndex,
1185311855 ) !Zir.Inst.Ref {
......@@ -12122,7 +12124,7 @@ const GenZir = struct {
1212212124 tag: Zir.Inst.Extended,
1212312125 /// Absolute node index. This function does the conversion to offset from Decl.
1212412126 node: Ast.Node.Index,
12125 asm_source: u32,
12127 asm_source: Zir.NullTerminatedString,
1212612128 output_type_bits: u32,
1212712129 is_volatile: bool,
1212812130 outputs: []const Zir.Inst.Asm.Output,
......@@ -12441,7 +12443,7 @@ const GenZir = struct {
1244112443 }
1244212444 }
1244312445
12444 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: u32, inst: Zir.Inst.Ref) !void {
12446 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void {
1244512447 if (gz.is_comptime) return;
1244612448
1244712449 _ = try gz.add(.{ .tag = tag, .data = .{
......@@ -12478,15 +12480,15 @@ const GenZir = struct {
1247812480
1247912481/// This can only be for short-lived references; the memory becomes invalidated
1248012482/// when another string is added.
12481fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {
12482 return @ptrCast(astgen.string_bytes.items[index..]);
12483fn nullTerminatedString(astgen: AstGen, index: Zir.NullTerminatedString) [*:0]const u8 {
12484 return @ptrCast(astgen.string_bytes.items[@intFromEnum(index)..]);
1248312485}
1248412486
1248512487/// Local variables shadowing detection, including function parameters.
1248612488fn detectLocalShadowing(
1248712489 astgen: *AstGen,
1248812490 scope: *Scope,
12489 ident_name: u32,
12491 ident_name: Zir.NullTerminatedString,
1249012492 name_token: Ast.TokenIndex,
1249112493 token_bytes: []const u8,
1249212494 id_cat: Scope.IdCat,
src/Autodoc.zig+54-53
......@@ -447,7 +447,7 @@ fn generateZirData(self: *Autodoc, output_dir: std.fs.Dir) !void {
447447const Scope = struct {
448448 parent: ?*Scope,
449449 map: std.AutoHashMapUnmanaged(
450 u32, // index into the current file's string table (decl name)
450 Zir.NullTerminatedString, // index into the current file's string table (decl name)
451451 *DeclStatus,
452452 ) = .{},
453453
......@@ -464,7 +464,7 @@ const Scope = struct {
464464 /// Another reason is that in some places we use the pointer to uniquely
465465 /// refer to a decl, as we wait for it to be analyzed. This means that
466466 /// those pointers must stay stable.
467 pub fn resolveDeclName(self: Scope, string_table_idx: u32, file: *File, inst: Zir.Inst.OptionalIndex) *DeclStatus {
467 pub fn resolveDeclName(self: Scope, string_table_idx: Zir.NullTerminatedString, file: *File, inst: Zir.Inst.OptionalIndex) *DeclStatus {
468468 var cur: ?*const Scope = &self;
469469 return while (cur) |s| : (cur = s.parent) {
470470 break s.map.get(string_table_idx) orelse continue;
......@@ -482,7 +482,7 @@ const Scope = struct {
482482 pub fn insertDeclRef(
483483 self: *Scope,
484484 arena: std.mem.Allocator,
485 decl_name_index: u32, // index into the current file's string table
485 decl_name_index: Zir.NullTerminatedString, // index into the current file's string table
486486 decl_status: DeclStatus,
487487 ) !void {
488488 const decl_status_ptr = try arena.create(DeclStatus);
......@@ -1250,7 +1250,7 @@ fn walkInstruction(
12501250 // @check
12511251 const str = data[@intFromEnum(inst)].str; //.get(file.zir);
12521252 const byte_count = str.len * @sizeOf(std.math.big.Limb);
1253 const limb_bytes = file.zir.string_bytes[str.start..][0..byte_count];
1253 const limb_bytes = file.zir.string_bytes[@intFromEnum(str.start)..][0..byte_count];
12541254
12551255 const limbs = try self.arena.alloc(std.math.big.Limb, str.len);
12561256 @memcpy(std.mem.sliceAsBytes(limbs)[0..limb_bytes.len], limb_bytes);
......@@ -2167,7 +2167,7 @@ fn walkInstruction(
21672167 // present in json
21682168 var sentinel: ?DocData.Expr = null;
21692169 if (ptr.flags.has_sentinel) {
2170 const ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
2170 const ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
21712171 const ref_result = try self.walkRef(
21722172 file,
21732173 parent_scope,
......@@ -2182,7 +2182,7 @@ fn walkInstruction(
21822182
21832183 var @"align": ?DocData.Expr = null;
21842184 if (ptr.flags.has_align) {
2185 const ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
2185 const ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
21862186 const ref_result = try self.walkRef(
21872187 file,
21882188 parent_scope,
......@@ -2196,7 +2196,7 @@ fn walkInstruction(
21962196 }
21972197 var address_space: ?DocData.Expr = null;
21982198 if (ptr.flags.has_addrspace) {
2199 const ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
2199 const ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
22002200 const ref_result = try self.walkRef(
22012201 file,
22022202 parent_scope,
......@@ -2210,7 +2210,7 @@ fn walkInstruction(
22102210 }
22112211 const bit_start: ?DocData.Expr = null;
22122212 if (ptr.flags.has_bit_range) {
2213 const ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
2213 const ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
22142214 const ref_result = try self.walkRef(
22152215 file,
22162216 parent_scope,
......@@ -2225,7 +2225,7 @@ fn walkInstruction(
22252225
22262226 var host_size: ?DocData.Expr = null;
22272227 if (ptr.flags.has_bit_range) {
2228 const ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
2228 const ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
22292229 const ref_result = try self.walkRef(
22302230 file,
22312231 parent_scope,
......@@ -3041,10 +3041,10 @@ fn walkInstruction(
30413041 );
30423042 var idx = extra.end;
30433043 for (fields) |*f| {
3044 const name = file.zir.nullTerminatedString(file.zir.extra[idx]);
3044 const name = file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[idx]));
30453045 idx += 1;
30463046
3047 const docs = file.zir.nullTerminatedString(file.zir.extra[idx]);
3047 const docs = file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[idx]));
30483048 idx += 1;
30493049
30503050 f.* = .{
......@@ -3706,10 +3706,10 @@ fn walkInstruction(
37063706 const has_value = @as(u1, @truncate(cur_bit_bag)) != 0;
37073707 cur_bit_bag >>= 1;
37083708
3709 const field_name_index = file.zir.extra[extra_index];
3709 const field_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
37103710 extra_index += 1;
37113711
3712 const doc_comment_index = file.zir.extra[extra_index];
3712 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
37133713 extra_index += 1;
37143714
37153715 const value_expr: ?DocData.Expr = if (has_value) blk: {
......@@ -3730,7 +3730,7 @@ fn walkInstruction(
37303730 const field_name = file.zir.nullTerminatedString(field_name_index);
37313731
37323732 try field_name_indexes.append(self.arena, self.ast_nodes.items.len);
3733 const doc_comment: ?[]const u8 = if (doc_comment_index != 0)
3733 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
37343734 file.zir.nullTerminatedString(doc_comment_index)
37353735 else
37363736 null;
......@@ -4085,10 +4085,13 @@ fn analyzeAllDecls(
40854085 {
40864086 var it = original_it;
40874087 while (it.next()) |d| {
4088 const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5];
4088 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 5]);
40894089 switch (decl_name_index) {
4090 0, 1, 2 => continue,
4091 else => if (file.zir.string_bytes[decl_name_index] == 0) {
4090 .empty,
4091 .unnamed_test_decl,
4092 .decltest,
4093 => continue,
4094 _ => if (file.zir.nullTerminatedString(decl_name_index).len == 0) {
40924095 continue;
40934096 },
40944097 }
......@@ -4195,31 +4198,31 @@ fn analyzeDecl(
41954198 // const line = file.zir.extra[extra_index];
41964199
41974200 extra_index += 1;
4198 const decl_name_index = file.zir.extra[extra_index];
4201 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
41994202
42004203 extra_index += 1;
42014204 const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[extra_index]);
42024205
42034206 extra_index += 1;
4204 const doc_comment_index = file.zir.extra[extra_index];
4207 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
42054208
42064209 extra_index += 1;
42074210 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
4208 const inst = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
4211 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
42094212 extra_index += 1;
42104213 break :inst inst;
42114214 };
42124215 _ = align_inst;
42134216
42144217 const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {
4215 const inst = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
4218 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
42164219 extra_index += 1;
42174220 break :inst inst;
42184221 };
42194222 _ = section_inst;
42204223
42214224 const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {
4222 const inst = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
4225 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
42234226 extra_index += 1;
42244227 break :inst inst;
42254228 };
......@@ -4230,9 +4233,9 @@ fn analyzeDecl(
42304233 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
42314234
42324235 const name: []const u8 = switch (decl_name_index) {
4233 0, 1, 2 => unreachable, // comptime or usingnamespace decl, decltest
4234 else => blk: {
4235 if (file.zir.string_bytes[decl_name_index] == 0) {
4236 .empty, .unnamed_test_decl, .decltest => unreachable,
4237 _ => blk: {
4238 if (decl_name_index == .empty) {
42364239 // test decl
42374240 unreachable;
42384241 }
......@@ -4240,7 +4243,7 @@ fn analyzeDecl(
42404243 },
42414244 };
42424245
4243 const doc_comment: ?[]const u8 = if (doc_comment_index != 0)
4246 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
42444247 file.zir.nullTerminatedString(doc_comment_index)
42454248 else
42464249 null;
......@@ -4319,13 +4322,13 @@ fn analyzeUsingnamespaceDecl(
43194322
43204323 const is_pub = @as(u1, @truncate(d.flags)) != 0;
43214324 const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 6]);
4322 const doc_comment_index = file.zir.extra[@intFromEnum(d.sub_index) + 7];
4325 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]);
43234326
43244327 // This is known to work because decl values are always block_inlines
43254328 const value_pl_node = data[@intFromEnum(value_index)].pl_node;
43264329 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
43274330
4328 const doc_comment: ?[]const u8 = if (doc_comment_index != 0)
4331 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
43294332 file.zir.nullTerminatedString(doc_comment_index)
43304333 else
43314334 null;
......@@ -4379,14 +4382,14 @@ fn analyzeDecltest(
43794382 const data = file.zir.instructions.items(.data);
43804383
43814384 const value_index = file.zir.extra[@intFromEnum(d.sub_index) + 6];
4382 const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 7];
4385 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]);
43834386
43844387 const value_pl_node = data[value_index].pl_node;
43854388 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
43864389
43874390 const test_source_code = try self.getBlockSource(file, parent_src, value_pl_node.src_node);
43884391
4389 const decl_name: ?[]const u8 = if (decl_name_index != 0)
4392 const decl_name: ?[]const u8 = if (decl_name_index != .empty)
43904393 file.zir.nullTerminatedString(decl_name_index)
43914394 else
43924395 null;
......@@ -5018,7 +5021,7 @@ fn analyzeFancyFunction(
50185021 .param, .param_comptime => {
50195022 const pl_tok = data[@intFromEnum(param_index)].pl_tok;
50205023 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
5021 const doc_comment = if (extra.data.doc_comment != 0)
5024 const doc_comment = if (extra.data.doc_comment != .empty)
50225025 file.zir.nullTerminatedString(extra.data.doc_comment)
50235026 else
50245027 "";
......@@ -5056,13 +5059,14 @@ fn analyzeFancyFunction(
50565059
50575060 var lib_name: []const u8 = "";
50585061 if (extra.data.bits.has_lib_name) {
5059 lib_name = file.zir.nullTerminatedString(file.zir.extra[extra_index]);
5062 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
5063 lib_name = file.zir.nullTerminatedString(lib_name_index);
50605064 extra_index += 1;
50615065 }
50625066
50635067 var align_index: ?usize = null;
50645068 if (extra.data.bits.has_align_ref) {
5065 const align_ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
5069 const align_ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
50665070 align_index = self.exprs.items.len;
50675071 _ = try self.walkRef(
50685072 file,
......@@ -5086,7 +5090,7 @@ fn analyzeFancyFunction(
50865090
50875091 var addrspace_index: ?usize = null;
50885092 if (extra.data.bits.has_addrspace_ref) {
5089 const addrspace_ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
5093 const addrspace_ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
50905094 addrspace_index = self.exprs.items.len;
50915095 _ = try self.walkRef(
50925096 file,
......@@ -5110,7 +5114,7 @@ fn analyzeFancyFunction(
51105114
51115115 var section_index: ?usize = null;
51125116 if (extra.data.bits.has_section_ref) {
5113 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
5117 const section_ref: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
51145118 section_index = self.exprs.items.len;
51155119 _ = try self.walkRef(
51165120 file,
......@@ -5310,7 +5314,7 @@ fn analyzeFunction(
53105314 .param, .param_comptime => {
53115315 const pl_tok = data[@intFromEnum(param_index)].pl_tok;
53125316 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
5313 const doc_comment = if (extra.data.doc_comment != 0)
5317 const doc_comment = if (extra.data.doc_comment != .empty)
53145318 file.zir.nullTerminatedString(extra.data.doc_comment)
53155319 else
53165320 "";
......@@ -5497,14 +5501,11 @@ fn collectUnionFieldInfo(
54975501 cur_bit_bag >>= 1;
54985502 _ = unused;
54995503
5500 const field_name = file.zir.nullTerminatedString(file.zir.extra[extra_index]);
5504 const field_name = file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index]));
55015505 extra_index += 1;
5502 const doc_comment_index = file.zir.extra[extra_index];
5506 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
55035507 extra_index += 1;
5504 const field_type = if (has_type)
5505 @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]))
5506 else
5507 .void_type;
5508 const field_type: Zir.Inst.Ref = if (has_type) @enumFromInt(file.zir.extra[extra_index]) else .void_type;
55085509 if (has_type) extra_index += 1;
55095510
55105511 if (has_align) extra_index += 1;
......@@ -5526,7 +5527,7 @@ fn collectUnionFieldInfo(
55265527 // ast node
55275528 {
55285529 try field_name_indexes.append(self.arena, self.ast_nodes.items.len);
5529 const doc_comment: ?[]const u8 = if (doc_comment_index != 0)
5530 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
55305531 file.zir.nullTerminatedString(doc_comment_index)
55315532 else
55325533 null;
......@@ -5559,8 +5560,8 @@ fn collectStructFieldInfo(
55595560 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
55605561
55615562 const Field = struct {
5562 field_name: ?u32,
5563 doc_comment_index: u32,
5563 field_name: Zir.NullTerminatedString,
5564 doc_comment_index: Zir.NullTerminatedString,
55645565 type_body_len: u32 = 0,
55655566 align_body_len: u32 = 0,
55665567 init_body_len: u32 = 0,
......@@ -5587,13 +5588,13 @@ fn collectStructFieldInfo(
55875588 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
55885589 cur_bit_bag >>= 1;
55895590
5590 const field_name: ?u32 = if (!is_tuple) blk: {
5591 const field_name: Zir.NullTerminatedString = if (!is_tuple) blk: {
55915592 const fname = file.zir.extra[extra_index];
55925593 extra_index += 1;
5593 break :blk fname;
5594 } else null;
5594 break :blk @enumFromInt(fname);
5595 } else .empty;
55955596
5596 const doc_comment_index = file.zir.extra[extra_index];
5597 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
55975598 extra_index += 1;
55985599
55995600 fields[field_i] = .{
......@@ -5604,7 +5605,7 @@ fn collectStructFieldInfo(
56045605 if (has_type_body) {
56055606 fields[field_i].type_body_len = file.zir.extra[extra_index];
56065607 } else {
5607 fields[field_i].type_ref = @as(Zir.Inst.Ref, @enumFromInt(file.zir.extra[extra_index]));
5608 fields[field_i].type_ref = @enumFromInt(file.zir.extra[extra_index]);
56085609 }
56095610 extra_index += 1;
56105611
......@@ -5686,12 +5687,12 @@ fn collectStructFieldInfo(
56865687 // ast node
56875688 {
56885689 try field_name_indexes.append(self.arena, self.ast_nodes.items.len);
5689 const doc_comment: ?[]const u8 = if (field.doc_comment_index != 0)
5690 const doc_comment: ?[]const u8 = if (field.doc_comment_index != .empty)
56905691 file.zir.nullTerminatedString(field.doc_comment_index)
56915692 else
56925693 null;
5693 const field_name: []const u8 = if (field.field_name) |f_name|
5694 file.zir.nullTerminatedString(f_name)
5694 const field_name: []const u8 = if (field.field_name != .empty)
5695 file.zir.nullTerminatedString(field.field_name)
56955696 else
56965697 "";
56975698
src/Module.zig+10-10
......@@ -4198,7 +4198,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
41984198
41994199 const line_off = zir.extra[decl_sub_index + 4];
42004200 const line = iter.parent_decl.relativeToLine(line_off);
4201 const decl_name_index = zir.extra[decl_sub_index + 5];
4201 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[decl_sub_index + 5]);
42024202 const decl_doccomment_index = zir.extra[decl_sub_index + 7];
42034203 const decl_zir_index = zir.extra[decl_sub_index + 6];
42044204 const decl_block_inst_data = zir.instructions.items(.data)[decl_zir_index].pl_node;
......@@ -4208,7 +4208,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
42084208 var is_named_test = false;
42094209 var kind: Decl.Kind = .named;
42104210 const decl_name: InternPool.NullTerminatedString = switch (decl_name_index) {
4211 0 => name: {
4211 .empty => name: {
42124212 if (export_bit) {
42134213 const i = iter.usingnamespace_index;
42144214 iter.usingnamespace_index += 1;
......@@ -4221,23 +4221,23 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
42214221 break :name try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i});
42224222 }
42234223 },
4224 1 => name: {
4224 .unnamed_test_decl => name: {
42254225 const i = iter.unnamed_test_index;
42264226 iter.unnamed_test_index += 1;
42274227 kind = .@"test";
42284228 break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i});
42294229 },
4230 2 => name: {
4230 .decltest => name: {
42314231 is_named_test = true;
4232 const test_name = zir.nullTerminatedString(decl_doccomment_index);
4232 const test_name = zir.nullTerminatedString(@enumFromInt(decl_doccomment_index));
42334233 kind = .@"test";
42344234 break :name try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{test_name});
42354235 },
4236 else => name: {
4236 _ => name: {
42374237 const raw_name = zir.nullTerminatedString(decl_name_index);
42384238 if (raw_name.len == 0) {
42394239 is_named_test = true;
4240 const test_name = zir.nullTerminatedString(decl_name_index + 1);
4240 const test_name = zir.nullTerminatedString(@enumFromInt(@intFromEnum(decl_name_index) + 1));
42414241 kind = .@"test";
42424242 break :name try ip.getOrPutStringFmt(gpa, "test.{s}", .{test_name});
42434243 } else {
......@@ -4246,7 +4246,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
42464246 },
42474247 };
42484248
4249 const is_exported = export_bit and decl_name_index != 0;
4249 const is_exported = export_bit and decl_name_index != .empty;
42504250 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
42514251
42524252 // We create a Decl for it regardless of analysis status.
......@@ -4271,8 +4271,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
42714271 // test decls if in test mode, get analyzed.
42724272 const decl_mod = namespace.file_scope.mod;
42734273 const want_analysis = is_exported or switch (decl_name_index) {
4274 0 => true, // comptime or usingnamespace decl
4275 1 => blk: {
4274 .empty => true, // comptime or usingnamespace decl
4275 .unnamed_test_decl => blk: {
42764276 // test decl with no name. Skip the part where we check against
42774277 // the test name filter.
42784278 if (!comp.config.is_test) break :blk false;
src/Sema.zig+20-15
......@@ -3044,7 +3044,8 @@ fn zirEnumDecl(
30443044 const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0;
30453045 cur_bit_bag >>= 1;
30463046
3047 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
3047 const field_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
3048 const field_name_zir = sema.code.nullTerminatedString(field_name_index);
30483049 extra_index += 1;
30493050
30503051 // doc comment
......@@ -3322,8 +3323,8 @@ fn zirErrorSetDecl(
33223323 var extra_index: u32 = @intCast(extra.end);
33233324 const extra_index_end = extra_index + (extra.data.fields_len * 2);
33243325 while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
3325 const str_index = sema.code.extra[extra_index];
3326 const name = sema.code.nullTerminatedString(str_index);
3326 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
3327 const name = sema.code.nullTerminatedString(name_index);
33273328 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
33283329 _ = try mod.getErrorValue(name_ip);
33293330 const result = names.getOrPutAssumeCapacity(name_ip);
......@@ -5522,7 +5523,7 @@ fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
55225523 const mod = sema.mod;
55235524 const int = sema.code.instructions.items(.data)[@intFromEnum(inst)].str;
55245525 const byte_count = int.len * @sizeOf(std.math.big.Limb);
5525 const limb_bytes = sema.code.string_bytes[int.start..][0..byte_count];
5526 const limb_bytes = sema.code.string_bytes[@intFromEnum(int.start)..][0..byte_count];
55265527
55275528 // TODO: this allocation and copy is only needed because the limbs may be unaligned.
55285529 // If ZIR is adjusted so that big int limbs are guaranteed to be aligned, these
......@@ -7999,11 +8000,11 @@ fn instantiateGenericCall(
79998000 } },
80008001 }));
80018002 const param_name: Zir.NullTerminatedString = switch (param_tag) {
8002 .param_anytype => @enumFromInt(fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.start),
8003 .param_anytype => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.start,
80038004 .param => name: {
80048005 const inst_data = fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].pl_tok;
80058006 const extra = fn_zir.extraData(Zir.Inst.Param, inst_data.payload_index);
8006 break :name @enumFromInt(extra.data.name);
8007 break :name extra.data.name;
80078008 },
80088009 else => unreachable,
80098010 };
......@@ -9616,7 +9617,7 @@ fn finishFunc(
96169617 .param_anytype => data[@intFromEnum(param_index)].str_tok.src(),
96179618 else => unreachable,
96189619 };
9619 const name = sema.code.nullTerminatedString2(name_nts);
9620 const name = sema.code.nullTerminatedString(name_nts);
96209621 if (name.len != 0) {
96219622 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{name});
96229623 } else {
......@@ -9690,7 +9691,7 @@ fn zirParam(
96909691 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
96919692 const src = inst_data.src();
96929693 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
9693 const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name);
9694 const param_name: Zir.NullTerminatedString = extra.data.name;
96949695 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
96959696
96969697 const param_ty = param_ty: {
......@@ -9781,7 +9782,7 @@ fn zirParamAnytype(
97819782 comptime_syntax: bool,
97829783) CompileError!void {
97839784 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
9784 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
9785 const param_name: Zir.NullTerminatedString = inst_data.start;
97859786
97869787 // We are evaluating a generic function without any comptime args provided.
97879788
......@@ -16184,7 +16185,7 @@ fn zirAsm(
1618416185 const is_global_assembly = sema.func_index == .none;
1618516186
1618616187 const asm_source: []const u8 = if (tmpl_is_expr) blk: {
16187 const tmpl: Zir.Inst.Ref = @enumFromInt(extra.data.asm_source);
16188 const tmpl: Zir.Inst.Ref = @enumFromInt(@intFromEnum(extra.data.asm_source));
1618816189 const s: []const u8 = try sema.resolveConstString(block, src, tmpl, .{
1618916190 .needed_comptime_reason = "assembly code must be comptime-known",
1619016191 });
......@@ -16272,7 +16273,8 @@ fn zirAsm(
1627216273
1627316274 const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
1627416275 for (clobbers) |*name| {
16275 name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
16276 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_i]);
16277 name.* = sema.code.nullTerminatedString(name_index);
1627616278 extra_i += 1;
1627716279
1627816280 needed_capacity += name.*.len / 4 + 1;
......@@ -24713,7 +24715,8 @@ fn zirVarExtended(
2471324715 var extra_index: usize = extra.end;
2471424716
2471524717 const lib_name = if (small.has_lib_name) lib_name: {
24716 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
24718 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
24719 const lib_name = sema.code.nullTerminatedString(lib_name_index);
2471724720 extra_index += 1;
2471824721 try sema.handleExternLibName(block, ty_src, lib_name);
2471924722 break :lib_name lib_name;
......@@ -24781,7 +24784,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2478124784 var extra_index: usize = extra.end;
2478224785
2478324786 const lib_name: ?[]const u8 = if (extra.data.bits.has_lib_name) blk: {
24784 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
24787 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
24788 const lib_name = sema.code.nullTerminatedString(lib_name_index);
2478524789 extra_index += 1;
2478624790 break :blk lib_name;
2478724791 } else null;
......@@ -35841,7 +35845,7 @@ fn semaStructFields(
3584135845
3584235846 var opt_field_name_zir: ?[:0]const u8 = null;
3584335847 if (!small.is_tuple) {
35844 opt_field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
35848 opt_field_name_zir = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index]));
3584535849 extra_index += 1;
3584635850 }
3584735851 extra_index += 1; // doc_comment
......@@ -36344,7 +36348,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3634436348 cur_bit_bag >>= 1;
3634536349 _ = unused;
3634636350
36347 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
36351 const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]);
36352 const field_name_zir = zir.nullTerminatedString(field_name_index);
3634836353 extra_index += 1;
3634936354
3635036355 // doc_comment
src/Zir.zig+42-44
......@@ -93,6 +93,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
9393
9494 Inst.Ref,
9595 Inst.Index,
96 NullTerminatedString,
9697 => @enumFromInt(code.extra[i]),
9798
9899 i32,
......@@ -112,18 +113,15 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
112113 };
113114}
114115
115/// TODO migrate to use this for type safety
116116pub const NullTerminatedString = enum(u32) {
117 empty = 0,
118 unnamed_test_decl = 1,
119 decltest = 2,
117120 _,
118121};
119122
120/// TODO: migrate to nullTerminatedString2 for type safety
121pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
122 return nullTerminatedString2(code, @enumFromInt(index));
123}
124
125123/// Given an index into `string_bytes` returns the null-terminated string found there.
126pub fn nullTerminatedString2(code: Zir, index: NullTerminatedString) [:0]const u8 {
124pub fn nullTerminatedString(code: Zir, index: NullTerminatedString) [:0]const u8 {
127125 const start = @intFromEnum(index);
128126 var end: u32 = start;
129127 while (code.string_bytes[end] != 0) {
......@@ -2298,17 +2296,17 @@ pub const Inst = struct {
22982296 /// For strings which may contain null bytes.
22992297 str: struct {
23002298 /// Offset into `string_bytes`.
2301 start: u32,
2299 start: NullTerminatedString,
23022300 /// Number of bytes in the string.
23032301 len: u32,
23042302
23052303 pub fn get(self: @This(), code: Zir) []const u8 {
2306 return code.string_bytes[self.start..][0..self.len];
2304 return code.string_bytes[@intFromEnum(self.start)..][0..self.len];
23072305 }
23082306 },
23092307 str_tok: struct {
23102308 /// Offset into `string_bytes`. Null-terminated.
2311 start: u32,
2309 start: NullTerminatedString,
23122310 /// Offset from Decl AST token index.
23132311 src_tok: u32,
23142312
......@@ -2385,7 +2383,7 @@ pub const Inst = struct {
23852383 },
23862384 str_op: struct {
23872385 /// Offset into `string_bytes`. Null-terminated.
2388 str: u32,
2386 str: NullTerminatedString,
23892387 operand: Ref,
23902388
23912389 pub fn getStr(self: @This(), zir: Zir) [:0]const u8 {
......@@ -2466,11 +2464,11 @@ pub const Inst = struct {
24662464 /// Trailing:
24672465 /// 0. Output for every outputs_len
24682466 /// 1. Input for every inputs_len
2469 /// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
2467 /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len.
24702468 pub const Asm = struct {
24712469 src_node: i32,
24722470 // null-terminated string index
2473 asm_source: u32,
2471 asm_source: NullTerminatedString,
24742472 /// 1 bit for each outputs_len: whether it uses `-> T` or not.
24752473 /// 0b0 - operand is a pointer to where to store the output.
24762474 /// 0b1 - operand is a type; asm expression has the output as the result.
......@@ -2479,18 +2477,18 @@ pub const Inst = struct {
24792477
24802478 pub const Output = struct {
24812479 /// index into string_bytes (null terminated)
2482 name: u32,
2480 name: NullTerminatedString,
24832481 /// index into string_bytes (null terminated)
2484 constraint: u32,
2482 constraint: NullTerminatedString,
24852483 /// How to interpret this is determined by `output_type_bits`.
24862484 operand: Ref,
24872485 };
24882486
24892487 pub const Input = struct {
24902488 /// index into string_bytes (null terminated)
2491 name: u32,
2489 name: NullTerminatedString,
24922490 /// index into string_bytes (null terminated)
2493 constraint: u32,
2491 constraint: NullTerminatedString,
24942492 operand: Ref,
24952493 };
24962494 };
......@@ -2524,7 +2522,7 @@ pub const Inst = struct {
25242522 };
25252523
25262524 /// Trailing:
2527 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2525 /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
25282526 /// if (has_align_ref and !has_align_body) {
25292527 /// 1. align: Ref,
25302528 /// }
......@@ -2598,7 +2596,7 @@ pub const Inst = struct {
25982596 };
25992597
26002598 /// Trailing:
2601 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2599 /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
26022600 /// 1. align: Ref, // if has_align is set
26032601 /// 2. init: Ref // if has_init is set
26042602 /// The source node is obtained from the containing `block_inline`.
......@@ -2672,7 +2670,7 @@ pub const Inst = struct {
26722670 flags: Call.Flags,
26732671 obj_ptr: Ref,
26742672 /// Offset into `string_bytes`.
2675 field_name_start: u32,
2673 field_name_start: NullTerminatedString,
26762674 };
26772675
26782676 pub const TypeOfPeer = struct {
......@@ -2871,7 +2869,7 @@ pub const Inst = struct {
28712869 pub const Field = struct {
28722870 lhs: Ref,
28732871 /// Offset into `string_bytes`.
2874 field_name_start: u32,
2872 field_name_start: NullTerminatedString,
28752873 };
28762874
28772875 pub const FieldNamed = struct {
......@@ -2900,7 +2898,7 @@ pub const Inst = struct {
29002898 /// 7. decl: { // for every decls_len
29012899 /// src_hash: [4]u32, // hash of source bytes
29022900 /// line: u32, // line number of decl, relative to parent
2903 /// name: u32, // null terminated string index
2901 /// name: NullTerminatedString, // null terminated string index
29042902 /// - 0 means comptime or usingnamespace decl.
29052903 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
29062904 /// - 1 means test decl with no name.
......@@ -2908,7 +2906,7 @@ pub const Inst = struct {
29082906 /// - if there is a 0 byte at the position `name` indexes, it indicates
29092907 /// this is a test decl, and the name starts at `name+1`.
29102908 /// value: Index,
2911 /// doc_comment: u32, 0 if no doc comment, if this is a decltest, doc_comment references the decl name in the string table
2909 /// doc_comment: u32, .empty if no doc comment, if this is a decltest, doc_comment references the decl name in the string table
29122910 /// align: Ref, // if corresponding bit is set
29132911 /// link_section_or_address_space: { // if corresponding bit is set.
29142912 /// link_section: Ref,
......@@ -2923,7 +2921,7 @@ pub const Inst = struct {
29232921 /// 0bX000: whether corresponding field has a type expression
29242922 /// 9. fields: { // for every fields_len
29252923 /// field_name: u32, // if !is_tuple
2926 /// doc_comment: u32, // 0 if no doc comment
2924 /// doc_comment: NullTerminatedString, // .empty if no doc comment
29272925 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
29282926 /// field_type_body_len: u32, // if corresponding bit is set
29292927 /// align_body_len: u32, // if corresponding bit is set
......@@ -2996,14 +2994,14 @@ pub const Inst = struct {
29962994 /// 6. decl: { // for every decls_len
29972995 /// src_hash: [4]u32, // hash of source bytes
29982996 /// line: u32, // line number of decl, relative to parent
2999 /// name: u32, // null terminated string index
2997 /// name: NullTerminatedString, // null terminated string index
30002998 /// - 0 means comptime or usingnamespace decl.
30012999 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
30023000 /// - 1 means test decl with no name.
30033001 /// - if there is a 0 byte at the position `name` indexes, it indicates
30043002 /// this is a test decl, and the name starts at `name+1`.
30053003 /// value: Index,
3006 /// doc_comment: u32, // 0 if no doc_comment
3004 /// doc_comment: u32, // .empty if no doc_comment
30073005 /// align: Ref, // if corresponding bit is set
30083006 /// link_section_or_address_space: { // if corresponding bit is set.
30093007 /// link_section: Ref,
......@@ -3015,7 +3013,7 @@ pub const Inst = struct {
30153013 /// - the bit is whether corresponding field has an value expression
30163014 /// 9. fields: { // for every fields_len
30173015 /// field_name: u32,
3018 /// doc_comment: u32, // 0 if no doc_comment
3016 /// doc_comment: u32, // .empty if no doc_comment
30193017 /// value: Ref, // if corresponding bit is set
30203018 /// }
30213019 pub const EnumDecl = struct {
......@@ -3046,14 +3044,14 @@ pub const Inst = struct {
30463044 /// 6. decl: { // for every decls_len
30473045 /// src_hash: [4]u32, // hash of source bytes
30483046 /// line: u32, // line number of decl, relative to parent
3049 /// name: u32, // null terminated string index
3047 /// name: NullTerminatedString, // null terminated string index
30503048 /// - 0 means comptime or usingnamespace decl.
30513049 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
30523050 /// - 1 means test decl with no name.
30533051 /// - if there is a 0 byte at the position `name` indexes, it indicates
30543052 /// this is a test decl, and the name starts at `name+1`.
30553053 /// value: Index,
3056 /// doc_comment: u32, // 0 if no doc comment
3054 /// doc_comment: NullTerminatedString, // .empty if no doc comment
30573055 /// align: Ref, // if corresponding bit is set
30583056 /// link_section_or_address_space: { // if corresponding bit is set.
30593057 /// link_section: Ref,
......@@ -3068,8 +3066,8 @@ pub const Inst = struct {
30683066 /// 0b0X00: whether corresponding field has a tag value expression
30693067 /// 0bX000: unused
30703068 /// 9. fields: { // for every fields_len
3071 /// field_name: u32, // null terminated string index
3072 /// doc_comment: u32, // 0 if no doc comment
3069 /// field_name: NullTerminatedString, // null terminated string index
3070 /// doc_comment: NullTerminatedString, // .empty if no doc comment
30733071 /// field_type: Ref, // if corresponding bit is set
30743072 /// - if none, means `anytype`.
30753073 /// align: Ref, // if corresponding bit is set
......@@ -3108,14 +3106,14 @@ pub const Inst = struct {
31083106 /// 3. decl: { // for every decls_len
31093107 /// src_hash: [4]u32, // hash of source bytes
31103108 /// line: u32, // line number of decl, relative to parent
3111 /// name: u32, // null terminated string index
3109 /// name: NullTerminatedString, // null terminated string index
31123110 /// - 0 means comptime or usingnamespace decl.
31133111 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
31143112 /// - 1 means test decl with no name.
31153113 /// - if there is a 0 byte at the position `name` indexes, it indicates
31163114 /// this is a test decl, and the name starts at `name+1`.
31173115 /// value: Index,
3118 /// doc_comment: u32, // 0 if no doc comment,
3116 /// doc_comment: NullTerminatedString, // .empty if no doc comment,
31193117 /// align: Ref, // if corresponding bit is set
31203118 /// link_section_or_address_space: { // if corresponding bit is set.
31213119 /// link_section: Ref,
......@@ -3133,8 +3131,8 @@ pub const Inst = struct {
31333131
31343132 /// Trailing:
31353133 /// { // for every fields_len
3136 /// field_name: u32 // null terminated string index
3137 /// doc_comment: u32 // null terminated string index
3134 /// field_name: NullTerminatedString // null terminated string index
3135 /// doc_comment: NullTerminatedString // null terminated string index
31383136 /// }
31393137 pub const ErrorSetDecl = struct {
31403138 fields_len: u32,
......@@ -3177,7 +3175,7 @@ pub const Inst = struct {
31773175
31783176 pub const Item = struct {
31793177 /// Null-terminated string table index.
3180 field_name: u32,
3178 field_name: NullTerminatedString,
31813179 /// The field init expression to be used as the field value.
31823180 init: Ref,
31833181 };
......@@ -3186,7 +3184,7 @@ pub const Inst = struct {
31863184 pub const FieldType = struct {
31873185 container_type: Ref,
31883186 /// Offset into `string_bytes`, null terminated.
3189 name_start: u32,
3187 name_start: NullTerminatedString,
31903188 };
31913189
31923190 pub const FieldTypeRef = struct {
......@@ -3266,9 +3264,9 @@ pub const Inst = struct {
32663264 /// Trailing: inst: Index // for every body_len
32673265 pub const Param = struct {
32683266 /// Null-terminated string index.
3269 name: u32,
3270 /// 0 if no doc comment
3271 doc_comment: u32,
3267 name: NullTerminatedString,
3268 /// Null-terminated string index.
3269 doc_comment: NullTerminatedString,
32723270 /// The body contains the type of the parameter.
32733271 body_len: u32,
32743272 };
......@@ -3293,7 +3291,7 @@ pub const Inst = struct {
32933291 /// If omitted, this is referring to a Decl via identifier, e.g. `a`.
32943292 namespace: Ref,
32953293 /// Null-terminated string index.
3296 decl_name: u32,
3294 decl_name: NullTerminatedString,
32973295 options: Ref,
32983296 };
32993297
......@@ -3311,7 +3309,7 @@ pub const Inst = struct {
33113309 /// It's a payload index of another `Item`.
33123310 pub const Item = struct {
33133311 /// null terminated string index
3314 msg: u32,
3312 msg: NullTerminatedString,
33153313 node: Ast.Node.Index,
33163314 /// If node is 0 then this will be populated.
33173315 token: Ast.TokenIndex,
......@@ -3335,7 +3333,7 @@ pub const Inst = struct {
33353333
33363334 pub const Item = struct {
33373335 /// null terminated string index
3338 name: u32,
3336 name: NullTerminatedString,
33393337 /// points to the import name
33403338 token: Ast.TokenIndex,
33413339 };
......@@ -3412,7 +3410,7 @@ pub const DeclIterator = struct {
34123410
34133411 const sub_index: ExtraIndex = @enumFromInt(it.extra_index);
34143412 it.extra_index += 5; // src_hash(4) + line(1)
3415 const name = it.zir.nullTerminatedString(it.zir.extra[it.extra_index]);
3413 const name = it.zir.nullTerminatedString(@enumFromInt(it.zir.extra[it.extra_index]));
34163414 it.extra_index += 3; // name(1) + value(1) + doc_comment(1)
34173415 it.extra_index += @as(u1, @truncate(flags >> 2)); // align
34183416 it.extra_index += @as(u1, @truncate(flags >> 3)); // link_section
src/print_zir.zig+28-26
......@@ -752,7 +752,7 @@ const Writer = struct {
752752 fn writeIntBig(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
753753 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
754754 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
755 const limb_bytes = self.code.string_bytes[inst_data.start..][0..byte_count];
755 const limb_bytes = self.code.nullTerminatedString(inst_data.start)[0..byte_count];
756756 // limb_bytes is not aligned properly; we must allocate and copy the bytes
757757 // in order to accomplish this.
758758 const limbs = try self.gpa.alloc(std.math.big.Limb, inst_data.len);
......@@ -945,7 +945,7 @@ const Writer = struct {
945945 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
946946 });
947947
948 if (extra.data.doc_comment != 0) {
948 if (extra.data.doc_comment != .empty) {
949949 try stream.writeAll("\n");
950950 try self.writeDocComment(stream, extra.data.doc_comment);
951951 try stream.writeByteNTimes(' ', self.indent);
......@@ -1226,7 +1226,7 @@ const Writer = struct {
12261226
12271227 try self.writeFlag(stream, "volatile, ", is_volatile);
12281228 if (tmpl_is_expr) {
1229 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(extra.data.asm_source)));
1229 try self.writeInstRef(stream, @enumFromInt(@intFromEnum(extra.data.asm_source)));
12301230 try stream.writeAll(", ");
12311231 } else {
12321232 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
......@@ -1281,7 +1281,7 @@ const Writer = struct {
12811281 while (i < clobbers_len) : (i += 1) {
12821282 const str_index = self.code.extra[extra_i];
12831283 extra_i += 1;
1284 const clobber = self.code.nullTerminatedString(str_index);
1284 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));
12851285 try stream.print("{}", .{std.zig.fmtId(clobber)});
12861286 if (i + 1 < clobbers_len) {
12871287 try stream.writeAll(", ");
......@@ -1466,12 +1466,12 @@ const Writer = struct {
14661466 const fields_per_u32 = 32 / bits_per_field;
14671467 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
14681468 const Field = struct {
1469 doc_comment_index: u32,
1469 doc_comment_index: Zir.NullTerminatedString,
14701470 type_len: u32 = 0,
14711471 align_len: u32 = 0,
14721472 init_len: u32 = 0,
14731473 type: Zir.Inst.Ref = .none,
1474 name: u32,
1474 name: Zir.NullTerminatedString,
14751475 is_comptime: bool,
14761476 };
14771477 const fields = try self.arena.alloc(Field, fields_len);
......@@ -1494,24 +1494,24 @@ const Writer = struct {
14941494 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
14951495 cur_bit_bag >>= 1;
14961496
1497 var field_name: u32 = 0;
1497 var field_name_index: Zir.NullTerminatedString = .empty;
14981498 if (!small.is_tuple) {
1499 field_name = self.code.extra[extra_index];
1499 field_name_index = @enumFromInt(self.code.extra[extra_index]);
15001500 extra_index += 1;
15011501 }
1502 const doc_comment_index = self.code.extra[extra_index];
1502 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
15031503 extra_index += 1;
15041504
15051505 fields[field_i] = .{
15061506 .doc_comment_index = doc_comment_index,
15071507 .is_comptime = is_comptime,
1508 .name = field_name,
1508 .name = field_name_index,
15091509 };
15101510
15111511 if (has_type_body) {
15121512 fields[field_i].type_len = self.code.extra[extra_index];
15131513 } else {
1514 fields[field_i].type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1514 fields[field_i].type = @enumFromInt(self.code.extra[extra_index]);
15151515 }
15161516 extra_index += 1;
15171517
......@@ -1536,7 +1536,7 @@ const Writer = struct {
15361536 try self.writeDocComment(stream, field.doc_comment_index);
15371537 try stream.writeByteNTimes(' ', self.indent);
15381538 try self.writeFlag(stream, "comptime ", field.is_comptime);
1539 if (field.name != 0) {
1539 if (field.name != .empty) {
15401540 const field_name = self.code.nullTerminatedString(field.name);
15411541 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
15421542 } else {
......@@ -1684,9 +1684,10 @@ const Writer = struct {
16841684
16851685 _ = unused;
16861686
1687 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1687 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1688 const field_name = self.code.nullTerminatedString(field_name_index);
16881689 extra_index += 1;
1689 const doc_comment_index = self.code.extra[extra_index];
1690 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
16901691 extra_index += 1;
16911692
16921693 try self.writeDocComment(stream, doc_comment_index);
......@@ -1756,7 +1757,7 @@ const Writer = struct {
17561757 extra_index += 1;
17571758 const decl_index: Zir.Inst.Index = @enumFromInt(self.code.extra[extra_index]);
17581759 extra_index += 1;
1759 const doc_comment_index = self.code.extra[extra_index];
1760 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
17601761 extra_index += 1;
17611762
17621763 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
......@@ -1789,9 +1790,9 @@ const Writer = struct {
17891790 try stream.writeByteNTimes(' ', self.indent);
17901791 try stream.print("[{d}] decltest {s}", .{ sub_index, self.code.nullTerminatedString(doc_comment_index) });
17911792 } else {
1792 const raw_decl_name = self.code.nullTerminatedString(decl_name_index);
1793 const raw_decl_name = self.code.nullTerminatedString(@enumFromInt(decl_name_index));
17931794 const decl_name = if (raw_decl_name.len == 0)
1794 self.code.nullTerminatedString(decl_name_index + 1)
1795 self.code.nullTerminatedString(@enumFromInt(decl_name_index + 1))
17951796 else
17961797 raw_decl_name;
17971798 const test_str = if (raw_decl_name.len == 0) "test \"" else "";
......@@ -1927,10 +1928,10 @@ const Writer = struct {
19271928 const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0;
19281929 cur_bit_bag >>= 1;
19291930
1930 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1931 const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
19311932 extra_index += 1;
19321933
1933 const doc_comment_index = self.code.extra[extra_index];
1934 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
19341935 extra_index += 1;
19351936
19361937 try self.writeDocComment(stream, doc_comment_index);
......@@ -2011,9 +2012,9 @@ const Writer = struct {
20112012 var extra_index = @as(u32, @intCast(extra.end));
20122013 const extra_index_end = extra_index + (extra.data.fields_len * 2);
20132014 while (extra_index < extra_index_end) : (extra_index += 2) {
2014 const str_index = self.code.extra[extra_index];
2015 const name = self.code.nullTerminatedString(str_index);
2016 const doc_comment_index = self.code.extra[extra_index + 1];
2015 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
2016 const name = self.code.nullTerminatedString(name_index);
2017 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index + 1]);
20172018 try self.writeDocComment(stream, doc_comment_index);
20182019 try stream.writeByteNTimes(' ', self.indent);
20192020 try stream.print("{},\n", .{std.zig.fmtId(name)});
......@@ -2292,7 +2293,7 @@ const Writer = struct {
22922293 var ret_ty_body: []const Zir.Inst.Index = &.{};
22932294
22942295 if (extra.data.bits.has_lib_name) {
2295 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
2296 const lib_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
22962297 extra_index += 1;
22972298 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
22982299 }
......@@ -2388,7 +2389,8 @@ const Writer = struct {
23882389
23892390 var extra_index: usize = extra.end;
23902391 if (small.has_lib_name) {
2391 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
2392 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
2393 const lib_name = self.code.nullTerminatedString(lib_name_index);
23922394 extra_index += 1;
23932395 try stream.print(", lib_name=\"{}\"", .{std.zig.fmtEscapes(lib_name)});
23942396 }
......@@ -2740,8 +2742,8 @@ const Writer = struct {
27402742 }
27412743 }
27422744
2743 fn writeDocComment(self: *Writer, stream: anytype, doc_comment_index: u32) !void {
2744 if (doc_comment_index != 0) {
2745 fn writeDocComment(self: *Writer, stream: anytype, doc_comment_index: Zir.NullTerminatedString) !void {
2746 if (doc_comment_index != .empty) {
27452747 const doc_comment = self.code.nullTerminatedString(doc_comment_index);
27462748 var it = std.mem.tokenizeScalar(u8, doc_comment, '\n');
27472749 while (it.next()) |doc_line| {