authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-23 18:31:55-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-23 18:31:55-05:00
log12c2de6ee205857e9ca0bcef4aa4d901fc5cc772
tree491f15df20182f428a92533e8efc2530c73c9dc2
parentf1b91bb41b2d810ecabf4c69cad91b24b3846b77
parent8a697262099d64b2ff222dc9271493fe3b5f2b76
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10662 from ziglang/doc-comments-zir

Doc comments zir

9 files changed, 212 insertions(+), 23 deletions(-)

lib/std/special/compiler_rt.zig+3-1
...@@ -26,7 +26,9 @@ comptime {...@@ -26,7 +26,9 @@ comptime {
26 if (builtin.zig_backend == .stage1) {26 if (builtin.zig_backend == .stage1) {
27 _ = @import("compiler_rt/atomics.zig");27 _ = @import("compiler_rt/atomics.zig");
28 }28 }
29 _ = @import("compiler_rt/clear_cache.zig").clear_cache;29 if (builtin.zig_backend != .stage2_llvm) { // TODO
30 _ = @import("compiler_rt/clear_cache.zig").clear_cache;
31 }
3032
31 const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2;33 const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2;
32 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });34 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
lib/std/zig/Ast.zig+18
...@@ -2120,6 +2120,14 @@ pub const full = struct {...@@ -2120,6 +2120,14 @@ pub const full = struct {
2120 section_node: Node.Index,2120 section_node: Node.Index,
2121 init_node: Node.Index,2121 init_node: Node.Index,
2122 };2122 };
2123
2124 pub fn firstToken(var_decl: VarDecl) TokenIndex {
2125 return var_decl.visib_token orelse
2126 var_decl.extern_export_token orelse
2127 var_decl.threadlocal_token orelse
2128 var_decl.comptime_token orelse
2129 var_decl.ast.mut_token;
2130 }
2123 };2131 };
21242132
2125 pub const If = struct {2133 pub const If = struct {
...@@ -2168,6 +2176,10 @@ pub const full = struct {...@@ -2168,6 +2176,10 @@ pub const full = struct {
2168 value_expr: Node.Index,2176 value_expr: Node.Index,
2169 align_expr: Node.Index,2177 align_expr: Node.Index,
2170 };2178 };
2179
2180 pub fn firstToken(cf: ContainerField) TokenIndex {
2181 return cf.comptime_token orelse cf.ast.name_token;
2182 }
2171 };2183 };
21722184
2173 pub const FnProto = struct {2185 pub const FnProto = struct {
...@@ -2197,6 +2209,12 @@ pub const full = struct {...@@ -2197,6 +2209,12 @@ pub const full = struct {
2197 type_expr: Node.Index,2209 type_expr: Node.Index,
2198 };2210 };
21992211
2212 pub fn firstToken(fn_proto: FnProto) TokenIndex {
2213 return fn_proto.visib_token orelse
2214 fn_proto.extern_export_inline_token orelse
2215 fn_proto.ast.fn_token;
2216 }
2217
2200 /// Abstracts over the fact that anytype and ... are not included2218 /// Abstracts over the fact that anytype and ... are not included
2201 /// in the params slice, since they are simple identifiers and2219 /// in the params slice, since they are simple identifiers and
2202 /// not sub-expressions.2220 /// not sub-expressions.
src/AstGen.zig+104-9
...@@ -1171,7 +1171,7 @@ fn fnProtoExpr(...@@ -1171,7 +1171,7 @@ fn fnProtoExpr(
1171 const main_tokens = tree.nodes.items(.main_token);1171 const main_tokens = tree.nodes.items(.main_token);
1172 const name_token = param.name_token orelse main_tokens[param_type_node];1172 const name_token = param.name_token orelse main_tokens[param_type_node];
1173 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;1173 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
1174 const param_inst = try block_scope.addParam(&param_gz, tag, name_token, param_name);1174 const param_inst = try block_scope.addParam(&param_gz, tag, name_token, param_name, param.first_doc_comment);
1175 assert(param_inst_expected == param_inst);1175 assert(param_inst_expected == param_inst);
1176 }1176 }
1177 }1177 }
...@@ -3080,9 +3080,9 @@ const WipMembers = struct {...@@ -3080,9 +3080,9 @@ const WipMembers = struct {
3080 /// struct, union, enum, and opaque decls all use same 4 bits per decl3080 /// struct, union, enum, and opaque decls all use same 4 bits per decl
3081 const bits_per_decl = 4;3081 const bits_per_decl = 4;
3082 const decls_per_u32 = 32 / bits_per_decl;3082 const decls_per_u32 = 32 / bits_per_decl;
3083 /// struct, union, enum, and opaque decls all have maximum size of 10 u32 slots3083 /// struct, union, enum, and opaque decls all have maximum size of 11 u32 slots
3084 /// (4 for src_hash + line + name + value + align + link_section + address_space)3084 /// (4 for src_hash + line + name + value + doc_comment + align + link_section + address_space )
3085 const max_decl_size = 10;3085 const max_decl_size = 11;
30863086
3087 pub fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {3087 pub fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3088 const payload_top = @intCast(u32, payload.items.len);3088 const payload_top = @intCast(u32, payload.items.len);
...@@ -3236,6 +3236,9 @@ fn fnDecl(...@@ -3236,6 +3236,9 @@ fn fnDecl(
3236 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;3236 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
3237 break :blk token_tags[maybe_inline_token] == .keyword_inline;3237 break :blk token_tags[maybe_inline_token] == .keyword_inline;
3238 };3238 };
3239
3240 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());
3241
3239 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;3242 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;
3240 wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);3243 wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);
32413244
...@@ -3294,7 +3297,7 @@ fn fnDecl(...@@ -3294,7 +3297,7 @@ fn fnDecl(
3294 const main_tokens = tree.nodes.items(.main_token);3297 const main_tokens = tree.nodes.items(.main_token);
3295 const name_token = param.name_token orelse main_tokens[param_type_node];3298 const name_token = param.name_token orelse main_tokens[param_type_node];
3296 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;3299 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
3297 const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name);3300 const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name, param.first_doc_comment);
3298 assert(param_inst_expected == param_inst);3301 assert(param_inst_expected == param_inst);
3299 break :param indexToRef(param_inst);3302 break :param indexToRef(param_inst);
3300 };3303 };
...@@ -3445,6 +3448,7 @@ fn fnDecl(...@@ -3445,6 +3448,7 @@ fn fnDecl(
3445 }3448 }
3446 wip_members.appendToDecl(fn_name_str_index);3449 wip_members.appendToDecl(fn_name_str_index);
3447 wip_members.appendToDecl(block_inst);3450 wip_members.appendToDecl(block_inst);
3451 wip_members.appendToDecl(doc_comment_index);
3448 if (align_inst != .none) {3452 if (align_inst != .none) {
3449 wip_members.appendToDecl(@enumToInt(align_inst));3453 wip_members.appendToDecl(@enumToInt(align_inst));
3450 }3454 }
...@@ -3519,6 +3523,8 @@ fn globalVarDecl(...@@ -3519,6 +3523,8 @@ fn globalVarDecl(
3519 break :blk lib_name_str.index;3523 break :blk lib_name_str.index;
3520 } else 0;3524 } else 0;
35213525
3526 const doc_comment_index = try astgen.docCommentAsString(var_decl.firstToken());
3527
3522 assert(var_decl.comptime_token == null); // handled by parser3528 assert(var_decl.comptime_token == null); // handled by parser
35233529
3524 const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: {3530 const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: {
...@@ -3594,6 +3600,7 @@ fn globalVarDecl(...@@ -3594,6 +3600,7 @@ fn globalVarDecl(
3594 }3600 }
3595 wip_members.appendToDecl(name_str_index);3601 wip_members.appendToDecl(name_str_index);
3596 wip_members.appendToDecl(block_inst);3602 wip_members.appendToDecl(block_inst);
3603 wip_members.appendToDecl(doc_comment_index); // doc_comment wip
3597 if (align_inst != .none) {3604 if (align_inst != .none) {
3598 wip_members.appendToDecl(@enumToInt(align_inst));3605 wip_members.appendToDecl(@enumToInt(align_inst));
3599 }3606 }
...@@ -3648,6 +3655,7 @@ fn comptimeDecl(...@@ -3648,6 +3655,7 @@ fn comptimeDecl(
3648 }3655 }
3649 wip_members.appendToDecl(0);3656 wip_members.appendToDecl(0);
3650 wip_members.appendToDecl(block_inst);3657 wip_members.appendToDecl(block_inst);
3658 wip_members.appendToDecl(0); // no doc comments on comptime decls
3651}3659}
36523660
3653fn usingnamespaceDecl(3661fn usingnamespaceDecl(
...@@ -3699,6 +3707,7 @@ fn usingnamespaceDecl(...@@ -3699,6 +3707,7 @@ fn usingnamespaceDecl(
3699 }3707 }
3700 wip_members.appendToDecl(0);3708 wip_members.appendToDecl(0);
3701 wip_members.appendToDecl(block_inst);3709 wip_members.appendToDecl(block_inst);
3710 wip_members.appendToDecl(0); // no doc comments on usingnamespace decls
3702}3711}
37033712
3704fn testDecl(3713fn testDecl(
...@@ -3802,6 +3811,7 @@ fn testDecl(...@@ -3802,6 +3811,7 @@ fn testDecl(
3802 }3811 }
3803 wip_members.appendToDecl(test_name);3812 wip_members.appendToDecl(test_name);
3804 wip_members.appendToDecl(block_inst);3813 wip_members.appendToDecl(block_inst);
3814 wip_members.appendToDecl(0); // no doc comments on test decls
3805}3815}
38063816
3807fn structDeclInner(3817fn structDeclInner(
...@@ -3857,7 +3867,7 @@ fn structDeclInner(...@@ -3857,7 +3867,7 @@ fn structDeclInner(
3857 const field_count = @intCast(u32, container_decl.ast.members.len - decl_count);3867 const field_count = @intCast(u32, container_decl.ast.members.len - decl_count);
38583868
3859 const bits_per_field = 4;3869 const bits_per_field = 4;
3860 const max_field_size = 4;3870 const max_field_size = 5;
3861 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);3871 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3862 defer wip_members.deinit();3872 defer wip_members.deinit();
38633873
...@@ -3881,6 +3891,9 @@ fn structDeclInner(...@@ -3881,6 +3891,9 @@ fn structDeclInner(
3881 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);3891 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
3882 wip_members.appendToField(@enumToInt(field_type));3892 wip_members.appendToField(@enumToInt(field_type));
38833893
3894 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
3895 wip_members.appendToField(doc_comment_index);
3896
3884 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);3897 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
38853898
3886 const have_align = member.ast.align_expr != 0;3899 const have_align = member.ast.align_expr != 0;
...@@ -3979,7 +3992,7 @@ fn unionDeclInner(...@@ -3979,7 +3992,7 @@ fn unionDeclInner(
3979 .none;3992 .none;
39803993
3981 const bits_per_field = 4;3994 const bits_per_field = 4;
3982 const max_field_size = 4;3995 const max_field_size = 5;
3983 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);3996 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3984 defer wip_members.deinit();3997 defer wip_members.deinit();
39853998
...@@ -3995,6 +4008,9 @@ fn unionDeclInner(...@@ -3995,6 +4008,9 @@ fn unionDeclInner(
3995 const field_name = try astgen.identAsString(member.ast.name_token);4008 const field_name = try astgen.identAsString(member.ast.name_token);
3996 wip_members.appendToField(field_name);4009 wip_members.appendToField(field_name);
39974010
4011 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
4012 wip_members.appendToField(doc_comment_index);
4013
3998 const have_type = member.ast.type_expr != 0;4014 const have_type = member.ast.type_expr != 0;
3999 const have_align = member.ast.align_expr != 0;4015 const have_align = member.ast.align_expr != 0;
4000 const have_value = member.ast.value_expr != 0;4016 const have_value = member.ast.value_expr != 0;
...@@ -4258,7 +4274,7 @@ fn containerDecl(...@@ -4258,7 +4274,7 @@ fn containerDecl(
4258 .none;4274 .none;
42594275
4260 const bits_per_field = 1;4276 const bits_per_field = 1;
4261 const max_field_size = 2;4277 const max_field_size = 3;
4262 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);4278 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4263 defer wip_members.deinit();4279 defer wip_members.deinit();
42644280
...@@ -4276,6 +4292,9 @@ fn containerDecl(...@@ -4276,6 +4292,9 @@ fn containerDecl(
4276 const field_name = try astgen.identAsString(member.ast.name_token);4292 const field_name = try astgen.identAsString(member.ast.name_token);
4277 wip_members.appendToField(field_name);4293 wip_members.appendToField(field_name);
42784294
4295 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
4296 wip_members.appendToField(doc_comment_index);
4297
4279 const have_value = member.ast.value_expr != 0;4298 const have_value = member.ast.value_expr != 0;
4280 wip_members.nextField(bits_per_field, .{have_value});4299 wip_members.nextField(bits_per_field, .{have_value});
42814300
...@@ -4506,8 +4525,11 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir...@@ -4506,8 +4525,11 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
4506 switch (token_tags[tok_i]) {4525 switch (token_tags[tok_i]) {
4507 .doc_comment, .comma => {},4526 .doc_comment, .comma => {},
4508 .identifier => {4527 .identifier => {
4528 try astgen.extra.ensureUnusedCapacity(gpa, 2);
4509 const str_index = try astgen.identAsString(tok_i);4529 const str_index = try astgen.identAsString(tok_i);
4510 try astgen.extra.append(gpa, str_index);4530 astgen.extra.appendAssumeCapacity(str_index);
4531 const doc_comment_index = try astgen.docCommentAsString(tok_i);
4532 astgen.extra.appendAssumeCapacity(doc_comment_index);
4511 fields_len += 1;4533 fields_len += 1;
4512 },4534 },
4513 .r_brace => break,4535 .r_brace => break,
...@@ -8784,6 +8806,72 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {...@@ -8784,6 +8806,72 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
8784 }8806 }
8785}8807}
87868808
8809/// Adds a doc comment block to `string_bytes` by walking backwards from `end_token`.
8810/// `end_token` must point at the first token after the last doc coment line.
8811/// Returns 0 if no doc comment is present.
8812fn docCommentAsString(astgen: *AstGen, end_token: Ast.TokenIndex) !u32 {
8813 if (end_token == 0) return @as(u32, 0);
8814
8815 const token_tags = astgen.tree.tokens.items(.tag);
8816
8817 var tok = end_token - 1;
8818 while (token_tags[tok] == .doc_comment) {
8819 if (tok == 0) break;
8820 tok -= 1;
8821 } else {
8822 tok += 1;
8823 }
8824 return docCommentAsStringFromFirst(astgen, end_token, tok);
8825}
8826
8827/// end_token must be > the index of the last doc comment.
8828fn docCommentAsStringFromFirst(
8829 astgen: *AstGen,
8830 end_token: Ast.TokenIndex,
8831 start_token: Ast.TokenIndex,
8832) !u32 {
8833 if (start_token == end_token) return 0;
8834
8835 const gpa = astgen.gpa;
8836 const string_bytes = &astgen.string_bytes;
8837 const str_index = @intCast(u32, string_bytes.items.len);
8838 const token_starts = astgen.tree.tokens.items(.start);
8839 const token_tags = astgen.tree.tokens.items(.tag);
8840
8841 const total_bytes = token_starts[end_token] - token_starts[start_token];
8842 try string_bytes.ensureUnusedCapacity(gpa, total_bytes);
8843
8844 var current_token = start_token;
8845 while (current_token < end_token) : (current_token += 1) {
8846 switch (token_tags[current_token]) {
8847 .doc_comment => {
8848 const tok_bytes = astgen.tree.tokenSlice(current_token)[3..];
8849 string_bytes.appendSliceAssumeCapacity(tok_bytes);
8850 if (current_token != end_token - 1) {
8851 string_bytes.appendAssumeCapacity('\n');
8852 }
8853 },
8854 else => break,
8855 }
8856 }
8857
8858 const key = string_bytes.items[str_index..];
8859 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, @as([]const u8, key), StringIndexAdapter{
8860 .bytes = string_bytes,
8861 }, StringIndexContext{
8862 .bytes = string_bytes,
8863 });
8864
8865 if (gop.found_existing) {
8866 string_bytes.shrinkRetainingCapacity(str_index);
8867 return gop.key_ptr.*;
8868 } else {
8869 gop.key_ptr.* = str_index;
8870 try string_bytes.append(gpa, 0);
8871 return str_index;
8872 }
8873}
8874
8787const IndexSlice = struct { index: u32, len: u32 };8875const IndexSlice = struct { index: u32, len: u32 };
87888876
8789fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {8877fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
...@@ -9629,6 +9717,7 @@ const GenZir = struct {...@@ -9629,6 +9717,7 @@ const GenZir = struct {
9629 /// Absolute token index. This function does the conversion to Decl offset.9717 /// Absolute token index. This function does the conversion to Decl offset.
9630 abs_tok_index: Ast.TokenIndex,9718 abs_tok_index: Ast.TokenIndex,
9631 name: u32,9719 name: u32,
9720 first_doc_comment: ?Ast.TokenIndex,
9632 ) !Zir.Inst.Index {9721 ) !Zir.Inst.Index {
9633 const gpa = gz.astgen.gpa;9722 const gpa = gz.astgen.gpa;
9634 const param_body = param_gz.instructionsSlice();9723 const param_body = param_gz.instructionsSlice();
...@@ -9636,8 +9725,14 @@ const GenZir = struct {...@@ -9636,8 +9725,14 @@ const GenZir = struct {
9636 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len +9725 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len +
9637 param_body.len);9726 param_body.len);
96389727
9728 const doc_comment_index = if (first_doc_comment) |first|
9729 try gz.astgen.docCommentAsStringFromFirst(abs_tok_index, first)
9730 else
9731 0;
9732
9639 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{9733 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
9640 .name = name,9734 .name = name,
9735 .doc_comment = doc_comment_index,
9641 .body_len = @intCast(u32, param_body.len),9736 .body_len = @intCast(u32, param_body.len),
9642 });9737 });
9643 gz.astgen.extra.appendSliceAssumeCapacity(param_body);9738 gz.astgen.extra.appendSliceAssumeCapacity(param_body);
src/Module.zig+4-4
...@@ -558,14 +558,14 @@ pub const Decl = struct {...@@ -558,14 +558,14 @@ pub const Decl = struct {
558 if (!decl.has_align) return .none;558 if (!decl.has_align) return .none;
559 assert(decl.zir_decl_index != 0);559 assert(decl.zir_decl_index != 0);
560 const zir = decl.getFileScope().zir;560 const zir = decl.getFileScope().zir;
561 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 7]);561 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]);
562 }562 }
563563
564 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {564 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {
565 if (!decl.has_linksection_or_addrspace) return .none;565 if (!decl.has_linksection_or_addrspace) return .none;
566 assert(decl.zir_decl_index != 0);566 assert(decl.zir_decl_index != 0);
567 const zir = decl.getFileScope().zir;567 const zir = decl.getFileScope().zir;
568 const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align);568 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align);
569 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);569 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
570 }570 }
571571
...@@ -573,7 +573,7 @@ pub const Decl = struct {...@@ -573,7 +573,7 @@ pub const Decl = struct {
573 if (!decl.has_linksection_or_addrspace) return .none;573 if (!decl.has_linksection_or_addrspace) return .none;
574 assert(decl.zir_decl_index != 0);574 assert(decl.zir_decl_index != 0);
575 const zir = decl.getFileScope().zir;575 const zir = decl.getFileScope().zir;
576 const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align) + 1;576 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1;
577 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);577 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
578 }578 }
579579
...@@ -4011,7 +4011,7 @@ pub fn scanNamespace(...@@ -4011,7 +4011,7 @@ pub fn scanNamespace(
4011 cur_bit_bag >>= 4;4011 cur_bit_bag >>= 4;
40124012
4013 const decl_sub_index = extra_index;4013 const decl_sub_index = extra_index;
4014 extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1)4014 extra_index += 8; // src_hash(4) + line(1) + name(1) + value(1) + doc_comment(1)
4015 extra_index += @truncate(u1, flags >> 2); // Align4015 extra_index += @truncate(u1, flags >> 2); // Align
4016 extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs4016 extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs
40174017
src/Sema.zig+15-3
...@@ -1916,6 +1916,9 @@ fn zirEnumDecl(...@@ -1916,6 +1916,9 @@ fn zirEnumDecl(
1916 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[extra_index]);1916 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
1917 extra_index += 1;1917 extra_index += 1;
19181918
1919 // doc comment
1920 extra_index += 1;
1921
1919 // This string needs to outlive the ZIR code.1922 // This string needs to outlive the ZIR code.
1920 const field_name = try new_decl_arena_allocator.dupe(u8, field_name_zir);1923 const field_name = try new_decl_arena_allocator.dupe(u8, field_name_zir);
19211924
...@@ -2103,7 +2106,6 @@ fn zirErrorSetDecl(...@@ -2103,7 +2106,6 @@ fn zirErrorSetDecl(
2103 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;2106 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2104 const src = inst_data.src();2107 const src = inst_data.src();
2105 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);2108 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
2106 const fields = sema.code.extra[extra.end..][0..extra.data.fields_len];
21072109
2108 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);2110 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
2109 errdefer new_decl_arena.deinit();2111 errdefer new_decl_arena.deinit();
...@@ -2121,8 +2123,12 @@ fn zirErrorSetDecl(...@@ -2121,8 +2123,12 @@ fn zirErrorSetDecl(
2121 errdefer sema.mod.abortAnonDecl(new_decl);2123 errdefer sema.mod.abortAnonDecl(new_decl);
21222124
2123 var names = Module.ErrorSet.NameMap{};2125 var names = Module.ErrorSet.NameMap{};
2124 try names.ensureUnusedCapacity(new_decl_arena_allocator, fields.len);2126 try names.ensureUnusedCapacity(new_decl_arena_allocator, extra.data.fields_len);
2125 for (fields) |str_index| {2127
2128 var extra_index = @intCast(u32, extra.end);
2129 const extra_index_end = extra_index + (extra.data.fields_len * 2);
2130 while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
2131 const str_index = sema.code.extra[extra_index];
2126 const name = try new_decl_arena_allocator.dupe(u8, sema.code.nullTerminatedString(str_index));2132 const name = try new_decl_arena_allocator.dupe(u8, sema.code.nullTerminatedString(str_index));
21272133
2128 // TODO: This check should be performed in AstGen instead.2134 // TODO: This check should be performed in AstGen instead.
...@@ -16313,6 +16319,9 @@ fn semaStructFields(...@@ -16313,6 +16319,9 @@ fn semaStructFields(
16313 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);16319 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
16314 extra_index += 1;16320 extra_index += 1;
1631516321
16322 // doc_comment
16323 extra_index += 1;
16324
16316 // This string needs to outlive the ZIR code.16325 // This string needs to outlive the ZIR code.
16317 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);16326 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);
16318 const field_ty: Type = if (field_type_ref == .none)16327 const field_ty: Type = if (field_type_ref == .none)
...@@ -16502,6 +16511,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -16502,6 +16511,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
16502 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);16511 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
16503 extra_index += 1;16512 extra_index += 1;
1650416513
16514 // doc_comment
16515 extra_index += 1;
16516
16505 const field_type_ref: Zir.Inst.Ref = if (has_type) blk: {16517 const field_type_ref: Zir.Inst.Ref = if (has_type) blk: {
16506 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);16518 const field_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
16507 extra_index += 1;16519 extra_index += 1;
src/Zir.zig+15-2
...@@ -2571,6 +2571,7 @@ pub const Inst = struct {...@@ -2571,6 +2571,7 @@ pub const Inst = struct {
2571 /// - if there is a 0 byte at the position `name` indexes, it indicates2571 /// - if there is a 0 byte at the position `name` indexes, it indicates
2572 /// this is a test decl, and the name starts at `name+1`.2572 /// this is a test decl, and the name starts at `name+1`.
2573 /// value: Index,2573 /// value: Index,
2574 /// doc_comment: u32, // 0 if no doc comment
2574 /// align: Ref, // if corresponding bit is set2575 /// align: Ref, // if corresponding bit is set
2575 /// link_section_or_address_space: { // if corresponding bit is set.2576 /// link_section_or_address_space: { // if corresponding bit is set.
2576 /// link_section: Ref,2577 /// link_section: Ref,
...@@ -2588,6 +2589,7 @@ pub const Inst = struct {...@@ -2588,6 +2589,7 @@ pub const Inst = struct {
2588 /// field_name: u32,2589 /// field_name: u32,
2589 /// field_type: Ref,2590 /// field_type: Ref,
2590 /// - if none, means `anytype`.2591 /// - if none, means `anytype`.
2592 /// doc_comment: u32, // 0 if no doc comment
2591 /// align: Ref, // if corresponding bit is set2593 /// align: Ref, // if corresponding bit is set
2592 /// default_value: Ref, // if corresponding bit is set2594 /// default_value: Ref, // if corresponding bit is set
2593 /// }2595 /// }
...@@ -2638,6 +2640,7 @@ pub const Inst = struct {...@@ -2638,6 +2640,7 @@ pub const Inst = struct {
2638 /// - if there is a 0 byte at the position `name` indexes, it indicates2640 /// - if there is a 0 byte at the position `name` indexes, it indicates
2639 /// this is a test decl, and the name starts at `name+1`.2641 /// this is a test decl, and the name starts at `name+1`.
2640 /// value: Index,2642 /// value: Index,
2643 /// doc_comment: u32, // 0 if no doc_comment
2641 /// align: Ref, // if corresponding bit is set2644 /// align: Ref, // if corresponding bit is set
2642 /// link_section_or_address_space: { // if corresponding bit is set.2645 /// link_section_or_address_space: { // if corresponding bit is set.
2643 /// link_section: Ref,2646 /// link_section: Ref,
...@@ -2649,6 +2652,7 @@ pub const Inst = struct {...@@ -2649,6 +2652,7 @@ pub const Inst = struct {
2649 /// - the bit is whether corresponding field has an value expression2652 /// - the bit is whether corresponding field has an value expression
2650 /// 9. fields: { // for every fields_len2653 /// 9. fields: { // for every fields_len
2651 /// field_name: u32,2654 /// field_name: u32,
2655 /// doc_comment: u32, // 0 if no doc_comment
2652 /// value: Ref, // if corresponding bit is set2656 /// value: Ref, // if corresponding bit is set
2653 /// }2657 /// }
2654 pub const EnumDecl = struct {2658 pub const EnumDecl = struct {
...@@ -2686,6 +2690,7 @@ pub const Inst = struct {...@@ -2686,6 +2690,7 @@ pub const Inst = struct {
2686 /// - if there is a 0 byte at the position `name` indexes, it indicates2690 /// - if there is a 0 byte at the position `name` indexes, it indicates
2687 /// this is a test decl, and the name starts at `name+1`.2691 /// this is a test decl, and the name starts at `name+1`.
2688 /// value: Index,2692 /// value: Index,
2693 /// doc_comment: u32, // 0 if no doc comment
2689 /// align: Ref, // if corresponding bit is set2694 /// align: Ref, // if corresponding bit is set
2690 /// link_section_or_address_space: { // if corresponding bit is set.2695 /// link_section_or_address_space: { // if corresponding bit is set.
2691 /// link_section: Ref,2696 /// link_section: Ref,
...@@ -2701,6 +2706,7 @@ pub const Inst = struct {...@@ -2701,6 +2706,7 @@ pub const Inst = struct {
2701 /// 0bX000: unused2706 /// 0bX000: unused
2702 /// 9. fields: { // for every fields_len2707 /// 9. fields: { // for every fields_len
2703 /// field_name: u32, // null terminated string index2708 /// field_name: u32, // null terminated string index
2709 /// doc_comment: u32, // 0 if no doc comment
2704 /// field_type: Ref, // if corresponding bit is set2710 /// field_type: Ref, // if corresponding bit is set
2705 /// - if none, means `anytype`.2711 /// - if none, means `anytype`.
2706 /// align: Ref, // if corresponding bit is set2712 /// align: Ref, // if corresponding bit is set
...@@ -2745,6 +2751,7 @@ pub const Inst = struct {...@@ -2745,6 +2751,7 @@ pub const Inst = struct {
2745 /// - if there is a 0 byte at the position `name` indexes, it indicates2751 /// - if there is a 0 byte at the position `name` indexes, it indicates
2746 /// this is a test decl, and the name starts at `name+1`.2752 /// this is a test decl, and the name starts at `name+1`.
2747 /// value: Index,2753 /// value: Index,
2754 /// doc_comment: u32, // 0 if no doc comment,
2748 /// align: Ref, // if corresponding bit is set2755 /// align: Ref, // if corresponding bit is set
2749 /// link_section_or_address_space: { // if corresponding bit is set.2756 /// link_section_or_address_space: { // if corresponding bit is set.
2750 /// link_section: Ref,2757 /// link_section: Ref,
...@@ -2760,7 +2767,11 @@ pub const Inst = struct {...@@ -2760,7 +2767,11 @@ pub const Inst = struct {
2760 };2767 };
2761 };2768 };
27622769
2763 /// Trailing: field_name: u32 // for every field: null terminated string index2770 /// Trailing:
2771 /// { // for every fields_len
2772 /// field_name: u32 // null terminated string index
2773 /// doc_comment: u32 // null terminated string index
2774 /// }
2764 pub const ErrorSetDecl = struct {2775 pub const ErrorSetDecl = struct {
2765 fields_len: u32,2776 fields_len: u32,
2766 };2777 };
...@@ -2899,6 +2910,8 @@ pub const Inst = struct {...@@ -2899,6 +2910,8 @@ pub const Inst = struct {
2899 pub const Param = struct {2910 pub const Param = struct {
2900 /// Null-terminated string index.2911 /// Null-terminated string index.
2901 name: u32,2912 name: u32,
2913 /// 0 if no doc comment
2914 doc_comment: u32,
2902 /// The body contains the type of the parameter.2915 /// The body contains the type of the parameter.
2903 body_len: u32,2916 body_len: u32,
2904 };2917 };
...@@ -3001,7 +3014,7 @@ pub const DeclIterator = struct {...@@ -3001,7 +3014,7 @@ pub const DeclIterator = struct {
3001 const sub_index = @intCast(u32, it.extra_index);3014 const sub_index = @intCast(u32, it.extra_index);
3002 it.extra_index += 5; // src_hash(4) + line(1)3015 it.extra_index += 5; // src_hash(4) + line(1)
3003 const name = it.zir.nullTerminatedString(it.zir.extra[it.extra_index]);3016 const name = it.zir.nullTerminatedString(it.zir.extra[it.extra_index]);
3004 it.extra_index += 2; // name(1) + value(1)3017 it.extra_index += 3; // name(1) + value(1) + doc_comment(1)
3005 it.extra_index += @truncate(u1, flags >> 2);3018 it.extra_index += @truncate(u1, flags >> 2);
3006 it.extra_index += @truncate(u1, flags >> 3);3019 it.extra_index += @truncate(u1, flags >> 3);
30073020
src/print_zir.zig+47-3
...@@ -785,6 +785,12 @@ const Writer = struct {...@@ -785,6 +785,12 @@ const Writer = struct {
785 try stream.print("\"{}\", ", .{785 try stream.print("\"{}\", ", .{
786 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),786 std.zig.fmtEscapes(self.code.nullTerminatedString(extra.data.name)),
787 });787 });
788
789 if (extra.data.doc_comment != 0) {
790 try stream.writeAll("\n");
791 try self.writeDocComment(stream, extra.data.doc_comment);
792 try stream.writeByteNTimes(' ', self.indent);
793 }
788 try self.writeBracedBody(stream, body);794 try self.writeBracedBody(stream, body);
789 try stream.writeAll(") ");795 try stream.writeAll(") ");
790 try self.writeSrc(stream, inst_data.src());796 try self.writeSrc(stream, inst_data.src());
...@@ -1207,6 +1213,10 @@ const Writer = struct {...@@ -1207,6 +1213,10 @@ const Writer = struct {
1207 extra_index += 1;1213 extra_index += 1;
1208 const field_type = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1214 const field_type = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1209 extra_index += 1;1215 extra_index += 1;
1216 const doc_comment_index = self.code.extra[extra_index];
1217 extra_index += 1;
1218
1219 try self.writeDocComment(stream, doc_comment_index);
12101220
1211 try stream.writeByteNTimes(' ', self.indent);1221 try stream.writeByteNTimes(' ', self.indent);
1212 try self.writeFlag(stream, "comptime ", is_comptime);1222 try self.writeFlag(stream, "comptime ", is_comptime);
...@@ -1332,6 +1342,10 @@ const Writer = struct {...@@ -1332,6 +1342,10 @@ const Writer = struct {
13321342
1333 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);1343 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1334 extra_index += 1;1344 extra_index += 1;
1345 const doc_comment_index = self.code.extra[extra_index];
1346 extra_index += 1;
1347
1348 try self.writeDocComment(stream, doc_comment_index);
1335 try stream.writeByteNTimes(' ', self.indent);1349 try stream.writeByteNTimes(' ', self.indent);
1336 try stream.print("{}", .{std.zig.fmtId(field_name)});1350 try stream.print("{}", .{std.zig.fmtId(field_name)});
13371351
...@@ -1398,6 +1412,9 @@ const Writer = struct {...@@ -1398,6 +1412,9 @@ const Writer = struct {
1398 extra_index += 1;1412 extra_index += 1;
1399 const decl_index = self.code.extra[extra_index];1413 const decl_index = self.code.extra[extra_index];
1400 extra_index += 1;1414 extra_index += 1;
1415 const doc_comment_index = self.code.extra[extra_index];
1416 extra_index += 1;
1417
1401 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {1418 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
1402 const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1419 const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1403 extra_index += 1;1420 extra_index += 1;
...@@ -1416,12 +1433,13 @@ const Writer = struct {...@@ -1416,12 +1433,13 @@ const Writer = struct {
14161433
1417 const pub_str = if (is_pub) "pub " else "";1434 const pub_str = if (is_pub) "pub " else "";
1418 const hash_bytes = @bitCast([16]u8, hash_u32s.*);1435 const hash_bytes = @bitCast([16]u8, hash_u32s.*);
1419 try stream.writeByteNTimes(' ', self.indent);
1420 if (decl_name_index == 0) {1436 if (decl_name_index == 0) {
1437 try stream.writeByteNTimes(' ', self.indent);
1421 const name = if (is_exported) "usingnamespace" else "comptime";1438 const name = if (is_exported) "usingnamespace" else "comptime";
1422 try stream.writeAll(pub_str);1439 try stream.writeAll(pub_str);
1423 try stream.writeAll(name);1440 try stream.writeAll(name);
1424 } else if (decl_name_index == 1) {1441 } else if (decl_name_index == 1) {
1442 try stream.writeByteNTimes(' ', self.indent);
1425 try stream.writeAll("test");1443 try stream.writeAll("test");
1426 } else {1444 } else {
1427 const raw_decl_name = self.code.nullTerminatedString(decl_name_index);1445 const raw_decl_name = self.code.nullTerminatedString(decl_name_index);
...@@ -1431,6 +1449,10 @@ const Writer = struct {...@@ -1431,6 +1449,10 @@ const Writer = struct {
1431 raw_decl_name;1449 raw_decl_name;
1432 const test_str = if (raw_decl_name.len == 0) "test " else "";1450 const test_str = if (raw_decl_name.len == 0) "test " else "";
1433 const export_str = if (is_exported) "export " else "";1451 const export_str = if (is_exported) "export " else "";
1452
1453 try self.writeDocComment(stream, doc_comment_index);
1454
1455 try stream.writeByteNTimes(' ', self.indent);
1434 try stream.print("[{d}] {s}{s}{s}{}", .{1456 try stream.print("[{d}] {s}{s}{s}{}", .{
1435 sub_index, pub_str, test_str, export_str, std.zig.fmtId(decl_name),1457 sub_index, pub_str, test_str, export_str, std.zig.fmtId(decl_name),
1436 });1458 });
...@@ -1556,6 +1578,11 @@ const Writer = struct {...@@ -1556,6 +1578,11 @@ const Writer = struct {
1556 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);1578 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1557 extra_index += 1;1579 extra_index += 1;
15581580
1581 const doc_comment_index = self.code.extra[extra_index];
1582 extra_index += 1;
1583
1584 try self.writeDocComment(stream, doc_comment_index);
1585
1559 try stream.writeByteNTimes(' ', self.indent);1586 try stream.writeByteNTimes(' ', self.indent);
1560 try stream.print("{}", .{std.zig.fmtId(field_name)});1587 try stream.print("{}", .{std.zig.fmtId(field_name)});
15611588
...@@ -1619,17 +1646,23 @@ const Writer = struct {...@@ -1619,17 +1646,23 @@ const Writer = struct {
1619 ) !void {1646 ) !void {
1620 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1647 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1621 const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);1648 const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
1622 const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
16231649
1624 try stream.print("{s}, ", .{@tagName(name_strategy)});1650 try stream.print("{s}, ", .{@tagName(name_strategy)});
16251651
1626 try stream.writeAll("{\n");1652 try stream.writeAll("{\n");
1627 self.indent += 2;1653 self.indent += 2;
1628 for (fields) |str_index| {1654
1655 var extra_index = @intCast(u32, extra.end);
1656 const extra_index_end = extra_index + (extra.data.fields_len * 2);
1657 while (extra_index < extra_index_end) : (extra_index += 2) {
1658 const str_index = self.code.extra[extra_index];
1629 const name = self.code.nullTerminatedString(str_index);1659 const name = self.code.nullTerminatedString(str_index);
1660 const doc_comment_index = self.code.extra[extra_index + 1];
1661 try self.writeDocComment(stream, doc_comment_index);
1630 try stream.writeByteNTimes(' ', self.indent);1662 try stream.writeByteNTimes(' ', self.indent);
1631 try stream.print("{},\n", .{std.zig.fmtId(name)});1663 try stream.print("{},\n", .{std.zig.fmtId(name)});
1632 }1664 }
1665
1633 self.indent -= 2;1666 self.indent -= 2;
1634 try stream.writeByteNTimes(' ', self.indent);1667 try stream.writeByteNTimes(' ', self.indent);
1635 try stream.writeAll("}) ");1668 try stream.writeAll("}) ");
...@@ -2121,6 +2154,17 @@ const Writer = struct {...@@ -2121,6 +2154,17 @@ const Writer = struct {
2121 }2154 }
2122 }2155 }
21232156
2157 fn writeDocComment(self: *Writer, stream: anytype, doc_comment_index: u32) !void {
2158 if (doc_comment_index != 0) {
2159 const doc_comment = self.code.nullTerminatedString(doc_comment_index);
2160 var it = std.mem.tokenize(u8, doc_comment, "\n");
2161 while (it.next()) |doc_line| {
2162 try stream.writeByteNTimes(' ', self.indent);
2163 try stream.print("///{s}\n", .{doc_line});
2164 }
2165 }
2166 }
2167
2124 fn writeBody(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void {2168 fn writeBody(self: *Writer, stream: anytype, body: []const Zir.Inst.Index) !void {
2125 for (body) |inst| {2169 for (body) |inst| {
2126 try stream.writeByteNTimes(' ', self.indent);2170 try stream.writeByteNTimes(' ', self.indent);
test/behavior/cast_llvm.zig+3-1
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1const builtin = @import("builtin");
1const std = @import("std");2const std = @import("std");
2const expect = std.testing.expect;3const expect = std.testing.expect;
3const mem = std.mem;4const mem = std.mem;
4const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
5const native_endian = @import("builtin").target.cpu.arch.endian();6const native_endian = builtin.target.cpu.arch.endian();
67
7test "pointer reinterpret const float to int" {8test "pointer reinterpret const float to int" {
8 // The hex representation is 0x3fe3333333333303.9 // The hex representation is 0x3fe3333333333303.
...@@ -46,6 +47,7 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {...@@ -46,6 +47,7 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {
46}47}
4748
48test "compile time int to ptr of function" {49test "compile time int to ptr of function" {
50 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO
49 try foobar(FUNCTION_CONSTANT);51 try foobar(FUNCTION_CONSTANT);
50}52}
5153
test/behavior/inttoptr.zig+3
...@@ -1,4 +1,7 @@...@@ -1,4 +1,7 @@
1const builtin = @import("builtin");
2
1test "casting random address to function pointer" {3test "casting random address to function pointer" {
4 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO
2 randomAddressToFunction();5 randomAddressToFunction();
3 comptime randomAddressToFunction();6 comptime randomAddressToFunction();
4}7}