authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-17 00:41:01+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-23 21:09:17+00:00
log18362ebe13ece2ea7c4f57303ec4687f55d2dba5
tree22eeda854078b1201eaf10d64bdfba19f916318d
parentaf5e731729592af4a5716edd3b1e03264d66ea46
signature Commit is signed but in an unrecognized format.

Zir: refactor `declaration` instruction representation

The new representation is often more compact. It is also more straightforward to understand: for instance, `extern` is represented on the `declaration` instruction itself rather than using a special instruction. The same applies to `var`, making both of these far more compact. This commit also separates the type and value bodies of a `declaration` instruction. This is a prerequisite for #131. In general, `declaration` now directly encodes details of the syntax form used, and the embedded ZIR bodies are for actual expressions. The only exception to this is functions, where ZIR is effectively designed as if we had #1717. `extern fn` declarations are modeled as `extern const` with a function type, and normal `fn` definitions are modeled as `const` with a `func{,_fancy,_inferred}` instruction. This may change in the future, but improving on this was out of scope for this commit.

14 files changed, 1248 insertions(+), 1119 deletions(-)

lib/std/zig/AstGen.zig+582-536
......@@ -106,7 +106,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
106106 Zir.Inst.SwitchBlock.Bits,
107107 Zir.Inst.SwitchBlockErrUnion.Bits,
108108 Zir.Inst.FuncFancy.Bits,
109 Zir.Inst.Declaration.Flags,
110109 => @bitCast(@field(extra, field.name)),
111110
112111 else => @compileError("bad field type"),
......@@ -1317,12 +1316,45 @@ fn fnProtoExpr(
13171316 return astgen.failTok(some, "function type cannot have a name", .{});
13181317 }
13191318
1319 if (fn_proto.ast.align_expr != 0) {
1320 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
1321 }
1322
1323 if (fn_proto.ast.addrspace_expr != 0) {
1324 return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});
1325 }
1326
1327 if (fn_proto.ast.section_expr != 0) {
1328 return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});
1329 }
1330
1331 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1332 const is_inferred_error = token_tags[maybe_bang] == .bang;
1333 if (is_inferred_error) {
1334 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
1335 }
1336
13201337 const is_extern = blk: {
13211338 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
13221339 break :blk token_tags[maybe_extern_token] == .keyword_extern;
13231340 };
13241341 assert(!is_extern);
13251342
1343 return fnProtoExprInner(gz, scope, ri, node, fn_proto, false);
1344}
1345
1346fn fnProtoExprInner(
1347 gz: *GenZir,
1348 scope: *Scope,
1349 ri: ResultInfo,
1350 node: Ast.Node.Index,
1351 fn_proto: Ast.full.FnProto,
1352 implicit_ccc: bool,
1353) InnerError!Zir.Inst.Ref {
1354 const astgen = gz.astgen;
1355 const tree = astgen.tree;
1356 const token_tags = tree.tokens.items(.tag);
1357
13261358 var block_scope = gz.makeSubBlock(scope);
13271359 defer block_scope.unstack();
13281360
......@@ -1386,18 +1418,6 @@ fn fnProtoExpr(
13861418 break :is_var_args false;
13871419 };
13881420
1389 if (fn_proto.ast.align_expr != 0) {
1390 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
1391 }
1392
1393 if (fn_proto.ast.addrspace_expr != 0) {
1394 return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});
1395 }
1396
1397 if (fn_proto.ast.section_expr != 0) {
1398 return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});
1399 }
1400
14011421 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
14021422 try expr(
14031423 &block_scope,
......@@ -1405,14 +1425,11 @@ fn fnProtoExpr(
14051425 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
14061426 fn_proto.ast.callconv_expr,
14071427 )
1428 else if (implicit_ccc)
1429 try block_scope.addBuiltinValue(node, .calling_convention_c)
14081430 else
1409 Zir.Inst.Ref.none;
1431 .none;
14101432
1411 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1412 const is_inferred_error = token_tags[maybe_bang] == .bang;
1413 if (is_inferred_error) {
1414 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
1415 }
14161433 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
14171434
14181435 const result = try block_scope.addFunc(.{
......@@ -1428,11 +1445,8 @@ fn fnProtoExpr(
14281445
14291446 .param_block = block_inst,
14301447 .body_gz = null,
1431 .lib_name = .empty,
14321448 .is_var_args = is_var_args,
14331449 .is_inferred_error = false,
1434 .is_test = false,
1435 .is_extern = false,
14361450 .is_noinline = false,
14371451 .noalias_bits = noalias_bits,
14381452
......@@ -4121,17 +4135,6 @@ fn fnDecl(
41214135
41224136 const saved_cursor = astgen.saveSourceCursor();
41234137
4124 var decl_gz: GenZir = .{
4125 .is_comptime = true,
4126 .decl_node_index = fn_proto.ast.proto_node,
4127 .decl_line = astgen.source_line,
4128 .parent = scope,
4129 .astgen = astgen,
4130 .instructions = gz.instructions,
4131 .instructions_top = gz.instructions.items.len,
4132 };
4133 defer decl_gz.unstack();
4134
41354138 const decl_column = astgen.source_column;
41364139
41374140 // Set this now, since parameter types, return type, etc may be generic.
......@@ -4152,12 +4155,140 @@ fn fnDecl(
41524155 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
41534156 break :blk token_tags[maybe_inline_token] == .keyword_inline;
41544157 };
4158 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
4159 const lib_name_str = try astgen.strLitAsString(lib_name_token);
4160 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
4161 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
4162 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
4163 } else if (lib_name_str.len == 0) {
4164 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
4165 }
4166 break :blk lib_name_str.index;
4167 } else .empty;
4168 if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) {
4169 return astgen.failNode(
4170 fn_proto.ast.callconv_expr,
4171 "explicit callconv incompatible with inline keyword",
4172 .{},
4173 );
4174 }
4175 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4176 const is_inferred_error = token_tags[maybe_bang] == .bang;
4177 if (body_node == 0) {
4178 if (!is_extern) {
4179 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
4180 }
4181 if (is_inferred_error) {
4182 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
4183 }
4184 } else {
4185 assert(!is_extern); // validated by parser (TODO why???)
4186 }
4187
4188 wip_members.nextDecl(decl_inst);
4189
4190 var type_gz: GenZir = .{
4191 .is_comptime = true,
4192 .decl_node_index = fn_proto.ast.proto_node,
4193 .decl_line = astgen.source_line,
4194 .parent = scope,
4195 .astgen = astgen,
4196 .instructions = gz.instructions,
4197 .instructions_top = gz.instructions.items.len,
4198 };
4199 defer type_gz.unstack();
4200
4201 if (is_extern) {
4202 // We include a function *type*, not a value.
4203 const type_inst = try fnProtoExprInner(&type_gz, &type_gz.base, .{ .rl = .none }, decl_node, fn_proto, true);
4204 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, decl_node);
4205 }
4206
4207 var align_gz = type_gz.makeSubBlock(scope);
4208 defer align_gz.unstack();
4209
4210 if (fn_proto.ast.align_expr != 0) {
4211 astgen.restoreSourceCursor(saved_cursor);
4212 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr);
4213 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4214 }
4215
4216 var linksection_gz = align_gz.makeSubBlock(scope);
4217 defer linksection_gz.unstack();
4218
4219 if (fn_proto.ast.section_expr != 0) {
4220 astgen.restoreSourceCursor(saved_cursor);
4221 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr);
4222 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4223 }
4224
4225 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4226 defer addrspace_gz.unstack();
4227
4228 if (fn_proto.ast.addrspace_expr != 0) {
4229 astgen.restoreSourceCursor(saved_cursor);
4230 const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space);
4231 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.section_expr);
4232 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4233 }
4234
4235 var value_gz = addrspace_gz.makeSubBlock(scope);
4236 defer value_gz.unstack();
4237
4238 if (!is_extern) {
4239 // We include a function *value*, not a type.
4240 astgen.restoreSourceCursor(saved_cursor);
4241 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto);
4242 }
4243
4244 // *Now* we can incorporate the full source code into the hasher.
4245 astgen.src_hasher.update(tree.getNodeSource(decl_node));
4246
4247 var hash: std.zig.SrcHash = undefined;
4248 astgen.src_hasher.final(&hash);
4249 try setDeclaration(decl_inst, .{
4250 .src_hash = hash,
4251 .src_line = type_gz.decl_line,
4252 .src_column = decl_column,
4253
4254 .kind = .@"const",
4255 .name = try astgen.identAsString(fn_name_token),
4256 .is_pub = is_pub,
4257 .is_threadlocal = false,
4258 .linkage = if (is_extern) .@"extern" else if (is_export) .@"export" else .normal,
4259 .lib_name = lib_name,
4260
4261 .type_gz = &type_gz,
4262 .align_gz = &align_gz,
4263 .linksection_gz = &linksection_gz,
4264 .addrspace_gz = &addrspace_gz,
4265 .value_gz = &value_gz,
4266 });
4267}
4268
4269fn fnDeclInner(
4270 astgen: *AstGen,
4271 decl_gz: *GenZir,
4272 scope: *Scope,
4273 saved_cursor: SourceCursor,
4274 decl_inst: Zir.Inst.Index,
4275 decl_node: Ast.Node.Index,
4276 body_node: Ast.Node.Index,
4277 fn_proto: Ast.full.FnProto,
4278) InnerError!void {
4279 const tree = astgen.tree;
4280 const token_tags = tree.tokens.items(.tag);
4281
41554282 const is_noinline = blk: {
41564283 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
41574284 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
41584285 };
4159
4160 wip_members.nextDecl(decl_inst);
4286 const has_inline_keyword = blk: {
4287 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4288 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4289 };
4290 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4291 const is_inferred_error = token_tags[maybe_bang] == .bang;
41614292
41624293 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
41634294 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
......@@ -4192,11 +4323,9 @@ fn fnDecl(
41924323 break :blk .empty;
41934324
41944325 const param_name = try astgen.identAsString(name_token);
4195 if (!is_extern) {
4196 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
4197 }
4326 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
41984327 break :blk param_name;
4199 } else if (!is_extern) {
4328 } else {
42004329 if (param.anytype_ellipsis3) |tok| {
42014330 return astgen.failTok(tok, "missing parameter name", .{});
42024331 } else {
......@@ -4225,7 +4354,7 @@ fn fnDecl(
42254354 }
42264355 return astgen.failNode(param.type_expr, "missing parameter name", .{});
42274356 }
4228 } else .empty;
4357 };
42294358
42304359 const param_inst = if (is_anytype) param: {
42314360 const name_token = param.name_token orelse param.anytype_ellipsis3.?;
......@@ -4251,12 +4380,12 @@ fn fnDecl(
42514380 break :param param_inst.toRef();
42524381 };
42534382
4254 if (param_name == .empty or is_extern) continue;
4383 if (param_name == .empty) continue;
42554384
42564385 const sub_scope = try astgen.arena.create(Scope.LocalVal);
42574386 sub_scope.* = .{
42584387 .parent = params_scope,
4259 .gen_zir = &decl_gz,
4388 .gen_zir = decl_gz,
42604389 .name = param_name,
42614390 .inst = param_inst,
42624391 .token_src = param.name_token.?,
......@@ -4268,23 +4397,9 @@ fn fnDecl(
42684397 break :is_var_args false;
42694398 };
42704399
4271 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
4272 const lib_name_str = try astgen.strLitAsString(lib_name_token);
4273 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
4274 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
4275 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
4276 } else if (lib_name_str.len == 0) {
4277 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
4278 }
4279 break :blk lib_name_str.index;
4280 } else .empty;
4281
4282 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4283 const is_inferred_error = token_tags[maybe_bang] == .bang;
4284
42854400 // After creating the function ZIR instruction, it will need to update the break
4286 // instructions inside the expression blocks for align, addrspace, cc, and ret_ty
4287 // to use the function instruction as the "block" to break from.
4401 // instructions inside the expression blocks for cc and ret_ty to use the function
4402 // instruction as the body to break from.
42884403
42894404 var ret_gz = decl_gz.makeSubBlock(params_scope);
42904405 defer ret_gz.unstack();
......@@ -4309,13 +4424,6 @@ fn fnDecl(
43094424 defer cc_gz.unstack();
43104425 const cc_ref: Zir.Inst.Ref = blk: {
43114426 if (fn_proto.ast.callconv_expr != 0) {
4312 if (has_inline_keyword) {
4313 return astgen.failNode(
4314 fn_proto.ast.callconv_expr,
4315 "explicit callconv incompatible with inline keyword",
4316 .{},
4317 );
4318 }
43194427 const inst = try expr(
43204428 &cc_gz,
43214429 scope,
......@@ -4328,10 +4436,6 @@ fn fnDecl(
43284436 }
43294437 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);
43304438 break :blk inst;
4331 } else if (is_extern) {
4332 const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_c);
4333 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);
4334 break :blk inst;
43354439 } else if (has_inline_keyword) {
43364440 const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_inline);
43374441 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);
......@@ -4341,167 +4445,86 @@ fn fnDecl(
43414445 }
43424446 };
43434447
4344 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
4345 if (!is_extern) {
4346 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
4347 }
4348 if (is_inferred_error) {
4349 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
4350 }
4351 break :func try decl_gz.addFunc(.{
4352 .src_node = decl_node,
4353 .cc_ref = cc_ref,
4354 .cc_gz = &cc_gz,
4355 .ret_ref = ret_ref,
4356 .ret_gz = &ret_gz,
4357 .ret_param_refs = ret_body_param_refs,
4358 .param_block = decl_inst,
4359 .param_insts = param_insts.items,
4360 .body_gz = null,
4361 .lib_name = lib_name,
4362 .is_var_args = is_var_args,
4363 .is_inferred_error = false,
4364 .is_test = false,
4365 .is_extern = true,
4366 .is_noinline = is_noinline,
4367 .noalias_bits = noalias_bits,
4368 .proto_hash = undefined, // ignored for `body_gz == null`
4369 });
4370 } else func: {
4371 var body_gz: GenZir = .{
4372 .is_comptime = false,
4373 .decl_node_index = fn_proto.ast.proto_node,
4374 .decl_line = decl_gz.decl_line,
4375 .parent = params_scope,
4376 .astgen = astgen,
4377 .instructions = gz.instructions,
4378 .instructions_top = gz.instructions.items.len,
4379 };
4380 defer body_gz.unstack();
4381
4382 // We want `params_scope` to be stacked like this:
4383 // body_gz (top)
4384 // param2
4385 // param1
4386 // param0
4387 // decl_gz (bottom)
4388
4389 // Construct the prototype hash.
4390 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
4391 // the *whole* function declaration, including its body.
4392 var proto_hasher = astgen.src_hasher;
4393 const proto_node = tree.nodes.items(.data)[decl_node].lhs;
4394 proto_hasher.update(tree.getNodeSource(proto_node));
4395 var proto_hash: std.zig.SrcHash = undefined;
4396 proto_hasher.final(&proto_hash);
4397
4398 const prev_fn_block = astgen.fn_block;
4399 const prev_fn_ret_ty = astgen.fn_ret_ty;
4400 defer {
4401 astgen.fn_block = prev_fn_block;
4402 astgen.fn_ret_ty = prev_fn_ret_ty;
4403 }
4404 astgen.fn_block = &body_gz;
4405 astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: {
4406 // We're essentially guaranteed to need the return type at some point,
4407 // since the return type is likely not `void` or `noreturn` so there
4408 // will probably be an explicit return requiring RLS. Fetch this
4409 // return type now so the rest of the function can use it.
4410 break :r try body_gz.addNode(.ret_type, decl_node);
4411 } else ret_ref;
4412
4413 const prev_var_args = astgen.fn_var_args;
4414 astgen.fn_var_args = is_var_args;
4415 defer astgen.fn_var_args = prev_var_args;
4416
4417 astgen.advanceSourceCursorToNode(body_node);
4418 const lbrace_line = astgen.source_line - decl_gz.decl_line;
4419 const lbrace_column = astgen.source_column;
4420
4421 _ = try fullBodyExpr(&body_gz, &body_gz.base, .{ .rl = .none }, body_node, .allow_branch_hint);
4422 try checkUsed(gz, scope, params_scope);
4423
4424 if (!body_gz.endsWithNoReturn()) {
4425 // As our last action before the return, "pop" the error trace if needed
4426 _ = try body_gz.addRestoreErrRetIndex(.ret, .always, decl_node);
4427
4428 // Add implicit return at end of function.
4429 _ = try body_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
4430 }
4431
4432 break :func try decl_gz.addFunc(.{
4433 .src_node = decl_node,
4434 .cc_ref = cc_ref,
4435 .cc_gz = &cc_gz,
4436 .ret_ref = ret_ref,
4437 .ret_gz = &ret_gz,
4438 .ret_param_refs = ret_body_param_refs,
4439 .lbrace_line = lbrace_line,
4440 .lbrace_column = lbrace_column,
4441 .param_block = decl_inst,
4442 .param_insts = param_insts.items,
4443 .body_gz = &body_gz,
4444 .lib_name = lib_name,
4445 .is_var_args = is_var_args,
4446 .is_inferred_error = is_inferred_error,
4447 .is_test = false,
4448 .is_extern = false,
4449 .is_noinline = is_noinline,
4450 .noalias_bits = noalias_bits,
4451 .proto_hash = proto_hash,
4452 });
4448 var body_gz: GenZir = .{
4449 .is_comptime = false,
4450 .decl_node_index = fn_proto.ast.proto_node,
4451 .decl_line = decl_gz.decl_line,
4452 .parent = params_scope,
4453 .astgen = astgen,
4454 .instructions = decl_gz.instructions,
4455 .instructions_top = decl_gz.instructions.items.len,
44534456 };
4457 defer body_gz.unstack();
4458
4459 // The scope stack looks like this:
4460 // body_gz (top)
4461 // param2
4462 // param1
4463 // param0
4464 // decl_gz (bottom)
4465
4466 // Construct the prototype hash.
4467 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
4468 // the *whole* function declaration, including its body.
4469 var proto_hasher = astgen.src_hasher;
4470 const proto_node = tree.nodes.items(.data)[decl_node].lhs;
4471 proto_hasher.update(tree.getNodeSource(proto_node));
4472 var proto_hash: std.zig.SrcHash = undefined;
4473 proto_hasher.final(&proto_hash);
44544474
4455 // Before we stack more stuff onto `decl_gz`, add its final instruction.
4456 _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst);
4475 const prev_fn_block = astgen.fn_block;
4476 const prev_fn_ret_ty = astgen.fn_ret_ty;
4477 defer {
4478 astgen.fn_block = prev_fn_block;
4479 astgen.fn_ret_ty = prev_fn_ret_ty;
4480 }
4481 astgen.fn_block = &body_gz;
4482 astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: {
4483 // We're essentially guaranteed to need the return type at some point,
4484 // since the return type is likely not `void` or `noreturn` so there
4485 // will probably be an explicit return requiring RLS. Fetch this
4486 // return type now so the rest of the function can use it.
4487 break :r try body_gz.addNode(.ret_type, decl_node);
4488 } else ret_ref;
44574489
4458 // Now that `cc_gz,` `ret_gz`, and `body_gz` are unstacked, we evaluate align, addrspace, and linksection.
4490 const prev_var_args = astgen.fn_var_args;
4491 astgen.fn_var_args = is_var_args;
4492 defer astgen.fn_var_args = prev_var_args;
44594493
4460 // We're jumping back in source, so restore the cursor.
4461 astgen.restoreSourceCursor(saved_cursor);
4494 astgen.advanceSourceCursorToNode(body_node);
4495 const lbrace_line = astgen.source_line - decl_gz.decl_line;
4496 const lbrace_column = astgen.source_column;
44624497
4463 var align_gz = decl_gz.makeSubBlock(scope);
4464 defer align_gz.unstack();
4465 if (fn_proto.ast.align_expr != 0) {
4466 const inst = try expr(&decl_gz, &decl_gz.base, coerced_align_ri, fn_proto.ast.align_expr);
4467 _ = try align_gz.addBreak(.break_inline, decl_inst, inst);
4468 }
4498 _ = try fullBodyExpr(&body_gz, &body_gz.base, .{ .rl = .none }, body_node, .allow_branch_hint);
4499 try checkUsed(decl_gz, scope, params_scope);
44694500
4470 var section_gz = align_gz.makeSubBlock(scope);
4471 defer section_gz.unstack();
4472 if (fn_proto.ast.section_expr != 0) {
4473 const inst = try expr(&decl_gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, fn_proto.ast.section_expr);
4474 _ = try section_gz.addBreak(.break_inline, decl_inst, inst);
4475 }
4501 if (!body_gz.endsWithNoReturn()) {
4502 // As our last action before the return, "pop" the error trace if needed
4503 _ = try body_gz.addRestoreErrRetIndex(.ret, .always, decl_node);
44764504
4477 var addrspace_gz = section_gz.makeSubBlock(scope);
4478 defer addrspace_gz.unstack();
4479 if (fn_proto.ast.addrspace_expr != 0) {
4480 const addrspace_ty = try decl_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space);
4481 const inst = try expr(&decl_gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr);
4482 _ = try addrspace_gz.addBreak(.break_inline, decl_inst, inst);
4505 // Add implicit return at end of function.
4506 _ = try body_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
44834507 }
44844508
4485 // *Now* we can incorporate the full source code into the hasher.
4486 astgen.src_hasher.update(tree.getNodeSource(decl_node));
4487
4488 var hash: std.zig.SrcHash = undefined;
4489 astgen.src_hasher.final(&hash);
4490 try setDeclaration(
4491 decl_inst,
4492 hash,
4493 .{ .named = fn_name_token },
4494 decl_gz.decl_line,
4495 decl_column,
4496 is_pub,
4497 is_export,
4498 &decl_gz,
4499 .{
4500 .align_gz = &align_gz,
4501 .linksection_gz = &section_gz,
4502 .addrspace_gz = &addrspace_gz,
4503 },
4504 );
4509 const func_inst = try decl_gz.addFunc(.{
4510 .src_node = decl_node,
4511 .cc_ref = cc_ref,
4512 .cc_gz = &cc_gz,
4513 .ret_ref = ret_ref,
4514 .ret_gz = &ret_gz,
4515 .ret_param_refs = ret_body_param_refs,
4516 .lbrace_line = lbrace_line,
4517 .lbrace_column = lbrace_column,
4518 .param_block = decl_inst,
4519 .param_insts = param_insts.items,
4520 .body_gz = &body_gz,
4521 .is_var_args = is_var_args,
4522 .is_inferred_error = is_inferred_error,
4523 .is_noinline = is_noinline,
4524 .noalias_bits = noalias_bits,
4525 .proto_hash = proto_hash,
4526 });
4527 _ = try decl_gz.addBreakWithSrcNode(.break_inline, decl_inst, func_inst, decl_node);
45054528}
45064529
45074530fn globalVarDecl(
......@@ -4522,26 +4545,7 @@ fn globalVarDecl(
45224545 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
45234546
45244547 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
4525 // We do this at the beginning so that the instruction index marks the range start
4526 // of the top level declaration.
4527 const decl_inst = try gz.makeDeclaration(node);
4528
45294548 const name_token = var_decl.ast.mut_token + 1;
4530 astgen.advanceSourceCursorToNode(node);
4531
4532 var block_scope: GenZir = .{
4533 .parent = scope,
4534 .decl_node_index = node,
4535 .decl_line = astgen.source_line,
4536 .astgen = astgen,
4537 .is_comptime = true,
4538 .instructions = gz.instructions,
4539 .instructions_top = gz.instructions.items.len,
4540 };
4541 defer block_scope.unstack();
4542
4543 const decl_column = astgen.source_column;
4544
45454549 const is_pub = var_decl.visib_token != null;
45464550 const is_export = blk: {
45474551 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
......@@ -4551,15 +4555,12 @@ fn globalVarDecl(
45514555 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
45524556 break :blk token_tags[maybe_extern_token] == .keyword_extern;
45534557 };
4554 wip_members.nextDecl(decl_inst);
4555
45564558 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
45574559 if (!is_mutable) {
45584560 return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});
45594561 }
45604562 break :blk true;
45614563 } else false;
4562
45634564 const lib_name = if (var_decl.lib_name) |lib_name_token| blk: {
45644565 const lib_name_str = try astgen.strLitAsString(lib_name_token);
45654566 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
......@@ -4571,9 +4572,14 @@ fn globalVarDecl(
45714572 break :blk lib_name_str.index;
45724573 } else .empty;
45734574
4574 assert(var_decl.comptime_token == null); // handled by parser
4575 astgen.advanceSourceCursorToNode(node);
4576
4577 const decl_column = astgen.source_column;
4578
4579 const decl_inst = try gz.makeDeclaration(node);
4580 wip_members.nextDecl(decl_inst);
45754581
4576 const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: {
4582 if (var_decl.ast.init_node != 0) {
45774583 if (is_extern) {
45784584 return astgen.failNode(
45794585 var_decl.ast.init_node,
......@@ -4581,102 +4587,91 @@ fn globalVarDecl(
45814587 .{},
45824588 );
45834589 }
4590 } else {
4591 if (!is_extern) {
4592 return astgen.failNode(node, "variables must be initialized", .{});
4593 }
4594 }
45844595
4585 const type_inst: Zir.Inst.Ref = if (var_decl.ast.type_node != 0)
4586 try expr(
4587 &block_scope,
4588 &block_scope.base,
4589 coerced_type_ri,
4590 var_decl.ast.type_node,
4591 )
4592 else
4593 .none;
4594
4595 block_scope.anon_name_strategy = .parent;
4596 if (is_extern and var_decl.ast.type_node == 0) {
4597 return astgen.failNode(node, "unable to infer variable type", .{});
4598 }
45964599
4597 const init_inst = try expr(
4598 &block_scope,
4599 &block_scope.base,
4600 if (type_inst != .none) .{ .rl = .{ .ty = type_inst } } else .{ .rl = .none },
4601 var_decl.ast.init_node,
4602 );
4600 assert(var_decl.comptime_token == null); // handled by parser
46034601
4604 if (is_mutable) {
4605 const var_inst = try block_scope.addVar(.{
4606 .var_type = type_inst,
4607 .lib_name = .empty,
4608 .align_inst = .none, // passed via the decls data
4609 .init = init_inst,
4610 .is_extern = false,
4611 .is_const = !is_mutable,
4612 .is_threadlocal = is_threadlocal,
4613 });
4614 break :vi var_inst;
4615 } else {
4616 break :vi init_inst;
4617 }
4618 } else if (!is_extern) {
4619 return astgen.failNode(node, "variables must be initialized", .{});
4620 } else if (var_decl.ast.type_node != 0) vi: {
4621 // Extern variable which has an explicit type.
4622 const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
4623
4624 block_scope.anon_name_strategy = .parent;
4625
4626 const var_inst = try block_scope.addVar(.{
4627 .var_type = type_inst,
4628 .lib_name = lib_name,
4629 .align_inst = .none, // passed via the decls data
4630 .init = .none,
4631 .is_extern = true,
4632 .is_const = !is_mutable,
4633 .is_threadlocal = is_threadlocal,
4634 });
4635 break :vi var_inst;
4636 } else {
4637 return astgen.failNode(node, "unable to infer variable type", .{});
4602 var type_gz: GenZir = .{
4603 .parent = scope,
4604 .decl_node_index = node,
4605 .decl_line = astgen.source_line,
4606 .astgen = astgen,
4607 .is_comptime = true,
4608 .instructions = gz.instructions,
4609 .instructions_top = gz.instructions.items.len,
46384610 };
4611 defer type_gz.unstack();
4612
4613 if (var_decl.ast.type_node != 0) {
4614 const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, var_decl.ast.type_node);
4615 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
4616 }
46394617
4640 // We do this at the end so that the instruction index marks the end
4641 // range of a top level declaration.
4642 _ = try block_scope.addBreakWithSrcNode(.break_inline, decl_inst, var_inst, node);
4618 var align_gz = type_gz.makeSubBlock(scope);
4619 defer align_gz.unstack();
46434620
4644 var align_gz = block_scope.makeSubBlock(scope);
46454621 if (var_decl.ast.align_node != 0) {
4646 const align_inst = try fullBodyExpr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node, .normal);
4622 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);
46474623 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
46484624 }
46494625
4650 var linksection_gz = align_gz.makeSubBlock(scope);
4626 var linksection_gz = type_gz.makeSubBlock(scope);
4627 defer linksection_gz.unstack();
4628
46514629 if (var_decl.ast.section_node != 0) {
4652 const linksection_inst = try fullBodyExpr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node, .normal);
4630 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);
46534631 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
46544632 }
46554633
4656 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4634 var addrspace_gz = type_gz.makeSubBlock(scope);
4635 defer addrspace_gz.unstack();
4636
46574637 if (var_decl.ast.addrspace_node != 0) {
46584638 const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space);
4659 const addrspace_inst = try fullBodyExpr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node, .normal);
4639 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node);
46604640 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
46614641 }
46624642
4643 var init_gz = type_gz.makeSubBlock(scope);
4644 defer init_gz.unstack();
4645
4646 if (var_decl.ast.init_node != 0) {
4647 init_gz.anon_name_strategy = .parent;
4648 const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{
4649 .rl = .{ .coerced_ty = decl_inst.toRef() },
4650 } else .{ .rl = .none };
4651 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node);
4652 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
4653 }
4654
46634655 var hash: std.zig.SrcHash = undefined;
46644656 astgen.src_hasher.final(&hash);
4665 try setDeclaration(
4666 decl_inst,
4667 hash,
4668 .{ .named = name_token },
4669 block_scope.decl_line,
4670 decl_column,
4671 is_pub,
4672 is_export,
4673 &block_scope,
4674 .{
4675 .align_gz = &align_gz,
4676 .linksection_gz = &linksection_gz,
4677 .addrspace_gz = &addrspace_gz,
4678 },
4679 );
4657 try setDeclaration(decl_inst, .{
4658 .src_hash = hash,
4659 .src_line = type_gz.decl_line,
4660 .src_column = decl_column,
4661
4662 .kind = if (is_mutable) .@"var" else .@"const",
4663 .name = try astgen.identAsString(name_token),
4664 .is_pub = is_pub,
4665 .is_threadlocal = is_threadlocal,
4666 .linkage = if (is_extern) .@"extern" else if (is_export) .@"export" else .normal,
4667 .lib_name = lib_name,
4668
4669 .type_gz = &type_gz,
4670 .align_gz = &align_gz,
4671 .linksection_gz = &linksection_gz,
4672 .addrspace_gz = &addrspace_gz,
4673 .value_gz = &init_gz,
4674 });
46804675}
46814676
46824677fn comptimeDecl(
......@@ -4702,37 +4697,45 @@ fn comptimeDecl(
47024697 wip_members.nextDecl(decl_inst);
47034698 astgen.advanceSourceCursorToNode(node);
47044699
4705 var decl_block: GenZir = .{
4700 // This is just needed for the `setDeclaration` call.
4701 var dummy_gz = gz.makeSubBlock(scope);
4702 defer dummy_gz.unstack();
4703
4704 var comptime_gz: GenZir = .{
47064705 .is_comptime = true,
47074706 .decl_node_index = node,
47084707 .decl_line = astgen.source_line,
47094708 .parent = scope,
47104709 .astgen = astgen,
4711 .instructions = gz.instructions,
4712 .instructions_top = gz.instructions.items.len,
4710 .instructions = dummy_gz.instructions,
4711 .instructions_top = dummy_gz.instructions.items.len,
47134712 };
4714 defer decl_block.unstack();
4713 defer comptime_gz.unstack();
47154714
47164715 const decl_column = astgen.source_column;
47174716
4718 const block_result = try fullBodyExpr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node, .normal);
4719 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
4720 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);
4717 const block_result = try fullBodyExpr(&comptime_gz, &comptime_gz.base, .{ .rl = .none }, body_node, .normal);
4718 if (comptime_gz.isEmpty() or !comptime_gz.refIsNoReturn(block_result)) {
4719 _ = try comptime_gz.addBreak(.break_inline, decl_inst, .void_value);
47214720 }
47224721
47234722 var hash: std.zig.SrcHash = undefined;
47244723 astgen.src_hasher.final(&hash);
4725 try setDeclaration(
4726 decl_inst,
4727 hash,
4728 .@"comptime",
4729 decl_block.decl_line,
4730 decl_column,
4731 false,
4732 false,
4733 &decl_block,
4734 null,
4735 );
4724 try setDeclaration(decl_inst, .{
4725 .src_hash = hash,
4726 .src_line = comptime_gz.decl_line,
4727 .src_column = decl_column,
4728 .kind = .@"comptime",
4729 .name = .empty,
4730 .is_pub = false,
4731 .is_threadlocal = false,
4732 .linkage = .normal,
4733 .type_gz = &dummy_gz,
4734 .align_gz = &dummy_gz,
4735 .linksection_gz = &dummy_gz,
4736 .addrspace_gz = &dummy_gz,
4737 .value_gz = &comptime_gz,
4738 });
47364739}
47374740
47384741fn usingnamespaceDecl(
......@@ -4764,7 +4767,11 @@ fn usingnamespaceDecl(
47644767 wip_members.nextDecl(decl_inst);
47654768 astgen.advanceSourceCursorToNode(node);
47664769
4767 var decl_block: GenZir = .{
4770 // This is just needed for the `setDeclaration` call.
4771 var dummy_gz = gz.makeSubBlock(scope);
4772 defer dummy_gz.unstack();
4773
4774 var usingnamespace_gz: GenZir = .{
47684775 .is_comptime = true,
47694776 .decl_node_index = node,
47704777 .decl_line = astgen.source_line,
......@@ -4773,26 +4780,30 @@ fn usingnamespaceDecl(
47734780 .instructions = gz.instructions,
47744781 .instructions_top = gz.instructions.items.len,
47754782 };
4776 defer decl_block.unstack();
4783 defer usingnamespace_gz.unstack();
47774784
47784785 const decl_column = astgen.source_column;
47794786
4780 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
4781 _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst);
4787 const namespace_inst = try typeExpr(&usingnamespace_gz, &usingnamespace_gz.base, type_expr);
4788 _ = try usingnamespace_gz.addBreak(.break_inline, decl_inst, namespace_inst);
47824789
47834790 var hash: std.zig.SrcHash = undefined;
47844791 astgen.src_hasher.final(&hash);
4785 try setDeclaration(
4786 decl_inst,
4787 hash,
4788 .@"usingnamespace",
4789 decl_block.decl_line,
4790 decl_column,
4791 is_pub,
4792 false,
4793 &decl_block,
4794 null,
4795 );
4792 try setDeclaration(decl_inst, .{
4793 .src_hash = hash,
4794 .src_line = usingnamespace_gz.decl_line,
4795 .src_column = decl_column,
4796 .kind = .@"usingnamespace",
4797 .name = .empty,
4798 .is_pub = is_pub,
4799 .is_threadlocal = false,
4800 .linkage = .normal,
4801 .type_gz = &dummy_gz,
4802 .align_gz = &dummy_gz,
4803 .linksection_gz = &dummy_gz,
4804 .addrspace_gz = &dummy_gz,
4805 .value_gz = &usingnamespace_gz,
4806 });
47964807}
47974808
47984809fn testDecl(
......@@ -4819,14 +4830,18 @@ fn testDecl(
48194830 wip_members.nextDecl(decl_inst);
48204831 astgen.advanceSourceCursorToNode(node);
48214832
4833 // This is just needed for the `setDeclaration` call.
4834 var dummy_gz: GenZir = gz.makeSubBlock(scope);
4835 defer dummy_gz.unstack();
4836
48224837 var decl_block: GenZir = .{
48234838 .is_comptime = true,
48244839 .decl_node_index = node,
48254840 .decl_line = astgen.source_line,
48264841 .parent = scope,
48274842 .astgen = astgen,
4828 .instructions = gz.instructions,
4829 .instructions_top = gz.instructions.items.len,
4843 .instructions = dummy_gz.instructions,
4844 .instructions_top = dummy_gz.instructions.items.len,
48304845 };
48314846 defer decl_block.unstack();
48324847
......@@ -4835,11 +4850,21 @@ fn testDecl(
48354850 const main_tokens = tree.nodes.items(.main_token);
48364851 const token_tags = tree.tokens.items(.tag);
48374852 const test_token = main_tokens[node];
4853
48384854 const test_name_token = test_token + 1;
4839 const test_name: DeclarationName = switch (token_tags[test_name_token]) {
4840 else => .unnamed_test,
4841 .string_literal => .{ .named_test = test_name_token },
4842 .identifier => blk: {
4855 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {
4856 else => .empty,
4857 .string_literal => name: {
4858 const name = try astgen.strLitAsString(test_name_token);
4859 const slice = astgen.string_bytes.items[@intFromEnum(name.index)..][0..name.len];
4860 if (mem.indexOfScalar(u8, slice, 0) != null) {
4861 return astgen.failTok(test_name_token, "test name cannot contain null bytes", .{});
4862 } else if (slice.len == 0) {
4863 return astgen.failTok(test_name_token, "empty test name must be omitted", .{});
4864 }
4865 break :name name.index;
4866 },
4867 .identifier => name: {
48434868 const ident_name_raw = tree.tokenSlice(test_name_token);
48444869
48454870 if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{});
......@@ -4909,7 +4934,7 @@ fn testDecl(
49094934 return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name});
49104935 }
49114936
4912 break :blk .{ .decltest = test_name_token };
4937 break :name try astgen.identAsString(test_name_token);
49134938 },
49144939 };
49154940
......@@ -4965,11 +4990,8 @@ fn testDecl(
49654990 .lbrace_column = lbrace_column,
49664991 .param_block = decl_inst,
49674992 .body_gz = &fn_block,
4968 .lib_name = .empty,
49694993 .is_var_args = false,
49704994 .is_inferred_error = false,
4971 .is_test = true,
4972 .is_extern = false,
49734995 .is_noinline = false,
49744996 .noalias_bits = 0,
49754997
......@@ -4981,17 +5003,27 @@ fn testDecl(
49815003
49825004 var hash: std.zig.SrcHash = undefined;
49835005 astgen.src_hasher.final(&hash);
4984 try setDeclaration(
4985 decl_inst,
4986 hash,
4987 test_name,
4988 decl_block.decl_line,
4989 decl_column,
4990 false,
4991 false,
4992 &decl_block,
4993 null,
4994 );
5006 try setDeclaration(decl_inst, .{
5007 .src_hash = hash,
5008 .src_line = decl_block.decl_line,
5009 .src_column = decl_column,
5010
5011 .kind = switch (token_tags[test_name_token]) {
5012 .string_literal => .@"test",
5013 .identifier => .decltest,
5014 else => .unnamed_test,
5015 },
5016 .name = test_name,
5017 .is_pub = false,
5018 .is_threadlocal = false,
5019 .linkage = .normal,
5020
5021 .type_gz = &dummy_gz,
5022 .align_gz = &dummy_gz,
5023 .linksection_gz = &dummy_gz,
5024 .addrspace_gz = &dummy_gz,
5025 .value_gz = &decl_block,
5026 });
49955027}
49965028
49975029fn structDeclInner(
......@@ -5882,7 +5914,8 @@ fn containerMember(
58825914 try addFailedDeclaration(
58835915 wip_members,
58845916 gz,
5885 .{ .named = full.name_token.? },
5917 .@"const",
5918 try astgen.identAsString(full.name_token.?),
58865919 full.ast.proto_node,
58875920 full.visib_token != null,
58885921 );
......@@ -5904,7 +5937,8 @@ fn containerMember(
59045937 try addFailedDeclaration(
59055938 wip_members,
59065939 gz,
5907 .{ .named = full.ast.mut_token + 1 },
5940 .@"const", // doesn't really matter
5941 try astgen.identAsString(full.ast.mut_token + 1),
59085942 member_node,
59095943 full.visib_token != null,
59105944 );
......@@ -5922,6 +5956,7 @@ fn containerMember(
59225956 wip_members,
59235957 gz,
59245958 .@"comptime",
5959 .empty,
59255960 member_node,
59265961 false,
59275962 );
......@@ -5938,6 +5973,7 @@ fn containerMember(
59385973 wip_members,
59395974 gz,
59405975 .@"usingnamespace",
5976 .empty,
59415977 member_node,
59425978 is_pub: {
59435979 const main_tokens = tree.nodes.items(.main_token);
......@@ -5962,6 +5998,7 @@ fn containerMember(
59625998 wip_members,
59635999 gz,
59646000 .unnamed_test,
6001 .empty,
59656002 member_node,
59666003 false,
59676004 );
......@@ -11670,23 +11707,6 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
1167011707 };
1167111708}
1167211709
11673fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !Zir.NullTerminatedString {
11674 const gpa = astgen.gpa;
11675 const string_bytes = &astgen.string_bytes;
11676 const str_index: u32 = @intCast(string_bytes.items.len);
11677 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
11678 try string_bytes.append(gpa, 0); // Indicates this is a test.
11679 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
11680 const slice = string_bytes.items[str_index + 1 ..];
11681 if (mem.indexOfScalar(u8, slice, 0) != null) {
11682 return astgen.failTok(str_lit_token, "test name cannot contain null bytes", .{});
11683 } else if (slice.len == 0) {
11684 return astgen.failTok(str_lit_token, "empty test name must be omitted", .{});
11685 }
11686 try string_bytes.append(gpa, 0);
11687 return @enumFromInt(str_index);
11688}
11689
1169011710const Scope = struct {
1169111711 tag: Tag,
1169211712
......@@ -12077,12 +12097,9 @@ const GenZir = struct {
1207712097 cc_ref: Zir.Inst.Ref,
1207812098 ret_ref: Zir.Inst.Ref,
1207912099
12080 lib_name: Zir.NullTerminatedString,
1208112100 noalias_bits: u32,
1208212101 is_var_args: bool,
1208312102 is_inferred_error: bool,
12084 is_test: bool,
12085 is_extern: bool,
1208612103 is_noinline: bool,
1208712104
1208812105 /// Ignored if `body_gz == null`.
......@@ -12150,9 +12167,8 @@ const GenZir = struct {
1215012167
1215112168 const body_len = astgen.countBodyLenAfterFixupsExtraRefs(body, args.param_insts);
1215212169
12153 const tag: Zir.Inst.Tag, const payload_index: u32 = if (args.cc_ref != .none or args.lib_name != .empty or
12154 args.is_var_args or args.is_test or args.is_extern or
12155 args.noalias_bits != 0 or args.is_noinline)
12170 const tag: Zir.Inst.Tag, const payload_index: u32 = if (args.cc_ref != .none or
12171 args.is_var_args or args.noalias_bits != 0 or args.is_noinline)
1215612172 inst_info: {
1215712173 try astgen.extra.ensureUnusedCapacity(
1215812174 gpa,
......@@ -12160,7 +12176,6 @@ const GenZir = struct {
1216012176 fancyFnExprExtraLen(astgen, &.{}, cc_body, args.cc_ref) +
1216112177 fancyFnExprExtraLen(astgen, args.ret_param_refs, ret_body, ret_ref) +
1216212178 body_len + src_locs_and_hash.len +
12163 @intFromBool(args.lib_name != .empty) +
1216412179 @intFromBool(args.noalias_bits != 0),
1216512180 );
1216612181 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
......@@ -12169,10 +12184,7 @@ const GenZir = struct {
1216912184 .bits = .{
1217012185 .is_var_args = args.is_var_args,
1217112186 .is_inferred_error = args.is_inferred_error,
12172 .is_test = args.is_test,
12173 .is_extern = args.is_extern,
1217412187 .is_noinline = args.is_noinline,
12175 .has_lib_name = args.lib_name != .empty,
1217612188 .has_any_noalias = args.noalias_bits != 0,
1217712189
1217812190 .has_cc_ref = args.cc_ref != .none,
......@@ -12182,9 +12194,6 @@ const GenZir = struct {
1218212194 .has_ret_ty_body = ret_body.len != 0,
1218312195 },
1218412196 });
12185 if (args.lib_name != .empty) {
12186 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
12187 }
1218812197
1218912198 const zir_datas = astgen.instructions.items(.data);
1219012199 if (cc_body.len != 0) {
......@@ -12279,61 +12288,6 @@ const GenZir = struct {
1227912288 @intFromBool(main_body.len > 0 or ref != .none);
1228012289 }
1228112290
12282 fn addVar(gz: *GenZir, args: struct {
12283 align_inst: Zir.Inst.Ref,
12284 lib_name: Zir.NullTerminatedString,
12285 var_type: Zir.Inst.Ref,
12286 init: Zir.Inst.Ref,
12287 is_extern: bool,
12288 is_const: bool,
12289 is_threadlocal: bool,
12290 }) !Zir.Inst.Ref {
12291 const astgen = gz.astgen;
12292 const gpa = astgen.gpa;
12293
12294 try gz.instructions.ensureUnusedCapacity(gpa, 1);
12295 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
12296
12297 try astgen.extra.ensureUnusedCapacity(
12298 gpa,
12299 @typeInfo(Zir.Inst.ExtendedVar).@"struct".fields.len +
12300 @intFromBool(args.lib_name != .empty) +
12301 @intFromBool(args.align_inst != .none) +
12302 @intFromBool(args.init != .none),
12303 );
12304 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
12305 .var_type = args.var_type,
12306 });
12307 if (args.lib_name != .empty) {
12308 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
12309 }
12310 if (args.align_inst != .none) {
12311 astgen.extra.appendAssumeCapacity(@intFromEnum(args.align_inst));
12312 }
12313 if (args.init != .none) {
12314 astgen.extra.appendAssumeCapacity(@intFromEnum(args.init));
12315 }
12316
12317 const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
12318 astgen.instructions.appendAssumeCapacity(.{
12319 .tag = .extended,
12320 .data = .{ .extended = .{
12321 .opcode = .variable,
12322 .small = @bitCast(Zir.Inst.ExtendedVar.Small{
12323 .has_lib_name = args.lib_name != .empty,
12324 .has_align = args.align_inst != .none,
12325 .has_init = args.init != .none,
12326 .is_extern = args.is_extern,
12327 .is_const = args.is_const,
12328 .is_threadlocal = args.is_threadlocal,
12329 }),
12330 .operand = payload_index,
12331 } },
12332 });
12333 gz.instructions.appendAssumeCapacity(new_index);
12334 return new_index.toRef();
12335 }
12336
1233712291 fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
1233812292 return gz.add(.{
1233912293 .tag = .int,
......@@ -13909,14 +13863,18 @@ const DeclarationName = union(enum) {
1390913863fn addFailedDeclaration(
1391013864 wip_members: *WipMembers,
1391113865 gz: *GenZir,
13912 name: DeclarationName,
13866 kind: Zir.Inst.Declaration.Unwrapped.Kind,
13867 name: Zir.NullTerminatedString,
1391313868 src_node: Ast.Node.Index,
1391413869 is_pub: bool,
1391513870) !void {
1391613871 const decl_inst = try gz.makeDeclaration(src_node);
1391713872 wip_members.nextDecl(decl_inst);
13918 var decl_gz = gz.makeSubBlock(&gz.base); // scope doesn't matter here
13919 _ = try decl_gz.add(.{
13873
13874 var dummy_gz = gz.makeSubBlock(&gz.base);
13875
13876 var value_gz = gz.makeSubBlock(&gz.base); // scope doesn't matter here
13877 _ = try value_gz.add(.{
1392013878 .tag = .extended,
1392113879 .data = .{ .extended = .{
1392213880 .opcode = .astgen_error,
......@@ -13924,110 +13882,198 @@ fn addFailedDeclaration(
1392413882 .operand = undefined,
1392513883 } },
1392613884 });
13927 try setDeclaration(
13928 decl_inst,
13929 @splat(0), // use a fixed hash to represent an AstGen failure; we don't care about source changes if AstGen still failed!
13930 name,
13931 gz.astgen.source_line,
13932 gz.astgen.source_column,
13933 is_pub,
13934 false, // we don't care about exports since semantic analysis will fail
13935 &decl_gz,
13936 null,
13937 );
13885
13886 try setDeclaration(decl_inst, .{
13887 .src_hash = @splat(0), // use a fixed hash to represent an AstGen failure; we don't care about source changes if AstGen still failed!
13888 .src_line = gz.astgen.source_line,
13889 .src_column = gz.astgen.source_column,
13890 .kind = kind,
13891 .name = name,
13892 .is_pub = is_pub,
13893 .is_threadlocal = false,
13894 .linkage = .normal,
13895 .type_gz = &dummy_gz,
13896 .align_gz = &dummy_gz,
13897 .linksection_gz = &dummy_gz,
13898 .addrspace_gz = &dummy_gz,
13899 .value_gz = &value_gz,
13900 });
1393813901}
1393913902
1394013903/// Sets all extra data for a `declaration` instruction.
13941/// Unstacks `value_gz`, `align_gz`, `linksection_gz`, and `addrspace_gz`.
13904/// Unstacks `type_gz`, `align_gz`, `linksection_gz`, `addrspace_gz`, and `value_gz`.
1394213905fn setDeclaration(
1394313906 decl_inst: Zir.Inst.Index,
13944 src_hash: std.zig.SrcHash,
13945 name: DeclarationName,
13946 src_line: u32,
13947 src_column: u32,
13948 is_pub: bool,
13949 is_export: bool,
13950 value_gz: *GenZir,
13951 /// May be `null` if all these blocks would be empty.
13952 /// If `null`, then `value_gz` must have nothing stacked on it.
13953 extra_gzs: ?struct {
13954 /// Must be stacked on `value_gz`.
13907 args: struct {
13908 src_hash: std.zig.SrcHash,
13909 src_line: u32,
13910 src_column: u32,
13911
13912 kind: Zir.Inst.Declaration.Unwrapped.Kind,
13913 name: Zir.NullTerminatedString,
13914 is_pub: bool,
13915 is_threadlocal: bool,
13916 linkage: Zir.Inst.Declaration.Unwrapped.Linkage,
13917 lib_name: Zir.NullTerminatedString = .empty,
13918
13919 type_gz: *GenZir,
13920 /// Must be stacked on `type_gz`.
1395513921 align_gz: *GenZir,
1395613922 /// Must be stacked on `align_gz`.
1395713923 linksection_gz: *GenZir,
13958 /// Must be stacked on `linksection_gz`, and have nothing stacked on it.
13924 /// Must be stacked on `linksection_gz`.
1395913925 addrspace_gz: *GenZir,
13926 /// Must be stacked on `addrspace_gz` and have nothing stacked on top of it.
13927 value_gz: *GenZir,
1396013928 },
1396113929) !void {
13962 const astgen = value_gz.astgen;
13930 const astgen = args.value_gz.astgen;
1396313931 const gpa = astgen.gpa;
1396413932
13965 const empty_body: []Zir.Inst.Index = &.{};
13966 const value_body, const align_body, const linksection_body, const addrspace_body = if (extra_gzs) |e| .{
13967 value_gz.instructionsSliceUpto(e.align_gz),
13968 e.align_gz.instructionsSliceUpto(e.linksection_gz),
13969 e.linksection_gz.instructionsSliceUpto(e.addrspace_gz),
13970 e.addrspace_gz.instructionsSlice(),
13971 } else .{ value_gz.instructionsSlice(), empty_body, empty_body, empty_body };
13933 const type_body = args.type_gz.instructionsSliceUpto(args.align_gz);
13934 const align_body = args.align_gz.instructionsSliceUpto(args.linksection_gz);
13935 const linksection_body = args.linksection_gz.instructionsSliceUpto(args.addrspace_gz);
13936 const addrspace_body = args.addrspace_gz.instructionsSliceUpto(args.value_gz);
13937 const value_body = args.value_gz.instructionsSlice();
13938
13939 const has_name = args.name != .empty;
13940 const has_lib_name = args.lib_name != .empty;
13941 const has_type_body = type_body.len != 0;
13942 const has_special_body = align_body.len != 0 or linksection_body.len != 0 or addrspace_body.len != 0;
13943 const has_value_body = value_body.len != 0;
13944
13945 const id: Zir.Inst.Declaration.Flags.Id = switch (args.kind) {
13946 .unnamed_test => .unnamed_test,
13947 .@"test" => .@"test",
13948 .decltest => .decltest,
13949 .@"comptime" => .@"comptime",
13950 .@"usingnamespace" => if (args.is_pub) .pub_usingnamespace else .@"usingnamespace",
13951 .@"const" => switch (args.linkage) {
13952 .normal => if (args.is_pub) id: {
13953 if (has_special_body) break :id .pub_const;
13954 if (has_type_body) break :id .pub_const_typed;
13955 break :id .pub_const_simple;
13956 } else id: {
13957 if (has_special_body) break :id .@"const";
13958 if (has_type_body) break :id .const_typed;
13959 break :id .const_simple;
13960 },
13961 .@"extern" => if (args.is_pub) id: {
13962 if (has_lib_name) break :id .pub_extern_const;
13963 if (has_special_body) break :id .pub_extern_const;
13964 break :id .pub_extern_const_simple;
13965 } else id: {
13966 if (has_lib_name) break :id .extern_const;
13967 if (has_special_body) break :id .extern_const;
13968 break :id .extern_const_simple;
13969 },
13970 .@"export" => if (args.is_pub) .pub_export_const else .export_const,
13971 },
13972 .@"var" => switch (args.linkage) {
13973 .normal => if (args.is_pub) id: {
13974 if (args.is_threadlocal) break :id .pub_var_threadlocal;
13975 if (has_special_body) break :id .pub_var;
13976 if (has_type_body) break :id .pub_var;
13977 break :id .pub_var_simple;
13978 } else id: {
13979 if (args.is_threadlocal) break :id .var_threadlocal;
13980 if (has_special_body) break :id .@"var";
13981 if (has_type_body) break :id .@"var";
13982 break :id .var_simple;
13983 },
13984 .@"extern" => if (args.is_pub) id: {
13985 if (args.is_threadlocal) break :id .pub_extern_var_threadlocal;
13986 break :id .pub_extern_var;
13987 } else id: {
13988 if (args.is_threadlocal) break :id .extern_var_threadlocal;
13989 break :id .extern_var;
13990 },
13991 .@"export" => if (args.is_pub) id: {
13992 if (args.is_threadlocal) break :id .pub_export_var_threadlocal;
13993 break :id .pub_export_var;
13994 } else id: {
13995 if (args.is_threadlocal) break :id .export_var_threadlocal;
13996 break :id .export_var;
13997 },
13998 },
13999 };
1397214000
13973 const value_len = astgen.countBodyLenAfterFixups(value_body);
14001 assert(id.hasTypeBody() or !has_type_body);
14002 assert(id.hasSpecialBodies() or !has_special_body);
14003 assert(id.hasValueBody() == has_value_body);
14004 assert(id.linkage() == args.linkage);
14005 assert(id.hasName() == has_name);
14006 assert(id.hasLibName() or !has_lib_name);
14007 assert(id.isPub() == args.is_pub);
14008 assert(id.isThreadlocal() == args.is_threadlocal);
14009
14010 const type_len = astgen.countBodyLenAfterFixups(type_body);
1397414011 const align_len = astgen.countBodyLenAfterFixups(align_body);
1397514012 const linksection_len = astgen.countBodyLenAfterFixups(linksection_body);
1397614013 const addrspace_len = astgen.countBodyLenAfterFixups(addrspace_body);
14014 const value_len = astgen.countBodyLenAfterFixups(value_body);
14015
14016 const src_hash_arr: [4]u32 = @bitCast(args.src_hash);
14017 const flags: Zir.Inst.Declaration.Flags = .{
14018 .src_line = @intCast(args.src_line),
14019 .src_column = @intCast(args.src_column),
14020 .id = id,
14021 };
14022 const flags_arr: [2]u32 = @bitCast(flags);
1397714023
13978 const src_hash_arr: [4]u32 = @bitCast(src_hash);
14024 const need_extra: usize =
14025 @typeInfo(Zir.Inst.Declaration).@"struct".fields.len +
14026 @as(usize, @intFromBool(id.hasName())) +
14027 @as(usize, @intFromBool(id.hasLibName())) +
14028 @as(usize, @intFromBool(id.hasTypeBody())) +
14029 3 * @as(usize, @intFromBool(id.hasSpecialBodies())) +
14030 @as(usize, @intFromBool(id.hasValueBody())) +
14031 type_len + align_len + linksection_len + addrspace_len + value_len;
14032
14033 try astgen.extra.ensureUnusedCapacity(gpa, need_extra);
1397914034
1398014035 const extra: Zir.Inst.Declaration = .{
1398114036 .src_hash_0 = src_hash_arr[0],
1398214037 .src_hash_1 = src_hash_arr[1],
1398314038 .src_hash_2 = src_hash_arr[2],
1398414039 .src_hash_3 = src_hash_arr[3],
13985 .name = switch (name) {
13986 .named => |tok| @enumFromInt(@intFromEnum(try astgen.identAsString(tok))),
13987 .named_test => |tok| @enumFromInt(@intFromEnum(try astgen.testNameString(tok))),
13988 .decltest => |tok| @enumFromInt(str_idx: {
13989 const idx = astgen.string_bytes.items.len;
13990 try astgen.string_bytes.append(gpa, 0); // indicates this is a test
13991 try astgen.appendIdentStr(tok, &astgen.string_bytes);
13992 try astgen.string_bytes.append(gpa, 0); // end of the string
13993 break :str_idx idx;
13994 }),
13995 .unnamed_test => .unnamed_test,
13996 .@"comptime" => .@"comptime",
13997 .@"usingnamespace" => .@"usingnamespace",
13998 },
13999 .src_line = src_line,
14000 .src_column = src_column,
14001 .flags = .{
14002 .value_body_len = @intCast(value_len),
14003 .is_pub = is_pub,
14004 .is_export = is_export,
14005 .test_is_decltest = name == .decltest,
14006 .has_align_linksection_addrspace = align_len != 0 or linksection_len != 0 or addrspace_len != 0,
14007 },
14040 .flags_0 = flags_arr[0],
14041 .flags_1 = flags_arr[1],
1400814042 };
14009 astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index = try astgen.addExtra(extra);
14010 if (extra.flags.has_align_linksection_addrspace) {
14011 try astgen.extra.appendSlice(gpa, &.{
14043 astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index =
14044 astgen.addExtraAssumeCapacity(extra);
14045
14046 if (id.hasName()) {
14047 astgen.extra.appendAssumeCapacity(@intFromEnum(args.name));
14048 }
14049 if (id.hasLibName()) {
14050 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
14051 }
14052 if (id.hasTypeBody()) {
14053 astgen.extra.appendAssumeCapacity(type_len);
14054 }
14055 if (id.hasSpecialBodies()) {
14056 astgen.extra.appendSliceAssumeCapacity(&.{
1401214057 align_len,
1401314058 linksection_len,
1401414059 addrspace_len,
1401514060 });
1401614061 }
14017 try astgen.extra.ensureUnusedCapacity(gpa, value_len + align_len + linksection_len + addrspace_len);
14018 astgen.appendBodyWithFixups(value_body);
14019 if (extra.flags.has_align_linksection_addrspace) {
14020 astgen.appendBodyWithFixups(align_body);
14021 astgen.appendBodyWithFixups(linksection_body);
14022 astgen.appendBodyWithFixups(addrspace_body);
14062 if (id.hasValueBody()) {
14063 astgen.extra.appendAssumeCapacity(value_len);
1402314064 }
1402414065
14025 if (extra_gzs) |e| {
14026 e.addrspace_gz.unstack();
14027 e.linksection_gz.unstack();
14028 e.align_gz.unstack();
14029 }
14030 value_gz.unstack();
14066 astgen.appendBodyWithFixups(type_body);
14067 astgen.appendBodyWithFixups(align_body);
14068 astgen.appendBodyWithFixups(linksection_body);
14069 astgen.appendBodyWithFixups(addrspace_body);
14070 astgen.appendBodyWithFixups(value_body);
14071
14072 args.value_gz.unstack();
14073 args.addrspace_gz.unstack();
14074 args.linksection_gz.unstack();
14075 args.align_gz.unstack();
14076 args.type_gz.unstack();
1403114077}
1403214078
1403314079/// Given a list of instructions, returns a list of all instructions which are a `ref` of one of the originals,
lib/std/zig/Zir.zig+392-95
......@@ -1868,10 +1868,6 @@ pub const Inst = struct {
18681868 /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
18691869 /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
18701870 pub const Extended = enum(u16) {
1871 /// Declares a global variable.
1872 /// `operand` is payload index to `ExtendedVar`.
1873 /// `small` is `ExtendedVar.Small`.
1874 variable,
18751871 /// A struct type definition. Contains references to ZIR instructions for
18761872 /// the field types, defaults, and alignments.
18771873 /// `operand` is payload index to `StructDecl`.
......@@ -2493,26 +2489,25 @@ pub const Inst = struct {
24932489 };
24942490
24952491 /// Trailing:
2496 /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
24972492 /// if (has_cc_ref and !has_cc_body) {
2498 /// 1. cc: Ref,
2493 /// 0. cc: Ref,
24992494 /// }
25002495 /// if (has_cc_body) {
2501 /// 2. cc_body_len: u32
2502 /// 3. cc_body: u32 // for each cc_body_len
2496 /// 1. cc_body_len: u32
2497 /// 2. cc_body: u32 // for each cc_body_len
25032498 /// }
25042499 /// if (has_ret_ty_ref and !has_ret_ty_body) {
2505 /// 4. ret_ty: Ref,
2500 /// 3. ret_ty: Ref,
25062501 /// }
25072502 /// if (has_ret_ty_body) {
2508 /// 5. ret_ty_body_len: u32
2509 /// 6. ret_ty_body: u32 // for each ret_ty_body_len
2503 /// 4. ret_ty_body_len: u32
2504 /// 5. ret_ty_body: u32 // for each ret_ty_body_len
25102505 /// }
2511 /// 7. noalias_bits: u32 // if has_any_noalias
2506 /// 6. noalias_bits: u32 // if has_any_noalias
25122507 /// - each bit starting with LSB corresponds to parameter indexes
2513 /// 8. body: Index // for each body_len
2514 /// 9. src_locs: Func.SrcLocs // if body_len != 0
2515 /// 10. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype
2508 /// 7. body: Index // for each body_len
2509 /// 8. src_locs: Func.SrcLocs // if body_len != 0
2510 /// 9. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype
25162511 pub const FuncFancy = struct {
25172512 /// Points to the block that contains the param instructions for this function.
25182513 /// If this is a `declaration`, it refers to the declaration's value body.
......@@ -2522,38 +2517,16 @@ pub const Inst = struct {
25222517
25232518 /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.
25242519 /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type.
2525 pub const Bits = packed struct {
2520 pub const Bits = packed struct(u32) {
25262521 is_var_args: bool,
25272522 is_inferred_error: bool,
2528 is_test: bool,
2529 is_extern: bool,
25302523 is_noinline: bool,
25312524 has_cc_ref: bool,
25322525 has_cc_body: bool,
25332526 has_ret_ty_ref: bool,
25342527 has_ret_ty_body: bool,
2535 has_lib_name: bool,
25362528 has_any_noalias: bool,
2537 _: u21 = undefined,
2538 };
2539 };
2540
2541 /// Trailing:
2542 /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
2543 /// 1. align: Ref, // if has_align is set
2544 /// 2. init: Ref // if has_init is set
2545 /// The source node is obtained from the containing `block_inline`.
2546 pub const ExtendedVar = struct {
2547 var_type: Ref,
2548
2549 pub const Small = packed struct {
2550 has_lib_name: bool,
2551 has_align: bool,
2552 has_init: bool,
2553 is_extern: bool,
2554 is_const: bool,
2555 is_threadlocal: bool,
2556 _: u10 = undefined,
2529 _: u24 = undefined,
25572530 };
25582531 };
25592532
......@@ -2582,39 +2555,301 @@ pub const Inst = struct {
25822555 };
25832556
25842557 /// Trailing:
2585 /// 0. align_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `align`
2586 /// 1. linksection_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `linksection`
2587 /// 2. addrspace_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `addrspace`
2588 /// 3. value_body_inst: Zir.Inst.Index
2589 /// - for each `value_body_len`
2558 /// 0. name: NullTerminatedString // if `flags.id.hasName()`
2559 /// 1. lib_name: NullTerminatedString // if `flags.id.hasLibName()`
2560 /// 2. type_body_len: u32 // if `flags.id.hasTypeBody()`
2561 /// 3. align_body_len: u32 // if `flags.id.hasSpecialBodies()`
2562 /// 4. linksection_body_len: u32 // if `flags.id.hasSpecialBodies()`
2563 /// 5. addrspace_body_len: u32 // if `flags.id.hasSpecialBodies()`
2564 /// 6. value_body_len: u32 // if `flags.id.hasValueBody()`
2565 /// 7. type_body_inst: Zir.Inst.Index
2566 /// - for each `type_body_len`
25902567 /// - body to be exited via `break_inline` to this `declaration` instruction
2591 /// 4. align_body_inst: Zir.Inst.Index
2568 /// 8. align_body_inst: Zir.Inst.Index
25922569 /// - for each `align_body_len`
25932570 /// - body to be exited via `break_inline` to this `declaration` instruction
2594 /// 5. linksection_body_inst: Zir.Inst.Index
2571 /// 9. linksection_body_inst: Zir.Inst.Index
25952572 /// - for each `linksection_body_len`
25962573 /// - body to be exited via `break_inline` to this `declaration` instruction
2597 /// 6. addrspace_body_inst: Zir.Inst.Index
2574 /// 10. addrspace_body_inst: Zir.Inst.Index
25982575 /// - for each `addrspace_body_len`
25992576 /// - body to be exited via `break_inline` to this `declaration` instruction
2577 /// 11. value_body_inst: Zir.Inst.Index
2578 /// - for each `value_body_len`
2579 /// - body to be exited via `break_inline` to this `declaration` instruction
2580 /// - within this body, the `declaration` instruction refers to the resolved type from the type body
26002581 pub const Declaration = struct {
26012582 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
26022583 src_hash_0: u32,
26032584 src_hash_1: u32,
26042585 src_hash_2: u32,
26052586 src_hash_3: u32,
2606 /// The name of this `Decl`. Also indicates whether it is a test, comptime block, etc.
2607 name: Name,
2608 src_line: u32,
2609 src_column: u32,
2610 flags: Flags,
2587 // These fields should be concatenated and reinterpreted as a `Flags`.
2588 flags_0: u32,
2589 flags_1: u32,
2590
2591 pub const Unwrapped = struct {
2592 pub const Kind = enum {
2593 unnamed_test,
2594 @"test",
2595 decltest,
2596 @"comptime",
2597 @"usingnamespace",
2598 @"const",
2599 @"var",
2600 };
26112601
2612 pub const Flags = packed struct(u32) {
2613 value_body_len: u28,
2602 pub const Linkage = enum {
2603 normal,
2604 @"extern",
2605 @"export",
2606 };
2607
2608 src_node: Ast.Node.Index,
2609
2610 src_line: u32,
2611 src_column: u32,
2612
2613 kind: Kind,
2614 /// Always `.empty` for `kind` of `unnamed_test`, `.@"comptime"`, `.@"usingnamespace"`.
2615 name: NullTerminatedString,
2616 /// Always `false` for `kind` of `unnamed_test`, `.@"test"`, `.decltest`, `.@"comptime"`.
26142617 is_pub: bool,
2615 is_export: bool,
2616 test_is_decltest: bool,
2617 has_align_linksection_addrspace: bool,
2618 /// Always `false` for `kind != .@"var"`.
2619 is_threadlocal: bool,
2620 /// Always `.normal` for `kind != .@"const" and kind != .@"var"`.
2621 linkage: Linkage,
2622 /// Always `.empty` for `linkage != .@"extern"`.
2623 lib_name: NullTerminatedString,
2624
2625 /// Always populated for `linkage == .@"extern".
2626 type_body: ?[]const Inst.Index,
2627 align_body: ?[]const Inst.Index,
2628 linksection_body: ?[]const Inst.Index,
2629 addrspace_body: ?[]const Inst.Index,
2630 /// Always populated for `linkage != .@"extern".
2631 value_body: ?[]const Inst.Index,
2632 };
2633
2634 pub const Flags = packed struct(u64) {
2635 src_line: u30,
2636 src_column: u29,
2637 id: Id,
2638
2639 pub const Id = enum(u5) {
2640 unnamed_test,
2641 @"test",
2642 decltest,
2643 @"comptime",
2644
2645 @"usingnamespace",
2646 pub_usingnamespace,
2647
2648 const_simple,
2649 const_typed,
2650 @"const",
2651 pub_const_simple,
2652 pub_const_typed,
2653 pub_const,
2654
2655 extern_const_simple,
2656 extern_const,
2657 pub_extern_const_simple,
2658 pub_extern_const,
2659
2660 export_const,
2661 pub_export_const,
2662
2663 var_simple,
2664 @"var",
2665 var_threadlocal,
2666 pub_var_simple,
2667 pub_var,
2668 pub_var_threadlocal,
2669
2670 extern_var,
2671 extern_var_threadlocal,
2672 pub_extern_var,
2673 pub_extern_var_threadlocal,
2674
2675 export_var,
2676 export_var_threadlocal,
2677 pub_export_var,
2678 pub_export_var_threadlocal,
2679
2680 pub fn hasName(id: Id) bool {
2681 return switch (id) {
2682 .unnamed_test,
2683 .@"comptime",
2684 .@"usingnamespace",
2685 .pub_usingnamespace,
2686 => false,
2687 else => true,
2688 };
2689 }
2690
2691 pub fn hasLibName(id: Id) bool {
2692 return switch (id) {
2693 .extern_const,
2694 .pub_extern_const,
2695 .extern_var,
2696 .extern_var_threadlocal,
2697 .pub_extern_var,
2698 .pub_extern_var_threadlocal,
2699 => true,
2700 else => false,
2701 };
2702 }
2703
2704 pub fn hasTypeBody(id: Id) bool {
2705 return switch (id) {
2706 .unnamed_test,
2707 .@"test",
2708 .decltest,
2709 .@"comptime",
2710 .@"usingnamespace",
2711 .pub_usingnamespace,
2712 => false, // these constructs are untyped
2713 .const_simple,
2714 .pub_const_simple,
2715 .var_simple,
2716 .pub_var_simple,
2717 => false, // these reprs omit type bodies
2718 else => true,
2719 };
2720 }
2721
2722 pub fn hasValueBody(id: Id) bool {
2723 return switch (id) {
2724 .extern_const_simple,
2725 .extern_const,
2726 .pub_extern_const_simple,
2727 .pub_extern_const,
2728 .extern_var,
2729 .extern_var_threadlocal,
2730 .pub_extern_var,
2731 .pub_extern_var_threadlocal,
2732 => false, // externs do not have values
2733 else => true,
2734 };
2735 }
2736
2737 pub fn hasSpecialBodies(id: Id) bool {
2738 return switch (id) {
2739 .unnamed_test,
2740 .@"test",
2741 .decltest,
2742 .@"comptime",
2743 .@"usingnamespace",
2744 .pub_usingnamespace,
2745 => false, // these constructs are untyped
2746 .const_simple,
2747 .const_typed,
2748 .pub_const_simple,
2749 .pub_const_typed,
2750 .extern_const_simple,
2751 .pub_extern_const_simple,
2752 .var_simple,
2753 .pub_var_simple,
2754 => false, // these reprs omit special bodies
2755 else => true,
2756 };
2757 }
2758
2759 pub fn linkage(id: Id) Declaration.Unwrapped.Linkage {
2760 return switch (id) {
2761 .extern_const_simple,
2762 .extern_const,
2763 .pub_extern_const_simple,
2764 .pub_extern_const,
2765 .extern_var,
2766 .extern_var_threadlocal,
2767 .pub_extern_var,
2768 .pub_extern_var_threadlocal,
2769 => .@"extern",
2770 .export_const,
2771 .pub_export_const,
2772 .export_var,
2773 .export_var_threadlocal,
2774 .pub_export_var,
2775 .pub_export_var_threadlocal,
2776 => .@"export",
2777 else => .normal,
2778 };
2779 }
2780
2781 pub fn kind(id: Id) Declaration.Unwrapped.Kind {
2782 return switch (id) {
2783 .unnamed_test => .unnamed_test,
2784 .@"test" => .@"test",
2785 .decltest => .decltest,
2786 .@"comptime" => .@"comptime",
2787 .@"usingnamespace", .pub_usingnamespace => .@"usingnamespace",
2788 .const_simple,
2789 .const_typed,
2790 .@"const",
2791 .pub_const_simple,
2792 .pub_const_typed,
2793 .pub_const,
2794 .extern_const_simple,
2795 .extern_const,
2796 .pub_extern_const_simple,
2797 .pub_extern_const,
2798 .export_const,
2799 .pub_export_const,
2800 => .@"const",
2801 .var_simple,
2802 .@"var",
2803 .var_threadlocal,
2804 .pub_var_simple,
2805 .pub_var,
2806 .pub_var_threadlocal,
2807 .extern_var,
2808 .extern_var_threadlocal,
2809 .pub_extern_var,
2810 .pub_extern_var_threadlocal,
2811 .export_var,
2812 .export_var_threadlocal,
2813 .pub_export_var,
2814 .pub_export_var_threadlocal,
2815 => .@"var",
2816 };
2817 }
2818
2819 pub fn isPub(id: Id) bool {
2820 return switch (id) {
2821 .pub_usingnamespace,
2822 .pub_const_simple,
2823 .pub_const_typed,
2824 .pub_const,
2825 .pub_extern_const_simple,
2826 .pub_extern_const,
2827 .pub_export_const,
2828 .pub_var_simple,
2829 .pub_var,
2830 .pub_var_threadlocal,
2831 .pub_extern_var,
2832 .pub_extern_var_threadlocal,
2833 .pub_export_var,
2834 .pub_export_var_threadlocal,
2835 => true,
2836 else => false,
2837 };
2838 }
2839
2840 pub fn isThreadlocal(id: Id) bool {
2841 return switch (id) {
2842 .var_threadlocal,
2843 .pub_var_threadlocal,
2844 .extern_var_threadlocal,
2845 .pub_extern_var_threadlocal,
2846 .export_var_threadlocal,
2847 .pub_export_var_threadlocal,
2848 => true,
2849 else => false,
2850 };
2851 }
2852 };
26182853 };
26192854
26202855 pub const Name = enum(u32) {
......@@ -2647,17 +2882,24 @@ pub const Inst = struct {
26472882 };
26482883
26492884 pub const Bodies = struct {
2650 value_body: []const Index,
2885 type_body: ?[]const Index,
26512886 align_body: ?[]const Index,
26522887 linksection_body: ?[]const Index,
26532888 addrspace_body: ?[]const Index,
2889 value_body: ?[]const Index,
26542890 };
26552891
26562892 pub fn getBodies(declaration: Declaration, extra_end: u32, zir: Zir) Bodies {
26572893 var extra_index: u32 = extra_end;
2658 const value_body_len = declaration.flags.value_body_len;
2894 const value_body_len = declaration.value_body_len;
2895 const type_body_len: u32 = len: {
2896 if (!declaration.flags().kind.hasTypeBody()) break :len 0;
2897 const len = zir.extra[extra_index];
2898 extra_index += 1;
2899 break :len len;
2900 };
26592901 const align_body_len, const linksection_body_len, const addrspace_body_len = lens: {
2660 if (!declaration.flags.has_align_linksection_addrspace) {
2902 if (!declaration.flags.kind.hasSpecialBodies()) {
26612903 break :lens .{ 0, 0, 0 };
26622904 }
26632905 const lens = zir.extra[extra_index..][0..3].*;
......@@ -2665,21 +2907,30 @@ pub const Inst = struct {
26652907 break :lens lens;
26662908 };
26672909 return .{
2668 .value_body = b: {
2669 defer extra_index += value_body_len;
2670 break :b zir.bodySlice(extra_index, value_body_len);
2910 .type_body = if (type_body_len == 0) null else b: {
2911 const b = zir.bodySlice(extra_index, type_body_len);
2912 extra_index += type_body_len;
2913 break :b b;
26712914 },
26722915 .align_body = if (align_body_len == 0) null else b: {
2673 defer extra_index += align_body_len;
2674 break :b zir.bodySlice(extra_index, align_body_len);
2916 const b = zir.bodySlice(extra_index, align_body_len);
2917 extra_index += align_body_len;
2918 break :b b;
26752919 },
26762920 .linksection_body = if (linksection_body_len == 0) null else b: {
2677 defer extra_index += linksection_body_len;
2678 break :b zir.bodySlice(extra_index, linksection_body_len);
2921 const b = zir.bodySlice(extra_index, linksection_body_len);
2922 extra_index += linksection_body_len;
2923 break :b b;
26792924 },
26802925 .addrspace_body = if (addrspace_body_len == 0) null else b: {
2681 defer extra_index += addrspace_body_len;
2682 break :b zir.bodySlice(extra_index, addrspace_body_len);
2926 const b = zir.bodySlice(extra_index, addrspace_body_len);
2927 extra_index += addrspace_body_len;
2928 break :b b;
2929 },
2930 .value_body = if (value_body_len == 0) null else b: {
2931 const b = zir.bodySlice(extra_index, value_body_len);
2932 extra_index += value_body_len;
2933 break :b b;
26832934 },
26842935 };
26852936 }
......@@ -3711,18 +3962,18 @@ pub const DeclContents = struct {
37113962pub fn findTrackable(zir: Zir, gpa: Allocator, contents: *DeclContents, decl_inst: Zir.Inst.Index) !void {
37123963 contents.clear();
37133964
3714 const declaration, const extra_end = zir.getDeclaration(decl_inst);
3715 const bodies = declaration.getBodies(extra_end, zir);
3965 const decl = zir.getDeclaration(decl_inst);
37163966
37173967 // `defer` instructions duplicate the same body arbitrarily many times, but we only want to traverse
37183968 // their contents once per defer. So, we store the extra index of the body here to deduplicate.
37193969 var found_defers: std.AutoHashMapUnmanaged(u32, void) = .empty;
37203970 defer found_defers.deinit(gpa);
37213971
3722 try zir.findTrackableBody(gpa, contents, &found_defers, bodies.value_body);
3723 if (bodies.align_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3724 if (bodies.linksection_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3725 if (bodies.addrspace_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3972 if (decl.type_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3973 if (decl.align_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3974 if (decl.linksection_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3975 if (decl.addrspace_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3976 if (decl.value_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
37263977}
37273978
37283979/// Like `findTrackable`, but only considers the `main_struct_inst` instruction. This may return more than
......@@ -3991,7 +4242,6 @@ fn findTrackableInner(
39914242 .value_placeholder => unreachable,
39924243
39934244 // Once again, we start with the boring tags.
3994 .variable,
39954245 .this,
39964246 .ret_addr,
39974247 .builtin_src,
......@@ -4237,7 +4487,6 @@ fn findTrackableInner(
42374487 const inst_data = datas[@intFromEnum(inst)].pl_node;
42384488 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
42394489 var extra_index: usize = extra.end;
4240 extra_index += @intFromBool(extra.data.bits.has_lib_name);
42414490
42424491 if (extra.data.bits.has_cc_body) {
42434492 const body_len = zir.extra[extra_index];
......@@ -4470,8 +4719,7 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {
44704719 return zir.bodySlice(param_block.end, param_block.data.body_len);
44714720 },
44724721 .declaration => {
4473 const decl, const extra_end = zir.getDeclaration(param_block_index);
4474 return decl.getBodies(extra_end, zir).value_body;
4722 return zir.getDeclaration(param_block_index).value_body.?;
44754723 },
44764724 else => unreachable,
44774725 }
......@@ -4526,7 +4774,6 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
45264774 var ret_ty_ref: Inst.Ref = .void_type;
45274775 var ret_ty_body: []const Inst.Index = &.{};
45284776
4529 extra_index += @intFromBool(extra.data.bits.has_lib_name);
45304777 if (extra.data.bits.has_cc_body) {
45314778 extra_index += zir.extra[extra_index] + 1;
45324779 } else if (extra.data.bits.has_cc_ref) {
......@@ -4555,17 +4802,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
45554802 },
45564803 else => unreachable,
45574804 };
4558 const param_body = switch (tags[@intFromEnum(info.param_block)]) {
4559 .block, .block_comptime, .block_inline => param_body: {
4560 const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index);
4561 break :param_body zir.bodySlice(param_block.end, param_block.data.body_len);
4562 },
4563 .declaration => param_body: {
4564 const decl, const extra_end = zir.getDeclaration(info.param_block);
4565 break :param_body decl.getBodies(extra_end, zir).value_body;
4566 },
4567 else => unreachable,
4568 };
4805 const param_body = zir.getParamBody(fn_inst);
45694806 var total_params_len: u32 = 0;
45704807 for (param_body) |inst| {
45714808 switch (tags[@intFromEnum(inst)]) {
......@@ -4585,13 +4822,74 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
45854822 };
45864823}
45874824
4588pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, u32 } {
4825pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) Inst.Declaration.Unwrapped {
45894826 assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);
45904827 const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].declaration;
45914828 const extra = zir.extraData(Inst.Declaration, pl_node.payload_index);
4829
4830 const flags_vals: [2]u32 = .{ extra.data.flags_0, extra.data.flags_1 };
4831 const flags: Inst.Declaration.Flags = @bitCast(flags_vals);
4832
4833 var extra_index = extra.end;
4834
4835 const name: NullTerminatedString = if (flags.id.hasName()) name: {
4836 const name = zir.extra[extra_index];
4837 extra_index += 1;
4838 break :name @enumFromInt(name);
4839 } else .empty;
4840
4841 const lib_name: NullTerminatedString = if (flags.id.hasLibName()) lib_name: {
4842 const lib_name = zir.extra[extra_index];
4843 extra_index += 1;
4844 break :lib_name @enumFromInt(lib_name);
4845 } else .empty;
4846
4847 const type_body_len: u32 = if (flags.id.hasTypeBody()) len: {
4848 const len = zir.extra[extra_index];
4849 extra_index += 1;
4850 break :len len;
4851 } else 0;
4852 const align_body_len: u32, const linksection_body_len: u32, const addrspace_body_len: u32 = lens: {
4853 if (!flags.id.hasSpecialBodies()) break :lens .{ 0, 0, 0 };
4854 const lens = zir.extra[extra_index..][0..3].*;
4855 extra_index += 3;
4856 break :lens lens;
4857 };
4858 const value_body_len: u32 = if (flags.id.hasValueBody()) len: {
4859 const len = zir.extra[extra_index];
4860 extra_index += 1;
4861 break :len len;
4862 } else 0;
4863
4864 const type_body = zir.bodySlice(extra_index, type_body_len);
4865 extra_index += type_body_len;
4866 const align_body = zir.bodySlice(extra_index, align_body_len);
4867 extra_index += align_body_len;
4868 const linksection_body = zir.bodySlice(extra_index, linksection_body_len);
4869 extra_index += linksection_body_len;
4870 const addrspace_body = zir.bodySlice(extra_index, addrspace_body_len);
4871 extra_index += addrspace_body_len;
4872 const value_body = zir.bodySlice(extra_index, value_body_len);
4873 extra_index += value_body_len;
4874
45924875 return .{
4593 extra.data,
4594 @intCast(extra.end),
4876 .src_node = pl_node.src_node,
4877
4878 .src_line = flags.src_line,
4879 .src_column = flags.src_column,
4880
4881 .kind = flags.id.kind(),
4882 .name = name,
4883 .is_pub = flags.id.isPub(),
4884 .is_threadlocal = flags.id.isThreadlocal(),
4885 .linkage = flags.id.linkage(),
4886 .lib_name = lib_name,
4887
4888 .type_body = if (type_body_len == 0) null else type_body,
4889 .align_body = if (align_body_len == 0) null else align_body,
4890 .linksection_body = if (linksection_body_len == 0) null else linksection_body,
4891 .addrspace_body = if (addrspace_body_len == 0) null else addrspace_body,
4892 .value_body = if (value_body_len == 0) null else value_body,
45954893 };
45964894}
45974895
......@@ -4636,7 +4934,6 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
46364934 }
46374935 const bits = extra.data.bits;
46384936 var extra_index = extra.end;
4639 extra_index += @intFromBool(bits.has_lib_name);
46404937 if (bits.has_cc_body) {
46414938 const body_len = zir.extra[extra_index];
46424939 extra_index += 1 + body_len;
src/InternPool.zig-7
......@@ -2018,7 +2018,6 @@ pub const Key = union(enum) {
20182018 ty: Index,
20192019 init: Index,
20202020 owner_nav: Nav.Index,
2021 lib_name: OptionalNullTerminatedString,
20222021 is_threadlocal: bool,
20232022 is_weak_linkage: bool,
20242023 };
......@@ -2741,7 +2740,6 @@ pub const Key = union(enum) {
27412740 return a_info.owner_nav == b_info.owner_nav and
27422741 a_info.ty == b_info.ty and
27432742 a_info.init == b_info.init and
2744 a_info.lib_name == b_info.lib_name and
27452743 a_info.is_threadlocal == b_info.is_threadlocal and
27462744 a_info.is_weak_linkage == b_info.is_weak_linkage;
27472745 },
......@@ -5573,9 +5571,6 @@ pub const Tag = enum(u8) {
55735571 /// May be `none`.
55745572 init: Index,
55755573 owner_nav: Nav.Index,
5576 /// Library name if specified.
5577 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
5578 lib_name: OptionalNullTerminatedString,
55795574 flags: Flags,
55805575
55815576 pub const Flags = packed struct(u32) {
......@@ -6928,7 +6923,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
69286923 .ty = extra.ty,
69296924 .init = extra.init,
69306925 .owner_nav = extra.owner_nav,
6931 .lib_name = extra.lib_name,
69326926 .is_threadlocal = extra.flags.is_threadlocal,
69336927 .is_weak_linkage = extra.flags.is_weak_linkage,
69346928 } };
......@@ -7575,7 +7569,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
75757569 .ty = variable.ty,
75767570 .init = variable.init,
75777571 .owner_nav = variable.owner_nav,
7578 .lib_name = variable.lib_name,
75797572 .flags = .{
75807573 .is_const = false,
75817574 .is_threadlocal = variable.is_threadlocal,
src/Sema.zig+40-224
......@@ -1284,7 +1284,6 @@ fn analyzeBodyInner(
12841284 const extended = datas[@intFromEnum(inst)].extended;
12851285 break :ext switch (extended.opcode) {
12861286 // zig fmt: off
1287 .variable => try sema.zirVarExtended( block, extended),
12881287 .struct_decl => try sema.zirStructDecl( block, extended, inst),
12891288 .enum_decl => try sema.zirEnumDecl( block, extended, inst),
12901289 .union_decl => try sema.zirUnionDecl( block, extended, inst),
......@@ -2114,13 +2113,33 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
21142113}
21152114
21162115/// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value.
2117/// InternPool key `variable` is considered a runtime value.
21182116/// Generic poison causes `error.GenericPoison` to be returned.
21192117fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2120 const val = (try sema.resolveValueAllowVariables(inst)) orelse return null;
2121 if (val.isGenericPoison()) return error.GenericPoison;
2122 if (sema.pt.zcu.intern_pool.isVariable(val.toIntern())) return null;
2123 return val;
2118 const zcu = sema.pt.zcu;
2119 assert(inst != .none);
2120
2121 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
2122 return opv;
2123 }
2124
2125 if (inst.toInterned()) |ip_index| {
2126 const val: Value = .fromInterned(ip_index);
2127
2128 assert(val.getVariable(zcu) == null);
2129 if (val.isPtrRuntimeValue(zcu)) return null;
2130 if (val.isGenericPoison()) return error.GenericPoison;
2131
2132 return val;
2133 } else {
2134 // Runtime-known value.
2135 const air_tags = sema.air_instructions.items(.tag);
2136 switch (air_tags[@intFromEnum(inst.toIndex().?)]) {
2137 .inferred_alloc => unreachable, // assertion failure
2138 .inferred_alloc_comptime => unreachable, // assertion failure
2139 else => {},
2140 }
2141 return null;
2142 }
21242143}
21252144
21262145/// Like `resolveValue`, but emits an error if the value is not comptime-known.
......@@ -2183,35 +2202,6 @@ fn resolveValueIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
21832202 return try sema.resolveLazyValue(val);
21842203}
21852204
2186/// Returns all InternPool keys representing values, including `variable`, `undef`, and `generic_poison`.
2187fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2188 const pt = sema.pt;
2189 assert(inst != .none);
2190 // First section of indexes correspond to a set number of constant values.
2191 if (@intFromEnum(inst) < InternPool.static_len) {
2192 return Value.fromInterned(@as(InternPool.Index, @enumFromInt(@intFromEnum(inst))));
2193 }
2194
2195 const air_tags = sema.air_instructions.items(.tag);
2196 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
2197 if (inst.toInterned()) |ip_index| {
2198 const val = Value.fromInterned(ip_index);
2199 if (val.getVariable(pt.zcu) != null) return val;
2200 }
2201 return opv;
2202 }
2203 const ip_index = inst.toInterned() orelse {
2204 switch (air_tags[@intFromEnum(inst.toIndex().?)]) {
2205 .inferred_alloc => unreachable,
2206 .inferred_alloc_comptime => unreachable,
2207 else => return null,
2208 }
2209 };
2210 const val = Value.fromInterned(ip_index);
2211 if (val.isPtrRuntimeValue(pt.zcu)) return null;
2212 return val;
2213}
2214
22152205/// Value Tag may be `undef` or `variable`.
22162206pub fn resolveFinalDeclValue(
22172207 sema: *Sema,
......@@ -2221,8 +2211,13 @@ pub fn resolveFinalDeclValue(
22212211) CompileError!Value {
22222212 const zcu = sema.pt.zcu;
22232213
2224 const val = try sema.resolveValueAllowVariables(air_ref) orelse {
2225 const value_comptime_reason: ?[]const u8 = if (air_ref.toInterned()) |_|
2214 const val = try sema.resolveValue(air_ref) orelse {
2215 const is_runtime_ptr = rt_ptr: {
2216 const ip_index = air_ref.toInterned() orelse break :rt_ptr false;
2217 const val: Value = .fromInterned(ip_index);
2218 break :rt_ptr val.isPtrRuntimeValue(zcu);
2219 };
2220 const value_comptime_reason: ?[]const u8 = if (is_runtime_ptr)
22262221 "thread local and dll imported variables have runtime-known addresses"
22272222 else
22282223 null;
......@@ -2232,10 +2227,8 @@ pub fn resolveFinalDeclValue(
22322227 .value_comptime_reason = value_comptime_reason,
22332228 });
22342229 };
2235 if (val.isGenericPoison()) return error.GenericPoison;
22362230
2237 const init_val: Value = if (val.getVariable(zcu)) |v| .fromInterned(v.init) else val;
2238 if (init_val.canMutateComptimeVarState(zcu)) {
2231 if (val.canMutateComptimeVarState(zcu)) {
22392232 return sema.fail(block, src, "global variable contains reference to comptime var", .{});
22402233 }
22412234
......@@ -9525,8 +9518,8 @@ fn zirFunc(
95259518 } else sema.owner.unwrap().cau;
95269519 const fn_is_exported = exported: {
95279520 const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;
9528 const zir_decl = sema.code.getDeclaration(decl_inst)[0];
9529 break :exported zir_decl.flags.is_export;
9521 const zir_decl = sema.code.getDeclaration(decl_inst);
9522 break :exported zir_decl.linkage == .@"export";
95309523 };
95319524 if (fn_is_exported) {
95329525 break :cc target.cCallingConvention() orelse {
......@@ -9557,10 +9550,8 @@ fn zirFunc(
95579550 ret_ty,
95589551 false,
95599552 inferred_error_set,
9560 false,
95619553 has_body,
95629554 src_locs,
9563 null,
95649555 0,
95659556 false,
95669557 );
......@@ -9619,7 +9610,7 @@ fn resolveGenericBody(
96199610/// respective `Decl` (either `ExternFn` or `Var`).
96209611/// The liveness of the duped library name is tied to liveness of `Zcu`.
96219612/// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`).
9622fn handleExternLibName(
9613pub fn handleExternLibName(
96239614 sema: *Sema,
96249615 block: *Block,
96259616 src_loc: LazySrcLoc,
......@@ -9843,10 +9834,8 @@ fn funcCommon(
98439834 bare_return_type: Type,
98449835 var_args: bool,
98459836 inferred_error_set: bool,
9846 is_extern: bool,
98479837 has_body: bool,
98489838 src_locs: Zir.Inst.Func.SrcLocs,
9849 opt_lib_name: ?[]const u8,
98509839 noalias_bits: u32,
98519840 is_noinline: bool,
98529841) CompileError!Air.Inst.Ref {
......@@ -9998,7 +9987,6 @@ fn funcCommon(
99989987 }
99999988
100009989 if (inferred_error_set) {
10001 assert(!is_extern);
100029990 assert(has_body);
100039991 if (!ret_poison)
100049992 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
......@@ -10050,32 +10038,6 @@ fn funcCommon(
1005010038 .is_noinline = is_noinline,
1005110039 });
1005210040
10053 if (is_extern) {
10054 assert(comptime_bits == 0);
10055 assert(!is_generic);
10056 if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, block.src(.{
10057 .node_offset_lib_name = src_node_offset,
10058 }), lib_name);
10059 const extern_func_index = try sema.resolveExternDecl(block, .fromInterned(func_ty), opt_lib_name, true, false);
10060 return finishFunc(
10061 sema,
10062 block,
10063 extern_func_index,
10064 func_ty,
10065 ret_poison,
10066 bare_return_type,
10067 ret_ty_src,
10068 cc,
10069 is_source_decl,
10070 ret_ty_requires_comptime,
10071 func_inst,
10072 cc_src,
10073 is_noinline,
10074 is_generic,
10075 final_is_generic,
10076 );
10077 }
10078
1007910041 if (has_body) {
1008010042 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
1008110043 .owner_nav = sema.getOwnerCauNav(),
......@@ -26711,135 +26673,6 @@ fn zirAwaitNosuspend(
2671126673 return sema.failWithUseOfAsync(block, src);
2671226674}
2671326675
26714fn zirVarExtended(
26715 sema: *Sema,
26716 block: *Block,
26717 extended: Zir.Inst.Extended.InstData,
26718) CompileError!Air.Inst.Ref {
26719 const pt = sema.pt;
26720 const zcu = pt.zcu;
26721 const ip = &zcu.intern_pool;
26722 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
26723 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
26724 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
26725 const small: Zir.Inst.ExtendedVar.Small = @bitCast(extended.small);
26726
26727 var extra_index: usize = extra.end;
26728
26729 const lib_name = if (small.has_lib_name) lib_name: {
26730 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
26731 const lib_name = sema.code.nullTerminatedString(lib_name_index);
26732 extra_index += 1;
26733 try sema.handleExternLibName(block, ty_src, lib_name);
26734 break :lib_name lib_name;
26735 } else null;
26736
26737 // ZIR supports encoding this information but it is not used; the information
26738 // is encoded via the Decl entry.
26739 assert(!small.has_align);
26740
26741 const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: {
26742 const init_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
26743 extra_index += 1;
26744 break :blk try sema.resolveInst(init_ref);
26745 } else .none;
26746
26747 const have_ty = extra.data.var_type != .none;
26748 const var_ty = if (have_ty)
26749 try sema.resolveType(block, ty_src, extra.data.var_type)
26750 else
26751 sema.typeOf(uncasted_init);
26752
26753 const init_val = if (uncasted_init != .none) blk: {
26754 const init = if (have_ty)
26755 try sema.coerce(block, var_ty, uncasted_init, init_src)
26756 else
26757 uncasted_init;
26758
26759 break :blk ((try sema.resolveValue(init)) orelse {
26760 return sema.failWithNeededComptime(block, init_src, .{
26761 .needed_comptime_reason = "container level variable initializers must be comptime-known",
26762 });
26763 }).toIntern();
26764 } else .none;
26765
26766 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
26767
26768 if (small.is_extern) {
26769 const extern_val = try sema.resolveExternDecl(block, var_ty, lib_name, small.is_const, small.is_threadlocal);
26770 return Air.internedToRef(extern_val);
26771 }
26772 assert(!small.is_const); // non-const non-extern variable is not legal
26773 return Air.internedToRef(try pt.intern(.{ .variable = .{
26774 .ty = var_ty.toIntern(),
26775 .init = init_val,
26776 .owner_nav = sema.getOwnerCauNav(),
26777 .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls),
26778 .is_threadlocal = small.is_threadlocal,
26779 .is_weak_linkage = false,
26780 } }));
26781}
26782
26783fn resolveExternDecl(
26784 sema: *Sema,
26785 block: *Block,
26786 ty: Type,
26787 opt_lib_name: ?[]const u8,
26788 is_const: bool,
26789 is_threadlocal: bool,
26790) CompileError!InternPool.Index {
26791 const pt = sema.pt;
26792 const zcu = pt.zcu;
26793 const ip = &zcu.intern_pool;
26794
26795 // We need to resolve the alignment and addrspace early.
26796 // Keep in sync with logic in `Zcu.PerThread.semaCau`.
26797 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
26798 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
26799
26800 const decl_inst, const decl_bodies = decl: {
26801 const decl_inst = sema.getOwnerCauDeclInst().resolve(ip) orelse return error.AnalysisFail;
26802 const zir_decl, const extra_end = sema.code.getDeclaration(decl_inst);
26803 break :decl .{ decl_inst, zir_decl.getBodies(extra_end, sema.code) };
26804 };
26805
26806 const alignment: InternPool.Alignment = a: {
26807 const align_body = decl_bodies.align_body orelse break :a .none;
26808 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);
26809 break :a try sema.analyzeAsAlign(block, align_src, align_ref);
26810 };
26811
26812 const @"addrspace": std.builtin.AddressSpace = as: {
26813 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(ty.toIntern())) {
26814 .func_type => .function,
26815 else => .variable,
26816 };
26817 const target = zcu.getTarget();
26818 const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
26819 .function => target_util.defaultAddressSpace(target, .function),
26820 .variable => target_util.defaultAddressSpace(target, .global_mutable),
26821 .constant => target_util.defaultAddressSpace(target, .global_constant),
26822 else => unreachable,
26823 };
26824 const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst);
26825 break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx);
26826 };
26827
26828 return pt.getExtern(.{
26829 .name = sema.getOwnerCauNavName(),
26830 .ty = ty.toIntern(),
26831 .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, opt_lib_name, .no_embedded_nulls),
26832 .is_const = is_const,
26833 .is_threadlocal = is_threadlocal,
26834 .is_weak_linkage = false,
26835 .is_dll_import = false,
26836 .alignment = alignment,
26837 .@"addrspace" = @"addrspace",
26838 .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction
26839 .owner_nav = undefined, // ignored by `getExtern`
26840 });
26841}
26842
2684326676fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2684426677 const tracy = trace(@src());
2684526678 defer tracy.end();
......@@ -26857,13 +26690,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2685726690
2685826691 var extra_index: usize = extra.end;
2685926692
26860 const lib_name: ?[]const u8 = if (extra.data.bits.has_lib_name) blk: {
26861 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
26862 const lib_name = sema.code.nullTerminatedString(lib_name_index);
26863 extra_index += 1;
26864 break :blk lib_name;
26865 } else null;
26866
2686726693 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
2686826694 const body_len = sema.code.extra[extra_index];
2686926695 extra_index += 1;
......@@ -26895,8 +26721,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2689526721 break :decl_inst cau.zir_index;
2689626722 } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau
2689726723
26898 const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail)[0];
26899 if (zir_decl.flags.is_export) {
26724 const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail);
26725 if (zir_decl.linkage == .@"export") {
2690026726 break :cc target.cCallingConvention() orelse {
2690126727 // This target has no default C calling convention. We sometimes trigger a similar
2690226728 // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
......@@ -26958,7 +26784,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2695826784
2695926785 const is_var_args = extra.data.bits.is_var_args;
2696026786 const is_inferred_error = extra.data.bits.is_inferred_error;
26961 const is_extern = extra.data.bits.is_extern;
2696226787 const is_noinline = extra.data.bits.is_noinline;
2696326788
2696426789 return sema.funcCommon(
......@@ -26969,10 +26794,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2696926794 ret_ty,
2697026795 is_var_args,
2697126796 is_inferred_error,
26972 is_extern,
2697326797 has_body,
2697426798 src_locs,
26975 lib_name,
2697626799 noalias_bits,
2697726800 is_noinline,
2697826801 );
......@@ -27467,7 +27290,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
2746727290}
2746827291
2746927292/// Emit a compile error if type cannot be used for a runtime variable.
27470fn validateVarType(
27293pub fn validateVarType(
2747127294 sema: *Sema,
2747227295 block: *Block,
2747327296 src: LazySrcLoc,
......@@ -29881,7 +29704,7 @@ fn elemPtrSlice(
2988129704 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
2988229705}
2988329706
29884fn coerce(
29707pub fn coerce(
2988529708 sema: *Sema,
2988629709 block: *Block,
2988729710 dest_ty_unresolved: Type,
......@@ -38843,13 +38666,6 @@ fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {
3884338666 return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;
3884438667}
3884538668
38846/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38847/// the declaration name from its corresponding `Nav`.
38848fn getOwnerCauNavName(sema: *Sema) InternPool.NullTerminatedString {
38849 const nav = sema.getOwnerCauNav();
38850 return sema.pt.zcu.intern_pool.getNav(nav).name;
38851}
38852
3885338669/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
3885438670/// the `TrackedInst` corresponding to this `declaration` instruction.
3885538671fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
src/Zcu.zig+33-46
......@@ -2679,24 +2679,14 @@ pub fn mapOldZirToNew(
26792679 {
26802680 var old_decl_it = old_zir.declIterator(match_item.old_inst);
26812681 while (old_decl_it.next()) |old_decl_inst| {
2682 const old_decl, _ = old_zir.getDeclaration(old_decl_inst);
2683 switch (old_decl.name) {
2682 const old_decl = old_zir.getDeclaration(old_decl_inst);
2683 switch (old_decl.kind) {
26842684 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
26852685 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),
26862686 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
2687 _ => {
2688 const name_nts = old_decl.name.toString(old_zir).?;
2689 const name = old_zir.nullTerminatedString(name_nts);
2690 if (old_decl.name.isNamedTest(old_zir)) {
2691 if (old_decl.flags.test_is_decltest) {
2692 try named_decltests.put(gpa, name, old_decl_inst);
2693 } else {
2694 try named_tests.put(gpa, name, old_decl_inst);
2695 }
2696 } else {
2697 try named_decls.put(gpa, name, old_decl_inst);
2698 }
2699 },
2687 .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
2688 .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
2689 .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
27002690 }
27012691 }
27022692 }
......@@ -2707,7 +2697,7 @@ pub fn mapOldZirToNew(
27072697
27082698 var new_decl_it = new_zir.declIterator(match_item.new_inst);
27092699 while (new_decl_it.next()) |new_decl_inst| {
2710 const new_decl, _ = new_zir.getDeclaration(new_decl_inst);
2700 const new_decl = new_zir.getDeclaration(new_decl_inst);
27112701 // Attempt to match this to a declaration in the old ZIR:
27122702 // * For named declarations (`const`/`var`/`fn`), we match based on name.
27132703 // * For named tests (`test "foo"`) and decltests (`test foo`), we also match based on name.
......@@ -2715,7 +2705,7 @@ pub fn mapOldZirToNew(
27152705 // * For comptime blocks, we match based on order.
27162706 // * For usingnamespace decls, we match based on order.
27172707 // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`.
2718 const old_decl_inst = switch (new_decl.name) {
2708 const old_decl_inst = switch (new_decl.kind) {
27192709 .@"comptime" => inst: {
27202710 if (comptime_decl_idx == comptime_decls.items.len) continue;
27212711 defer comptime_decl_idx += 1;
......@@ -2731,18 +2721,17 @@ pub fn mapOldZirToNew(
27312721 defer unnamed_test_idx += 1;
27322722 break :inst unnamed_tests.items[unnamed_test_idx];
27332723 },
2734 _ => inst: {
2735 const name_nts = new_decl.name.toString(new_zir).?;
2736 const name = new_zir.nullTerminatedString(name_nts);
2737 if (new_decl.name.isNamedTest(new_zir)) {
2738 if (new_decl.flags.test_is_decltest) {
2739 break :inst named_decltests.get(name) orelse continue;
2740 } else {
2741 break :inst named_tests.get(name) orelse continue;
2742 }
2743 } else {
2744 break :inst named_decls.get(name) orelse continue;
2745 }
2724 .@"test" => inst: {
2725 const name = new_zir.nullTerminatedString(new_decl.name);
2726 break :inst named_tests.get(name) orelse continue;
2727 },
2728 .decltest => inst: {
2729 const name = new_zir.nullTerminatedString(new_decl.name);
2730 break :inst named_decltests.get(name) orelse continue;
2731 },
2732 .@"const", .@"var" => inst: {
2733 const name = new_zir.nullTerminatedString(new_decl.name);
2734 break :inst named_decls.get(name) orelse continue;
27462735 },
27472736 };
27482737
......@@ -3353,20 +3342,20 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
33533342 const file = zcu.fileByIndex(inst_info.file);
33543343 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
33553344 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3356 const declaration = zir.getDeclaration(inst_info.inst)[0];
3357 const want_analysis = switch (declaration.name) {
3345 const decl = zir.getDeclaration(inst_info.inst);
3346 const want_analysis = switch (decl.kind) {
33583347 .@"usingnamespace" => unreachable,
3348 .@"const", .@"var" => unreachable,
33593349 .@"comptime" => true,
3360 else => a: {
3350 .unnamed_test => comp.config.is_test and file.mod == zcu.main_mod,
3351 .@"test", .decltest => a: {
33613352 if (!comp.config.is_test) break :a false;
33623353 if (file.mod != zcu.main_mod) break :a false;
3363 if (declaration.name.isNamedTest(zir)) {
3364 const nav = ip.getCau(cau).owner.unwrap().nav;
3365 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
3366 for (comp.test_filters) |test_filter| {
3367 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3368 } else break :a false;
3369 }
3354 const nav = ip.getCau(cau).owner.unwrap().nav;
3355 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
3356 for (comp.test_filters) |test_filter| {
3357 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3358 } else break :a false;
33703359 break :a true;
33713360 },
33723361 };
......@@ -3388,8 +3377,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
33883377 const file = zcu.fileByIndex(inst_info.file);
33893378 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
33903379 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3391 const declaration = zir.getDeclaration(inst_info.inst)[0];
3392 if (declaration.flags.is_export) {
3380 const decl = zir.getDeclaration(inst_info.inst);
3381 if (decl.linkage == .@"export") {
33933382 const unit = AnalUnit.wrap(.{ .cau = cau });
33943383 if (!result.contains(unit)) {
33953384 log.debug("type '{}': ref cau %{}", .{
......@@ -3407,8 +3396,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
34073396 const file = zcu.fileByIndex(inst_info.file);
34083397 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
34093398 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3410 const declaration = zir.getDeclaration(inst_info.inst)[0];
3411 if (declaration.flags.is_export) {
3399 const decl = zir.getDeclaration(inst_info.inst);
3400 if (decl.linkage == .@"export") {
34123401 const unit = AnalUnit.wrap(.{ .cau = cau });
34133402 if (!result.contains(unit)) {
34143403 log.debug("type '{}': ref cau %{}", .{
......@@ -3522,9 +3511,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
35223511 const ip = &zcu.intern_pool;
35233512 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;
35243513 const zir = zcu.fileByIndex(inst_info.file).zir;
3525 const inst = zir.instructions.get(@intFromEnum(inst_info.inst));
3526 assert(inst.tag == .declaration);
3527 return zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line;
3514 return zir.getDeclaration(inst_info.inst).src_line;
35283515}
35293516
35303517pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {
src/Zcu/PerThread.zig+151-85
......@@ -469,12 +469,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
469469 {
470470 var it = old_zir.declIterator(old_inst);
471471 while (it.next()) |decl_inst| {
472 const decl_name = old_zir.getDeclaration(decl_inst)[0].name;
473 switch (decl_name) {
474 .@"comptime", .@"usingnamespace", .unnamed_test => continue,
475 _ => if (decl_name.isNamedTest(old_zir)) continue,
476 }
477 const name_zir = decl_name.toString(old_zir).?;
472 const name_zir = old_zir.getDeclaration(decl_inst).name;
473 if (name_zir == .empty) continue;
478474 const name_ip = try zcu.intern_pool.getOrPutString(
479475 zcu.gpa,
480476 pt.tid,
......@@ -488,12 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
488484 {
489485 var it = new_zir.declIterator(new_inst);
490486 while (it.next()) |decl_inst| {
491 const decl_name = new_zir.getDeclaration(decl_inst)[0].name;
492 switch (decl_name) {
493 .@"comptime", .@"usingnamespace", .unnamed_test => continue,
494 _ => if (decl_name.isNamedTest(new_zir)) continue,
495 }
496 const name_zir = decl_name.toString(new_zir).?;
487 const name_zir = new_zir.getDeclaration(decl_inst).name;
488 if (name_zir == .empty) continue;
497489 const name_ip = try zcu.intern_pool.getOrPutString(
498490 zcu.gpa,
499491 pt.tid,
......@@ -1252,10 +1244,7 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
12521244 };
12531245 defer block.instructions.deinit(gpa);
12541246
1255 const zir_decl: Zir.Inst.Declaration, const decl_bodies: Zir.Inst.Declaration.Bodies = decl: {
1256 const decl, const extra_end = zir.getDeclaration(inst_info.inst);
1257 break :decl .{ decl, decl.getBodies(extra_end, zir) };
1258 };
1247 const zir_decl = zir.getDeclaration(inst_info.inst);
12591248
12601249 // We have to fetch this state before resolving the body because of the `nav_already_populated`
12611250 // case below. We might change the language in future so that align/linksection/etc for functions
......@@ -1265,7 +1254,134 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
12651254 .nav => |nav| ip.getNav(nav),
12661255 };
12671256
1268 const result_ref = try sema.resolveInlineBody(&block, decl_bodies.value_body, inst_info.inst);
1257 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
1258 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
1259 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
1260 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1261 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
1262
1263 // First, we must resolve the declaration's type. To do this, we analyze the type body if available,
1264 // or otherwise, we analyze the value body, populating `early_val` in the process.
1265
1266 const decl_ty: Type, const early_val: ?Value = if (zir_decl.type_body) |type_body| ty: {
1267 // We evaluate only the type now; no need for the value yet.
1268 const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_info.inst);
1269 const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
1270 break :ty .{ .fromInterned(type_ref.toInterned().?), null };
1271 } else ty: {
1272 // We don't have a type body, so we need to evaluate the value immediately.
1273 const value_body = zir_decl.value_body.?;
1274 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1275 const val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1276 break :ty .{ val.typeOf(zcu), val };
1277 };
1278
1279 switch (zir_decl.kind) {
1280 .unnamed_test, .@"test", .decltest => assert(decl_ty.zigTypeTag(zcu) == .@"fn"),
1281 .@"comptime" => assert(decl_ty.toIntern() == .void_type),
1282 .@"usingnamespace" => {},
1283 .@"const" => {},
1284 .@"var" => try sema.validateVarType(
1285 &block,
1286 if (zir_decl.type_body != null) ty_src else init_src,
1287 decl_ty,
1288 zir_decl.linkage == .@"extern",
1289 ),
1290 }
1291
1292 // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine
1293 // the full pointer type of this declaration.
1294
1295 const alignment: InternPool.Alignment = a: {
1296 const align_body = zir_decl.align_body orelse break :a .none;
1297 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
1298 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
1299 };
1300
1301 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
1302 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
1303 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
1304 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
1305 .needed_comptime_reason = "linksection must be comptime-known",
1306 });
1307 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
1308 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
1309 } else if (bytes.len == 0) {
1310 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
1311 }
1312 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
1313 };
1314
1315 const @"addrspace": std.builtin.AddressSpace = as: {
1316 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {
1317 .@"var" => .variable,
1318 else => switch (decl_ty.zigTypeTag(zcu)) {
1319 .@"fn" => .function,
1320 else => .constant,
1321 },
1322 };
1323 const target = zcu.getTarget();
1324 const addrspace_body = zir_decl.addrspace_body orelse break :as switch (addrspace_ctx) {
1325 .function => target_util.defaultAddressSpace(target, .function),
1326 .variable => target_util.defaultAddressSpace(target, .global_mutable),
1327 .constant => target_util.defaultAddressSpace(target, .global_constant),
1328 else => unreachable,
1329 };
1330 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
1331 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
1332 };
1333
1334 // Lastly, we must evaluate the value if we have not already done so. Note, however, that extern declarations
1335 // don't have an associated value body.
1336
1337 const final_val: ?Value = early_val orelse if (zir_decl.value_body) |value_body| val: {
1338 // Put the resolved type into `inst_map` to be used as the result type of the init.
1339 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{inst_info.inst});
1340 sema.inst_map.putAssumeCapacity(inst_info.inst, Air.internedToRef(decl_ty.toIntern()));
1341 const uncoerced_result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1342 assert(sema.inst_map.remove(inst_info.inst));
1343
1344 const result_ref = try sema.coerce(&block, decl_ty, uncoerced_result_ref, init_src);
1345 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1346 } else null;
1347
1348 // TODO: missing validation?
1349
1350 const decl_val: Value = switch (zir_decl.linkage) {
1351 .normal, .@"export" => switch (zir_decl.kind) {
1352 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{
1353 .ty = decl_ty.toIntern(),
1354 .init = final_val.?.toIntern(),
1355 .owner_nav = cau.owner.unwrap().nav,
1356 .is_threadlocal = zir_decl.is_threadlocal,
1357 .is_weak_linkage = false,
1358 } })),
1359 else => final_val.?,
1360 },
1361 .@"extern" => val: {
1362 assert(final_val == null); // extern decls do not have a value body
1363 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
1364 break :l zir.nullTerminatedString(zir_decl.lib_name);
1365 } else null;
1366 if (lib_name) |l| {
1367 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });
1368 try sema.handleExternLibName(&block, lib_name_src, l);
1369 }
1370 break :val .fromInterned(try pt.getExtern(.{
1371 .name = old_nav_info.name,
1372 .ty = decl_ty.toIntern(),
1373 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),
1374 .is_const = zir_decl.kind == .@"const",
1375 .is_threadlocal = zir_decl.is_threadlocal,
1376 .is_weak_linkage = false,
1377 .is_dll_import = false,
1378 .alignment = alignment,
1379 .@"addrspace" = @"addrspace",
1380 .zir_index = cau.zir_index, // `declaration` instruction
1381 .owner_nav = undefined, // ignored by `getExtern`
1382 }));
1383 },
1384 };
12691385
12701386 const nav_index = switch (cau.owner.unwrap()) {
12711387 .none => {
......@@ -1282,15 +1398,6 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
12821398 .type => unreachable, // Handled at top of function.
12831399 };
12841400
1285 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
1286 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
1287 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
1288 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1289 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
1290
1291 const decl_val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1292 const decl_ty = decl_val.typeOf(zcu);
1293
12941401 switch (decl_val.toIntern()) {
12951402 .generic_poison => unreachable, // assertion failure
12961403 .unreachable_value => unreachable, // assertion failure
......@@ -1331,50 +1438,10 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
13311438 };
13321439
13331440 // Keep in sync with logic in `Sema.zirVarExtended`.
1334 const alignment: InternPool.Alignment = a: {
1335 const align_body = decl_bodies.align_body orelse break :a .none;
1336 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
1337 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
1338 };
1339
1340 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
1341 const linksection_body = decl_bodies.linksection_body orelse break :ls .none;
1342 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
1343 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
1344 .needed_comptime_reason = "linksection must be comptime-known",
1345 });
1346 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
1347 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
1348 } else if (bytes.len == 0) {
1349 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
1350 }
1351 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
1352 };
1353
1354 const @"addrspace": std.builtin.AddressSpace = as: {
1355 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
1356 .func => .function,
1357 .variable => .variable,
1358 .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type)
1359 .function
1360 else
1361 .variable,
1362 else => .constant,
1363 };
1364 const target = zcu.getTarget();
1365 const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
1366 .function => target_util.defaultAddressSpace(target, .function),
1367 .variable => target_util.defaultAddressSpace(target, .global_mutable),
1368 .constant => target_util.defaultAddressSpace(target, .global_constant),
1369 else => unreachable,
1370 };
1371 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
1372 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
1373 };
13741441
13751442 if (is_owned_fn) {
13761443 // linksection etc are legal, except some targets do not support function alignment.
1377 if (decl_bodies.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
1444 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
13781445 return sema.fail(&block, align_src, "target does not support function alignment", .{});
13791446 }
13801447 } else if (try decl_ty.comptimeOnlySema(pt)) {
......@@ -1383,13 +1450,13 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
13831450 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
13841451 else => "comptime-only type",
13851452 };
1386 if (decl_bodies.align_body != null) {
1453 if (zir_decl.align_body != null) {
13871454 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
13881455 }
1389 if (decl_bodies.linksection_body != null) {
1456 if (zir_decl.linksection_body != null) {
13901457 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
13911458 }
1392 if (decl_bodies.addrspace_body != null) {
1459 if (zir_decl.addrspace_body != null) {
13931460 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
13941461 }
13951462 }
......@@ -1404,9 +1471,9 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
14041471 // Mark the `Cau` as completed before evaluating the export!
14051472 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
14061473
1407 if (zir_decl.flags.is_export) {
1408 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.flags.is_pub) });
1409 const name_slice = zir.nullTerminatedString(zir_decl.name.toString(zir).?);
1474 if (zir_decl.linkage == .@"export") {
1475 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1476 const name_slice = zir.nullTerminatedString(zir_decl.name);
14101477 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
14111478 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_index);
14121479 }
......@@ -1919,13 +1986,11 @@ const ScanDeclIter = struct {
19191986 const zir = file.zir;
19201987 const ip = &zcu.intern_pool;
19211988
1922 const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;
1923 const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
1924 const declaration = extra.data;
1989 const decl = zir.getDeclaration(decl_inst);
19251990
19261991 const Kind = enum { @"comptime", @"usingnamespace", @"test", named };
19271992
1928 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (declaration.name) {
1993 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (decl.kind) {
19291994 .@"comptime" => info: {
19301995 if (iter.pass != .unnamed) return;
19311996 break :info .{
......@@ -1954,21 +2019,22 @@ const ScanDeclIter = struct {
19542019 false,
19552020 };
19562021 },
1957 _ => if (declaration.name.isNamedTest(zir)) info: {
2022 .@"test", .decltest => |kind| info: {
19582023 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
19592024 if (iter.pass != .unnamed) return;
1960 const prefix = if (declaration.flags.test_is_decltest) "decltest" else "test";
2025 const prefix = @tagName(kind);
19612026 break :info .{
1962 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(declaration.name.toString(zir).?) })).toOptional(),
2027 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(decl.name) })).toOptional(),
19632028 .@"test",
19642029 true,
19652030 };
1966 } else info: {
2031 },
2032 .@"const", .@"var" => info: {
19672033 if (iter.pass != .named) return;
19682034 const name = try ip.getOrPutString(
19692035 gpa,
19702036 pt.tid,
1971 zir.nullTerminatedString(declaration.name.toString(zir).?),
2037 zir.nullTerminatedString(decl.name),
19722038 .no_embedded_nulls,
19732039 );
19742040 try iter.seen_decls.putNoClobber(gpa, name, {});
......@@ -2030,7 +2096,7 @@ const ScanDeclIter = struct {
20302096 if (comp.incremental) {
20312097 @panic("'usingnamespace' is not supported by incremental compilation");
20322098 }
2033 if (declaration.flags.is_pub) {
2099 if (decl.is_pub) {
20342100 try namespace.pub_usingnamespace.append(gpa, nav);
20352101 } else {
20362102 try namespace.priv_usingnamespace.append(gpa, nav);
......@@ -2056,7 +2122,7 @@ const ScanDeclIter = struct {
20562122 break :a true;
20572123 },
20582124 .named => a: {
2059 if (declaration.flags.is_pub) {
2125 if (decl.is_pub) {
20602126 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
20612127 } else {
20622128 try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
......@@ -2068,7 +2134,7 @@ const ScanDeclIter = struct {
20682134 },
20692135 };
20702136
2071 if (existing_cau == null and (want_analysis or declaration.flags.is_export)) {
2137 if (existing_cau == null and (want_analysis or decl.linkage == .@"export")) {
20722138 log.debug(
20732139 "scanDecl queue analyze_cau file='{s}' cau_index={d}",
20742140 .{ namespace.fileScope(zcu).sub_file_path, cau },
src/codegen.zig+1-1
......@@ -853,7 +853,7 @@ fn genNavRef(
853853
854854 const nav_index, const is_extern, const lib_name, const is_threadlocal = switch (ip.indexToKey(zcu.navValue(ref_nav_index).toIntern())) {
855855 .func => |func| .{ func.owner_nav, false, .none, false },
856 .variable => |variable| .{ variable.owner_nav, false, variable.lib_name, variable.is_threadlocal },
856 .variable => |variable| .{ variable.owner_nav, false, .none, variable.is_threadlocal },
857857 .@"extern" => |@"extern"| .{ @"extern".owner_nav, true, @"extern".lib_name, @"extern".is_threadlocal },
858858 else => .{ ref_nav_index, false, .none, false },
859859 };
src/codegen/llvm.zig+1-2
......@@ -2939,7 +2939,6 @@ pub const Object = struct {
29392939 const sret = firstParamSRet(fn_info, zcu, target);
29402940
29412941 const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) {
2942 .variable => |variable| .{ false, variable.lib_name },
29432942 .@"extern" => |@"extern"| .{ true, @"extern".lib_name },
29442943 else => .{ false, .none },
29452944 };
......@@ -4803,7 +4802,7 @@ pub const NavGen = struct {
48034802 const resolved = nav.status.resolved;
48044803
48054804 const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) {
4806 .variable => |variable| .{ false, variable.lib_name, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
4805 .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
48074806 .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav },
48084807 else => .{ false, .none, false, false, false, true, resolved.val, nav_index },
48094808 };
src/link/Dwarf.zig+12-48
......@@ -2259,24 +2259,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
22592259 switch (ip.indexToKey(nav_val.toIntern())) {
22602260 else => {
22612261 assert(file.zir_loaded);
2262 const decl = file.zir.getDeclaration(inst_info.inst)[0];
2262 const decl = file.zir.getDeclaration(inst_info.inst);
22632263
22642264 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
22652265 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
22662266 break :parent .{
22672267 parent_namespace_ptr.owner_type,
2268 switch (decl.name) {
2269 .@"comptime",
2270 .@"usingnamespace",
2271 .unnamed_test,
2272 => DW.ACCESS.private,
2273 _ => if (decl.name.isNamedTest(file.zir))
2274 DW.ACCESS.private
2275 else if (decl.flags.is_pub)
2276 DW.ACCESS.public
2277 else
2278 DW.ACCESS.private,
2279 },
2268 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
22802269 };
22812270 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
22822271
......@@ -2301,24 +2290,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
23012290 },
23022291 .variable => |variable| {
23032292 assert(file.zir_loaded);
2304 const decl = file.zir.getDeclaration(inst_info.inst)[0];
2293 const decl = file.zir.getDeclaration(inst_info.inst);
23052294
23062295 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
23072296 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
23082297 break :parent .{
23092298 parent_namespace_ptr.owner_type,
2310 switch (decl.name) {
2311 .@"comptime",
2312 .@"usingnamespace",
2313 .unnamed_test,
2314 => DW.ACCESS.private,
2315 _ => if (decl.name.isNamedTest(file.zir))
2316 DW.ACCESS.private
2317 else if (decl.flags.is_pub)
2318 DW.ACCESS.public
2319 else
2320 DW.ACCESS.private,
2321 },
2299 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
23222300 };
23232301 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
23242302
......@@ -2341,24 +2319,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
23412319 },
23422320 .func => |func| {
23432321 assert(file.zir_loaded);
2344 const decl = file.zir.getDeclaration(inst_info.inst)[0];
2322 const decl = file.zir.getDeclaration(inst_info.inst);
23452323
23462324 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
23472325 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
23482326 break :parent .{
23492327 parent_namespace_ptr.owner_type,
2350 switch (decl.name) {
2351 .@"comptime",
2352 .@"usingnamespace",
2353 .unnamed_test,
2354 => DW.ACCESS.private,
2355 _ => if (decl.name.isNamedTest(file.zir))
2356 DW.ACCESS.private
2357 else if (decl.flags.is_pub)
2358 DW.ACCESS.public
2359 else
2360 DW.ACCESS.private,
2361 },
2328 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
23622329 };
23632330 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
23642331
......@@ -2585,12 +2552,11 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
25852552 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
25862553 const file = zcu.fileByIndex(inst_info.file);
25872554 assert(file.zir_loaded);
2588 const decl = file.zir.getDeclaration(inst_info.inst)[0];
2555 const decl = file.zir.getDeclaration(inst_info.inst);
25892556
2590 const is_test = switch (decl.name) {
2591 .unnamed_test => true,
2592 .@"comptime", .@"usingnamespace" => false,
2593 _ => decl.name.isNamedTest(file.zir),
2557 const is_test = switch (decl.kind) {
2558 .unnamed_test, .@"test", .decltest => true,
2559 .@"comptime", .@"usingnamespace", .@"const", .@"var" => false,
25942560 };
25952561 if (is_test) {
25962562 // This isn't actually a comptime Nav! It's a test, so it'll definitely never be referenced at comptime.
......@@ -2601,7 +2567,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
26012567 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
26022568 break :parent .{
26032569 parent_namespace_ptr.owner_type,
2604 if (decl.flags.is_pub) DW.ACCESS.public else DW.ACCESS.private,
2570 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
26052571 };
26062572 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
26072573
......@@ -4198,9 +4164,7 @@ pub fn updateNavLineNumber(dwarf: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.I
41984164 assert(inst_info.inst != .main_struct_inst);
41994165 const file = zcu.fileByIndex(inst_info.file);
42004166
4201 const inst = file.zir.instructions.get(@intFromEnum(inst_info.inst));
4202 assert(inst.tag == .declaration);
4203 const line = file.zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line;
4167 const line = file.zir.getDeclaration(inst_info.inst).src_line;
42044168 var line_buf: [4]u8 = undefined;
42054169 std.mem.writeInt(u32, &line_buf, line, dwarf.endian);
42064170
src/link/Wasm/ZigObject.zig+1-1
......@@ -241,7 +241,7 @@ pub fn updateNav(
241241
242242 const nav_val = zcu.navValue(nav_index);
243243 const is_extern, const lib_name, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
244 .variable => |variable| .{ false, variable.lib_name, Value.fromInterned(variable.init) },
244 .variable => |variable| .{ false, .none, Value.fromInterned(variable.init) },
245245 .func => return,
246246 .@"extern" => |@"extern"| if (ip.isFunctionType(nav.typeOf(ip)))
247247 return
src/print_zir.zig+29-69
......@@ -542,7 +542,6 @@ const Writer = struct {
542542
543543 .@"asm" => try self.writeAsm(stream, extended, false),
544544 .asm_expr => try self.writeAsm(stream, extended, true),
545 .variable => try self.writeVarExtended(stream, extended),
546545 .alloc => try self.writeAllocExtended(stream, extended),
547546
548547 .compile_log => try self.writeNodeMultiOp(stream, extended),
......@@ -2347,7 +2346,6 @@ const Writer = struct {
23472346 inferred_error_set,
23482347 false,
23492348 false,
2350 false,
23512349
23522350 .none,
23532351 &.{},
......@@ -2371,13 +2369,6 @@ const Writer = struct {
23712369 var ret_ty_ref: Zir.Inst.Ref = .none;
23722370 var ret_ty_body: []const Zir.Inst.Index = &.{};
23732371
2374 if (extra.data.bits.has_lib_name) {
2375 const lib_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
2376 extra_index += 1;
2377 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
2378 }
2379 try self.writeFlag(stream, "test, ", extra.data.bits.is_test);
2380
23812372 if (extra.data.bits.has_cc_body) {
23822373 const body_len = self.code.extra[extra_index];
23832374 extra_index += 1;
......@@ -2414,7 +2405,6 @@ const Writer = struct {
24142405 stream,
24152406 extra.data.bits.is_inferred_error,
24162407 extra.data.bits.is_var_args,
2417 extra.data.bits.is_extern,
24182408 extra.data.bits.is_noinline,
24192409 cc_ref,
24202410 cc_body,
......@@ -2427,36 +2417,6 @@ const Writer = struct {
24272417 );
24282418 }
24292419
2430 fn writeVarExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
2431 const extra = self.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
2432 const small = @as(Zir.Inst.ExtendedVar.Small, @bitCast(extended.small));
2433
2434 try self.writeInstRef(stream, extra.data.var_type);
2435
2436 var extra_index: usize = extra.end;
2437 if (small.has_lib_name) {
2438 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
2439 const lib_name = self.code.nullTerminatedString(lib_name_index);
2440 extra_index += 1;
2441 try stream.print(", lib_name=\"{}\"", .{std.zig.fmtEscapes(lib_name)});
2442 }
2443 const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
2444 const align_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
2445 extra_index += 1;
2446 break :blk align_inst;
2447 };
2448 const init_inst: Zir.Inst.Ref = if (!small.has_init) .none else blk: {
2449 const init_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
2450 extra_index += 1;
2451 break :blk init_inst;
2452 };
2453 try self.writeFlag(stream, ", is_extern", small.is_extern);
2454 try self.writeFlag(stream, ", is_threadlocal", small.is_threadlocal);
2455 try self.writeOptionalInstRef(stream, ", align=", align_inst);
2456 try self.writeOptionalInstRef(stream, ", init=", init_inst);
2457 try stream.writeAll("))");
2458 }
2459
24602420 fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
24612421 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
24622422 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
......@@ -2604,7 +2564,6 @@ const Writer = struct {
26042564 stream: anytype,
26052565 inferred_error_set: bool,
26062566 var_args: bool,
2607 is_extern: bool,
26082567 is_noinline: bool,
26092568 cc_ref: Zir.Inst.Ref,
26102569 cc_body: []const Zir.Inst.Index,
......@@ -2618,7 +2577,6 @@ const Writer = struct {
26182577 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
26192578 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
26202579 try self.writeFlag(stream, "vargs, ", var_args);
2621 try self.writeFlag(stream, "extern, ", is_extern);
26222580 try self.writeFlag(stream, "inferror, ", inferred_error_set);
26232581 try self.writeFlag(stream, "noinline, ", is_noinline);
26242582
......@@ -2664,56 +2622,58 @@ const Writer = struct {
26642622 }
26652623
26662624 fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2667 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].declaration;
2668 const extra = self.code.extraData(Zir.Inst.Declaration, inst_data.payload_index);
2625 const decl = self.code.getDeclaration(inst);
26692626
26702627 const prev_parent_decl_node = self.parent_decl_node;
26712628 defer self.parent_decl_node = prev_parent_decl_node;
2672 self.parent_decl_node = inst_data.src_node;
2629 self.parent_decl_node = decl.src_node;
26732630
2674 if (extra.data.flags.is_pub) try stream.writeAll("pub ");
2675 if (extra.data.flags.is_export) try stream.writeAll("export ");
2676 switch (extra.data.name) {
2631 if (decl.is_pub) try stream.writeAll("pub ");
2632 switch (decl.linkage) {
2633 .normal => {},
2634 .@"export" => try stream.writeAll("export "),
2635 .@"extern" => try stream.writeAll("extern "),
2636 }
2637 switch (decl.kind) {
26772638 .@"comptime" => try stream.writeAll("comptime"),
26782639 .@"usingnamespace" => try stream.writeAll("usingnamespace"),
26792640 .unnamed_test => try stream.writeAll("test"),
2680 _ => {
2681 const name = extra.data.name.toString(self.code).?;
2682 const prefix = if (extra.data.name.isNamedTest(self.code)) p: {
2683 break :p if (extra.data.flags.test_is_decltest) "decltest " else "test ";
2684 } else "";
2685 try stream.print("{s}'{s}'", .{ prefix, self.code.nullTerminatedString(name) });
2641 .@"test", .decltest, .@"const", .@"var" => {
2642 try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
26862643 },
26872644 }
2688 const src_hash_arr: [4]u32 = .{
2689 extra.data.src_hash_0,
2690 extra.data.src_hash_1,
2691 extra.data.src_hash_2,
2692 extra.data.src_hash_3,
2693 };
2694 const src_hash_bytes: [16]u8 = @bitCast(src_hash_arr);
2695 try stream.print(" line({d}) hash({})", .{ extra.data.src_line, std.fmt.fmtSliceHexLower(&src_hash_bytes) });
2645 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2646 try stream.print(" line({d}) column({d}) hash({})", .{
2647 decl.src_line,
2648 decl.src_column,
2649 std.fmt.fmtSliceHexLower(&src_hash),
2650 });
26962651
26972652 {
2698 const bodies = extra.data.getBodies(@intCast(extra.end), self.code);
2699
2700 try stream.writeAll(" value=");
2701 try self.writeBracedDecl(stream, bodies.value_body);
2653 if (decl.type_body) |b| {
2654 try stream.writeAll(" type=");
2655 try self.writeBracedDecl(stream, b);
2656 }
27022657
2703 if (bodies.align_body) |b| {
2658 if (decl.align_body) |b| {
27042659 try stream.writeAll(" align=");
27052660 try self.writeBracedDecl(stream, b);
27062661 }
27072662
2708 if (bodies.linksection_body) |b| {
2663 if (decl.linksection_body) |b| {
27092664 try stream.writeAll(" linksection=");
27102665 try self.writeBracedDecl(stream, b);
27112666 }
27122667
2713 if (bodies.addrspace_body) |b| {
2668 if (decl.addrspace_body) |b| {
27142669 try stream.writeAll(" addrspace=");
27152670 try self.writeBracedDecl(stream, b);
27162671 }
2672
2673 if (decl.value_body) |b| {
2674 try stream.writeAll(" value=");
2675 try self.writeBracedDecl(stream, b);
2676 }
27172677 }
27182678
27192679 try stream.writeAll(") ");
test/cases/compile_errors/address_of_threadlocal_not_comptime_known.zig+2-1
......@@ -10,4 +10,5 @@ pub export fn entry() void {
1010// target=native
1111//
1212// :2:36: error: unable to resolve comptime value
13// :2:36: note: container level variable initializers must be comptime-known
13// :2:36: note: global variable initializer must be comptime-known
14// :2:36: note: thread local and dll imported variables have runtime-known addresses
test/cases/compile_errors/type_variables_must_be_constant.zig+2-2
......@@ -7,5 +7,5 @@ export fn entry() foo {
77// backend=stage2
88// target=native
99//
10// :1:5: error: variable of type 'type' must be const or comptime
11// :1:5: note: types are not available at runtime
10// :1:11: error: variable of type 'type' must be const or comptime
11// :1:11: note: types are not available at runtime
test/cases/compile_errors/use_invalid_number_literal_as_array_index.zig+2-2
......@@ -8,5 +8,5 @@ export fn entry() void {
88// backend=stage2
99// target=native
1010//
11// :1:5: error: variable of type 'comptime_int' must be const or comptime
12// :1:5: note: to modify this variable at runtime, it must be given an explicit fixed-size number type
11// :1:9: error: variable of type 'comptime_int' must be const or comptime
12// :1:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type