authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-25 02:58:27+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-12-25 02:58:27+00:00
log497592c9b45a94fb7b6028bf45b80f183e395a9b
tree467873c408750cb4223f3ccf31775e42ec9fbd5c
parentaf5e731729592af4a5716edd3b1e03264d66ea46
parent3afda4322c34dedc2319701fdfac3505c8d311e9
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22303 from mlugg/131-new

compiler: analyze type and value of global declarations separately

29 files changed, 3095 insertions(+), 2546 deletions(-)

lib/std/zig/AstGen.zig+582-536
...@@ -106,7 +106,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -106,7 +106,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
106 Zir.Inst.SwitchBlock.Bits,106 Zir.Inst.SwitchBlock.Bits,
107 Zir.Inst.SwitchBlockErrUnion.Bits,107 Zir.Inst.SwitchBlockErrUnion.Bits,
108 Zir.Inst.FuncFancy.Bits,108 Zir.Inst.FuncFancy.Bits,
109 Zir.Inst.Declaration.Flags,
110 => @bitCast(@field(extra, field.name)),109 => @bitCast(@field(extra, field.name)),
111110
112 else => @compileError("bad field type"),111 else => @compileError("bad field type"),
...@@ -1317,12 +1316,45 @@ fn fnProtoExpr(...@@ -1317,12 +1316,45 @@ fn fnProtoExpr(
1317 return astgen.failTok(some, "function type cannot have a name", .{});1316 return astgen.failTok(some, "function type cannot have a name", .{});
1318 }1317 }
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
1320 const is_extern = blk: {1337 const is_extern = blk: {
1321 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;1338 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
1322 break :blk token_tags[maybe_extern_token] == .keyword_extern;1339 break :blk token_tags[maybe_extern_token] == .keyword_extern;
1323 };1340 };
1324 assert(!is_extern);1341 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
1326 var block_scope = gz.makeSubBlock(scope);1358 var block_scope = gz.makeSubBlock(scope);
1327 defer block_scope.unstack();1359 defer block_scope.unstack();
13281360
...@@ -1386,18 +1418,6 @@ fn fnProtoExpr(...@@ -1386,18 +1418,6 @@ fn fnProtoExpr(
1386 break :is_var_args false;1418 break :is_var_args false;
1387 };1419 };
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
1401 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)1421 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
1402 try expr(1422 try expr(
1403 &block_scope,1423 &block_scope,
...@@ -1405,14 +1425,11 @@ fn fnProtoExpr(...@@ -1405,14 +1425,11 @@ fn fnProtoExpr(
1405 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },1425 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
1406 fn_proto.ast.callconv_expr,1426 fn_proto.ast.callconv_expr,
1407 )1427 )
1428 else if (implicit_ccc)
1429 try block_scope.addBuiltinValue(node, .calling_convention_c)
1408 else1430 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 }
1416 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);1433 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
14171434
1418 const result = try block_scope.addFunc(.{1435 const result = try block_scope.addFunc(.{
...@@ -1428,11 +1445,8 @@ fn fnProtoExpr(...@@ -1428,11 +1445,8 @@ fn fnProtoExpr(
14281445
1429 .param_block = block_inst,1446 .param_block = block_inst,
1430 .body_gz = null,1447 .body_gz = null,
1431 .lib_name = .empty,
1432 .is_var_args = is_var_args,1448 .is_var_args = is_var_args,
1433 .is_inferred_error = false,1449 .is_inferred_error = false,
1434 .is_test = false,
1435 .is_extern = false,
1436 .is_noinline = false,1450 .is_noinline = false,
1437 .noalias_bits = noalias_bits,1451 .noalias_bits = noalias_bits,
14381452
...@@ -4121,17 +4135,6 @@ fn fnDecl(...@@ -4121,17 +4135,6 @@ fn fnDecl(
41214135
4122 const saved_cursor = astgen.saveSourceCursor();4136 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
4135 const decl_column = astgen.source_column;4138 const decl_column = astgen.source_column;
41364139
4137 // Set this now, since parameter types, return type, etc may be generic.4140 // Set this now, since parameter types, return type, etc may be generic.
...@@ -4152,12 +4155,140 @@ fn fnDecl(...@@ -4152,12 +4155,140 @@ fn fnDecl(
4152 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;4155 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4153 break :blk token_tags[maybe_inline_token] == .keyword_inline;4156 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4154 };4157 };
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
4155 const is_noinline = blk: {4282 const is_noinline = blk: {
4156 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;4283 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4157 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;4284 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
4158 };4285 };
41594286 const has_inline_keyword = blk: {
4160 wip_members.nextDecl(decl_inst);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
4162 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.4293 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
4163 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);4294 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
...@@ -4192,11 +4323,9 @@ fn fnDecl(...@@ -4192,11 +4323,9 @@ fn fnDecl(
4192 break :blk .empty;4323 break :blk .empty;
41934324
4194 const param_name = try astgen.identAsString(name_token);4325 const param_name = try astgen.identAsString(name_token);
4195 if (!is_extern) {4326 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
4196 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
4197 }
4198 break :blk param_name;4327 break :blk param_name;
4199 } else if (!is_extern) {4328 } else {
4200 if (param.anytype_ellipsis3) |tok| {4329 if (param.anytype_ellipsis3) |tok| {
4201 return astgen.failTok(tok, "missing parameter name", .{});4330 return astgen.failTok(tok, "missing parameter name", .{});
4202 } else {4331 } else {
...@@ -4225,7 +4354,7 @@ fn fnDecl(...@@ -4225,7 +4354,7 @@ fn fnDecl(
4225 }4354 }
4226 return astgen.failNode(param.type_expr, "missing parameter name", .{});4355 return astgen.failNode(param.type_expr, "missing parameter name", .{});
4227 }4356 }
4228 } else .empty;4357 };
42294358
4230 const param_inst = if (is_anytype) param: {4359 const param_inst = if (is_anytype) param: {
4231 const name_token = param.name_token orelse param.anytype_ellipsis3.?;4360 const name_token = param.name_token orelse param.anytype_ellipsis3.?;
...@@ -4251,12 +4380,12 @@ fn fnDecl(...@@ -4251,12 +4380,12 @@ fn fnDecl(
4251 break :param param_inst.toRef();4380 break :param param_inst.toRef();
4252 };4381 };
42534382
4254 if (param_name == .empty or is_extern) continue;4383 if (param_name == .empty) continue;
42554384
4256 const sub_scope = try astgen.arena.create(Scope.LocalVal);4385 const sub_scope = try astgen.arena.create(Scope.LocalVal);
4257 sub_scope.* = .{4386 sub_scope.* = .{
4258 .parent = params_scope,4387 .parent = params_scope,
4259 .gen_zir = &decl_gz,4388 .gen_zir = decl_gz,
4260 .name = param_name,4389 .name = param_name,
4261 .inst = param_inst,4390 .inst = param_inst,
4262 .token_src = param.name_token.?,4391 .token_src = param.name_token.?,
...@@ -4268,23 +4397,9 @@ fn fnDecl(...@@ -4268,23 +4397,9 @@ fn fnDecl(
4268 break :is_var_args false;4397 break :is_var_args false;
4269 };4398 };
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
4285 // After creating the function ZIR instruction, it will need to update the break4400 // 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_ty4401 // instructions inside the expression blocks for cc and ret_ty to use the function
4287 // to use the function instruction as the "block" to break from.4402 // instruction as the body to break from.
42884403
4289 var ret_gz = decl_gz.makeSubBlock(params_scope);4404 var ret_gz = decl_gz.makeSubBlock(params_scope);
4290 defer ret_gz.unstack();4405 defer ret_gz.unstack();
...@@ -4309,13 +4424,6 @@ fn fnDecl(...@@ -4309,13 +4424,6 @@ fn fnDecl(
4309 defer cc_gz.unstack();4424 defer cc_gz.unstack();
4310 const cc_ref: Zir.Inst.Ref = blk: {4425 const cc_ref: Zir.Inst.Ref = blk: {
4311 if (fn_proto.ast.callconv_expr != 0) {4426 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 }
4319 const inst = try expr(4427 const inst = try expr(
4320 &cc_gz,4428 &cc_gz,
4321 scope,4429 scope,
...@@ -4328,10 +4436,6 @@ fn fnDecl(...@@ -4328,10 +4436,6 @@ fn fnDecl(
4328 }4436 }
4329 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);4437 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);
4330 break :blk inst;4438 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;
4335 } else if (has_inline_keyword) {4439 } else if (has_inline_keyword) {
4336 const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_inline);4440 const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_inline);
4337 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);4441 _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst);
...@@ -4341,167 +4445,86 @@ fn fnDecl(...@@ -4341,167 +4445,86 @@ fn fnDecl(
4341 }4445 }
4342 };4446 };
43434447
4344 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {4448 var body_gz: GenZir = .{
4345 if (!is_extern) {4449 .is_comptime = false,
4346 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});4450 .decl_node_index = fn_proto.ast.proto_node,
4347 }4451 .decl_line = decl_gz.decl_line,
4348 if (is_inferred_error) {4452 .parent = params_scope,
4349 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});4453 .astgen = astgen,
4350 }4454 .instructions = decl_gz.instructions,
4351 break :func try decl_gz.addFunc(.{4455 .instructions_top = decl_gz.instructions.items.len,
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 });
4453 };4456 };
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.4475 const prev_fn_block = astgen.fn_block;
4456 _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst);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.4494 astgen.advanceSourceCursorToNode(body_node);
4461 astgen.restoreSourceCursor(saved_cursor);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);4498 _ = try fullBodyExpr(&body_gz, &body_gz.base, .{ .rl = .none }, body_node, .allow_branch_hint);
4464 defer align_gz.unstack();4499 try checkUsed(decl_gz, scope, params_scope);
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 }
44694500
4470 var section_gz = align_gz.makeSubBlock(scope);4501 if (!body_gz.endsWithNoReturn()) {
4471 defer section_gz.unstack();4502 // As our last action before the return, "pop" the error trace if needed
4472 if (fn_proto.ast.section_expr != 0) {4503 _ = try body_gz.addRestoreErrRetIndex(.ret, .always, decl_node);
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 }
44764504
4477 var addrspace_gz = section_gz.makeSubBlock(scope);4505 // Add implicit return at end of function.
4478 defer addrspace_gz.unstack();4506 _ = try body_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node));
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);
4483 }4507 }
44844508
4485 // *Now* we can incorporate the full source code into the hasher.4509 const func_inst = try decl_gz.addFunc(.{
4486 astgen.src_hasher.update(tree.getNodeSource(decl_node));4510 .src_node = decl_node,
44874511 .cc_ref = cc_ref,
4488 var hash: std.zig.SrcHash = undefined;4512 .cc_gz = &cc_gz,
4489 astgen.src_hasher.final(&hash);4513 .ret_ref = ret_ref,
4490 try setDeclaration(4514 .ret_gz = &ret_gz,
4491 decl_inst,4515 .ret_param_refs = ret_body_param_refs,
4492 hash,4516 .lbrace_line = lbrace_line,
4493 .{ .named = fn_name_token },4517 .lbrace_column = lbrace_column,
4494 decl_gz.decl_line,4518 .param_block = decl_inst,
4495 decl_column,4519 .param_insts = param_insts.items,
4496 is_pub,4520 .body_gz = &body_gz,
4497 is_export,4521 .is_var_args = is_var_args,
4498 &decl_gz,4522 .is_inferred_error = is_inferred_error,
4499 .{4523 .is_noinline = is_noinline,
4500 .align_gz = &align_gz,4524 .noalias_bits = noalias_bits,
4501 .linksection_gz = &section_gz,4525 .proto_hash = proto_hash,
4502 .addrspace_gz = &addrspace_gz,4526 });
4503 },4527 _ = try decl_gz.addBreakWithSrcNode(.break_inline, decl_inst, func_inst, decl_node);
4504 );
4505}4528}
45064529
4507fn globalVarDecl(4530fn globalVarDecl(
...@@ -4522,26 +4545,7 @@ fn globalVarDecl(...@@ -4522,26 +4545,7 @@ fn globalVarDecl(
4522 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));4545 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
45234546
4524 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;4547 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
4529 const name_token = var_decl.ast.mut_token + 1;4548 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
4545 const is_pub = var_decl.visib_token != null;4549 const is_pub = var_decl.visib_token != null;
4546 const is_export = blk: {4550 const is_export = blk: {
4547 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;4551 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
...@@ -4551,15 +4555,12 @@ fn globalVarDecl(...@@ -4551,15 +4555,12 @@ fn globalVarDecl(
4551 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;4555 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
4552 break :blk token_tags[maybe_extern_token] == .keyword_extern;4556 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4553 };4557 };
4554 wip_members.nextDecl(decl_inst);
4555
4556 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {4558 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
4557 if (!is_mutable) {4559 if (!is_mutable) {
4558 return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});4560 return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});
4559 }4561 }
4560 break :blk true;4562 break :blk true;
4561 } else false;4563 } else false;
4562
4563 const lib_name = if (var_decl.lib_name) |lib_name_token| blk: {4564 const lib_name = if (var_decl.lib_name) |lib_name_token| blk: {
4564 const lib_name_str = try astgen.strLitAsString(lib_name_token);4565 const lib_name_str = try astgen.strLitAsString(lib_name_token);
4565 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];4566 const lib_name_slice = astgen.string_bytes.items[@intFromEnum(lib_name_str.index)..][0..lib_name_str.len];
...@@ -4571,9 +4572,14 @@ fn globalVarDecl(...@@ -4571,9 +4572,14 @@ fn globalVarDecl(
4571 break :blk lib_name_str.index;4572 break :blk lib_name_str.index;
4572 } else .empty;4573 } else .empty;
45734574
4574 assert(var_decl.comptime_token == null); // handled by parser4575 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) {
4577 if (is_extern) {4583 if (is_extern) {
4578 return astgen.failNode(4584 return astgen.failNode(
4579 var_decl.ast.init_node,4585 var_decl.ast.init_node,
...@@ -4581,102 +4587,91 @@ fn globalVarDecl(...@@ -4581,102 +4587,91 @@ fn globalVarDecl(
4581 .{},4587 .{},
4582 );4588 );
4583 }4589 }
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)4596 if (is_extern and var_decl.ast.type_node == 0) {
4586 try expr(4597 return astgen.failNode(node, "unable to infer variable type", .{});
4587 &block_scope,4598 }
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;
45964599
4597 const init_inst = try expr(4600 assert(var_decl.comptime_token == null); // handled by parser
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 );
46034601
4604 if (is_mutable) {4602 var type_gz: GenZir = .{
4605 const var_inst = try block_scope.addVar(.{4603 .parent = scope,
4606 .var_type = type_inst,4604 .decl_node_index = node,
4607 .lib_name = .empty,4605 .decl_line = astgen.source_line,
4608 .align_inst = .none, // passed via the decls data4606 .astgen = astgen,
4609 .init = init_inst,4607 .is_comptime = true,
4610 .is_extern = false,4608 .instructions = gz.instructions,
4611 .is_const = !is_mutable,4609 .instructions_top = gz.instructions.items.len,
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", .{});
4638 };4610 };
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 end4618 var align_gz = type_gz.makeSubBlock(scope);
4641 // range of a top level declaration.4619 defer align_gz.unstack();
4642 _ = try block_scope.addBreakWithSrcNode(.break_inline, decl_inst, var_inst, node);
46434620
4644 var align_gz = block_scope.makeSubBlock(scope);
4645 if (var_decl.ast.align_node != 0) {4621 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);
4647 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);4623 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4648 }4624 }
46494625
4650 var linksection_gz = align_gz.makeSubBlock(scope);4626 var linksection_gz = type_gz.makeSubBlock(scope);
4627 defer linksection_gz.unstack();
4628
4651 if (var_decl.ast.section_node != 0) {4629 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);
4653 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);4631 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4654 }4632 }
46554633
4656 var addrspace_gz = linksection_gz.makeSubBlock(scope);4634 var addrspace_gz = type_gz.makeSubBlock(scope);
4635 defer addrspace_gz.unstack();
4636
4657 if (var_decl.ast.addrspace_node != 0) {4637 if (var_decl.ast.addrspace_node != 0) {
4658 const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space);4638 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);
4660 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);4640 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4661 }4641 }
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
4663 var hash: std.zig.SrcHash = undefined;4655 var hash: std.zig.SrcHash = undefined;
4664 astgen.src_hasher.final(&hash);4656 astgen.src_hasher.final(&hash);
4665 try setDeclaration(4657 try setDeclaration(decl_inst, .{
4666 decl_inst,4658 .src_hash = hash,
4667 hash,4659 .src_line = type_gz.decl_line,
4668 .{ .named = name_token },4660 .src_column = decl_column,
4669 block_scope.decl_line,4661
4670 decl_column,4662 .kind = if (is_mutable) .@"var" else .@"const",
4671 is_pub,4663 .name = try astgen.identAsString(name_token),
4672 is_export,4664 .is_pub = is_pub,
4673 &block_scope,4665 .is_threadlocal = is_threadlocal,
4674 .{4666 .linkage = if (is_extern) .@"extern" else if (is_export) .@"export" else .normal,
4675 .align_gz = &align_gz,4667 .lib_name = lib_name,
4676 .linksection_gz = &linksection_gz,4668
4677 .addrspace_gz = &addrspace_gz,4669 .type_gz = &type_gz,
4678 },4670 .align_gz = &align_gz,
4679 );4671 .linksection_gz = &linksection_gz,
4672 .addrspace_gz = &addrspace_gz,
4673 .value_gz = &init_gz,
4674 });
4680}4675}
46814676
4682fn comptimeDecl(4677fn comptimeDecl(
...@@ -4702,37 +4697,45 @@ fn comptimeDecl(...@@ -4702,37 +4697,45 @@ fn comptimeDecl(
4702 wip_members.nextDecl(decl_inst);4697 wip_members.nextDecl(decl_inst);
4703 astgen.advanceSourceCursorToNode(node);4698 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 = .{
4706 .is_comptime = true,4705 .is_comptime = true,
4707 .decl_node_index = node,4706 .decl_node_index = node,
4708 .decl_line = astgen.source_line,4707 .decl_line = astgen.source_line,
4709 .parent = scope,4708 .parent = scope,
4710 .astgen = astgen,4709 .astgen = astgen,
4711 .instructions = gz.instructions,4710 .instructions = dummy_gz.instructions,
4712 .instructions_top = gz.instructions.items.len,4711 .instructions_top = dummy_gz.instructions.items.len,
4713 };4712 };
4714 defer decl_block.unstack();4713 defer comptime_gz.unstack();
47154714
4716 const decl_column = astgen.source_column;4715 const decl_column = astgen.source_column;
47174716
4718 const block_result = try fullBodyExpr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node, .normal);4717 const block_result = try fullBodyExpr(&comptime_gz, &comptime_gz.base, .{ .rl = .none }, body_node, .normal);
4719 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {4718 if (comptime_gz.isEmpty() or !comptime_gz.refIsNoReturn(block_result)) {
4720 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);4719 _ = try comptime_gz.addBreak(.break_inline, decl_inst, .void_value);
4721 }4720 }
47224721
4723 var hash: std.zig.SrcHash = undefined;4722 var hash: std.zig.SrcHash = undefined;
4724 astgen.src_hasher.final(&hash);4723 astgen.src_hasher.final(&hash);
4725 try setDeclaration(4724 try setDeclaration(decl_inst, .{
4726 decl_inst,4725 .src_hash = hash,
4727 hash,4726 .src_line = comptime_gz.decl_line,
4728 .@"comptime",4727 .src_column = decl_column,
4729 decl_block.decl_line,4728 .kind = .@"comptime",
4730 decl_column,4729 .name = .empty,
4731 false,4730 .is_pub = false,
4732 false,4731 .is_threadlocal = false,
4733 &decl_block,4732 .linkage = .normal,
4734 null,4733 .type_gz = &dummy_gz,
4735 );4734 .align_gz = &dummy_gz,
4735 .linksection_gz = &dummy_gz,
4736 .addrspace_gz = &dummy_gz,
4737 .value_gz = &comptime_gz,
4738 });
4736}4739}
47374740
4738fn usingnamespaceDecl(4741fn usingnamespaceDecl(
...@@ -4764,7 +4767,11 @@ fn usingnamespaceDecl(...@@ -4764,7 +4767,11 @@ fn usingnamespaceDecl(
4764 wip_members.nextDecl(decl_inst);4767 wip_members.nextDecl(decl_inst);
4765 astgen.advanceSourceCursorToNode(node);4768 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 = .{
4768 .is_comptime = true,4775 .is_comptime = true,
4769 .decl_node_index = node,4776 .decl_node_index = node,
4770 .decl_line = astgen.source_line,4777 .decl_line = astgen.source_line,
...@@ -4773,26 +4780,30 @@ fn usingnamespaceDecl(...@@ -4773,26 +4780,30 @@ fn usingnamespaceDecl(
4773 .instructions = gz.instructions,4780 .instructions = gz.instructions,
4774 .instructions_top = gz.instructions.items.len,4781 .instructions_top = gz.instructions.items.len,
4775 };4782 };
4776 defer decl_block.unstack();4783 defer usingnamespace_gz.unstack();
47774784
4778 const decl_column = astgen.source_column;4785 const decl_column = astgen.source_column;
47794786
4780 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);4787 const namespace_inst = try typeExpr(&usingnamespace_gz, &usingnamespace_gz.base, type_expr);
4781 _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst);4788 _ = try usingnamespace_gz.addBreak(.break_inline, decl_inst, namespace_inst);
47824789
4783 var hash: std.zig.SrcHash = undefined;4790 var hash: std.zig.SrcHash = undefined;
4784 astgen.src_hasher.final(&hash);4791 astgen.src_hasher.final(&hash);
4785 try setDeclaration(4792 try setDeclaration(decl_inst, .{
4786 decl_inst,4793 .src_hash = hash,
4787 hash,4794 .src_line = usingnamespace_gz.decl_line,
4788 .@"usingnamespace",4795 .src_column = decl_column,
4789 decl_block.decl_line,4796 .kind = .@"usingnamespace",
4790 decl_column,4797 .name = .empty,
4791 is_pub,4798 .is_pub = is_pub,
4792 false,4799 .is_threadlocal = false,
4793 &decl_block,4800 .linkage = .normal,
4794 null,4801 .type_gz = &dummy_gz,
4795 );4802 .align_gz = &dummy_gz,
4803 .linksection_gz = &dummy_gz,
4804 .addrspace_gz = &dummy_gz,
4805 .value_gz = &usingnamespace_gz,
4806 });
4796}4807}
47974808
4798fn testDecl(4809fn testDecl(
...@@ -4819,14 +4830,18 @@ fn testDecl(...@@ -4819,14 +4830,18 @@ fn testDecl(
4819 wip_members.nextDecl(decl_inst);4830 wip_members.nextDecl(decl_inst);
4820 astgen.advanceSourceCursorToNode(node);4831 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
4822 var decl_block: GenZir = .{4837 var decl_block: GenZir = .{
4823 .is_comptime = true,4838 .is_comptime = true,
4824 .decl_node_index = node,4839 .decl_node_index = node,
4825 .decl_line = astgen.source_line,4840 .decl_line = astgen.source_line,
4826 .parent = scope,4841 .parent = scope,
4827 .astgen = astgen,4842 .astgen = astgen,
4828 .instructions = gz.instructions,4843 .instructions = dummy_gz.instructions,
4829 .instructions_top = gz.instructions.items.len,4844 .instructions_top = dummy_gz.instructions.items.len,
4830 };4845 };
4831 defer decl_block.unstack();4846 defer decl_block.unstack();
48324847
...@@ -4835,11 +4850,21 @@ fn testDecl(...@@ -4835,11 +4850,21 @@ fn testDecl(
4835 const main_tokens = tree.nodes.items(.main_token);4850 const main_tokens = tree.nodes.items(.main_token);
4836 const token_tags = tree.tokens.items(.tag);4851 const token_tags = tree.tokens.items(.tag);
4837 const test_token = main_tokens[node];4852 const test_token = main_tokens[node];
4853
4838 const test_name_token = test_token + 1;4854 const test_name_token = test_token + 1;
4839 const test_name: DeclarationName = switch (token_tags[test_name_token]) {4855 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {
4840 else => .unnamed_test,4856 else => .empty,
4841 .string_literal => .{ .named_test = test_name_token },4857 .string_literal => name: {
4842 .identifier => blk: {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: {
4843 const ident_name_raw = tree.tokenSlice(test_name_token);4868 const ident_name_raw = tree.tokenSlice(test_name_token);
48444869
4845 if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{});4870 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(...@@ -4909,7 +4934,7 @@ fn testDecl(
4909 return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name});4934 return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name});
4910 }4935 }
49114936
4912 break :blk .{ .decltest = test_name_token };4937 break :name try astgen.identAsString(test_name_token);
4913 },4938 },
4914 };4939 };
49154940
...@@ -4965,11 +4990,8 @@ fn testDecl(...@@ -4965,11 +4990,8 @@ fn testDecl(
4965 .lbrace_column = lbrace_column,4990 .lbrace_column = lbrace_column,
4966 .param_block = decl_inst,4991 .param_block = decl_inst,
4967 .body_gz = &fn_block,4992 .body_gz = &fn_block,
4968 .lib_name = .empty,
4969 .is_var_args = false,4993 .is_var_args = false,
4970 .is_inferred_error = false,4994 .is_inferred_error = false,
4971 .is_test = true,
4972 .is_extern = false,
4973 .is_noinline = false,4995 .is_noinline = false,
4974 .noalias_bits = 0,4996 .noalias_bits = 0,
49754997
...@@ -4981,17 +5003,27 @@ fn testDecl(...@@ -4981,17 +5003,27 @@ fn testDecl(
49815003
4982 var hash: std.zig.SrcHash = undefined;5004 var hash: std.zig.SrcHash = undefined;
4983 astgen.src_hasher.final(&hash);5005 astgen.src_hasher.final(&hash);
4984 try setDeclaration(5006 try setDeclaration(decl_inst, .{
4985 decl_inst,5007 .src_hash = hash,
4986 hash,5008 .src_line = decl_block.decl_line,
4987 test_name,5009 .src_column = decl_column,
4988 decl_block.decl_line,5010
4989 decl_column,5011 .kind = switch (token_tags[test_name_token]) {
4990 false,5012 .string_literal => .@"test",
4991 false,5013 .identifier => .decltest,
4992 &decl_block,5014 else => .unnamed_test,
4993 null,5015 },
4994 );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 });
4995}5027}
49965028
4997fn structDeclInner(5029fn structDeclInner(
...@@ -5882,7 +5914,8 @@ fn containerMember(...@@ -5882,7 +5914,8 @@ fn containerMember(
5882 try addFailedDeclaration(5914 try addFailedDeclaration(
5883 wip_members,5915 wip_members,
5884 gz,5916 gz,
5885 .{ .named = full.name_token.? },5917 .@"const",
5918 try astgen.identAsString(full.name_token.?),
5886 full.ast.proto_node,5919 full.ast.proto_node,
5887 full.visib_token != null,5920 full.visib_token != null,
5888 );5921 );
...@@ -5904,7 +5937,8 @@ fn containerMember(...@@ -5904,7 +5937,8 @@ fn containerMember(
5904 try addFailedDeclaration(5937 try addFailedDeclaration(
5905 wip_members,5938 wip_members,
5906 gz,5939 gz,
5907 .{ .named = full.ast.mut_token + 1 },5940 .@"const", // doesn't really matter
5941 try astgen.identAsString(full.ast.mut_token + 1),
5908 member_node,5942 member_node,
5909 full.visib_token != null,5943 full.visib_token != null,
5910 );5944 );
...@@ -5922,6 +5956,7 @@ fn containerMember(...@@ -5922,6 +5956,7 @@ fn containerMember(
5922 wip_members,5956 wip_members,
5923 gz,5957 gz,
5924 .@"comptime",5958 .@"comptime",
5959 .empty,
5925 member_node,5960 member_node,
5926 false,5961 false,
5927 );5962 );
...@@ -5938,6 +5973,7 @@ fn containerMember(...@@ -5938,6 +5973,7 @@ fn containerMember(
5938 wip_members,5973 wip_members,
5939 gz,5974 gz,
5940 .@"usingnamespace",5975 .@"usingnamespace",
5976 .empty,
5941 member_node,5977 member_node,
5942 is_pub: {5978 is_pub: {
5943 const main_tokens = tree.nodes.items(.main_token);5979 const main_tokens = tree.nodes.items(.main_token);
...@@ -5962,6 +5998,7 @@ fn containerMember(...@@ -5962,6 +5998,7 @@ fn containerMember(
5962 wip_members,5998 wip_members,
5963 gz,5999 gz,
5964 .unnamed_test,6000 .unnamed_test,
6001 .empty,
5965 member_node,6002 member_node,
5966 false,6003 false,
5967 );6004 );
...@@ -11670,23 +11707,6 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {...@@ -11670,23 +11707,6 @@ fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
11670 };11707 };
11671}11708}
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
11690const Scope = struct {11710const Scope = struct {
11691 tag: Tag,11711 tag: Tag,
1169211712
...@@ -12077,12 +12097,9 @@ const GenZir = struct {...@@ -12077,12 +12097,9 @@ const GenZir = struct {
12077 cc_ref: Zir.Inst.Ref,12097 cc_ref: Zir.Inst.Ref,
12078 ret_ref: Zir.Inst.Ref,12098 ret_ref: Zir.Inst.Ref,
1207912099
12080 lib_name: Zir.NullTerminatedString,
12081 noalias_bits: u32,12100 noalias_bits: u32,
12082 is_var_args: bool,12101 is_var_args: bool,
12083 is_inferred_error: bool,12102 is_inferred_error: bool,
12084 is_test: bool,
12085 is_extern: bool,
12086 is_noinline: bool,12103 is_noinline: bool,
1208712104
12088 /// Ignored if `body_gz == null`.12105 /// Ignored if `body_gz == null`.
...@@ -12150,9 +12167,8 @@ const GenZir = struct {...@@ -12150,9 +12167,8 @@ const GenZir = struct {
1215012167
12151 const body_len = astgen.countBodyLenAfterFixupsExtraRefs(body, args.param_insts);12168 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 or12170 const tag: Zir.Inst.Tag, const payload_index: u32 = if (args.cc_ref != .none or
12154 args.is_var_args or args.is_test or args.is_extern or12171 args.is_var_args or args.noalias_bits != 0 or args.is_noinline)
12155 args.noalias_bits != 0 or args.is_noinline)
12156 inst_info: {12172 inst_info: {
12157 try astgen.extra.ensureUnusedCapacity(12173 try astgen.extra.ensureUnusedCapacity(
12158 gpa,12174 gpa,
...@@ -12160,7 +12176,6 @@ const GenZir = struct {...@@ -12160,7 +12176,6 @@ const GenZir = struct {
12160 fancyFnExprExtraLen(astgen, &.{}, cc_body, args.cc_ref) +12176 fancyFnExprExtraLen(astgen, &.{}, cc_body, args.cc_ref) +
12161 fancyFnExprExtraLen(astgen, args.ret_param_refs, ret_body, ret_ref) +12177 fancyFnExprExtraLen(astgen, args.ret_param_refs, ret_body, ret_ref) +
12162 body_len + src_locs_and_hash.len +12178 body_len + src_locs_and_hash.len +
12163 @intFromBool(args.lib_name != .empty) +
12164 @intFromBool(args.noalias_bits != 0),12179 @intFromBool(args.noalias_bits != 0),
12165 );12180 );
12166 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{12181 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
...@@ -12169,10 +12184,7 @@ const GenZir = struct {...@@ -12169,10 +12184,7 @@ const GenZir = struct {
12169 .bits = .{12184 .bits = .{
12170 .is_var_args = args.is_var_args,12185 .is_var_args = args.is_var_args,
12171 .is_inferred_error = args.is_inferred_error,12186 .is_inferred_error = args.is_inferred_error,
12172 .is_test = args.is_test,
12173 .is_extern = args.is_extern,
12174 .is_noinline = args.is_noinline,12187 .is_noinline = args.is_noinline,
12175 .has_lib_name = args.lib_name != .empty,
12176 .has_any_noalias = args.noalias_bits != 0,12188 .has_any_noalias = args.noalias_bits != 0,
1217712189
12178 .has_cc_ref = args.cc_ref != .none,12190 .has_cc_ref = args.cc_ref != .none,
...@@ -12182,9 +12194,6 @@ const GenZir = struct {...@@ -12182,9 +12194,6 @@ const GenZir = struct {
12182 .has_ret_ty_body = ret_body.len != 0,12194 .has_ret_ty_body = ret_body.len != 0,
12183 },12195 },
12184 });12196 });
12185 if (args.lib_name != .empty) {
12186 astgen.extra.appendAssumeCapacity(@intFromEnum(args.lib_name));
12187 }
1218812197
12189 const zir_datas = astgen.instructions.items(.data);12198 const zir_datas = astgen.instructions.items(.data);
12190 if (cc_body.len != 0) {12199 if (cc_body.len != 0) {
...@@ -12279,61 +12288,6 @@ const GenZir = struct {...@@ -12279,61 +12288,6 @@ const GenZir = struct {
12279 @intFromBool(main_body.len > 0 or ref != .none);12288 @intFromBool(main_body.len > 0 or ref != .none);
12280 }12289 }
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
12337 fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {12291 fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
12338 return gz.add(.{12292 return gz.add(.{
12339 .tag = .int,12293 .tag = .int,
...@@ -13909,14 +13863,18 @@ const DeclarationName = union(enum) {...@@ -13909,14 +13863,18 @@ const DeclarationName = union(enum) {
13909fn addFailedDeclaration(13863fn addFailedDeclaration(
13910 wip_members: *WipMembers,13864 wip_members: *WipMembers,
13911 gz: *GenZir,13865 gz: *GenZir,
13912 name: DeclarationName,13866 kind: Zir.Inst.Declaration.Unwrapped.Kind,
13867 name: Zir.NullTerminatedString,
13913 src_node: Ast.Node.Index,13868 src_node: Ast.Node.Index,
13914 is_pub: bool,13869 is_pub: bool,
13915) !void {13870) !void {
13916 const decl_inst = try gz.makeDeclaration(src_node);13871 const decl_inst = try gz.makeDeclaration(src_node);
13917 wip_members.nextDecl(decl_inst);13872 wip_members.nextDecl(decl_inst);
13918 var decl_gz = gz.makeSubBlock(&gz.base); // scope doesn't matter here13873
13919 _ = try decl_gz.add(.{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(.{
13920 .tag = .extended,13878 .tag = .extended,
13921 .data = .{ .extended = .{13879 .data = .{ .extended = .{
13922 .opcode = .astgen_error,13880 .opcode = .astgen_error,
...@@ -13924,110 +13882,198 @@ fn addFailedDeclaration(...@@ -13924,110 +13882,198 @@ fn addFailedDeclaration(
13924 .operand = undefined,13882 .operand = undefined,
13925 } },13883 } },
13926 });13884 });
13927 try setDeclaration(13885
13928 decl_inst,13886 try setDeclaration(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!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!
13930 name,13888 .src_line = gz.astgen.source_line,
13931 gz.astgen.source_line,13889 .src_column = gz.astgen.source_column,
13932 gz.astgen.source_column,13890 .kind = kind,
13933 is_pub,13891 .name = name,
13934 false, // we don't care about exports since semantic analysis will fail13892 .is_pub = is_pub,
13935 &decl_gz,13893 .is_threadlocal = false,
13936 null,13894 .linkage = .normal,
13937 );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 });
13938}13901}
1393913902
13940/// Sets all extra data for a `declaration` instruction.13903/// 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`.
13942fn setDeclaration(13905fn setDeclaration(
13943 decl_inst: Zir.Inst.Index,13906 decl_inst: Zir.Inst.Index,
13944 src_hash: std.zig.SrcHash,13907 args: struct {
13945 name: DeclarationName,13908 src_hash: std.zig.SrcHash,
13946 src_line: u32,13909 src_line: u32,
13947 src_column: u32,13910 src_column: u32,
13948 is_pub: bool,13911
13949 is_export: bool,13912 kind: Zir.Inst.Declaration.Unwrapped.Kind,
13950 value_gz: *GenZir,13913 name: Zir.NullTerminatedString,
13951 /// May be `null` if all these blocks would be empty.13914 is_pub: bool,
13952 /// If `null`, then `value_gz` must have nothing stacked on it.13915 is_threadlocal: bool,
13953 extra_gzs: ?struct {13916 linkage: Zir.Inst.Declaration.Unwrapped.Linkage,
13954 /// Must be stacked on `value_gz`.13917 lib_name: Zir.NullTerminatedString = .empty,
13918
13919 type_gz: *GenZir,
13920 /// Must be stacked on `type_gz`.
13955 align_gz: *GenZir,13921 align_gz: *GenZir,
13956 /// Must be stacked on `align_gz`.13922 /// Must be stacked on `align_gz`.
13957 linksection_gz: *GenZir,13923 linksection_gz: *GenZir,
13958 /// Must be stacked on `linksection_gz`, and have nothing stacked on it.13924 /// Must be stacked on `linksection_gz`.
13959 addrspace_gz: *GenZir,13925 addrspace_gz: *GenZir,
13926 /// Must be stacked on `addrspace_gz` and have nothing stacked on top of it.
13927 value_gz: *GenZir,
13960 },13928 },
13961) !void {13929) !void {
13962 const astgen = value_gz.astgen;13930 const astgen = args.value_gz.astgen;
13963 const gpa = astgen.gpa;13931 const gpa = astgen.gpa;
1396413932
13965 const empty_body: []Zir.Inst.Index = &.{};13933 const type_body = args.type_gz.instructionsSliceUpto(args.align_gz);
13966 const value_body, const align_body, const linksection_body, const addrspace_body = if (extra_gzs) |e| .{13934 const align_body = args.align_gz.instructionsSliceUpto(args.linksection_gz);
13967 value_gz.instructionsSliceUpto(e.align_gz),13935 const linksection_body = args.linksection_gz.instructionsSliceUpto(args.addrspace_gz);
13968 e.align_gz.instructionsSliceUpto(e.linksection_gz),13936 const addrspace_body = args.addrspace_gz.instructionsSliceUpto(args.value_gz);
13969 e.linksection_gz.instructionsSliceUpto(e.addrspace_gz),13937 const value_body = args.value_gz.instructionsSlice();
13970 e.addrspace_gz.instructionsSlice(),13938
13971 } else .{ value_gz.instructionsSlice(), empty_body, empty_body, empty_body };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);
13974 const align_len = astgen.countBodyLenAfterFixups(align_body);14011 const align_len = astgen.countBodyLenAfterFixups(align_body);
13975 const linksection_len = astgen.countBodyLenAfterFixups(linksection_body);14012 const linksection_len = astgen.countBodyLenAfterFixups(linksection_body);
13976 const addrspace_len = astgen.countBodyLenAfterFixups(addrspace_body);14013 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
13980 const extra: Zir.Inst.Declaration = .{14035 const extra: Zir.Inst.Declaration = .{
13981 .src_hash_0 = src_hash_arr[0],14036 .src_hash_0 = src_hash_arr[0],
13982 .src_hash_1 = src_hash_arr[1],14037 .src_hash_1 = src_hash_arr[1],
13983 .src_hash_2 = src_hash_arr[2],14038 .src_hash_2 = src_hash_arr[2],
13984 .src_hash_3 = src_hash_arr[3],14039 .src_hash_3 = src_hash_arr[3],
13985 .name = switch (name) {14040 .flags_0 = flags_arr[0],
13986 .named => |tok| @enumFromInt(@intFromEnum(try astgen.identAsString(tok))),14041 .flags_1 = flags_arr[1],
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 },
14008 };14042 };
14009 astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index = try astgen.addExtra(extra);14043 astgen.instructions.items(.data)[@intFromEnum(decl_inst)].declaration.payload_index =
14010 if (extra.flags.has_align_linksection_addrspace) {14044 astgen.addExtraAssumeCapacity(extra);
14011 try astgen.extra.appendSlice(gpa, &.{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(&.{
14012 align_len,14057 align_len,
14013 linksection_len,14058 linksection_len,
14014 addrspace_len,14059 addrspace_len,
14015 });14060 });
14016 }14061 }
14017 try astgen.extra.ensureUnusedCapacity(gpa, value_len + align_len + linksection_len + addrspace_len);14062 if (id.hasValueBody()) {
14018 astgen.appendBodyWithFixups(value_body);14063 astgen.extra.appendAssumeCapacity(value_len);
14019 if (extra.flags.has_align_linksection_addrspace) {
14020 astgen.appendBodyWithFixups(align_body);
14021 astgen.appendBodyWithFixups(linksection_body);
14022 astgen.appendBodyWithFixups(addrspace_body);
14023 }14064 }
1402414065
14025 if (extra_gzs) |e| {14066 astgen.appendBodyWithFixups(type_body);
14026 e.addrspace_gz.unstack();14067 astgen.appendBodyWithFixups(align_body);
14027 e.linksection_gz.unstack();14068 astgen.appendBodyWithFixups(linksection_body);
14028 e.align_gz.unstack();14069 astgen.appendBodyWithFixups(addrspace_body);
14029 }14070 astgen.appendBodyWithFixups(value_body);
14030 value_gz.unstack();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();
14031}14077}
1403214078
14033/// Given a list of instructions, returns a list of all instructions which are a `ref` of one of the originals,14079/// 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 {...@@ -1868,10 +1868,6 @@ pub const Inst = struct {
1868 /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.1868 /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
1869 /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.1869 /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
1870 pub const Extended = enum(u16) {1870 pub const Extended = enum(u16) {
1871 /// Declares a global variable.
1872 /// `operand` is payload index to `ExtendedVar`.
1873 /// `small` is `ExtendedVar.Small`.
1874 variable,
1875 /// A struct type definition. Contains references to ZIR instructions for1871 /// A struct type definition. Contains references to ZIR instructions for
1876 /// the field types, defaults, and alignments.1872 /// the field types, defaults, and alignments.
1877 /// `operand` is payload index to `StructDecl`.1873 /// `operand` is payload index to `StructDecl`.
...@@ -2493,26 +2489,25 @@ pub const Inst = struct {...@@ -2493,26 +2489,25 @@ pub const Inst = struct {
2493 };2489 };
24942490
2495 /// Trailing:2491 /// Trailing:
2496 /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
2497 /// if (has_cc_ref and !has_cc_body) {2492 /// if (has_cc_ref and !has_cc_body) {
2498 /// 1. cc: Ref,2493 /// 0. cc: Ref,
2499 /// }2494 /// }
2500 /// if (has_cc_body) {2495 /// if (has_cc_body) {
2501 /// 2. cc_body_len: u322496 /// 1. cc_body_len: u32
2502 /// 3. cc_body: u32 // for each cc_body_len2497 /// 2. cc_body: u32 // for each cc_body_len
2503 /// }2498 /// }
2504 /// if (has_ret_ty_ref and !has_ret_ty_body) {2499 /// if (has_ret_ty_ref and !has_ret_ty_body) {
2505 /// 4. ret_ty: Ref,2500 /// 3. ret_ty: Ref,
2506 /// }2501 /// }
2507 /// if (has_ret_ty_body) {2502 /// if (has_ret_ty_body) {
2508 /// 5. ret_ty_body_len: u322503 /// 4. ret_ty_body_len: u32
2509 /// 6. ret_ty_body: u32 // for each ret_ty_body_len2504 /// 5. ret_ty_body: u32 // for each ret_ty_body_len
2510 /// }2505 /// }
2511 /// 7. noalias_bits: u32 // if has_any_noalias2506 /// 6. noalias_bits: u32 // if has_any_noalias
2512 /// - each bit starting with LSB corresponds to parameter indexes2507 /// - each bit starting with LSB corresponds to parameter indexes
2513 /// 8. body: Index // for each body_len2508 /// 7. body: Index // for each body_len
2514 /// 9. src_locs: Func.SrcLocs // if body_len != 02509 /// 8. src_locs: Func.SrcLocs // if body_len != 0
2515 /// 10. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype2510 /// 9. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype
2516 pub const FuncFancy = struct {2511 pub const FuncFancy = struct {
2517 /// Points to the block that contains the param instructions for this function.2512 /// Points to the block that contains the param instructions for this function.
2518 /// If this is a `declaration`, it refers to the declaration's value body.2513 /// If this is a `declaration`, it refers to the declaration's value body.
...@@ -2522,38 +2517,16 @@ pub const Inst = struct {...@@ -2522,38 +2517,16 @@ pub const Inst = struct {
25222517
2523 /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.2518 /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.
2524 /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type.2519 /// 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) {
2526 is_var_args: bool,2521 is_var_args: bool,
2527 is_inferred_error: bool,2522 is_inferred_error: bool,
2528 is_test: bool,
2529 is_extern: bool,
2530 is_noinline: bool,2523 is_noinline: bool,
2531 has_cc_ref: bool,2524 has_cc_ref: bool,
2532 has_cc_body: bool,2525 has_cc_body: bool,
2533 has_ret_ty_ref: bool,2526 has_ret_ty_ref: bool,
2534 has_ret_ty_body: bool,2527 has_ret_ty_body: bool,
2535 has_lib_name: bool,
2536 has_any_noalias: bool,2528 has_any_noalias: bool,
2537 _: u21 = undefined,2529 _: u24 = 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,
2557 };2530 };
2558 };2531 };
25592532
...@@ -2582,39 +2555,301 @@ pub const Inst = struct {...@@ -2582,39 +2555,301 @@ pub const Inst = struct {
2582 };2555 };
25832556
2584 /// Trailing:2557 /// Trailing:
2585 /// 0. align_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `align`2558 /// 0. name: NullTerminatedString // if `flags.id.hasName()`
2586 /// 1. linksection_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `linksection`2559 /// 1. lib_name: NullTerminatedString // if `flags.id.hasLibName()`
2587 /// 2. addrspace_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `addrspace`2560 /// 2. type_body_len: u32 // if `flags.id.hasTypeBody()`
2588 /// 3. value_body_inst: Zir.Inst.Index2561 /// 3. align_body_len: u32 // if `flags.id.hasSpecialBodies()`
2589 /// - for each `value_body_len`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`
2590 /// - body to be exited via `break_inline` to this `declaration` instruction2567 /// - body to be exited via `break_inline` to this `declaration` instruction
2591 /// 4. align_body_inst: Zir.Inst.Index2568 /// 8. align_body_inst: Zir.Inst.Index
2592 /// - for each `align_body_len`2569 /// - for each `align_body_len`
2593 /// - body to be exited via `break_inline` to this `declaration` instruction2570 /// - body to be exited via `break_inline` to this `declaration` instruction
2594 /// 5. linksection_body_inst: Zir.Inst.Index2571 /// 9. linksection_body_inst: Zir.Inst.Index
2595 /// - for each `linksection_body_len`2572 /// - for each `linksection_body_len`
2596 /// - body to be exited via `break_inline` to this `declaration` instruction2573 /// - body to be exited via `break_inline` to this `declaration` instruction
2597 /// 6. addrspace_body_inst: Zir.Inst.Index2574 /// 10. addrspace_body_inst: Zir.Inst.Index
2598 /// - for each `addrspace_body_len`2575 /// - for each `addrspace_body_len`
2599 /// - body to be exited via `break_inline` to this `declaration` instruction2576 /// - 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
2600 pub const Declaration = struct {2581 pub const Declaration = struct {
2601 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.2582 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
2602 src_hash_0: u32,2583 src_hash_0: u32,
2603 src_hash_1: u32,2584 src_hash_1: u32,
2604 src_hash_2: u32,2585 src_hash_2: u32,
2605 src_hash_3: u32,2586 src_hash_3: u32,
2606 /// The name of this `Decl`. Also indicates whether it is a test, comptime block, etc.2587 // These fields should be concatenated and reinterpreted as a `Flags`.
2607 name: Name,2588 flags_0: u32,
2608 src_line: u32,2589 flags_1: u32,
2609 src_column: u32,2590
2610 flags: Flags,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) {2602 pub const Linkage = enum {
2613 value_body_len: u28,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"`.
2614 is_pub: bool,2617 is_pub: bool,
2615 is_export: bool,2618 /// Always `false` for `kind != .@"var"`.
2616 test_is_decltest: bool,2619 is_threadlocal: bool,
2617 has_align_linksection_addrspace: 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 };
2618 };2853 };
26192854
2620 pub const Name = enum(u32) {2855 pub const Name = enum(u32) {
...@@ -2647,17 +2882,24 @@ pub const Inst = struct {...@@ -2647,17 +2882,24 @@ pub const Inst = struct {
2647 };2882 };
26482883
2649 pub const Bodies = struct {2884 pub const Bodies = struct {
2650 value_body: []const Index,2885 type_body: ?[]const Index,
2651 align_body: ?[]const Index,2886 align_body: ?[]const Index,
2652 linksection_body: ?[]const Index,2887 linksection_body: ?[]const Index,
2653 addrspace_body: ?[]const Index,2888 addrspace_body: ?[]const Index,
2889 value_body: ?[]const Index,
2654 };2890 };
26552891
2656 pub fn getBodies(declaration: Declaration, extra_end: u32, zir: Zir) Bodies {2892 pub fn getBodies(declaration: Declaration, extra_end: u32, zir: Zir) Bodies {
2657 var extra_index: u32 = extra_end;2893 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 };
2659 const align_body_len, const linksection_body_len, const addrspace_body_len = lens: {2901 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()) {
2661 break :lens .{ 0, 0, 0 };2903 break :lens .{ 0, 0, 0 };
2662 }2904 }
2663 const lens = zir.extra[extra_index..][0..3].*;2905 const lens = zir.extra[extra_index..][0..3].*;
...@@ -2665,21 +2907,30 @@ pub const Inst = struct {...@@ -2665,21 +2907,30 @@ pub const Inst = struct {
2665 break :lens lens;2907 break :lens lens;
2666 };2908 };
2667 return .{2909 return .{
2668 .value_body = b: {2910 .type_body = if (type_body_len == 0) null else b: {
2669 defer extra_index += value_body_len;2911 const b = zir.bodySlice(extra_index, type_body_len);
2670 break :b zir.bodySlice(extra_index, value_body_len);2912 extra_index += type_body_len;
2913 break :b b;
2671 },2914 },
2672 .align_body = if (align_body_len == 0) null else b: {2915 .align_body = if (align_body_len == 0) null else b: {
2673 defer extra_index += align_body_len;2916 const b = zir.bodySlice(extra_index, align_body_len);
2674 break :b zir.bodySlice(extra_index, align_body_len);2917 extra_index += align_body_len;
2918 break :b b;
2675 },2919 },
2676 .linksection_body = if (linksection_body_len == 0) null else b: {2920 .linksection_body = if (linksection_body_len == 0) null else b: {
2677 defer extra_index += linksection_body_len;2921 const b = zir.bodySlice(extra_index, linksection_body_len);
2678 break :b zir.bodySlice(extra_index, linksection_body_len);2922 extra_index += linksection_body_len;
2923 break :b b;
2679 },2924 },
2680 .addrspace_body = if (addrspace_body_len == 0) null else b: {2925 .addrspace_body = if (addrspace_body_len == 0) null else b: {
2681 defer extra_index += addrspace_body_len;2926 const b = zir.bodySlice(extra_index, addrspace_body_len);
2682 break :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;
2683 },2934 },
2684 };2935 };
2685 }2936 }
...@@ -3711,18 +3962,18 @@ pub const DeclContents = struct {...@@ -3711,18 +3962,18 @@ pub const DeclContents = struct {
3711pub fn findTrackable(zir: Zir, gpa: Allocator, contents: *DeclContents, decl_inst: Zir.Inst.Index) !void {3962pub fn findTrackable(zir: Zir, gpa: Allocator, contents: *DeclContents, decl_inst: Zir.Inst.Index) !void {
3712 contents.clear();3963 contents.clear();
37133964
3714 const declaration, const extra_end = zir.getDeclaration(decl_inst);3965 const decl = zir.getDeclaration(decl_inst);
3715 const bodies = declaration.getBodies(extra_end, zir);
37163966
3717 // `defer` instructions duplicate the same body arbitrarily many times, but we only want to traverse3967 // `defer` instructions duplicate the same body arbitrarily many times, but we only want to traverse
3718 // their contents once per defer. So, we store the extra index of the body here to deduplicate.3968 // their contents once per defer. So, we store the extra index of the body here to deduplicate.
3719 var found_defers: std.AutoHashMapUnmanaged(u32, void) = .empty;3969 var found_defers: std.AutoHashMapUnmanaged(u32, void) = .empty;
3720 defer found_defers.deinit(gpa);3970 defer found_defers.deinit(gpa);
37213971
3722 try zir.findTrackableBody(gpa, contents, &found_defers, bodies.value_body);3972 if (decl.type_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);
3723 if (bodies.align_body) |b| try zir.findTrackableBody(gpa, contents, &found_defers, b);3973 if (decl.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);3974 if (decl.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);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);
3726}3977}
37273978
3728/// Like `findTrackable`, but only considers the `main_struct_inst` instruction. This may return more than3979/// Like `findTrackable`, but only considers the `main_struct_inst` instruction. This may return more than
...@@ -3991,7 +4242,6 @@ fn findTrackableInner(...@@ -3991,7 +4242,6 @@ fn findTrackableInner(
3991 .value_placeholder => unreachable,4242 .value_placeholder => unreachable,
39924243
3993 // Once again, we start with the boring tags.4244 // Once again, we start with the boring tags.
3994 .variable,
3995 .this,4245 .this,
3996 .ret_addr,4246 .ret_addr,
3997 .builtin_src,4247 .builtin_src,
...@@ -4237,7 +4487,6 @@ fn findTrackableInner(...@@ -4237,7 +4487,6 @@ fn findTrackableInner(
4237 const inst_data = datas[@intFromEnum(inst)].pl_node;4487 const inst_data = datas[@intFromEnum(inst)].pl_node;
4238 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);4488 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
4239 var extra_index: usize = extra.end;4489 var extra_index: usize = extra.end;
4240 extra_index += @intFromBool(extra.data.bits.has_lib_name);
42414490
4242 if (extra.data.bits.has_cc_body) {4491 if (extra.data.bits.has_cc_body) {
4243 const body_len = zir.extra[extra_index];4492 const body_len = zir.extra[extra_index];
...@@ -4470,8 +4719,7 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {...@@ -4470,8 +4719,7 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {
4470 return zir.bodySlice(param_block.end, param_block.data.body_len);4719 return zir.bodySlice(param_block.end, param_block.data.body_len);
4471 },4720 },
4472 .declaration => {4721 .declaration => {
4473 const decl, const extra_end = zir.getDeclaration(param_block_index);4722 return zir.getDeclaration(param_block_index).value_body.?;
4474 return decl.getBodies(extra_end, zir).value_body;
4475 },4723 },
4476 else => unreachable,4724 else => unreachable,
4477 }4725 }
...@@ -4526,7 +4774,6 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4526,7 +4774,6 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4526 var ret_ty_ref: Inst.Ref = .void_type;4774 var ret_ty_ref: Inst.Ref = .void_type;
4527 var ret_ty_body: []const Inst.Index = &.{};4775 var ret_ty_body: []const Inst.Index = &.{};
45284776
4529 extra_index += @intFromBool(extra.data.bits.has_lib_name);
4530 if (extra.data.bits.has_cc_body) {4777 if (extra.data.bits.has_cc_body) {
4531 extra_index += zir.extra[extra_index] + 1;4778 extra_index += zir.extra[extra_index] + 1;
4532 } else if (extra.data.bits.has_cc_ref) {4779 } else if (extra.data.bits.has_cc_ref) {
...@@ -4555,17 +4802,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4555,17 +4802,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4555 },4802 },
4556 else => unreachable,4803 else => unreachable,
4557 };4804 };
4558 const param_body = switch (tags[@intFromEnum(info.param_block)]) {4805 const param_body = zir.getParamBody(fn_inst);
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 };
4569 var total_params_len: u32 = 0;4806 var total_params_len: u32 = 0;
4570 for (param_body) |inst| {4807 for (param_body) |inst| {
4571 switch (tags[@intFromEnum(inst)]) {4808 switch (tags[@intFromEnum(inst)]) {
...@@ -4585,13 +4822,74 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -4585,13 +4822,74 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
4585 };4822 };
4586}4823}
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 {
4589 assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);4826 assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);
4590 const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].declaration;4827 const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].declaration;
4591 const extra = zir.extraData(Inst.Declaration, pl_node.payload_index);4828 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
4592 return .{4875 return .{
4593 extra.data,4876 .src_node = pl_node.src_node,
4594 @intCast(extra.end),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,
4595 };4893 };
4596}4894}
45974895
...@@ -4636,7 +4934,6 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {...@@ -4636,7 +4934,6 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
4636 }4934 }
4637 const bits = extra.data.bits;4935 const bits = extra.data.bits;
4638 var extra_index = extra.end;4936 var extra_index = extra.end;
4639 extra_index += @intFromBool(bits.has_lib_name);
4640 if (bits.has_cc_body) {4937 if (bits.has_cc_body) {
4641 const body_len = zir.extra[extra_index];4938 const body_len = zir.extra[extra_index];
4642 extra_index += 1 + body_len;4939 extra_index += 1 + body_len;
src/Compilation.zig+52-29
...@@ -348,12 +348,15 @@ const Job = union(enum) {...@@ -348,12 +348,15 @@ const Job = union(enum) {
348 /// Corresponds to the task in `link.Task`.348 /// Corresponds to the task in `link.Task`.
349 /// Only needed for backends that haven't yet been updated to not race against Sema.349 /// Only needed for backends that haven't yet been updated to not race against Sema.
350 codegen_type: InternPool.Index,350 codegen_type: InternPool.Index,
351 /// The `Cau` must be semantically analyzed (and possibly export itself).351 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
352 /// This may be its first time being analyzed, or it may be outdated.
353 /// If the unit is a function, a `codegen_func` job will then be queued.
354 analyze_comptime_unit: InternPool.AnalUnit,
355 /// This function must be semantically analyzed.
352 /// This may be its first time being analyzed, or it may be outdated.356 /// This may be its first time being analyzed, or it may be outdated.
353 analyze_cau: InternPool.Cau.Index,
354 /// Analyze the body of a runtime function.
355 /// After analysis, a `codegen_func` job will be queued.357 /// After analysis, a `codegen_func` job will be queued.
356 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.358 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.
359 /// This job is separate from `analyze_comptime_unit` because it has a different priority.
357 analyze_func: InternPool.Index,360 analyze_func: InternPool.Index,
358 /// The main source file for the module needs to be analyzed.361 /// The main source file for the module needs to be analyzed.
359 analyze_mod: *Package.Module,362 analyze_mod: *Package.Module,
...@@ -2903,6 +2906,7 @@ const Header = extern struct {...@@ -2903,6 +2906,7 @@ const Header = extern struct {
2903 file_deps_len: u32,2906 file_deps_len: u32,
2904 src_hash_deps_len: u32,2907 src_hash_deps_len: u32,
2905 nav_val_deps_len: u32,2908 nav_val_deps_len: u32,
2909 nav_ty_deps_len: u32,
2906 namespace_deps_len: u32,2910 namespace_deps_len: u32,
2907 namespace_name_deps_len: u32,2911 namespace_name_deps_len: u32,
2908 first_dependency_len: u32,2912 first_dependency_len: u32,
...@@ -2946,6 +2950,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2946,6 +2950,7 @@ pub fn saveState(comp: *Compilation) !void {
2946 .file_deps_len = @intCast(ip.file_deps.count()),2950 .file_deps_len = @intCast(ip.file_deps.count()),
2947 .src_hash_deps_len = @intCast(ip.src_hash_deps.count()),2951 .src_hash_deps_len = @intCast(ip.src_hash_deps.count()),
2948 .nav_val_deps_len = @intCast(ip.nav_val_deps.count()),2952 .nav_val_deps_len = @intCast(ip.nav_val_deps.count()),
2953 .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()),
2949 .namespace_deps_len = @intCast(ip.namespace_deps.count()),2954 .namespace_deps_len = @intCast(ip.namespace_deps.count()),
2950 .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()),2955 .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()),
2951 .first_dependency_len = @intCast(ip.first_dependency.count()),2956 .first_dependency_len = @intCast(ip.first_dependency.count()),
...@@ -2976,6 +2981,8 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2976,6 +2981,8 @@ pub fn saveState(comp: *Compilation) !void {
2976 addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values()));2981 addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values()));
2977 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys()));2982 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys()));
2978 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values()));2983 addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values()));
2984 addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys()));
2985 addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values()));
2979 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys()));2986 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys()));
2980 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values()));2987 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values()));
2981 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys()));2988 addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys()));
...@@ -3141,8 +3148,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3141,8 +3148,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3141 }3148 }
31423149
3143 const file_index = switch (anal_unit.unwrap()) {3150 const file_index = switch (anal_unit.unwrap()) {
3144 .cau => |cau| zcu.namespacePtr(ip.getCau(cau).namespace).file_scope,3151 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
3145 .func => |ip_index| (zcu.funcInfo(ip_index).zir_body_inst.resolveFull(ip) orelse continue).file,3152 .nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
3153 .type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
3154 .func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
3146 };3155 };
31473156
3148 // Skip errors for AnalUnits within files that had a parse failure.3157 // Skip errors for AnalUnits within files that had a parse failure.
...@@ -3374,11 +3383,9 @@ pub fn addModuleErrorMsg(...@@ -3374,11 +3383,9 @@ pub fn addModuleErrorMsg(
3374 const rt_file_path = try src.file_scope.fullPath(gpa);3383 const rt_file_path = try src.file_scope.fullPath(gpa);
3375 defer gpa.free(rt_file_path);3384 defer gpa.free(rt_file_path);
3376 const name = switch (ref.referencer.unwrap()) {3385 const name = switch (ref.referencer.unwrap()) {
3377 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {3386 .@"comptime" => "comptime",
3378 .nav => |nav| ip.getNav(nav).name.toSlice(ip),3387 .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
3379 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),3388 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
3380 .none => "comptime",
3381 },
3382 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),3389 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
3383 };3390 };
3384 try ref_traces.append(gpa, .{3391 try ref_traces.append(gpa, .{
...@@ -3641,10 +3648,14 @@ fn performAllTheWorkInner(...@@ -3641,10 +3648,14 @@ fn performAllTheWorkInner(
3641 // If there's no work queued, check if there's anything outdated3648 // If there's no work queued, check if there's anything outdated
3642 // which we need to work on, and queue it if so.3649 // which we need to work on, and queue it if so.
3643 if (try zcu.findOutdatedToAnalyze()) |outdated| {3650 if (try zcu.findOutdatedToAnalyze()) |outdated| {
3644 switch (outdated.unwrap()) {3651 try comp.queueJob(switch (outdated.unwrap()) {
3645 .cau => |cau| try comp.queueJob(.{ .analyze_cau = cau }),3652 .func => |f| .{ .analyze_func = f },
3646 .func => |func| try comp.queueJob(.{ .analyze_func = func }),3653 .@"comptime",
3647 }3654 .nav_ty,
3655 .nav_val,
3656 .type,
3657 => .{ .analyze_comptime_unit = outdated },
3658 });
3648 continue;3659 continue;
3649 }3660 }
3650 }3661 }
...@@ -3667,13 +3678,13 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre...@@ -3667,13 +3678,13 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
3667 .codegen_nav => |nav_index| {3678 .codegen_nav => |nav_index| {
3668 const zcu = comp.zcu.?;3679 const zcu = comp.zcu.?;
3669 const nav = zcu.intern_pool.getNav(nav_index);3680 const nav = zcu.intern_pool.getNav(nav_index);
3670 if (nav.analysis_owner.unwrap()) |cau| {3681 if (nav.analysis != null) {
3671 const unit = InternPool.AnalUnit.wrap(.{ .cau = cau });3682 const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
3672 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {3683 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
3673 return;3684 return;
3674 }3685 }
3675 }3686 }
3676 assert(nav.status == .resolved);3687 assert(nav.status == .fully_resolved);
3677 comp.dispatchCodegenTask(tid, .{ .codegen_nav = nav_index });3688 comp.dispatchCodegenTask(tid, .{ .codegen_nav = nav_index });
3678 },3689 },
3679 .codegen_func => |func| {3690 .codegen_func => |func| {
...@@ -3688,36 +3699,48 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre...@@ -3688,36 +3699,48 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
36883699
3689 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));3700 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
3690 defer pt.deactivate();3701 defer pt.deactivate();
3691 pt.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {3702
3692 error.OutOfMemory => return error.OutOfMemory,3703 pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) {
3704 error.OutOfMemory => |e| return e,
3693 error.AnalysisFail => return,3705 error.AnalysisFail => return,
3694 };3706 };
3695 },3707 },
3696 .analyze_cau => |cau_index| {3708 .analyze_comptime_unit => |unit| {
3709 const named_frame = tracy.namedFrame("analyze_comptime_unit");
3710 defer named_frame.end();
3711
3697 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));3712 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
3698 defer pt.deactivate();3713 defer pt.deactivate();
3699 pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) {3714
3700 error.OutOfMemory => return error.OutOfMemory,3715 const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {
3716 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
3717 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
3718 .nav_val => |nav| pt.ensureNavValUpToDate(nav),
3719 .type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
3720 .func => unreachable,
3721 };
3722 maybe_err catch |err| switch (err) {
3723 error.OutOfMemory => |e| return e,
3701 error.AnalysisFail => return,3724 error.AnalysisFail => return,
3702 };3725 };
3726
3703 queue_test_analysis: {3727 queue_test_analysis: {
3704 if (!comp.config.is_test) break :queue_test_analysis;3728 if (!comp.config.is_test) break :queue_test_analysis;
3729 const nav = switch (unit.unwrap()) {
3730 .nav_val => |nav| nav,
3731 else => break :queue_test_analysis,
3732 };
37053733
3706 // Check if this is a test function.3734 // Check if this is a test function.
3707 const ip = &pt.zcu.intern_pool;3735 const ip = &pt.zcu.intern_pool;
3708 const cau = ip.getCau(cau_index);3736 if (!pt.zcu.test_functions.contains(nav)) {
3709 const nav_index = switch (cau.owner.unwrap()) {
3710 .none, .type => break :queue_test_analysis,
3711 .nav => |nav| nav,
3712 };
3713 if (!pt.zcu.test_functions.contains(nav_index)) {
3714 break :queue_test_analysis;3737 break :queue_test_analysis;
3715 }3738 }
37163739
3717 // Tests are always emitted in test binaries. The decl_refs are created by3740 // Tests are always emitted in test binaries. The decl_refs are created by
3718 // Zcu.populateTestFunctions, but this will not queue body analysis, so do3741 // Zcu.populateTestFunctions, but this will not queue body analysis, so do
3719 // that now.3742 // that now.
3720 try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav_index).status.resolved.val);3743 try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val);
3721 }3744 }
3722 },3745 },
3723 .resolve_type_fully => |ty| {3746 .resolve_type_fully => |ty| {
src/InternPool.zig+355-336
...@@ -34,6 +34,9 @@ src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index),...@@ -34,6 +34,9 @@ src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index),
34/// Dependencies on the value of a Nav.34/// Dependencies on the value of a Nav.
35/// Value is index into `dep_entries` of the first dependency on this Nav value.35/// Value is index into `dep_entries` of the first dependency on this Nav value.
36nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),36nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
37/// Dependencies on the type of a Nav.
38/// Value is index into `dep_entries` of the first dependency on this Nav value.
39nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
37/// Dependencies on an interned value, either:40/// Dependencies on an interned value, either:
38/// * a runtime function (invalidated when its IES changes)41/// * a runtime function (invalidated when its IES changes)
39/// * a container type requiring resolution (invalidated when the type must be recreated at a new index)42/// * a container type requiring resolution (invalidated when the type must be recreated at a new index)
...@@ -80,6 +83,7 @@ pub const empty: InternPool = .{...@@ -80,6 +83,7 @@ pub const empty: InternPool = .{
80 .file_deps = .empty,83 .file_deps = .empty,
81 .src_hash_deps = .empty,84 .src_hash_deps = .empty,
82 .nav_val_deps = .empty,85 .nav_val_deps = .empty,
86 .nav_ty_deps = .empty,
83 .interned_deps = .empty,87 .interned_deps = .empty,
84 .namespace_deps = .empty,88 .namespace_deps = .empty,
85 .namespace_name_deps = .empty,89 .namespace_name_deps = .empty,
...@@ -363,33 +367,56 @@ pub fn rehashTrackedInsts(...@@ -363,33 +367,56 @@ pub fn rehashTrackedInsts(
363}367}
364368
365/// Analysis Unit. Represents a single entity which undergoes semantic analysis.369/// Analysis Unit. Represents a single entity which undergoes semantic analysis.
366/// This is either a `Cau` or a runtime function.
367/// The LSB is used as a tag bit.
368/// This is the "source" of an incremental dependency edge.370/// This is the "source" of an incremental dependency edge.
369pub const AnalUnit = packed struct(u32) {371pub const AnalUnit = packed struct(u64) {
370 kind: enum(u1) { cau, func },372 kind: Kind,
371 index: u31,373 id: u32,
372 pub const Unwrapped = union(enum) {374
373 cau: Cau.Index,375 pub const Kind = enum(u32) {
376 @"comptime",
377 nav_val,
378 nav_ty,
379 type,
380 func,
381 };
382
383 pub const Unwrapped = union(Kind) {
384 /// This `AnalUnit` analyzes the body of the given `comptime` declaration.
385 @"comptime": ComptimeUnit.Id,
386 /// This `AnalUnit` resolves the value of the given `Nav`.
387 nav_val: Nav.Index,
388 /// This `AnalUnit` resolves the type of the given `Nav`.
389 nav_ty: Nav.Index,
390 /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type.
391 /// Generated tag enums are never used here (they do not undergo type resolution).
392 type: InternPool.Index,
393 /// This `AnalUnit` analyzes the body of the given runtime function.
374 func: InternPool.Index,394 func: InternPool.Index,
375 };395 };
376 pub fn unwrap(as: AnalUnit) Unwrapped {396
377 return switch (as.kind) {397 pub fn unwrap(au: AnalUnit) Unwrapped {
378 .cau => .{ .cau = @enumFromInt(as.index) },398 return switch (au.kind) {
379 .func => .{ .func = @enumFromInt(as.index) },399 inline else => |tag| @unionInit(
400 Unwrapped,
401 @tagName(tag),
402 @enumFromInt(au.id),
403 ),
380 };404 };
381 }405 }
382 pub fn wrap(raw: Unwrapped) AnalUnit {406 pub fn wrap(raw: Unwrapped) AnalUnit {
383 return switch (raw) {407 return switch (raw) {
384 .cau => |cau| .{ .kind = .cau, .index = @intCast(@intFromEnum(cau)) },408 inline else => |id, tag| .{
385 .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) },409 .kind = tag,
410 .id = @intFromEnum(id),
411 },
386 };412 };
387 }413 }
414
388 pub fn toOptional(as: AnalUnit) Optional {415 pub fn toOptional(as: AnalUnit) Optional {
389 return @enumFromInt(@as(u32, @bitCast(as)));416 return @enumFromInt(@as(u64, @bitCast(as)));
390 }417 }
391 pub const Optional = enum(u32) {418 pub const Optional = enum(u64) {
392 none = std.math.maxInt(u32),419 none = std.math.maxInt(u64),
393 _,420 _,
394 pub fn unwrap(opt: Optional) ?AnalUnit {421 pub fn unwrap(opt: Optional) ?AnalUnit {
395 return switch (opt) {422 return switch (opt) {
...@@ -400,97 +427,30 @@ pub const AnalUnit = packed struct(u32) {...@@ -400,97 +427,30 @@ pub const AnalUnit = packed struct(u32) {
400 };427 };
401};428};
402429
403/// Comptime Analysis Unit. This is the "subject" of semantic analysis where the root context is430pub const ComptimeUnit = extern struct {
404/// comptime; every `Sema` is owned by either a `Cau` or a runtime function (see `AnalUnit`).
405/// The state stored here is immutable.
406///
407/// * Every ZIR `declaration` has a `Cau` (post-instantiation) to analyze the declaration body.
408/// * Every `struct`, `union`, and `enum` has a `Cau` for type resolution.
409///
410/// The analysis status of a `Cau` is known only from state in `Zcu`.
411/// An entry in `Zcu.failed_analysis` indicates an analysis failure with associated error message.
412/// An entry in `Zcu.transitive_failed_analysis` indicates a transitive analysis failure.
413///
414/// 12 bytes.
415pub const Cau = struct {
416 /// The `declaration`, `struct_decl`, `enum_decl`, or `union_decl` instruction which this `Cau` analyzes.
417 zir_index: TrackedInst.Index,431 zir_index: TrackedInst.Index,
418 /// The namespace which this `Cau` should be analyzed within.
419 namespace: NamespaceIndex,432 namespace: NamespaceIndex,
420 /// This field essentially tells us what to do with the information resulting from
421 /// semantic analysis. See `Owner.Unwrapped` for details.
422 owner: Owner,
423
424 /// See `Owner.Unwrapped` for details. In terms of representation, the `InternPool.Index`
425 /// or `Nav.Index` is cast to a `u31` and stored in `index`. As a special case, if
426 /// `@as(u32, @bitCast(owner)) == 0xFFFF_FFFF`, then the value is treated as `.none`.
427 pub const Owner = packed struct(u32) {
428 kind: enum(u1) { type, nav },
429 index: u31,
430
431 pub const Unwrapped = union(enum) {
432 /// This `Cau` exists in isolation. It is a global `comptime` declaration, or (TODO ANYTHING ELSE?).
433 /// After semantic analysis completes, the result is discarded.
434 none,
435 /// This `Cau` is owned by the given type for type resolution.
436 /// This is a `struct`, `union`, or `enum` type.
437 type: InternPool.Index,
438 /// This `Cau` is owned by the given `Nav` to resolve its value.
439 /// When analyzing the `Cau`, the resulting value is stored as the value of this `Nav`.
440 nav: Nav.Index,
441 };
442433
443 pub fn unwrap(owner: Owner) Unwrapped {434 comptime {
444 if (@as(u32, @bitCast(owner)) == std.math.maxInt(u32)) {435 assert(std.meta.hasUniqueRepresentation(ComptimeUnit));
445 return .none;436 }
446 }
447 return switch (owner.kind) {
448 .type => .{ .type = @enumFromInt(owner.index) },
449 .nav => .{ .nav = @enumFromInt(owner.index) },
450 };
451 }
452
453 fn wrap(raw: Unwrapped) Owner {
454 return switch (raw) {
455 .none => @bitCast(@as(u32, std.math.maxInt(u32))),
456 .type => |ty| .{ .kind = .type, .index = @intCast(@intFromEnum(ty)) },
457 .nav => |nav| .{ .kind = .nav, .index = @intCast(@intFromEnum(nav)) },
458 };
459 }
460 };
461437
462 pub const Index = enum(u32) {438 pub const Id = enum(u32) {
463 _,439 _,
464 pub const Optional = enum(u32) {
465 none = std.math.maxInt(u32),
466 _,
467 pub fn unwrap(opt: Optional) ?Cau.Index {
468 return switch (opt) {
469 .none => null,
470 _ => @enumFromInt(@intFromEnum(opt)),
471 };
472 }
473
474 const debug_state = InternPool.debug_state;
475 };
476 pub fn toOptional(i: Cau.Index) Optional {
477 return @enumFromInt(@intFromEnum(i));
478 }
479 const Unwrapped = struct {440 const Unwrapped = struct {
480 tid: Zcu.PerThread.Id,441 tid: Zcu.PerThread.Id,
481 index: u32,442 index: u32,
482443 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) ComptimeUnit.Id {
483 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Cau.Index {
484 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());444 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
485 assert(unwrapped.index <= ip.getIndexMask(u31));445 assert(unwrapped.index <= ip.getIndexMask(u32));
486 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 |446 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 |
487 unwrapped.index);447 unwrapped.index);
488 }448 }
489 };449 };
490 fn unwrap(cau_index: Cau.Index, ip: *const InternPool) Unwrapped {450 fn unwrap(id: Id, ip: *const InternPool) Unwrapped {
491 return .{451 return .{
492 .tid = @enumFromInt(@intFromEnum(cau_index) >> ip.tid_shift_31 & ip.getTidMask()),452 .tid = @enumFromInt(@intFromEnum(id) >> ip.tid_shift_32 & ip.getTidMask()),
493 .index = @intFromEnum(cau_index) & ip.getIndexMask(u31),453 .index = @intFromEnum(id) & ip.getIndexMask(u31),
494 };454 };
495 }455 }
496456
...@@ -507,6 +467,11 @@ pub const Cau = struct {...@@ -507,6 +467,11 @@ pub const Cau = struct {
507/// * Generic instances have a `Nav` corresponding to the instantiated function.467/// * Generic instances have a `Nav` corresponding to the instantiated function.
508/// * `@extern` calls create a `Nav` whose value is a `.@"extern"`.468/// * `@extern` calls create a `Nav` whose value is a `.@"extern"`.
509///469///
470/// This data structure is optimized for the `analysis_info != null` case, because this is much more
471/// common in practice; the other case is used only for externs and for generic instances. At the time
472/// of writing, in the compiler itself, around 74% of all `Nav`s have `analysis_info != null`.
473/// (Specifically, 104225 / 140923)
474///
510/// `Nav.Repr` is the in-memory representation.475/// `Nav.Repr` is the in-memory representation.
511pub const Nav = struct {476pub const Nav = struct {
512 /// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it.477 /// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it.
...@@ -514,16 +479,31 @@ pub const Nav = struct {...@@ -514,16 +479,31 @@ pub const Nav = struct {
514 name: NullTerminatedString,479 name: NullTerminatedString,
515 /// The fully-qualified name of this `Nav`.480 /// The fully-qualified name of this `Nav`.
516 fqn: NullTerminatedString,481 fqn: NullTerminatedString,
517 /// If the value of this `Nav` is resolved by semantic analysis, it is within this `Cau`.482 /// This field is populated iff this `Nav` is resolved by semantic analysis.
518 /// If this is `.none`, then `status == .resolved` always.483 /// If this is `null`, then `status == .resolved` always.
519 analysis_owner: Cau.Index.Optional,484 analysis: ?struct {
485 namespace: NamespaceIndex,
486 zir_index: TrackedInst.Index,
487 },
520 /// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.488 /// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.
521 is_usingnamespace: bool,489 is_usingnamespace: bool,
522 status: union(enum) {490 status: union(enum) {
523 /// This `Nav` is pending semantic analysis through `analysis_owner`.491 /// This `Nav` is pending semantic analysis.
524 unresolved,492 unresolved,
493 /// The type of this `Nav` is resolved; the value is queued for resolution.
494 type_resolved: struct {
495 type: InternPool.Index,
496 alignment: Alignment,
497 @"linksection": OptionalNullTerminatedString,
498 @"addrspace": std.builtin.AddressSpace,
499 is_const: bool,
500 is_threadlocal: bool,
501 /// This field is whether this `Nav` is a literal `extern` definition.
502 /// It does *not* tell you whether this might alias an extern fn (see #21027).
503 is_extern_decl: bool,
504 },
525 /// The value of this `Nav` is resolved.505 /// The value of this `Nav` is resolved.
526 resolved: struct {506 fully_resolved: struct {
527 val: InternPool.Index,507 val: InternPool.Index,
528 alignment: Alignment,508 alignment: Alignment,
529 @"linksection": OptionalNullTerminatedString,509 @"linksection": OptionalNullTerminatedString,
...@@ -531,30 +511,96 @@ pub const Nav = struct {...@@ -531,30 +511,96 @@ pub const Nav = struct {
531 },511 },
532 },512 },
533513
534 /// Asserts that `status == .resolved`.514 /// Asserts that `status != .unresolved`.
535 pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index {515 pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index {
536 return ip.typeOf(nav.status.resolved.val);516 return switch (nav.status) {
517 .unresolved => unreachable,
518 .type_resolved => |r| r.type,
519 .fully_resolved => |r| ip.typeOf(r.val),
520 };
521 }
522
523 /// Always returns `null` for `status == .type_resolved`. This function is inteded
524 /// to be used by code generation, since semantic analysis will ensure that any `Nav`
525 /// which is potentially `extern` is fully resolved.
526 /// Asserts that `status != .unresolved`.
527 pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {
528 return switch (nav.status) {
529 .unresolved => unreachable,
530 .type_resolved => null,
531 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
532 .@"extern" => |e| e,
533 else => null,
534 },
535 };
537 }536 }
538537
539 /// Asserts that `status == .resolved`.538 /// Asserts that `status != .unresolved`.
540 pub fn isExtern(nav: Nav, ip: *const InternPool) bool {539 pub fn getAddrspace(nav: Nav) std.builtin.AddressSpace {
541 return ip.indexToKey(nav.status.resolved.val) == .@"extern";540 return switch (nav.status) {
541 .unresolved => unreachable,
542 .type_resolved => |r| r.@"addrspace",
543 .fully_resolved => |r| r.@"addrspace",
544 };
545 }
546
547 /// Asserts that `status != .unresolved`.
548 pub fn getAlignment(nav: Nav) Alignment {
549 return switch (nav.status) {
550 .unresolved => unreachable,
551 .type_resolved => |r| r.alignment,
552 .fully_resolved => |r| r.alignment,
553 };
554 }
555
556 /// Asserts that `status != .unresolved`.
557 pub fn isThreadlocal(nav: Nav, ip: *const InternPool) bool {
558 return switch (nav.status) {
559 .unresolved => unreachable,
560 .type_resolved => |r| r.is_threadlocal,
561 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
562 .@"extern" => |e| e.is_threadlocal,
563 .variable => |v| v.is_threadlocal,
564 else => false,
565 },
566 };
567 }
568
569 /// If this returns `true`, then a pointer to this `Nav` might actually be encoded as a pointer
570 /// to some other `Nav` due to an extern definition or extern alias (see #21027).
571 /// This query is valid on `Nav`s for whom only the type is resolved.
572 /// Asserts that `status != .unresolved`.
573 pub fn isExternOrFn(nav: Nav, ip: *const InternPool) bool {
574 return switch (nav.status) {
575 .unresolved => unreachable,
576 .type_resolved => |r| {
577 if (r.is_extern_decl) return true;
578 const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable;
579 if (tag == .@"fn") return true;
580 return false;
581 },
582 .fully_resolved => |r| {
583 if (ip.indexToKey(r.val) == .@"extern") return true;
584 const tag = ip.zigTypeTagOrPoison(ip.typeOf(r.val)) catch unreachable;
585 if (tag == .@"fn") return true;
586 return false;
587 },
588 };
542 }589 }
543590
544 /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations.591 /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations.
545 /// This is a `declaration`.592 /// This is a `declaration`.
546 pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index {593 pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index {
547 if (nav.analysis_owner.unwrap()) |cau| {594 if (nav.analysis) |a| {
548 return ip.getCau(cau).zir_index;595 return a.zir_index;
549 }596 }
550 // A `Nav` with no corresponding `Cau` always has a resolved value.597 // A `Nav` which does not undergo analysis always has a resolved value.
551 return switch (ip.indexToKey(nav.status.resolved.val)) {598 return switch (ip.indexToKey(nav.status.fully_resolved.val)) {
552 .func => |func| {599 .func => |func| {
553 // Since there was no `analysis_owner`, this must be an instantiation.600 // Since `analysis` was not populated, this must be an instantiation.
554 // Go up to the generic owner and consult *its* `analysis_owner`.601 // Go up to the generic owner and consult *its* `analysis` field.
555 const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav);602 const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav);
556 const go_cau = ip.getCau(go_nav.analysis_owner.unwrap().?);603 return go_nav.analysis.?.zir_index;
557 return go_cau.zir_index;
558 },604 },
559 .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern605 .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern
560 else => unreachable,606 else => unreachable,
...@@ -600,24 +646,29 @@ pub const Nav = struct {...@@ -600,24 +646,29 @@ pub const Nav = struct {
600 };646 };
601647
602 /// The compact in-memory representation of a `Nav`.648 /// The compact in-memory representation of a `Nav`.
603 /// 18 bytes.649 /// 26 bytes.
604 const Repr = struct {650 const Repr = struct {
605 name: NullTerminatedString,651 name: NullTerminatedString,
606 fqn: NullTerminatedString,652 fqn: NullTerminatedString,
607 analysis_owner: Cau.Index.Optional,653 // The following 1 fields are either both populated, or both `.none`.
608 /// Populated only if `bits.status == .resolved`.654 analysis_namespace: OptionalNamespaceIndex,
609 val: InternPool.Index,655 analysis_zir_index: TrackedInst.Index.Optional,
610 /// Populated only if `bits.status == .resolved`.656 /// Populated only if `bits.status != .unresolved`.
657 type_or_val: InternPool.Index,
658 /// Populated only if `bits.status != .unresolved`.
611 @"linksection": OptionalNullTerminatedString,659 @"linksection": OptionalNullTerminatedString,
612 bits: Bits,660 bits: Bits,
613661
614 const Bits = packed struct(u16) {662 const Bits = packed struct(u16) {
615 status: enum(u1) { unresolved, resolved },663 status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl },
616 /// Populated only if `bits.status == .resolved`.664 /// Populated only if `bits.status != .unresolved`.
617 alignment: Alignment,665 alignment: Alignment,
618 /// Populated only if `bits.status == .resolved`.666 /// Populated only if `bits.status != .unresolved`.
619 @"addrspace": std.builtin.AddressSpace,667 @"addrspace": std.builtin.AddressSpace,
620 _: u3 = 0,668 /// Populated only if `bits.status == .type_resolved`.
669 is_const: bool,
670 /// Populated only if `bits.status == .type_resolved`.
671 is_threadlocal: bool,
621 is_usingnamespace: bool,672 is_usingnamespace: bool,
622 };673 };
623674
...@@ -625,12 +676,27 @@ pub const Nav = struct {...@@ -625,12 +676,27 @@ pub const Nav = struct {
625 return .{676 return .{
626 .name = repr.name,677 .name = repr.name,
627 .fqn = repr.fqn,678 .fqn = repr.fqn,
628 .analysis_owner = repr.analysis_owner,679 .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{
680 .namespace = namespace,
681 .zir_index = repr.analysis_zir_index.unwrap().?,
682 } else a: {
683 assert(repr.analysis_zir_index == .none);
684 break :a null;
685 },
629 .is_usingnamespace = repr.bits.is_usingnamespace,686 .is_usingnamespace = repr.bits.is_usingnamespace,
630 .status = switch (repr.bits.status) {687 .status = switch (repr.bits.status) {
631 .unresolved => .unresolved,688 .unresolved => .unresolved,
632 .resolved => .{ .resolved = .{689 .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{
633 .val = repr.val,690 .type = repr.type_or_val,
691 .alignment = repr.bits.alignment,
692 .@"linksection" = repr.@"linksection",
693 .@"addrspace" = repr.bits.@"addrspace",
694 .is_const = repr.bits.is_const,
695 .is_threadlocal = repr.bits.is_threadlocal,
696 .is_extern_decl = repr.bits.status == .type_resolved_extern_decl,
697 } },
698 .fully_resolved => .{ .fully_resolved = .{
699 .val = repr.type_or_val,
634 .alignment = repr.bits.alignment,700 .alignment = repr.bits.alignment,
635 .@"linksection" = repr.@"linksection",701 .@"linksection" = repr.@"linksection",
636 .@"addrspace" = repr.bits.@"addrspace",702 .@"addrspace" = repr.bits.@"addrspace",
...@@ -646,14 +712,17 @@ pub const Nav = struct {...@@ -646,14 +712,17 @@ pub const Nav = struct {
646 return .{712 return .{
647 .name = nav.name,713 .name = nav.name,
648 .fqn = nav.fqn,714 .fqn = nav.fqn,
649 .analysis_owner = nav.analysis_owner,715 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,
650 .val = switch (nav.status) {716 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,
717 .type_or_val = switch (nav.status) {
651 .unresolved => .none,718 .unresolved => .none,
652 .resolved => |r| r.val,719 .type_resolved => |r| r.type,
720 .fully_resolved => |r| r.val,
653 },721 },
654 .@"linksection" = switch (nav.status) {722 .@"linksection" = switch (nav.status) {
655 .unresolved => .none,723 .unresolved => .none,
656 .resolved => |r| r.@"linksection",724 .type_resolved => |r| r.@"linksection",
725 .fully_resolved => |r| r.@"linksection",
657 },726 },
658 .bits = switch (nav.status) {727 .bits = switch (nav.status) {
659 .unresolved => .{728 .unresolved => .{
...@@ -661,12 +730,24 @@ pub const Nav = struct {...@@ -661,12 +730,24 @@ pub const Nav = struct {
661 .alignment = .none,730 .alignment = .none,
662 .@"addrspace" = .generic,731 .@"addrspace" = .generic,
663 .is_usingnamespace = nav.is_usingnamespace,732 .is_usingnamespace = nav.is_usingnamespace,
733 .is_const = false,
734 .is_threadlocal = false,
735 },
736 .type_resolved => |r| .{
737 .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved,
738 .alignment = r.alignment,
739 .@"addrspace" = r.@"addrspace",
740 .is_usingnamespace = nav.is_usingnamespace,
741 .is_const = r.is_const,
742 .is_threadlocal = r.is_threadlocal,
664 },743 },
665 .resolved => |r| .{744 .fully_resolved => |r| .{
666 .status = .resolved,745 .status = .fully_resolved,
667 .alignment = r.alignment,746 .alignment = r.alignment,
668 .@"addrspace" = r.@"addrspace",747 .@"addrspace" = r.@"addrspace",
669 .is_usingnamespace = nav.is_usingnamespace,748 .is_usingnamespace = nav.is_usingnamespace,
749 .is_const = false,
750 .is_threadlocal = false,
670 },751 },
671 },752 },
672 };753 };
...@@ -677,6 +758,7 @@ pub const Dependee = union(enum) {...@@ -677,6 +758,7 @@ pub const Dependee = union(enum) {
677 file: FileIndex,758 file: FileIndex,
678 src_hash: TrackedInst.Index,759 src_hash: TrackedInst.Index,
679 nav_val: Nav.Index,760 nav_val: Nav.Index,
761 nav_ty: Nav.Index,
680 interned: Index,762 interned: Index,
681 namespace: TrackedInst.Index,763 namespace: TrackedInst.Index,
682 namespace_name: NamespaceNameKey,764 namespace_name: NamespaceNameKey,
...@@ -726,6 +808,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI...@@ -726,6 +808,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
726 .file => |x| ip.file_deps.get(x),808 .file => |x| ip.file_deps.get(x),
727 .src_hash => |x| ip.src_hash_deps.get(x),809 .src_hash => |x| ip.src_hash_deps.get(x),
728 .nav_val => |x| ip.nav_val_deps.get(x),810 .nav_val => |x| ip.nav_val_deps.get(x),
811 .nav_ty => |x| ip.nav_ty_deps.get(x),
729 .interned => |x| ip.interned_deps.get(x),812 .interned => |x| ip.interned_deps.get(x),
730 .namespace => |x| ip.namespace_deps.get(x),813 .namespace => |x| ip.namespace_deps.get(x),
731 .namespace_name => |x| ip.namespace_name_deps.get(x),814 .namespace_name => |x| ip.namespace_name_deps.get(x),
...@@ -763,6 +846,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend...@@ -763,6 +846,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
763 .file => ip.file_deps,846 .file => ip.file_deps,
764 .src_hash => ip.src_hash_deps,847 .src_hash => ip.src_hash_deps,
765 .nav_val => ip.nav_val_deps,848 .nav_val => ip.nav_val_deps,
849 .nav_ty => ip.nav_ty_deps,
766 .interned => ip.interned_deps,850 .interned => ip.interned_deps,
767 .namespace => ip.namespace_deps,851 .namespace => ip.namespace_deps,
768 .namespace_name => ip.namespace_name_deps,852 .namespace_name => ip.namespace_name_deps,
...@@ -862,8 +946,8 @@ const Local = struct {...@@ -862,8 +946,8 @@ const Local = struct {
862 tracked_insts: ListMutate,946 tracked_insts: ListMutate,
863 files: ListMutate,947 files: ListMutate,
864 maps: ListMutate,948 maps: ListMutate,
865 caus: ListMutate,
866 navs: ListMutate,949 navs: ListMutate,
950 comptime_units: ListMutate,
867951
868 namespaces: BucketListMutate,952 namespaces: BucketListMutate,
869 } align(std.atomic.cache_line),953 } align(std.atomic.cache_line),
...@@ -876,8 +960,8 @@ const Local = struct {...@@ -876,8 +960,8 @@ const Local = struct {
876 tracked_insts: TrackedInsts,960 tracked_insts: TrackedInsts,
877 files: List(File),961 files: List(File),
878 maps: Maps,962 maps: Maps,
879 caus: Caus,
880 navs: Navs,963 navs: Navs,
964 comptime_units: ComptimeUnits,
881965
882 namespaces: Namespaces,966 namespaces: Namespaces,
883967
...@@ -899,8 +983,8 @@ const Local = struct {...@@ -899,8 +983,8 @@ const Local = struct {
899 const Strings = List(struct { u8 });983 const Strings = List(struct { u8 });
900 const TrackedInsts = List(struct { TrackedInst.MaybeLost });984 const TrackedInsts = List(struct { TrackedInst.MaybeLost });
901 const Maps = List(struct { FieldMap });985 const Maps = List(struct { FieldMap });
902 const Caus = List(struct { Cau });
903 const Navs = List(Nav.Repr);986 const Navs = List(Nav.Repr);
987 const ComptimeUnits = List(struct { ComptimeUnit });
904988
905 const namespaces_bucket_width = 8;989 const namespaces_bucket_width = 8;
906 const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1;990 const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1;
...@@ -1275,21 +1359,21 @@ const Local = struct {...@@ -1275,21 +1359,21 @@ const Local = struct {
1275 };1359 };
1276 }1360 }
12771361
1278 pub fn getMutableCaus(local: *Local, gpa: Allocator) Caus.Mutable {1362 pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {
1279 return .{1363 return .{
1280 .gpa = gpa,1364 .gpa = gpa,
1281 .arena = &local.mutate.arena,1365 .arena = &local.mutate.arena,
1282 .mutate = &local.mutate.caus,1366 .mutate = &local.mutate.navs,
1283 .list = &local.shared.caus,1367 .list = &local.shared.navs,
1284 };1368 };
1285 }1369 }
12861370
1287 pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {1371 pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable {
1288 return .{1372 return .{
1289 .gpa = gpa,1373 .gpa = gpa,
1290 .arena = &local.mutate.arena,1374 .arena = &local.mutate.arena,
1291 .mutate = &local.mutate.navs,1375 .mutate = &local.mutate.comptime_units,
1292 .list = &local.shared.navs,1376 .list = &local.shared.comptime_units,
1293 };1377 };
1294 }1378 }
12951379
...@@ -2018,7 +2102,6 @@ pub const Key = union(enum) {...@@ -2018,7 +2102,6 @@ pub const Key = union(enum) {
2018 ty: Index,2102 ty: Index,
2019 init: Index,2103 init: Index,
2020 owner_nav: Nav.Index,2104 owner_nav: Nav.Index,
2021 lib_name: OptionalNullTerminatedString,
2022 is_threadlocal: bool,2105 is_threadlocal: bool,
2023 is_weak_linkage: bool,2106 is_weak_linkage: bool,
2024 };2107 };
...@@ -2111,36 +2194,36 @@ pub const Key = union(enum) {...@@ -2111,36 +2194,36 @@ pub const Key = union(enum) {
2111 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);2194 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);
2112 }2195 }
21132196
2114 pub fn setAnalysisState(func: Func, ip: *InternPool, state: FuncAnalysis.State) void {2197 pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void {
2115 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2198 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2116 extra_mutex.lock();2199 extra_mutex.lock();
2117 defer extra_mutex.unlock();2200 defer extra_mutex.unlock();
21182201
2119 const analysis_ptr = func.analysisPtr(ip);2202 const analysis_ptr = func.analysisPtr(ip);
2120 var analysis = analysis_ptr.*;2203 var analysis = analysis_ptr.*;
2121 analysis.state = state;2204 analysis.calls_or_awaits_errorable_fn = value;
2122 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);2205 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
2123 }2206 }
21242207
2125 pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void {2208 pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {
2126 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2209 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2127 extra_mutex.lock();2210 extra_mutex.lock();
2128 defer extra_mutex.unlock();2211 defer extra_mutex.unlock();
21292212
2130 const analysis_ptr = func.analysisPtr(ip);2213 const analysis_ptr = func.analysisPtr(ip);
2131 var analysis = analysis_ptr.*;2214 var analysis = analysis_ptr.*;
2132 analysis.calls_or_awaits_errorable_fn = value;2215 analysis.branch_hint = hint;
2133 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);2216 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
2134 }2217 }
21352218
2136 pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {2219 pub fn setAnalyzed(func: Func, ip: *InternPool) void {
2137 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2220 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2138 extra_mutex.lock();2221 extra_mutex.lock();
2139 defer extra_mutex.unlock();2222 defer extra_mutex.unlock();
21402223
2141 const analysis_ptr = func.analysisPtr(ip);2224 const analysis_ptr = func.analysisPtr(ip);
2142 var analysis = analysis_ptr.*;2225 var analysis = analysis_ptr.*;
2143 analysis.branch_hint = hint;2226 analysis.is_analyzed = true;
2144 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);2227 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
2145 }2228 }
21462229
...@@ -2741,7 +2824,6 @@ pub const Key = union(enum) {...@@ -2741,7 +2824,6 @@ pub const Key = union(enum) {
2741 return a_info.owner_nav == b_info.owner_nav and2824 return a_info.owner_nav == b_info.owner_nav and
2742 a_info.ty == b_info.ty and2825 a_info.ty == b_info.ty and
2743 a_info.init == b_info.init and2826 a_info.init == b_info.init and
2744 a_info.lib_name == b_info.lib_name and
2745 a_info.is_threadlocal == b_info.is_threadlocal and2827 a_info.is_threadlocal == b_info.is_threadlocal and
2746 a_info.is_weak_linkage == b_info.is_weak_linkage;2828 a_info.is_weak_linkage == b_info.is_weak_linkage;
2747 },2829 },
...@@ -3054,8 +3136,6 @@ pub const LoadedUnionType = struct {...@@ -3054,8 +3136,6 @@ pub const LoadedUnionType = struct {
3054 // TODO: the non-fqn will be needed by the new dwarf structure3136 // TODO: the non-fqn will be needed by the new dwarf structure
3055 /// The name of this union type.3137 /// The name of this union type.
3056 name: NullTerminatedString,3138 name: NullTerminatedString,
3057 /// The `Cau` within which type resolution occurs.
3058 cau: Cau.Index,
3059 /// Represents the declarations inside this union.3139 /// Represents the declarations inside this union.
3060 namespace: NamespaceIndex,3140 namespace: NamespaceIndex,
3061 /// The enum tag type.3141 /// The enum tag type.
...@@ -3372,7 +3452,6 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {...@@ -3372,7 +3452,6 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
3372 .tid = unwrapped_index.tid,3452 .tid = unwrapped_index.tid,
3373 .extra_index = data,3453 .extra_index = data,
3374 .name = type_union.data.name,3454 .name = type_union.data.name,
3375 .cau = type_union.data.cau,
3376 .namespace = type_union.data.namespace,3455 .namespace = type_union.data.namespace,
3377 .enum_tag_ty = type_union.data.tag_ty,3456 .enum_tag_ty = type_union.data.tag_ty,
3378 .field_types = field_types,3457 .field_types = field_types,
...@@ -3389,8 +3468,6 @@ pub const LoadedStructType = struct {...@@ -3389,8 +3468,6 @@ pub const LoadedStructType = struct {
3389 // TODO: the non-fqn will be needed by the new dwarf structure3468 // TODO: the non-fqn will be needed by the new dwarf structure
3390 /// The name of this struct type.3469 /// The name of this struct type.
3391 name: NullTerminatedString,3470 name: NullTerminatedString,
3392 /// The `Cau` within which type resolution occurs.
3393 cau: Cau.Index,
3394 namespace: NamespaceIndex,3471 namespace: NamespaceIndex,
3395 /// Index of the `struct_decl` or `reify` ZIR instruction.3472 /// Index of the `struct_decl` or `reify` ZIR instruction.
3396 zir_index: TrackedInst.Index,3473 zir_index: TrackedInst.Index,
...@@ -3981,7 +4058,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3981,7 +4058,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3981 switch (item.tag) {4058 switch (item.tag) {
3982 .type_struct => {4059 .type_struct => {
3983 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);4060 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
3984 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]);
3985 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);4061 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
3986 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);4062 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
3987 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];4063 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];
...@@ -4068,7 +4144,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4068,7 +4144,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4068 .tid = unwrapped_index.tid,4144 .tid = unwrapped_index.tid,
4069 .extra_index = item.data,4145 .extra_index = item.data,
4070 .name = name,4146 .name = name,
4071 .cau = cau,
4072 .namespace = namespace,4147 .namespace = namespace,
4073 .zir_index = zir_index,4148 .zir_index = zir_index,
4074 .layout = if (flags.is_extern) .@"extern" else .auto,4149 .layout = if (flags.is_extern) .@"extern" else .auto,
...@@ -4085,7 +4160,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4085,7 +4160,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4085 },4160 },
4086 .type_struct_packed, .type_struct_packed_inits => {4161 .type_struct_packed, .type_struct_packed_inits => {
4087 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);4162 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
4088 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?]);
4089 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);4163 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
4090 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];4164 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
4091 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);4165 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);
...@@ -4132,7 +4206,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4132,7 +4206,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4132 .tid = unwrapped_index.tid,4206 .tid = unwrapped_index.tid,
4133 .extra_index = item.data,4207 .extra_index = item.data,
4134 .name = name,4208 .name = name,
4135 .cau = cau,
4136 .namespace = namespace,4209 .namespace = namespace,
4137 .zir_index = zir_index,4210 .zir_index = zir_index,
4138 .layout = .@"packed",4211 .layout = .@"packed",
...@@ -4155,9 +4228,6 @@ pub const LoadedEnumType = struct {...@@ -4155,9 +4228,6 @@ pub const LoadedEnumType = struct {
4155 // TODO: the non-fqn will be needed by the new dwarf structure4228 // TODO: the non-fqn will be needed by the new dwarf structure
4156 /// The name of this enum type.4229 /// The name of this enum type.
4157 name: NullTerminatedString,4230 name: NullTerminatedString,
4158 /// The `Cau` within which type resolution occurs.
4159 /// `null` if this is a generated tag type.
4160 cau: Cau.Index.Optional,
4161 /// Represents the declarations inside this enum.4231 /// Represents the declarations inside this enum.
4162 namespace: NamespaceIndex,4232 namespace: NamespaceIndex,
4163 /// An integer type which is used for the numerical value of the enum.4233 /// An integer type which is used for the numerical value of the enum.
...@@ -4234,21 +4304,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {...@@ -4234,21 +4304,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
4234 .type_enum_auto => {4304 .type_enum_auto => {
4235 const extra = extraDataTrail(extra_list, EnumAuto, item.data);4305 const extra = extraDataTrail(extra_list, EnumAuto, item.data);
4236 var extra_index: u32 = @intCast(extra.end);4306 var extra_index: u32 = @intCast(extra.end);
4237 const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {4307 if (extra.data.zir_index == .none) {
4238 extra_index += 1; // owner_union4308 extra_index += 1; // owner_union
4239 break :cau .none;4309 }
4240 } else cau: {
4241 const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4242 extra_index += 1; // cau
4243 break :cau cau.toOptional();
4244 };
4245 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {4310 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4246 extra_index += 2; // type_hash: PackedU644311 extra_index += 2; // type_hash: PackedU64
4247 break :c 0;4312 break :c 0;
4248 } else extra.data.captures_len;4313 } else extra.data.captures_len;
4249 return .{4314 return .{
4250 .name = extra.data.name,4315 .name = extra.data.name,
4251 .cau = cau,
4252 .namespace = extra.data.namespace,4316 .namespace = extra.data.namespace,
4253 .tag_ty = extra.data.int_tag_type,4317 .tag_ty = extra.data.int_tag_type,
4254 .names = .{4318 .names = .{
...@@ -4274,21 +4338,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {...@@ -4274,21 +4338,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
4274 };4338 };
4275 const extra = extraDataTrail(extra_list, EnumExplicit, item.data);4339 const extra = extraDataTrail(extra_list, EnumExplicit, item.data);
4276 var extra_index: u32 = @intCast(extra.end);4340 var extra_index: u32 = @intCast(extra.end);
4277 const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {4341 if (extra.data.zir_index == .none) {
4278 extra_index += 1; // owner_union4342 extra_index += 1; // owner_union
4279 break :cau .none;4343 }
4280 } else cau: {
4281 const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4282 extra_index += 1; // cau
4283 break :cau cau.toOptional();
4284 };
4285 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {4344 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4286 extra_index += 2; // type_hash: PackedU644345 extra_index += 2; // type_hash: PackedU64
4287 break :c 0;4346 break :c 0;
4288 } else extra.data.captures_len;4347 } else extra.data.captures_len;
4289 return .{4348 return .{
4290 .name = extra.data.name,4349 .name = extra.data.name,
4291 .cau = cau,
4292 .namespace = extra.data.namespace,4350 .namespace = extra.data.namespace,
4293 .tag_ty = extra.data.int_tag_type,4351 .tag_ty = extra.data.int_tag_type,
4294 .names = .{4352 .names = .{
...@@ -5258,7 +5316,6 @@ pub const Tag = enum(u8) {...@@ -5258,7 +5316,6 @@ pub const Tag = enum(u8) {
5258 .payload = EnumExplicit,5316 .payload = EnumExplicit,
5259 .trailing = struct {5317 .trailing = struct {
5260 owner_union: Index,5318 owner_union: Index,
5261 cau: ?Cau.Index,
5262 captures: ?[]CaptureValue,5319 captures: ?[]CaptureValue,
5263 type_hash: ?u64,5320 type_hash: ?u64,
5264 field_names: []NullTerminatedString,5321 field_names: []NullTerminatedString,
...@@ -5304,7 +5361,6 @@ pub const Tag = enum(u8) {...@@ -5304,7 +5361,6 @@ pub const Tag = enum(u8) {
5304 .payload = EnumAuto,5361 .payload = EnumAuto,
5305 .trailing = struct {5362 .trailing = struct {
5306 owner_union: ?Index,5363 owner_union: ?Index,
5307 cau: ?Cau.Index,
5308 captures: ?[]CaptureValue,5364 captures: ?[]CaptureValue,
5309 type_hash: ?u64,5365 type_hash: ?u64,
5310 field_names: []NullTerminatedString,5366 field_names: []NullTerminatedString,
...@@ -5573,9 +5629,6 @@ pub const Tag = enum(u8) {...@@ -5573,9 +5629,6 @@ pub const Tag = enum(u8) {
5573 /// May be `none`.5629 /// May be `none`.
5574 init: Index,5630 init: Index,
5575 owner_nav: Nav.Index,5631 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,
5579 flags: Flags,5632 flags: Flags,
55805633
5581 pub const Flags = packed struct(u32) {5634 pub const Flags = packed struct(u32) {
...@@ -5684,7 +5737,6 @@ pub const Tag = enum(u8) {...@@ -5684,7 +5737,6 @@ pub const Tag = enum(u8) {
5684 size: u32,5737 size: u32,
5685 /// Only valid after .have_layout5738 /// Only valid after .have_layout
5686 padding: u32,5739 padding: u32,
5687 cau: Cau.Index,
5688 namespace: NamespaceIndex,5740 namespace: NamespaceIndex,
5689 /// The enum that provides the list of field names and values.5741 /// The enum that provides the list of field names and values.
5690 tag_ty: Index,5742 tag_ty: Index,
...@@ -5715,7 +5767,6 @@ pub const Tag = enum(u8) {...@@ -5715,7 +5767,6 @@ pub const Tag = enum(u8) {
5715 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits5767 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
5716 pub const TypeStructPacked = struct {5768 pub const TypeStructPacked = struct {
5717 name: NullTerminatedString,5769 name: NullTerminatedString,
5718 cau: Cau.Index,
5719 zir_index: TrackedInst.Index,5770 zir_index: TrackedInst.Index,
5720 fields_len: u32,5771 fields_len: u32,
5721 namespace: NamespaceIndex,5772 namespace: NamespaceIndex,
...@@ -5763,7 +5814,6 @@ pub const Tag = enum(u8) {...@@ -5763,7 +5814,6 @@ pub const Tag = enum(u8) {
5763 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved5814 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
5764 pub const TypeStruct = struct {5815 pub const TypeStruct = struct {
5765 name: NullTerminatedString,5816 name: NullTerminatedString,
5766 cau: Cau.Index,
5767 zir_index: TrackedInst.Index,5817 zir_index: TrackedInst.Index,
5768 namespace: NamespaceIndex,5818 namespace: NamespaceIndex,
5769 fields_len: u32,5819 fields_len: u32,
...@@ -5820,7 +5870,7 @@ pub const Tag = enum(u8) {...@@ -5820,7 +5870,7 @@ pub const Tag = enum(u8) {
5820/// equality or hashing, except for `inferred_error_set` which is considered5870/// equality or hashing, except for `inferred_error_set` which is considered
5821/// to be part of the type of the function.5871/// to be part of the type of the function.
5822pub const FuncAnalysis = packed struct(u32) {5872pub const FuncAnalysis = packed struct(u32) {
5823 state: State,5873 is_analyzed: bool,
5824 branch_hint: std.builtin.BranchHint,5874 branch_hint: std.builtin.BranchHint,
5825 is_noinline: bool,5875 is_noinline: bool,
5826 calls_or_awaits_errorable_fn: bool,5876 calls_or_awaits_errorable_fn: bool,
...@@ -5828,20 +5878,7 @@ pub const FuncAnalysis = packed struct(u32) {...@@ -5828,20 +5878,7 @@ pub const FuncAnalysis = packed struct(u32) {
5828 inferred_error_set: bool,5878 inferred_error_set: bool,
5829 disable_instrumentation: bool,5879 disable_instrumentation: bool,
58305880
5831 _: u23 = 0,5881 _: u24 = 0,
5832
5833 pub const State = enum(u2) {
5834 /// The runtime function has never been referenced.
5835 /// As such, it has never been analyzed, nor is it queued for analysis.
5836 unreferenced,
5837 /// The runtime function has been referenced, but has not yet been analyzed.
5838 /// Its semantic analysis is queued.
5839 queued,
5840 /// The runtime function has been (or is currently being) semantically analyzed.
5841 /// To know if analysis succeeded, consult `zcu.[transitive_]failed_analysis`.
5842 /// To know if analysis is up-to-date, consult `zcu.[potentially_]outdated`.
5843 analyzed,
5844 };
5845};5882};
58465883
5847pub const Bytes = struct {5884pub const Bytes = struct {
...@@ -6093,11 +6130,10 @@ pub const Array = struct {...@@ -6093,11 +6130,10 @@ pub const Array = struct {
60936130
6094/// Trailing:6131/// Trailing:
6095/// 0. owner_union: Index // if `zir_index == .none`6132/// 0. owner_union: Index // if `zir_index == .none`
6096/// 1. cau: Cau.Index // if `zir_index != .none`6133/// 1. capture: CaptureValue // for each `captures_len`
6097/// 2. capture: CaptureValue // for each `captures_len`6134/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6098/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)6135/// 3. field name: NullTerminatedString for each fields_len; declaration order
6099/// 4. field name: NullTerminatedString for each fields_len; declaration order6136/// 4. tag value: Index for each fields_len; declaration order
6100/// 5. tag value: Index for each fields_len; declaration order
6101pub const EnumExplicit = struct {6137pub const EnumExplicit = struct {
6102 name: NullTerminatedString,6138 name: NullTerminatedString,
6103 /// `std.math.maxInt(u32)` indicates this type is reified.6139 /// `std.math.maxInt(u32)` indicates this type is reified.
...@@ -6120,10 +6156,9 @@ pub const EnumExplicit = struct {...@@ -6120,10 +6156,9 @@ pub const EnumExplicit = struct {
61206156
6121/// Trailing:6157/// Trailing:
6122/// 0. owner_union: Index // if `zir_index == .none`6158/// 0. owner_union: Index // if `zir_index == .none`
6123/// 1. cau: Cau.Index // if `zir_index != .none`6159/// 1. capture: CaptureValue // for each `captures_len`
6124/// 2. capture: CaptureValue // for each `captures_len`6160/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6125/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)6161/// 3. field name: NullTerminatedString for each fields_len; declaration order
6126/// 4. field name: NullTerminatedString for each fields_len; declaration order
6127pub const EnumAuto = struct {6162pub const EnumAuto = struct {
6128 name: NullTerminatedString,6163 name: NullTerminatedString,
6129 /// `std.math.maxInt(u32)` indicates this type is reified.6164 /// `std.math.maxInt(u32)` indicates this type is reified.
...@@ -6413,32 +6448,32 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6413,32 +6448,32 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6413 ip.locals = try gpa.alloc(Local, used_threads);6448 ip.locals = try gpa.alloc(Local, used_threads);
6414 @memset(ip.locals, .{6449 @memset(ip.locals, .{
6415 .shared = .{6450 .shared = .{
6416 .items = Local.List(Item).empty,6451 .items = .empty,
6417 .extra = Local.Extra.empty,6452 .extra = .empty,
6418 .limbs = Local.Limbs.empty,6453 .limbs = .empty,
6419 .strings = Local.Strings.empty,6454 .strings = .empty,
6420 .tracked_insts = Local.TrackedInsts.empty,6455 .tracked_insts = .empty,
6421 .files = Local.List(File).empty,6456 .files = .empty,
6422 .maps = Local.Maps.empty,6457 .maps = .empty,
6423 .caus = Local.Caus.empty,6458 .navs = .empty,
6424 .navs = Local.Navs.empty,6459 .comptime_units = .empty,
64256460
6426 .namespaces = Local.Namespaces.empty,6461 .namespaces = .empty,
6427 },6462 },
6428 .mutate = .{6463 .mutate = .{
6429 .arena = .{},6464 .arena = .{},
64306465
6431 .items = Local.ListMutate.empty,6466 .items = .empty,
6432 .extra = Local.ListMutate.empty,6467 .extra = .empty,
6433 .limbs = Local.ListMutate.empty,6468 .limbs = .empty,
6434 .strings = Local.ListMutate.empty,6469 .strings = .empty,
6435 .tracked_insts = Local.ListMutate.empty,6470 .tracked_insts = .empty,
6436 .files = Local.ListMutate.empty,6471 .files = .empty,
6437 .maps = Local.ListMutate.empty,6472 .maps = .empty,
6438 .caus = Local.ListMutate.empty,6473 .navs = .empty,
6439 .navs = Local.ListMutate.empty,6474 .comptime_units = .empty,
64406475
6441 .namespaces = Local.BucketListMutate.empty,6476 .namespaces = .empty,
6442 },6477 },
6443 });6478 });
64446479
...@@ -6486,6 +6521,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -6486,6 +6521,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
6486 ip.file_deps.deinit(gpa);6521 ip.file_deps.deinit(gpa);
6487 ip.src_hash_deps.deinit(gpa);6522 ip.src_hash_deps.deinit(gpa);
6488 ip.nav_val_deps.deinit(gpa);6523 ip.nav_val_deps.deinit(gpa);
6524 ip.nav_ty_deps.deinit(gpa);
6489 ip.interned_deps.deinit(gpa);6525 ip.interned_deps.deinit(gpa);
6490 ip.namespace_deps.deinit(gpa);6526 ip.namespace_deps.deinit(gpa);
6491 ip.namespace_name_deps.deinit(gpa);6527 ip.namespace_name_deps.deinit(gpa);
...@@ -6511,7 +6547,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -6511,7 +6547,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
6511 namespace.priv_decls.deinit(gpa);6547 namespace.priv_decls.deinit(gpa);
6512 namespace.pub_usingnamespace.deinit(gpa);6548 namespace.pub_usingnamespace.deinit(gpa);
6513 namespace.priv_usingnamespace.deinit(gpa);6549 namespace.priv_usingnamespace.deinit(gpa);
6514 namespace.other_decls.deinit(gpa);6550 namespace.comptime_decls.deinit(gpa);
6551 namespace.test_decls.deinit(gpa);
6515 }6552 }
6516 };6553 };
6517 const maps = local.getMutableMaps(gpa);6554 const maps = local.getMutableMaps(gpa);
...@@ -6530,8 +6567,6 @@ pub fn activate(ip: *const InternPool) void {...@@ -6530,8 +6567,6 @@ pub fn activate(ip: *const InternPool) void {
6530 _ = OptionalString.debug_state;6567 _ = OptionalString.debug_state;
6531 _ = NullTerminatedString.debug_state;6568 _ = NullTerminatedString.debug_state;
6532 _ = OptionalNullTerminatedString.debug_state;6569 _ = OptionalNullTerminatedString.debug_state;
6533 _ = Cau.Index.debug_state;
6534 _ = Cau.Index.Optional.debug_state;
6535 _ = Nav.Index.debug_state;6570 _ = Nav.Index.debug_state;
6536 _ = Nav.Index.Optional.debug_state;6571 _ = Nav.Index.Optional.debug_state;
6537 std.debug.assert(debug_state.intern_pool == null);6572 std.debug.assert(debug_state.intern_pool == null);
...@@ -6716,14 +6751,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6716,14 +6751,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6716 if (extra.data.captures_len == std.math.maxInt(u32)) {6751 if (extra.data.captures_len == std.math.maxInt(u32)) {
6717 break :ns .{ .reified = .{6752 break :ns .{ .reified = .{
6718 .zir_index = zir_index,6753 .zir_index = zir_index,
6719 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),6754 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6720 } };6755 } };
6721 }6756 }
6722 break :ns .{ .declared = .{6757 break :ns .{ .declared = .{
6723 .zir_index = zir_index,6758 .zir_index = zir_index,
6724 .captures = .{ .owned = .{6759 .captures = .{ .owned = .{
6725 .tid = unwrapped_index.tid,6760 .tid = unwrapped_index.tid,
6726 .start = extra.end + 1,6761 .start = extra.end,
6727 .len = extra.data.captures_len,6762 .len = extra.data.captures_len,
6728 } },6763 } },
6729 } };6764 } };
...@@ -6740,14 +6775,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6740,14 +6775,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6740 if (extra.data.captures_len == std.math.maxInt(u32)) {6775 if (extra.data.captures_len == std.math.maxInt(u32)) {
6741 break :ns .{ .reified = .{6776 break :ns .{ .reified = .{
6742 .zir_index = zir_index,6777 .zir_index = zir_index,
6743 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),6778 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6744 } };6779 } };
6745 }6780 }
6746 break :ns .{ .declared = .{6781 break :ns .{ .declared = .{
6747 .zir_index = zir_index,6782 .zir_index = zir_index,
6748 .captures = .{ .owned = .{6783 .captures = .{ .owned = .{
6749 .tid = unwrapped_index.tid,6784 .tid = unwrapped_index.tid,
6750 .start = extra.end + 1,6785 .start = extra.end,
6751 .len = extra.data.captures_len,6786 .len = extra.data.captures_len,
6752 } },6787 } },
6753 } };6788 } };
...@@ -6928,7 +6963,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6928,7 +6963,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6928 .ty = extra.ty,6963 .ty = extra.ty,
6929 .init = extra.init,6964 .init = extra.init,
6930 .owner_nav = extra.owner_nav,6965 .owner_nav = extra.owner_nav,
6931 .lib_name = extra.lib_name,
6932 .is_threadlocal = extra.flags.is_threadlocal,6966 .is_threadlocal = extra.flags.is_threadlocal,
6933 .is_weak_linkage = extra.flags.is_weak_linkage,6967 .is_weak_linkage = extra.flags.is_weak_linkage,
6934 } };6968 } };
...@@ -6944,8 +6978,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6944,8 +6978,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6944 .is_threadlocal = extra.flags.is_threadlocal,6978 .is_threadlocal = extra.flags.is_threadlocal,
6945 .is_weak_linkage = extra.flags.is_weak_linkage,6979 .is_weak_linkage = extra.flags.is_weak_linkage,
6946 .is_dll_import = extra.flags.is_dll_import,6980 .is_dll_import = extra.flags.is_dll_import,
6947 .alignment = nav.status.resolved.alignment,6981 .alignment = nav.status.fully_resolved.alignment,
6948 .@"addrspace" = nav.status.resolved.@"addrspace",6982 .@"addrspace" = nav.status.fully_resolved.@"addrspace",
6949 .zir_index = extra.zir_index,6983 .zir_index = extra.zir_index,
6950 .owner_nav = extra.owner_nav,6984 .owner_nav = extra.owner_nav,
6951 } };6985 } };
...@@ -7575,7 +7609,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7575,7 +7609,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7575 .ty = variable.ty,7609 .ty = variable.ty,
7576 .init = variable.init,7610 .init = variable.init,
7577 .owner_nav = variable.owner_nav,7611 .owner_nav = variable.owner_nav,
7578 .lib_name = variable.lib_name,
7579 .flags = .{7612 .flags = .{
7580 .is_const = false,7613 .is_const = false,
7581 .is_threadlocal = variable.is_threadlocal,7614 .is_threadlocal = variable.is_threadlocal,
...@@ -8330,7 +8363,6 @@ pub fn getUnionType(...@@ -8330,7 +8363,6 @@ pub fn getUnionType(
8330 .size = std.math.maxInt(u32),8363 .size = std.math.maxInt(u32),
8331 .padding = std.math.maxInt(u32),8364 .padding = std.math.maxInt(u32),
8332 .name = undefined, // set by `finish`8365 .name = undefined, // set by `finish`
8333 .cau = undefined, // set by `finish`
8334 .namespace = undefined, // set by `finish`8366 .namespace = undefined, // set by `finish`
8335 .tag_ty = ini.enum_tag_ty,8367 .tag_ty = ini.enum_tag_ty,
8336 .zir_index = switch (ini.key) {8368 .zir_index = switch (ini.key) {
...@@ -8382,7 +8414,6 @@ pub fn getUnionType(...@@ -8382,7 +8414,6 @@ pub fn getUnionType(
8382 .tid = tid,8414 .tid = tid,
8383 .index = gop.put(),8415 .index = gop.put(),
8384 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,8416 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
8385 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "cau").?,
8386 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,8417 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
8387 } };8418 } };
8388}8419}
...@@ -8391,7 +8422,6 @@ pub const WipNamespaceType = struct {...@@ -8391,7 +8422,6 @@ pub const WipNamespaceType = struct {
8391 tid: Zcu.PerThread.Id,8422 tid: Zcu.PerThread.Id,
8392 index: Index,8423 index: Index,
8393 type_name_extra_index: u32,8424 type_name_extra_index: u32,
8394 cau_extra_index: ?u32,
8395 namespace_extra_index: u32,8425 namespace_extra_index: u32,
83968426
8397 pub fn setName(8427 pub fn setName(
...@@ -8407,18 +8437,11 @@ pub const WipNamespaceType = struct {...@@ -8407,18 +8437,11 @@ pub const WipNamespaceType = struct {
8407 pub fn finish(8437 pub fn finish(
8408 wip: WipNamespaceType,8438 wip: WipNamespaceType,
8409 ip: *InternPool,8439 ip: *InternPool,
8410 analysis_owner: Cau.Index.Optional,
8411 namespace: NamespaceIndex,8440 namespace: NamespaceIndex,
8412 ) Index {8441 ) Index {
8413 const extra = ip.getLocalShared(wip.tid).extra.acquire();8442 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8414 const extra_items = extra.view().items(.@"0");8443 const extra_items = extra.view().items(.@"0");
84158444
8416 if (wip.cau_extra_index) |i| {
8417 extra_items[i] = @intFromEnum(analysis_owner.unwrap().?);
8418 } else {
8419 assert(analysis_owner == .none);
8420 }
8421
8422 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);8445 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
84238446
8424 return wip.index;8447 return wip.index;
...@@ -8517,7 +8540,6 @@ pub fn getStructType(...@@ -8517,7 +8540,6 @@ pub fn getStructType(
8517 ini.fields_len); // inits8540 ini.fields_len); // inits
8518 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{8541 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
8519 .name = undefined, // set by `finish`8542 .name = undefined, // set by `finish`
8520 .cau = undefined, // set by `finish`
8521 .zir_index = zir_index,8543 .zir_index = zir_index,
8522 .fields_len = ini.fields_len,8544 .fields_len = ini.fields_len,
8523 .namespace = undefined, // set by `finish`8545 .namespace = undefined, // set by `finish`
...@@ -8562,7 +8584,6 @@ pub fn getStructType(...@@ -8562,7 +8584,6 @@ pub fn getStructType(
8562 .tid = tid,8584 .tid = tid,
8563 .index = gop.put(),8585 .index = gop.put(),
8564 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,8586 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
8565 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?,
8566 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,8587 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
8567 } };8588 } };
8568 },8589 },
...@@ -8585,7 +8606,6 @@ pub fn getStructType(...@@ -8585,7 +8606,6 @@ pub fn getStructType(
8585 1); // names_map8606 1); // names_map
8586 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{8607 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
8587 .name = undefined, // set by `finish`8608 .name = undefined, // set by `finish`
8588 .cau = undefined, // set by `finish`
8589 .zir_index = zir_index,8609 .zir_index = zir_index,
8590 .namespace = undefined, // set by `finish`8610 .namespace = undefined, // set by `finish`
8591 .fields_len = ini.fields_len,8611 .fields_len = ini.fields_len,
...@@ -8654,7 +8674,6 @@ pub fn getStructType(...@@ -8654,7 +8674,6 @@ pub fn getStructType(
8654 .tid = tid,8674 .tid = tid,
8655 .index = gop.put(),8675 .index = gop.put(),
8656 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,8676 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
8657 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "cau").?,
8658 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,8677 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
8659 } };8678 } };
8660}8679}
...@@ -8878,7 +8897,7 @@ pub fn getFuncDecl(...@@ -8878,7 +8897,7 @@ pub fn getFuncDecl(
88788897
8879 const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{8898 const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{
8880 .analysis = .{8899 .analysis = .{
8881 .state = .unreferenced,8900 .is_analyzed = false,
8882 .branch_hint = .none,8901 .branch_hint = .none,
8883 .is_noinline = key.is_noinline,8902 .is_noinline = key.is_noinline,
8884 .calls_or_awaits_errorable_fn = false,8903 .calls_or_awaits_errorable_fn = false,
...@@ -8987,7 +9006,7 @@ pub fn getFuncDeclIes(...@@ -8987,7 +9006,7 @@ pub fn getFuncDeclIes(
89879006
8988 const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{9007 const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{
8989 .analysis = .{9008 .analysis = .{
8990 .state = .unreferenced,9009 .is_analyzed = false,
8991 .branch_hint = .none,9010 .branch_hint = .none,
8992 .is_noinline = key.is_noinline,9011 .is_noinline = key.is_noinline,
8993 .calls_or_awaits_errorable_fn = false,9012 .calls_or_awaits_errorable_fn = false,
...@@ -9183,7 +9202,7 @@ pub fn getFuncInstance(...@@ -9183,7 +9202,7 @@ pub fn getFuncInstance(
91839202
9184 const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{9203 const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{
9185 .analysis = .{9204 .analysis = .{
9186 .state = .unreferenced,9205 .is_analyzed = false,
9187 .branch_hint = .none,9206 .branch_hint = .none,
9188 .is_noinline = arg.is_noinline,9207 .is_noinline = arg.is_noinline,
9189 .calls_or_awaits_errorable_fn = false,9208 .calls_or_awaits_errorable_fn = false,
...@@ -9281,7 +9300,7 @@ pub fn getFuncInstanceIes(...@@ -9281,7 +9300,7 @@ pub fn getFuncInstanceIes(
92819300
9282 const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{9301 const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{
9283 .analysis = .{9302 .analysis = .{
9284 .state = .unreferenced,9303 .is_analyzed = false,
9285 .branch_hint = .none,9304 .branch_hint = .none,
9286 .is_noinline = arg.is_noinline,9305 .is_noinline = arg.is_noinline,
9287 .calls_or_awaits_errorable_fn = false,9306 .calls_or_awaits_errorable_fn = false,
...@@ -9390,7 +9409,7 @@ fn finishFuncInstance(...@@ -9390,7 +9409,7 @@ fn finishFuncInstance(
9390 func_extra_index: u32,9409 func_extra_index: u32,
9391) Allocator.Error!void {9410) Allocator.Error!void {
9392 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);9411 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);
9393 const fn_namespace = ip.getCau(fn_owner_nav.analysis_owner.unwrap().?).namespace;9412 const fn_namespace = fn_owner_nav.analysis.?.namespace;
93949413
9395 // TODO: improve this name9414 // TODO: improve this name
9396 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{9415 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{
...@@ -9400,9 +9419,9 @@ fn finishFuncInstance(...@@ -9400,9 +9419,9 @@ fn finishFuncInstance(
9400 .name = nav_name,9419 .name = nav_name,
9401 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name),9420 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name),
9402 .val = func_index,9421 .val = func_index,
9403 .alignment = fn_owner_nav.status.resolved.alignment,9422 .alignment = fn_owner_nav.status.fully_resolved.alignment,
9404 .@"linksection" = fn_owner_nav.status.resolved.@"linksection",9423 .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection",
9405 .@"addrspace" = fn_owner_nav.status.resolved.@"addrspace",9424 .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace",
9406 });9425 });
94079426
9408 // Populate the owner_nav field which was left undefined until now.9427 // Populate the owner_nav field which was left undefined until now.
...@@ -9436,7 +9455,6 @@ pub const WipEnumType = struct {...@@ -9436,7 +9455,6 @@ pub const WipEnumType = struct {
9436 index: Index,9455 index: Index,
9437 tag_ty_index: u32,9456 tag_ty_index: u32,
9438 type_name_extra_index: u32,9457 type_name_extra_index: u32,
9439 cau_extra_index: u32,
9440 namespace_extra_index: u32,9458 namespace_extra_index: u32,
9441 names_map: MapIndex,9459 names_map: MapIndex,
9442 names_start: u32,9460 names_start: u32,
...@@ -9456,13 +9474,11 @@ pub const WipEnumType = struct {...@@ -9456,13 +9474,11 @@ pub const WipEnumType = struct {
9456 pub fn prepare(9474 pub fn prepare(
9457 wip: WipEnumType,9475 wip: WipEnumType,
9458 ip: *InternPool,9476 ip: *InternPool,
9459 analysis_owner: Cau.Index,
9460 namespace: NamespaceIndex,9477 namespace: NamespaceIndex,
9461 ) void {9478 ) void {
9462 const extra = ip.getLocalShared(wip.tid).extra.acquire();9479 const extra = ip.getLocalShared(wip.tid).extra.acquire();
9463 const extra_items = extra.view().items(.@"0");9480 const extra_items = extra.view().items(.@"0");
94649481
9465 extra_items[wip.cau_extra_index] = @intFromEnum(analysis_owner);
9466 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);9482 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
9467 }9483 }
94689484
...@@ -9563,7 +9579,6 @@ pub fn getEnumType(...@@ -9563,7 +9579,6 @@ pub fn getEnumType(
9563 .reified => 2, // type_hash: PackedU649579 .reified => 2, // type_hash: PackedU64
9564 } +9580 } +
9565 // zig fmt: on9581 // zig fmt: on
9566 1 + // cau
9567 ini.fields_len); // field types9582 ini.fields_len); // field types
95689583
9569 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{9584 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
...@@ -9584,8 +9599,6 @@ pub fn getEnumType(...@@ -9584,8 +9599,6 @@ pub fn getEnumType(
9584 .tag = .type_enum_auto,9599 .tag = .type_enum_auto,
9585 .data = extra_index,9600 .data = extra_index,
9586 });9601 });
9587 const cau_extra_index = extra.view().len;
9588 extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
9589 switch (ini.key) {9602 switch (ini.key) {
9590 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),9603 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
9591 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),9604 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
...@@ -9598,7 +9611,6 @@ pub fn getEnumType(...@@ -9598,7 +9611,6 @@ pub fn getEnumType(
9598 .index = gop.put(),9611 .index = gop.put(),
9599 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,9612 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
9600 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,9613 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
9601 .cau_extra_index = @intCast(cau_extra_index),
9602 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,9614 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
9603 .names_map = names_map,9615 .names_map = names_map,
9604 .names_start = @intCast(names_start),9616 .names_start = @intCast(names_start),
...@@ -9623,7 +9635,6 @@ pub fn getEnumType(...@@ -9623,7 +9635,6 @@ pub fn getEnumType(
9623 .reified => 2, // type_hash: PackedU649635 .reified => 2, // type_hash: PackedU64
9624 } +9636 } +
9625 // zig fmt: on9637 // zig fmt: on
9626 1 + // cau
9627 ini.fields_len + // field types9638 ini.fields_len + // field types
9628 ini.fields_len * @intFromBool(ini.has_values)); // field values9639 ini.fields_len * @intFromBool(ini.has_values)); // field values
96299640
...@@ -9650,8 +9661,6 @@ pub fn getEnumType(...@@ -9650,8 +9661,6 @@ pub fn getEnumType(
9650 },9661 },
9651 .data = extra_index,9662 .data = extra_index,
9652 });9663 });
9653 const cau_extra_index = extra.view().len;
9654 extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
9655 switch (ini.key) {9664 switch (ini.key) {
9656 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),9665 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
9657 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),9666 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
...@@ -9668,7 +9677,6 @@ pub fn getEnumType(...@@ -9668,7 +9677,6 @@ pub fn getEnumType(
9668 .index = gop.put(),9677 .index = gop.put(),
9669 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,9678 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
9670 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,9679 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
9671 .cau_extra_index = @intCast(cau_extra_index),
9672 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,9680 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
9673 .names_map = names_map,9681 .names_map = names_map,
9674 .names_start = @intCast(names_start),9682 .names_start = @intCast(names_start),
...@@ -9865,7 +9873,6 @@ pub fn getOpaqueType(...@@ -9865,7 +9873,6 @@ pub fn getOpaqueType(
9865 .tid = tid,9873 .tid = tid,
9866 .index = gop.put(),9874 .index = gop.put(),
9867 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,9875 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
9868 .cau_extra_index = null, // opaques do not undergo type resolution
9869 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,9876 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
9870 },9877 },
9871 };9878 };
...@@ -9981,7 +9988,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {...@@ -9981,7 +9988,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
9981 inline for (@typeInfo(@TypeOf(item)).@"struct".fields) |field| {9988 inline for (@typeInfo(@TypeOf(item)).@"struct".fields) |field| {
9982 extra.appendAssumeCapacity(.{switch (field.type) {9989 extra.appendAssumeCapacity(.{switch (field.type) {
9983 Index,9990 Index,
9984 Cau.Index,
9985 Nav.Index,9991 Nav.Index,
9986 NamespaceIndex,9992 NamespaceIndex,
9987 OptionalNamespaceIndex,9993 OptionalNamespaceIndex,
...@@ -10044,7 +10050,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat...@@ -10044,7 +10050,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
10044 const extra_item = extra_items[extra_index];10050 const extra_item = extra_items[extra_index];
10045 @field(result, field.name) = switch (field.type) {10051 @field(result, field.name) = switch (field.type) {
10046 Index,10052 Index,
10047 Cau.Index,
10048 Nav.Index,10053 Nav.Index,
10049 NamespaceIndex,10054 NamespaceIndex,
10050 OptionalNamespaceIndex,10055 OptionalNamespaceIndex,
...@@ -11065,12 +11070,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11065,12 +11070,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11065 try bw.flush();11070 try bw.flush();
11066}11071}
1106711072
11068pub fn getCau(ip: *const InternPool, index: Cau.Index) Cau {
11069 const unwrapped = index.unwrap(ip);
11070 const caus = ip.getLocalShared(unwrapped.tid).caus.acquire();
11071 return caus.view().items(.@"0")[unwrapped.index];
11072}
11073
11074pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {11073pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
11075 const unwrapped = index.unwrap(ip);11074 const unwrapped = index.unwrap(ip);
11076 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();11075 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();
...@@ -11084,51 +11083,34 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names...@@ -11084,51 +11083,34 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names
11084 return &namespaces_bucket[unwrapped_namespace_index.index];11083 return &namespaces_bucket[unwrapped_namespace_index.index];
11085}11084}
1108611085
11087/// Create a `Cau` associated with the type at the given `InternPool.Index`.11086/// Create a `ComptimeUnit`, forming an `AnalUnit` for a `comptime` declaration.
11088pub fn createTypeCau(11087pub fn createComptimeUnit(
11089 ip: *InternPool,11088 ip: *InternPool,
11090 gpa: Allocator,11089 gpa: Allocator,
11091 tid: Zcu.PerThread.Id,11090 tid: Zcu.PerThread.Id,
11092 zir_index: TrackedInst.Index,11091 zir_index: TrackedInst.Index,
11093 namespace: NamespaceIndex,11092 namespace: NamespaceIndex,
11094 owner_type: InternPool.Index,11093) Allocator.Error!ComptimeUnit.Id {
11095) Allocator.Error!Cau.Index {11094 const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa);
11096 const caus = ip.getLocal(tid).getMutableCaus(gpa);11095 const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{
11097 const index_unwrapped: Cau.Index.Unwrapped = .{
11098 .tid = tid,11096 .tid = tid,
11099 .index = caus.mutate.len,11097 .index = comptime_units.mutate.len,
11100 };11098 };
11101 try caus.append(.{.{11099 try comptime_units.append(.{.{
11102 .zir_index = zir_index,11100 .zir_index = zir_index,
11103 .namespace = namespace,11101 .namespace = namespace,
11104 .owner = Cau.Owner.wrap(.{ .type = owner_type }),
11105 }});11102 }});
11106 return index_unwrapped.wrap(ip);11103 return id_unwrapped.wrap(ip);
11107}11104}
1110811105
11109/// Create a `Cau` for a `comptime` declaration.11106pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit {
11110pub fn createComptimeCau(11107 const unwrapped = id.unwrap(ip);
11111 ip: *InternPool,11108 const comptime_units = ip.getLocalShared(unwrapped.tid).comptime_units.acquire();
11112 gpa: Allocator,11109 return comptime_units.view().items(.@"0")[unwrapped.index];
11113 tid: Zcu.PerThread.Id,
11114 zir_index: TrackedInst.Index,
11115 namespace: NamespaceIndex,
11116) Allocator.Error!Cau.Index {
11117 const caus = ip.getLocal(tid).getMutableCaus(gpa);
11118 const index_unwrapped: Cau.Index.Unwrapped = .{
11119 .tid = tid,
11120 .index = caus.mutate.len,
11121 };
11122 try caus.append(.{.{
11123 .zir_index = zir_index,
11124 .namespace = namespace,
11125 .owner = Cau.Owner.wrap(.none),
11126 }});
11127 return index_unwrapped.wrap(ip);
11128}11110}
1112911111
11130/// Create a `Nav` not associated with any `Cau`.11112/// Create a `Nav` which does not undergo semantic analysis.
11131/// Since there is no analysis owner, the `Nav`'s value must be known at creation time.11113/// Since it is never analyzed, the `Nav`'s value must be known at creation time.
11132pub fn createNav(11114pub fn createNav(
11133 ip: *InternPool,11115 ip: *InternPool,
11134 gpa: Allocator,11116 gpa: Allocator,
...@@ -11150,8 +11132,8 @@ pub fn createNav(...@@ -11150,8 +11132,8 @@ pub fn createNav(
11150 try navs.append(Nav.pack(.{11132 try navs.append(Nav.pack(.{
11151 .name = opts.name,11133 .name = opts.name,
11152 .fqn = opts.fqn,11134 .fqn = opts.fqn,
11153 .analysis_owner = .none,11135 .analysis = null,
11154 .status = .{ .resolved = .{11136 .status = .{ .fully_resolved = .{
11155 .val = opts.val,11137 .val = opts.val,
11156 .alignment = opts.alignment,11138 .alignment = opts.alignment,
11157 .@"linksection" = opts.@"linksection",11139 .@"linksection" = opts.@"linksection",
...@@ -11162,10 +11144,9 @@ pub fn createNav(...@@ -11162,10 +11144,9 @@ pub fn createNav(
11162 return index_unwrapped.wrap(ip);11144 return index_unwrapped.wrap(ip);
11163}11145}
1116411146
11165/// Create a `Cau` and `Nav` which are paired. The value of the `Nav` is11147/// Create a `Nav` which undergoes semantic analysis because it corresponds to a source declaration.
11166/// determined by semantic analysis of the `Cau`. The value of the `Nav`11148/// The value of the `Nav` is initially unresolved.
11167/// is initially unresolved.11149pub fn createDeclNav(
11168pub fn createPairedCauNav(
11169 ip: *InternPool,11150 ip: *InternPool,
11170 gpa: Allocator,11151 gpa: Allocator,
11171 tid: Zcu.PerThread.Id,11152 tid: Zcu.PerThread.Id,
...@@ -11175,36 +11156,72 @@ pub fn createPairedCauNav(...@@ -11175,36 +11156,72 @@ pub fn createPairedCauNav(
11175 namespace: NamespaceIndex,11156 namespace: NamespaceIndex,
11176 /// TODO: this is hacky! See `Nav.is_usingnamespace`.11157 /// TODO: this is hacky! See `Nav.is_usingnamespace`.
11177 is_usingnamespace: bool,11158 is_usingnamespace: bool,
11178) Allocator.Error!struct { Cau.Index, Nav.Index } {11159) Allocator.Error!Nav.Index {
11179 const caus = ip.getLocal(tid).getMutableCaus(gpa);
11180 const navs = ip.getLocal(tid).getMutableNavs(gpa);11160 const navs = ip.getLocal(tid).getMutableNavs(gpa);
1118111161
11182 try caus.ensureUnusedCapacity(1);
11183 try navs.ensureUnusedCapacity(1);11162 try navs.ensureUnusedCapacity(1);
1118411163
11185 const cau = Cau.Index.Unwrapped.wrap(.{
11186 .tid = tid,
11187 .index = caus.mutate.len,
11188 }, ip);
11189 const nav = Nav.Index.Unwrapped.wrap(.{11164 const nav = Nav.Index.Unwrapped.wrap(.{
11190 .tid = tid,11165 .tid = tid,
11191 .index = navs.mutate.len,11166 .index = navs.mutate.len,
11192 }, ip);11167 }, ip);
1119311168
11194 caus.appendAssumeCapacity(.{.{
11195 .zir_index = zir_index,
11196 .namespace = namespace,
11197 .owner = Cau.Owner.wrap(.{ .nav = nav }),
11198 }});
11199 navs.appendAssumeCapacity(Nav.pack(.{11169 navs.appendAssumeCapacity(Nav.pack(.{
11200 .name = name,11170 .name = name,
11201 .fqn = fqn,11171 .fqn = fqn,
11202 .analysis_owner = cau.toOptional(),11172 .analysis = .{
11173 .namespace = namespace,
11174 .zir_index = zir_index,
11175 },
11203 .status = .unresolved,11176 .status = .unresolved,
11204 .is_usingnamespace = is_usingnamespace,11177 .is_usingnamespace = is_usingnamespace,
11205 }));11178 }));
1120611179
11207 return .{ cau, nav };11180 return nav;
11181}
11182
11183/// Resolve the type of a `Nav` with an analysis owner.
11184/// If its status is already `resolved`, the old value is discarded.
11185pub fn resolveNavType(
11186 ip: *InternPool,
11187 nav: Nav.Index,
11188 resolved: struct {
11189 type: InternPool.Index,
11190 alignment: Alignment,
11191 @"linksection": OptionalNullTerminatedString,
11192 @"addrspace": std.builtin.AddressSpace,
11193 is_const: bool,
11194 is_threadlocal: bool,
11195 is_extern_decl: bool,
11196 },
11197) void {
11198 const unwrapped = nav.unwrap(ip);
11199
11200 const local = ip.getLocal(unwrapped.tid);
11201 local.mutate.extra.mutex.lock();
11202 defer local.mutate.extra.mutex.unlock();
11203
11204 const navs = local.shared.navs.view();
11205
11206 const nav_analysis_namespace = navs.items(.analysis_namespace);
11207 const nav_analysis_zir_index = navs.items(.analysis_zir_index);
11208 const nav_types = navs.items(.type_or_val);
11209 const nav_linksections = navs.items(.@"linksection");
11210 const nav_bits = navs.items(.bits);
11211
11212 assert(nav_analysis_namespace[unwrapped.index] != .none);
11213 assert(nav_analysis_zir_index[unwrapped.index] != .none);
11214
11215 @atomicStore(InternPool.Index, &nav_types[unwrapped.index], resolved.type, .release);
11216 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);
11217
11218 var bits = nav_bits[unwrapped.index];
11219 bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved;
11220 bits.alignment = resolved.alignment;
11221 bits.@"addrspace" = resolved.@"addrspace";
11222 bits.is_const = resolved.is_const;
11223 bits.is_threadlocal = resolved.is_threadlocal;
11224 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);
11208}11225}
1120911226
11210/// Resolve the value of a `Nav` with an analysis owner.11227/// Resolve the value of a `Nav` with an analysis owner.
...@@ -11227,18 +11244,20 @@ pub fn resolveNavValue(...@@ -11227,18 +11244,20 @@ pub fn resolveNavValue(
1122711244
11228 const navs = local.shared.navs.view();11245 const navs = local.shared.navs.view();
1122911246
11230 const nav_analysis_owners = navs.items(.analysis_owner);11247 const nav_analysis_namespace = navs.items(.analysis_namespace);
11231 const nav_vals = navs.items(.val);11248 const nav_analysis_zir_index = navs.items(.analysis_zir_index);
11249 const nav_vals = navs.items(.type_or_val);
11232 const nav_linksections = navs.items(.@"linksection");11250 const nav_linksections = navs.items(.@"linksection");
11233 const nav_bits = navs.items(.bits);11251 const nav_bits = navs.items(.bits);
1123411252
11235 assert(nav_analysis_owners[unwrapped.index] != .none);11253 assert(nav_analysis_namespace[unwrapped.index] != .none);
11254 assert(nav_analysis_zir_index[unwrapped.index] != .none);
1123611255
11237 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);11256 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);
11238 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);11257 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);
1123911258
11240 var bits = nav_bits[unwrapped.index];11259 var bits = nav_bits[unwrapped.index];
11241 bits.status = .resolved;11260 bits.status = .fully_resolved;
11242 bits.alignment = resolved.alignment;11261 bits.alignment = resolved.alignment;
11243 bits.@"addrspace" = resolved.@"addrspace";11262 bits.@"addrspace" = resolved.@"addrspace";
11244 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);11263 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);
src/Sema.zig+273-404
...@@ -1284,7 +1284,6 @@ fn analyzeBodyInner(...@@ -1284,7 +1284,6 @@ fn analyzeBodyInner(
1284 const extended = datas[@intFromEnum(inst)].extended;1284 const extended = datas[@intFromEnum(inst)].extended;
1285 break :ext switch (extended.opcode) {1285 break :ext switch (extended.opcode) {
1286 // zig fmt: off1286 // zig fmt: off
1287 .variable => try sema.zirVarExtended( block, extended),
1288 .struct_decl => try sema.zirStructDecl( block, extended, inst),1287 .struct_decl => try sema.zirStructDecl( block, extended, inst),
1289 .enum_decl => try sema.zirEnumDecl( block, extended, inst),1288 .enum_decl => try sema.zirEnumDecl( block, extended, inst),
1290 .union_decl => try sema.zirUnionDecl( block, extended, inst),1289 .union_decl => try sema.zirUnionDecl( block, extended, inst),
...@@ -2114,13 +2113,33 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)...@@ -2114,13 +2113,33 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
2114}2113}
21152114
2116/// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value.2115/// 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.
2118/// Generic poison causes `error.GenericPoison` to be returned.2116/// Generic poison causes `error.GenericPoison` to be returned.
2119fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {2117fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2120 const val = (try sema.resolveValueAllowVariables(inst)) orelse return null;2118 const zcu = sema.pt.zcu;
2121 if (val.isGenericPoison()) return error.GenericPoison;2119 assert(inst != .none);
2122 if (sema.pt.zcu.intern_pool.isVariable(val.toIntern())) return null;2120
2123 return val;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 }
2124}2143}
21252144
2126/// Like `resolveValue`, but emits an error if the value is not comptime-known.2145/// 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 {...@@ -2183,35 +2202,6 @@ fn resolveValueIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2183 return try sema.resolveLazyValue(val);2202 return try sema.resolveLazyValue(val);
2184}2203}
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
2215/// Value Tag may be `undef` or `variable`.2205/// Value Tag may be `undef` or `variable`.
2216pub fn resolveFinalDeclValue(2206pub fn resolveFinalDeclValue(
2217 sema: *Sema,2207 sema: *Sema,
...@@ -2221,8 +2211,13 @@ pub fn resolveFinalDeclValue(...@@ -2221,8 +2211,13 @@ pub fn resolveFinalDeclValue(
2221) CompileError!Value {2211) CompileError!Value {
2222 const zcu = sema.pt.zcu;2212 const zcu = sema.pt.zcu;
22232213
2224 const val = try sema.resolveValueAllowVariables(air_ref) orelse {2214 const val = try sema.resolveValue(air_ref) orelse {
2225 const value_comptime_reason: ?[]const u8 = if (air_ref.toInterned()) |_|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)
2226 "thread local and dll imported variables have runtime-known addresses"2221 "thread local and dll imported variables have runtime-known addresses"
2227 else2222 else
2228 null;2223 null;
...@@ -2232,10 +2227,8 @@ pub fn resolveFinalDeclValue(...@@ -2232,10 +2227,8 @@ pub fn resolveFinalDeclValue(
2232 .value_comptime_reason = value_comptime_reason,2227 .value_comptime_reason = value_comptime_reason,
2233 });2228 });
2234 };2229 };
2235 if (val.isGenericPoison()) return error.GenericPoison;
22362230
2237 const init_val: Value = if (val.getVariable(zcu)) |v| .fromInterned(v.init) else val;2231 if (val.canMutateComptimeVarState(zcu)) {
2238 if (init_val.canMutateComptimeVarState(zcu)) {
2239 return sema.fail(block, src, "global variable contains reference to comptime var", .{});2232 return sema.fail(block, src, "global variable contains reference to comptime var", .{});
2240 }2233 }
22412234
...@@ -2877,7 +2870,7 @@ fn zirStructDecl(...@@ -2877,7 +2870,7 @@ fn zirStructDecl(
2877 };2870 };
2878 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {2871 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {
2879 .existing => |ty| {2872 .existing => |ty| {
2880 const new_ty = try pt.ensureTypeUpToDate(ty, false);2873 const new_ty = try pt.ensureTypeUpToDate(ty);
28812874
2882 // Make sure we update the namespace if the declaration is re-analyzed, to pick2875 // Make sure we update the namespace if the declaration is re-analyzed, to pick
2883 // up on e.g. changed comptime decls.2876 // up on e.g. changed comptime decls.
...@@ -2907,12 +2900,10 @@ fn zirStructDecl(...@@ -2907,12 +2900,10 @@ fn zirStructDecl(
2907 });2900 });
2908 errdefer pt.destroyNamespace(new_namespace_index);2901 errdefer pt.destroyNamespace(new_namespace_index);
29092902
2910 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
2911
2912 if (pt.zcu.comp.incremental) {2903 if (pt.zcu.comp.incremental) {
2913 try ip.addDependency(2904 try ip.addDependency(
2914 sema.gpa,2905 sema.gpa,
2915 AnalUnit.wrap(.{ .cau = new_cau_index }),2906 AnalUnit.wrap(.{ .type = wip_ty.index }),
2916 .{ .src_hash = tracked_inst },2907 .{ .src_hash = tracked_inst },
2917 );2908 );
2918 }2909 }
...@@ -2929,7 +2920,7 @@ fn zirStructDecl(...@@ -2929,7 +2920,7 @@ fn zirStructDecl(
2929 }2920 }
2930 try sema.declareDependency(.{ .interned = wip_ty.index });2921 try sema.declareDependency(.{ .interned = wip_ty.index });
2931 try sema.addTypeReferenceEntry(src, wip_ty.index);2922 try sema.addTypeReferenceEntry(src, wip_ty.index);
2932 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));2923 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
2933}2924}
29342925
2935fn createTypeName(2926fn createTypeName(
...@@ -3107,7 +3098,7 @@ fn zirEnumDecl(...@@ -3107,7 +3098,7 @@ fn zirEnumDecl(
3107 };3098 };
3108 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {3099 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {
3109 .existing => |ty| {3100 .existing => |ty| {
3110 const new_ty = try pt.ensureTypeUpToDate(ty, false);3101 const new_ty = try pt.ensureTypeUpToDate(ty);
31113102
3112 // Make sure we update the namespace if the declaration is re-analyzed, to pick3103 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3113 // up on e.g. changed comptime decls.3104 // up on e.g. changed comptime decls.
...@@ -3143,16 +3134,14 @@ fn zirEnumDecl(...@@ -3143,16 +3134,14 @@ fn zirEnumDecl(
3143 });3134 });
3144 errdefer if (!done) pt.destroyNamespace(new_namespace_index);3135 errdefer if (!done) pt.destroyNamespace(new_namespace_index);
31453136
3146 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
3147
3148 try pt.scanNamespace(new_namespace_index, decls);3137 try pt.scanNamespace(new_namespace_index, decls);
31493138
3150 try sema.declareDependency(.{ .interned = wip_ty.index });3139 try sema.declareDependency(.{ .interned = wip_ty.index });
3151 try sema.addTypeReferenceEntry(src, wip_ty.index);3140 try sema.addTypeReferenceEntry(src, wip_ty.index);
31523141
3153 // We've finished the initial construction of this type, and are about to perform analysis.3142 // We've finished the initial construction of this type, and are about to perform analysis.
3154 // Set the Cau and namespace appropriately, and don't destroy anything on failure.3143 // Set the namespace appropriately, and don't destroy anything on failure.
3155 wip_ty.prepare(ip, new_cau_index, new_namespace_index);3144 wip_ty.prepare(ip, new_namespace_index);
3156 done = true;3145 done = true;
31573146
3158 try Sema.resolveDeclaredEnum(3147 try Sema.resolveDeclaredEnum(
...@@ -3162,7 +3151,6 @@ fn zirEnumDecl(...@@ -3162,7 +3151,6 @@ fn zirEnumDecl(
3162 tracked_inst,3151 tracked_inst,
3163 new_namespace_index,3152 new_namespace_index,
3164 type_name,3153 type_name,
3165 new_cau_index,
3166 small,3154 small,
3167 body,3155 body,
3168 tag_type_ref,3156 tag_type_ref,
...@@ -3252,7 +3240,7 @@ fn zirUnionDecl(...@@ -3252,7 +3240,7 @@ fn zirUnionDecl(
3252 };3240 };
3253 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {3241 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {
3254 .existing => |ty| {3242 .existing => |ty| {
3255 const new_ty = try pt.ensureTypeUpToDate(ty, false);3243 const new_ty = try pt.ensureTypeUpToDate(ty);
32563244
3257 // Make sure we update the namespace if the declaration is re-analyzed, to pick3245 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3258 // up on e.g. changed comptime decls.3246 // up on e.g. changed comptime decls.
...@@ -3282,12 +3270,10 @@ fn zirUnionDecl(...@@ -3282,12 +3270,10 @@ fn zirUnionDecl(
3282 });3270 });
3283 errdefer pt.destroyNamespace(new_namespace_index);3271 errdefer pt.destroyNamespace(new_namespace_index);
32843272
3285 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
3286
3287 if (pt.zcu.comp.incremental) {3273 if (pt.zcu.comp.incremental) {
3288 try zcu.intern_pool.addDependency(3274 try zcu.intern_pool.addDependency(
3289 gpa,3275 gpa,
3290 AnalUnit.wrap(.{ .cau = new_cau_index }),3276 AnalUnit.wrap(.{ .type = wip_ty.index }),
3291 .{ .src_hash = tracked_inst },3277 .{ .src_hash = tracked_inst },
3292 );3278 );
3293 }3279 }
...@@ -3304,7 +3290,7 @@ fn zirUnionDecl(...@@ -3304,7 +3290,7 @@ fn zirUnionDecl(
3304 }3290 }
3305 try sema.declareDependency(.{ .interned = wip_ty.index });3291 try sema.declareDependency(.{ .interned = wip_ty.index });
3306 try sema.addTypeReferenceEntry(src, wip_ty.index);3292 try sema.addTypeReferenceEntry(src, wip_ty.index);
3307 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));3293 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3308}3294}
33093295
3310fn zirOpaqueDecl(3296fn zirOpaqueDecl(
...@@ -3389,7 +3375,7 @@ fn zirOpaqueDecl(...@@ -3389,7 +3375,7 @@ fn zirOpaqueDecl(
3389 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });3375 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3390 }3376 }
3391 try sema.addTypeReferenceEntry(src, wip_ty.index);3377 try sema.addTypeReferenceEntry(src, wip_ty.index);
3392 return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));3378 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3393}3379}
33943380
3395fn zirErrorSetDecl(3381fn zirErrorSetDecl(
...@@ -6509,9 +6495,9 @@ pub fn analyzeExport(...@@ -6509,9 +6495,9 @@ pub fn analyzeExport(
6509 if (options.linkage == .internal)6495 if (options.linkage == .internal)
6510 return;6496 return;
65116497
6512 try sema.ensureNavResolved(src, orig_nav_index);6498 try sema.ensureNavResolved(src, orig_nav_index, .fully);
65136499
6514 const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.resolved.val)) {6500 const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
6515 .variable => |v| v.owner_nav,6501 .variable => |v| v.owner_nav,
6516 .@"extern" => |e| e.owner_nav,6502 .@"extern" => |e| e.owner_nav,
6517 .func => |f| f.owner_nav,6503 .func => |f| f.owner_nav,
...@@ -6534,7 +6520,7 @@ pub fn analyzeExport(...@@ -6534,7 +6520,7 @@ pub fn analyzeExport(
6534 }6520 }
65356521
6536 // TODO: some backends might support re-exporting extern decls6522 // TODO: some backends might support re-exporting extern decls
6537 if (exported_nav.isExtern(ip)) {6523 if (exported_nav.getExtern(ip) != null) {
6538 return sema.fail(block, src, "export target cannot be extern", .{});6524 return sema.fail(block, src, "export target cannot be extern", .{});
6539 }6525 }
65406526
...@@ -6554,7 +6540,11 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {...@@ -6554,7 +6540,11 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6554 const ip = &zcu.intern_pool;6540 const ip = &zcu.intern_pool;
6555 const func = switch (sema.owner.unwrap()) {6541 const func = switch (sema.owner.unwrap()) {
6556 .func => |func| func,6542 .func => |func| func,
6557 .cau => return, // does nothing outside a function6543 .@"comptime",
6544 .nav_val,
6545 .nav_ty,
6546 .type,
6547 => return, // does nothing outside a function
6558 };6548 };
6559 ip.funcSetDisableInstrumentation(func);6549 ip.funcSetDisableInstrumentation(func);
6560 sema.allow_memoize = false;6550 sema.allow_memoize = false;
...@@ -6865,8 +6855,8 @@ fn lookupInNamespace(...@@ -6865,8 +6855,8 @@ fn lookupInNamespace(
6865 }6855 }
68666856
6867 for (usingnamespaces.items) |sub_ns_nav| {6857 for (usingnamespaces.items) |sub_ns_nav| {
6868 try sema.ensureNavResolved(src, sub_ns_nav);6858 try sema.ensureNavResolved(src, sub_ns_nav, .fully);
6869 const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.resolved.val);6859 const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val);
6870 const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));6860 const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));
6871 try checked_namespaces.put(gpa, sub_ns, {});6861 try checked_namespaces.put(gpa, sub_ns, {});
6872 }6862 }
...@@ -6875,11 +6865,8 @@ fn lookupInNamespace(...@@ -6875,11 +6865,8 @@ fn lookupInNamespace(
68756865
6876 ignore_self: {6866 ignore_self: {
6877 const skip_nav = switch (sema.owner.unwrap()) {6867 const skip_nav = switch (sema.owner.unwrap()) {
6878 .func => break :ignore_self,6868 .@"comptime", .type, .func => break :ignore_self,
6879 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {6869 .nav_ty, .nav_val => |nav| nav,
6880 .none, .type => break :ignore_self,
6881 .nav => |nav| nav,
6882 },
6883 };6870 };
6884 var i: usize = 0;6871 var i: usize = 0;
6885 while (i < candidates.items.len) {6872 while (i < candidates.items.len) {
...@@ -7139,7 +7126,7 @@ fn zirCall(...@@ -7139,7 +7126,7 @@ fn zirCall(
7139 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);7126 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
71407127
7141 switch (sema.owner.unwrap()) {7128 switch (sema.owner.unwrap()) {
7142 .cau => input_is_error = false,7129 .@"comptime", .type, .nav_ty, .nav_val => input_is_error = false,
7143 .func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {7130 .func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
7144 // No errorable fn actually called; we have no error return trace7131 // No errorable fn actually called; we have no error return trace
7145 input_is_error = false;7132 input_is_error = false;
...@@ -7700,12 +7687,13 @@ fn analyzeCall(...@@ -7700,12 +7687,13 @@ fn analyzeCall(
7700 .ptr => |ptr| blk: {7687 .ptr => |ptr| blk: {
7701 switch (ptr.base_addr) {7688 switch (ptr.base_addr) {
7702 .nav => |nav_index| if (ptr.byte_offset == 0) {7689 .nav => |nav_index| if (ptr.byte_offset == 0) {
7690 try sema.ensureNavResolved(call_src, nav_index, .fully);
7703 const nav = ip.getNav(nav_index);7691 const nav = ip.getNav(nav_index);
7704 if (nav.isExtern(ip))7692 if (nav.getExtern(ip) != null)
7705 return sema.fail(block, call_src, "{s} call of extern function pointer", .{7693 return sema.fail(block, call_src, "{s} call of extern function pointer", .{
7706 if (is_comptime_call) "comptime" else "inline",7694 if (is_comptime_call) "comptime" else "inline",
7707 });7695 });
7708 break :blk nav.status.resolved.val;7696 break :blk nav.status.fully_resolved.val;
7709 },7697 },
7710 else => {},7698 else => {},
7711 }7699 }
...@@ -7754,11 +7742,9 @@ fn analyzeCall(...@@ -7754,11 +7742,9 @@ fn analyzeCall(
7754 // The call site definitely depends on the function's signature.7742 // The call site definitely depends on the function's signature.
7755 try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst });7743 try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst });
77567744
7757 // This is not a function instance, so the function's `Nav` has a7745 // This is not a function instance, so the function's `Nav` has analysis
7758 // `Cau` -- we don't need to check `generic_owner`.7746 // state -- we don't need to check `generic_owner`.
7759 const fn_nav = ip.getNav(module_fn.owner_nav);7747 const fn_nav = ip.getNav(module_fn.owner_nav);
7760 const fn_cau_index = fn_nav.analysis_owner.unwrap().?;
7761 const fn_cau = ip.getCau(fn_cau_index);
77627748
7763 // We effectively want a child Sema here, but can't literally do that, because we need AIR7749 // We effectively want a child Sema here, but can't literally do that, because we need AIR
7764 // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in7750 // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in
...@@ -7766,7 +7752,7 @@ fn analyzeCall(...@@ -7766,7 +7752,7 @@ fn analyzeCall(
7766 // whenever performing an operation where the difference matters.7752 // whenever performing an operation where the difference matters.
7767 var ics = InlineCallSema.init(7753 var ics = InlineCallSema.init(
7768 sema,7754 sema,
7769 zcu.cauFileScope(fn_cau_index).zir,7755 zcu.navFileScope(module_fn.owner_nav).zir,
7770 module_fn_index,7756 module_fn_index,
7771 block.error_return_trace_index,7757 block.error_return_trace_index,
7772 );7758 );
...@@ -7776,7 +7762,7 @@ fn analyzeCall(...@@ -7776,7 +7762,7 @@ fn analyzeCall(
7776 .parent = null,7762 .parent = null,
7777 .sema = sema,7763 .sema = sema,
7778 // The function body exists in the same namespace as the corresponding function declaration.7764 // The function body exists in the same namespace as the corresponding function declaration.
7779 .namespace = fn_cau.namespace,7765 .namespace = fn_nav.analysis.?.namespace,
7780 .instructions = .{},7766 .instructions = .{},
7781 .label = null,7767 .label = null,
7782 .inlining = &inlining,7768 .inlining = &inlining,
...@@ -7787,7 +7773,7 @@ fn analyzeCall(...@@ -7787,7 +7773,7 @@ fn analyzeCall(
7787 .runtime_cond = block.runtime_cond,7773 .runtime_cond = block.runtime_cond,
7788 .runtime_loop = block.runtime_loop,7774 .runtime_loop = block.runtime_loop,
7789 .runtime_index = block.runtime_index,7775 .runtime_index = block.runtime_index,
7790 .src_base_inst = fn_cau.zir_index,7776 .src_base_inst = fn_nav.analysis.?.zir_index,
7791 .type_name_ctx = fn_nav.fqn,7777 .type_name_ctx = fn_nav.fqn,
7792 };7778 };
77937779
...@@ -7802,7 +7788,7 @@ fn analyzeCall(...@@ -7802,7 +7788,7 @@ fn analyzeCall(
7802 // mutate comptime state.7788 // mutate comptime state.
7803 // TODO: comptime call memoization is currently not supported under incremental compilation7789 // TODO: comptime call memoization is currently not supported under incremental compilation
7804 // since dependencies are not marked on callers. If we want to keep this around (we should7790 // since dependencies are not marked on callers. If we want to keep this around (we should
7805 // check that it's worthwhile first!), each memoized call needs a `Cau`.7791 // check that it's worthwhile first!), each memoized call needs an `AnalUnit`.
7806 var should_memoize = !zcu.comp.incremental;7792 var should_memoize = !zcu.comp.incremental;
78077793
7808 // If it's a comptime function call, we need to memoize it as long as no external7794 // If it's a comptime function call, we need to memoize it as long as no external
...@@ -7911,7 +7897,7 @@ fn analyzeCall(...@@ -7911,7 +7897,7 @@ fn analyzeCall(
79117897
7912 // Since we're doing an inline call, we depend on the source code of the whole7898 // Since we're doing an inline call, we depend on the source code of the whole
7913 // function declaration.7899 // function declaration.
7914 try sema.declareDependency(.{ .src_hash = fn_cau.zir_index });7900 try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index });
79157901
7916 new_fn_info.return_type = sema.fn_ret_ty.toIntern();7902 new_fn_info.return_type = sema.fn_ret_ty.toIntern();
7917 if (!is_comptime_call and !block.is_typeof) {7903 if (!is_comptime_call and !block.is_typeof) {
...@@ -8023,7 +8009,7 @@ fn analyzeCall(...@@ -8023,7 +8009,7 @@ fn analyzeCall(
8023 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);8009 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
80248010
8025 switch (sema.owner.unwrap()) {8011 switch (sema.owner.unwrap()) {
8026 .cau => {},8012 .@"comptime", .nav_ty, .nav_val, .type => {},
8027 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {8013 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
8028 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);8014 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
8029 },8015 },
...@@ -8062,7 +8048,10 @@ fn analyzeCall(...@@ -8062,7 +8048,10 @@ fn analyzeCall(
8062 switch (zcu.intern_pool.indexToKey(func_val.toIntern())) {8048 switch (zcu.intern_pool.indexToKey(func_val.toIntern())) {
8063 .func => break :skip_safety,8049 .func => break :skip_safety,
8064 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {8050 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
8065 .nav => |nav| if (!ip.getNav(nav).isExtern(ip)) break :skip_safety,8051 .nav => |nav| {
8052 try sema.ensureNavResolved(call_src, nav, .fully);
8053 if (ip.getNav(nav).getExtern(ip) == null) break :skip_safety;
8054 },
8066 else => {},8055 else => {},
8067 },8056 },
8068 else => {},8057 else => {},
...@@ -8259,7 +8248,7 @@ fn instantiateGenericCall(...@@ -8259,7 +8248,7 @@ fn instantiateGenericCall(
8259 });8248 });
8260 const generic_owner = switch (zcu.intern_pool.indexToKey(func_val.toIntern())) {8249 const generic_owner = switch (zcu.intern_pool.indexToKey(func_val.toIntern())) {
8261 .func => func_val.toIntern(),8250 .func => func_val.toIntern(),
8262 .ptr => |ptr| ip.getNav(ptr.base_addr.nav).status.resolved.val,8251 .ptr => |ptr| ip.getNav(ptr.base_addr.nav).status.fully_resolved.val,
8263 else => unreachable,8252 else => unreachable,
8264 };8253 };
8265 const generic_owner_func = zcu.intern_pool.indexToKey(generic_owner).func;8254 const generic_owner_func = zcu.intern_pool.indexToKey(generic_owner).func;
...@@ -8275,10 +8264,9 @@ fn instantiateGenericCall(...@@ -8275,10 +8264,9 @@ fn instantiateGenericCall(
8275 // The actual monomorphization happens via adding `func_instance` to8264 // The actual monomorphization happens via adding `func_instance` to
8276 // `InternPool`.8265 // `InternPool`.
82778266
8278 // Since we are looking at the generic owner here, it has a `Cau`.8267 // Since we are looking at the generic owner here, it has analysis state.
8279 const fn_nav = ip.getNav(generic_owner_func.owner_nav);8268 const fn_nav = ip.getNav(generic_owner_func.owner_nav);
8280 const fn_cau = ip.getCau(fn_nav.analysis_owner.unwrap().?);8269 const fn_zir = zcu.navFileScope(generic_owner_func.owner_nav).zir;
8281 const fn_zir = zcu.namespacePtr(fn_cau.namespace).fileScope(zcu).zir;
8282 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip) orelse return error.AnalysisFail);8270 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip) orelse return error.AnalysisFail);
82838271
8284 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());8272 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
...@@ -8319,11 +8307,11 @@ fn instantiateGenericCall(...@@ -8319,11 +8307,11 @@ fn instantiateGenericCall(
8319 var child_block: Block = .{8307 var child_block: Block = .{
8320 .parent = null,8308 .parent = null,
8321 .sema = &child_sema,8309 .sema = &child_sema,
8322 .namespace = fn_cau.namespace,8310 .namespace = fn_nav.analysis.?.namespace,
8323 .instructions = .{},8311 .instructions = .{},
8324 .inlining = null,8312 .inlining = null,
8325 .is_comptime = true,8313 .is_comptime = true,
8326 .src_base_inst = fn_cau.zir_index,8314 .src_base_inst = fn_nav.analysis.?.zir_index,
8327 .type_name_ctx = fn_nav.fqn,8315 .type_name_ctx = fn_nav.fqn,
8328 };8316 };
8329 defer child_block.instructions.deinit(gpa);8317 defer child_block.instructions.deinit(gpa);
...@@ -8488,7 +8476,7 @@ fn instantiateGenericCall(...@@ -8488,7 +8476,7 @@ fn instantiateGenericCall(
8488 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);8476 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
84898477
8490 switch (sema.owner.unwrap()) {8478 switch (sema.owner.unwrap()) {
8491 .cau => {},8479 .@"comptime", .nav_ty, .nav_val, .type => {},
8492 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {8480 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
8493 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);8481 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
8494 },8482 },
...@@ -9517,16 +9505,13 @@ fn zirFunc(...@@ -9517,16 +9505,13 @@ fn zirFunc(
9517 // the callconv based on whether it is exported. Otherwise, the callconv defaults9505 // the callconv based on whether it is exported. Otherwise, the callconv defaults
9518 // to `.auto`.9506 // to `.auto`.
9519 const cc: std.builtin.CallingConvention = if (has_body) cc: {9507 const cc: std.builtin.CallingConvention = if (has_body) cc: {
9520 const func_decl_cau = if (sema.generic_owner != .none) cau: {9508 const func_decl_nav = if (sema.generic_owner != .none) nav: {
9521 const generic_owner_fn = zcu.funcInfo(sema.generic_owner);9509 break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
9522 // The generic owner definitely has a `Cau` for the corresponding function declaration.9510 } else sema.owner.unwrap().nav_val;
9523 const generic_owner_nav = ip.getNav(generic_owner_fn.owner_nav);
9524 break :cau generic_owner_nav.analysis_owner.unwrap().?;
9525 } else sema.owner.unwrap().cau;
9526 const fn_is_exported = exported: {9511 const fn_is_exported = exported: {
9527 const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;9512 const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;
9528 const zir_decl = sema.code.getDeclaration(decl_inst)[0];9513 const zir_decl = sema.code.getDeclaration(decl_inst);
9529 break :exported zir_decl.flags.is_export;9514 break :exported zir_decl.linkage == .@"export";
9530 };9515 };
9531 if (fn_is_exported) {9516 if (fn_is_exported) {
9532 break :cc target.cCallingConvention() orelse {9517 break :cc target.cCallingConvention() orelse {
...@@ -9557,10 +9542,8 @@ fn zirFunc(...@@ -9557,10 +9542,8 @@ fn zirFunc(
9557 ret_ty,9542 ret_ty,
9558 false,9543 false,
9559 inferred_error_set,9544 inferred_error_set,
9560 false,
9561 has_body,9545 has_body,
9562 src_locs,9546 src_locs,
9563 null,
9564 0,9547 0,
9565 false,9548 false,
9566 );9549 );
...@@ -9619,7 +9602,7 @@ fn resolveGenericBody(...@@ -9619,7 +9602,7 @@ fn resolveGenericBody(
9619/// respective `Decl` (either `ExternFn` or `Var`).9602/// respective `Decl` (either `ExternFn` or `Var`).
9620/// The liveness of the duped library name is tied to liveness of `Zcu`.9603/// The liveness of the duped library name is tied to liveness of `Zcu`.
9621/// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`).9604/// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`).
9622fn handleExternLibName(9605pub fn handleExternLibName(
9623 sema: *Sema,9606 sema: *Sema,
9624 block: *Block,9607 block: *Block,
9625 src_loc: LazySrcLoc,9608 src_loc: LazySrcLoc,
...@@ -9843,10 +9826,8 @@ fn funcCommon(...@@ -9843,10 +9826,8 @@ fn funcCommon(
9843 bare_return_type: Type,9826 bare_return_type: Type,
9844 var_args: bool,9827 var_args: bool,
9845 inferred_error_set: bool,9828 inferred_error_set: bool,
9846 is_extern: bool,
9847 has_body: bool,9829 has_body: bool,
9848 src_locs: Zir.Inst.Func.SrcLocs,9830 src_locs: Zir.Inst.Func.SrcLocs,
9849 opt_lib_name: ?[]const u8,
9850 noalias_bits: u32,9831 noalias_bits: u32,
9851 is_noinline: bool,9832 is_noinline: bool,
9852) CompileError!Air.Inst.Ref {9833) CompileError!Air.Inst.Ref {
...@@ -9998,12 +9979,11 @@ fn funcCommon(...@@ -9998,12 +9979,11 @@ fn funcCommon(
9998 }9979 }
99999980
10000 if (inferred_error_set) {9981 if (inferred_error_set) {
10001 assert(!is_extern);
10002 assert(has_body);9982 assert(has_body);
10003 if (!ret_poison)9983 if (!ret_poison)
10004 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9984 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
10005 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{9985 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{
10006 .owner_nav = sema.getOwnerCauNav(),9986 .owner_nav = sema.owner.unwrap().nav_val,
100079987
10008 .param_types = param_types,9988 .param_types = param_types,
10009 .noalias_bits = noalias_bits,9989 .noalias_bits = noalias_bits,
...@@ -10050,35 +10030,9 @@ fn funcCommon(...@@ -10050,35 +10030,9 @@ fn funcCommon(
10050 .is_noinline = is_noinline,10030 .is_noinline = is_noinline,
10051 });10031 });
1005210032
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
10079 if (has_body) {10033 if (has_body) {
10080 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{10034 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
10081 .owner_nav = sema.getOwnerCauNav(),10035 .owner_nav = sema.owner.unwrap().nav_val,
10082 .ty = func_ty,10036 .ty = func_ty,
10083 .cc = cc,10037 .cc = cc,
10084 .is_noinline = is_noinline,10038 .is_noinline = is_noinline,
...@@ -17702,7 +17656,7 @@ fn zirAsm(...@@ -17702,7 +17656,7 @@ fn zirAsm(
17702 if (is_volatile) {17656 if (is_volatile) {
17703 return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{});17657 return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{});
17704 }17658 }
17705 try zcu.addGlobalAssembly(sema.owner.unwrap().cau, asm_source);17659 try zcu.addGlobalAssembly(sema.owner, asm_source);
17706 return .void_value;17660 return .void_value;
17707 }17661 }
1770817662
...@@ -18193,7 +18147,7 @@ fn zirThis(...@@ -18193,7 +18147,7 @@ fn zirThis(
18193 _ = extended;18147 _ = extended;
18194 const pt = sema.pt;18148 const pt = sema.pt;
18195 const namespace = pt.zcu.namespacePtr(block.namespace);18149 const namespace = pt.zcu.namespacePtr(block.namespace);
18196 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type, false);18150 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
18197 switch (pt.zcu.intern_pool.indexToKey(new_ty)) {18151 switch (pt.zcu.intern_pool.indexToKey(new_ty)) {
18198 .struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),18152 .struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),
18199 .opaque_type => {},18153 .opaque_type => {},
...@@ -19359,13 +19313,11 @@ fn typeInfoNamespaceDecls(...@@ -19359,13 +19313,11 @@ fn typeInfoNamespaceDecls(
19359 }19313 }
1936019314
19361 for (namespace.pub_usingnamespace.items) |nav| {19315 for (namespace.pub_usingnamespace.items) |nav| {
19362 if (ip.getNav(nav).analysis_owner.unwrap()) |cau| {19316 if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
19363 if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .cau = cau }))) {19317 continue;
19364 continue;
19365 }
19366 }19318 }
19367 try sema.ensureNavResolved(src, nav);19319 try sema.ensureNavResolved(src, nav, .fully);
19368 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.resolved.val);19320 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val);
19369 try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);19321 try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);
19370 }19322 }
19371}19323}
...@@ -21225,14 +21177,13 @@ fn structInitAnon(...@@ -21225,14 +21177,13 @@ fn structInitAnon(
21225 .file_scope = block.getFileScopeIndex(zcu),21177 .file_scope = block.getFileScopeIndex(zcu),
21226 .generation = zcu.generation,21178 .generation = zcu.generation,
21227 });21179 });
21228 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip.index);
21229 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });21180 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
21230 codegen_type: {21181 codegen_type: {
21231 if (zcu.comp.config.use_llvm) break :codegen_type;21182 if (zcu.comp.config.use_llvm) break :codegen_type;
21232 if (block.ownerModule().strip) break :codegen_type;21183 if (block.ownerModule().strip) break :codegen_type;
21233 try zcu.comp.queueJob(.{ .codegen_type = wip.index });21184 try zcu.comp.queueJob(.{ .codegen_type = wip.index });
21234 }21185 }
21235 break :ty wip.finish(ip, new_cau_index.toOptional(), new_namespace_index);21186 break :ty wip.finish(ip, new_namespace_index);
21236 },21187 },
21237 .existing => |ty| ty,21188 .existing => |ty| ty,
21238 };21189 };
...@@ -21656,7 +21607,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -21656,7 +21607,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
21656 .func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {21607 .func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
21657 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);21608 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
21658 },21609 },
21659 .cau => {},21610 .@"comptime", .nav_ty, .nav_val, .type => {},
21660 }21611 }
21661 return Air.internedToRef(try pt.intern(.{ .opt = .{21612 return Air.internedToRef(try pt.intern(.{ .opt = .{
21662 .ty = opt_ptr_stack_trace_ty.toIntern(),21613 .ty = opt_ptr_stack_trace_ty.toIntern(),
...@@ -22334,7 +22285,7 @@ fn zirReify(...@@ -22334,7 +22285,7 @@ fn zirReify(
22334 });22285 });
2233522286
22336 try sema.addTypeReferenceEntry(src, wip_ty.index);22287 try sema.addTypeReferenceEntry(src, wip_ty.index);
22337 return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));22288 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
22338 },22289 },
22339 .@"union" => {22290 .@"union" => {
22340 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));22291 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -22543,11 +22494,9 @@ fn reifyEnum(...@@ -22543,11 +22494,9 @@ fn reifyEnum(
22543 .generation = zcu.generation,22494 .generation = zcu.generation,
22544 });22495 });
2254522496
22546 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
22547
22548 try sema.declareDependency(.{ .interned = wip_ty.index });22497 try sema.declareDependency(.{ .interned = wip_ty.index });
22549 try sema.addTypeReferenceEntry(src, wip_ty.index);22498 try sema.addTypeReferenceEntry(src, wip_ty.index);
22550 wip_ty.prepare(ip, new_cau_index, new_namespace_index);22499 wip_ty.prepare(ip, new_namespace_index);
22551 wip_ty.setTagTy(ip, tag_ty.toIntern());22500 wip_ty.setTagTy(ip, tag_ty.toIntern());
22552 done = true;22501 done = true;
2255322502
...@@ -22849,8 +22798,6 @@ fn reifyUnion(...@@ -22849,8 +22798,6 @@ fn reifyUnion(
22849 .generation = zcu.generation,22798 .generation = zcu.generation,
22850 });22799 });
2285122800
22852 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
22853
22854 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });22801 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
22855 codegen_type: {22802 codegen_type: {
22856 if (zcu.comp.config.use_llvm) break :codegen_type;22803 if (zcu.comp.config.use_llvm) break :codegen_type;
...@@ -22860,7 +22807,7 @@ fn reifyUnion(...@@ -22860,7 +22807,7 @@ fn reifyUnion(
22860 }22807 }
22861 try sema.declareDependency(.{ .interned = wip_ty.index });22808 try sema.declareDependency(.{ .interned = wip_ty.index });
22862 try sema.addTypeReferenceEntry(src, wip_ty.index);22809 try sema.addTypeReferenceEntry(src, wip_ty.index);
22863 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));22810 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
22864}22811}
2286522812
22866fn reifyTuple(22813fn reifyTuple(
...@@ -23208,8 +23155,6 @@ fn reifyStruct(...@@ -23208,8 +23155,6 @@ fn reifyStruct(
23208 .generation = zcu.generation,23155 .generation = zcu.generation,
23209 });23156 });
2321023157
23211 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
23212
23213 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });23158 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
23214 codegen_type: {23159 codegen_type: {
23215 if (zcu.comp.config.use_llvm) break :codegen_type;23160 if (zcu.comp.config.use_llvm) break :codegen_type;
...@@ -23219,7 +23164,7 @@ fn reifyStruct(...@@ -23219,7 +23164,7 @@ fn reifyStruct(
23219 }23164 }
23220 try sema.declareDependency(.{ .interned = wip_ty.index });23165 try sema.declareDependency(.{ .interned = wip_ty.index });
23221 try sema.addTypeReferenceEntry(src, wip_ty.index);23166 try sema.addTypeReferenceEntry(src, wip_ty.index);
23222 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));23167 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
23223}23168}
2322423169
23225fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {23170fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
...@@ -26711,135 +26656,6 @@ fn zirAwaitNosuspend(...@@ -26711,135 +26656,6 @@ fn zirAwaitNosuspend(
26711 return sema.failWithUseOfAsync(block, src);26656 return sema.failWithUseOfAsync(block, src);
26712}26657}
2671326658
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
26843fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {26659fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
26844 const tracy = trace(@src());26660 const tracy = trace(@src());
26845 defer tracy.end();26661 defer tracy.end();
...@@ -26857,13 +26673,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26857,13 +26673,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2685726673
26858 var extra_index: usize = extra.end;26674 var extra_index: usize = extra.end;
2685926675
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
26867 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {26676 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
26868 const body_len = sema.code.extra[extra_index];26677 const body_len = sema.code.extra[extra_index];
26869 extra_index += 1;26678 extra_index += 1;
...@@ -26887,16 +26696,14 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26887,16 +26696,14 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26887 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);26696 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);
26888 } else cc: {26697 } else cc: {
26889 if (has_body) {26698 if (has_body) {
26890 const decl_inst = if (sema.generic_owner != .none) decl_inst: {26699 const func_decl_nav = if (sema.generic_owner != .none) nav: {
26891 // Generic instance -- use the original function declaration to26700 // Generic instance -- use the original function declaration to
26892 // look for the `export` syntax.26701 // look for the `export` syntax.
26893 const nav = zcu.intern_pool.getNav(zcu.funcInfo(sema.generic_owner).owner_nav);26702 break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
26894 const cau = zcu.intern_pool.getCau(nav.analysis_owner.unwrap().?);26703 } else sema.owner.unwrap().nav_val;
26895 break :decl_inst cau.zir_index;26704 const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;
26896 } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau26705 const zir_decl = sema.code.getDeclaration(func_decl_inst);
2689726706 if (zir_decl.linkage == .@"export") {
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) {
26900 break :cc target.cCallingConvention() orelse {26707 break :cc target.cCallingConvention() orelse {
26901 // This target has no default C calling convention. We sometimes trigger a similar26708 // This target has no default C calling convention. We sometimes trigger a similar
26902 // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,26709 // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
...@@ -26958,7 +26765,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26958,7 +26765,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2695826765
26959 const is_var_args = extra.data.bits.is_var_args;26766 const is_var_args = extra.data.bits.is_var_args;
26960 const is_inferred_error = extra.data.bits.is_inferred_error;26767 const is_inferred_error = extra.data.bits.is_inferred_error;
26961 const is_extern = extra.data.bits.is_extern;
26962 const is_noinline = extra.data.bits.is_noinline;26768 const is_noinline = extra.data.bits.is_noinline;
2696326769
26964 return sema.funcCommon(26770 return sema.funcCommon(
...@@ -26969,10 +26775,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26969,10 +26775,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26969 ret_ty,26775 ret_ty,
26970 is_var_args,26776 is_var_args,
26971 is_inferred_error,26777 is_inferred_error,
26972 is_extern,
26973 has_body,26778 has_body,
26974 src_locs,26779 src_locs,
26975 lib_name,
26976 noalias_bits,26780 noalias_bits,
26977 is_noinline,26781 is_noinline,
26978 );26782 );
...@@ -27285,8 +27089,16 @@ fn zirBuiltinExtern(...@@ -27285,8 +27089,16 @@ fn zirBuiltinExtern(
27285 // `builtin_extern` doesn't provide enough information, and isn't currently tracked.27089 // `builtin_extern` doesn't provide enough information, and isn't currently tracked.
27286 // So, for now, just use our containing `declaration`.27090 // So, for now, just use our containing `declaration`.
27287 .zir_index = switch (sema.owner.unwrap()) {27091 .zir_index = switch (sema.owner.unwrap()) {
27288 .cau => sema.getOwnerCauDeclInst(),27092 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
27289 .func => sema.getOwnerFuncDeclInst(),27093 .type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?,
27094 .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
27095 .func => |func| zir_index: {
27096 const func_info = zcu.funcInfo(func);
27097 const owner_func_info = if (func_info.generic_owner != .none) owner: {
27098 break :owner zcu.funcInfo(func_info.generic_owner);
27099 } else func_info;
27100 break :zir_index ip.getNav(owner_func_info.owner_nav).analysis.?.zir_index;
27101 },
27290 },27102 },
27291 .owner_nav = undefined, // ignored by `getExtern`27103 .owner_nav = undefined, // ignored by `getExtern`
27292 });27104 });
...@@ -27467,7 +27279,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:...@@ -27467,7 +27279,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
27467}27279}
2746827280
27469/// Emit a compile error if type cannot be used for a runtime variable.27281/// Emit a compile error if type cannot be used for a runtime variable.
27470fn validateVarType(27282pub fn validateVarType(
27471 sema: *Sema,27283 sema: *Sema,
27472 block: *Block,27284 block: *Block,
27473 src: LazySrcLoc,27285 src: LazySrcLoc,
...@@ -27934,7 +27746,7 @@ fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.Pan...@@ -27934,7 +27746,7 @@ fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.Pan
27934 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,27746 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
27935 error.OutOfMemory => |e| return e,27747 error.OutOfMemory => |e| return e,
27936 }).?;27748 }).?;
27937 try sema.ensureNavResolved(src, msg_nav_index);27749 try sema.ensureNavResolved(src, msg_nav_index, .fully);
27938 zcu.panic_messages[@intFromEnum(panic_id)] = msg_nav_index.toOptional();27750 zcu.panic_messages[@intFromEnum(panic_id)] = msg_nav_index.toOptional();
27939 return msg_nav_index;27751 return msg_nav_index;
27940}27752}
...@@ -29881,7 +29693,7 @@ fn elemPtrSlice(...@@ -29881,7 +29693,7 @@ fn elemPtrSlice(
29881 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);29693 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
29882}29694}
2988329695
29884fn coerce(29696pub fn coerce(
29885 sema: *Sema,29697 sema: *Sema,
29886 block: *Block,29698 block: *Block,
29887 dest_ty_unresolved: Type,29699 dest_ty_unresolved: Type,
...@@ -32841,34 +32653,45 @@ fn addTypeReferenceEntry(...@@ -32841,34 +32653,45 @@ fn addTypeReferenceEntry(
32841 try zcu.addTypeReference(sema.owner, referenced_type, src);32653 try zcu.addTypeReference(sema.owner, referenced_type, src);
32842}32654}
3284332655
32844pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!void {32656pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
32845 const pt = sema.pt;32657 const pt = sema.pt;
32846 const zcu = pt.zcu;32658 const zcu = pt.zcu;
32847 const ip = &zcu.intern_pool;32659 const ip = &zcu.intern_pool;
3284832660
32849 const nav = ip.getNav(nav_index);32661 const nav = ip.getNav(nav_index);
3285032662 if (nav.analysis == null) {
32851 const cau_index = nav.analysis_owner.unwrap() orelse {32663 assert(nav.status == .fully_resolved);
32852 assert(nav.status == .resolved);
32853 return;32664 return;
32854 };32665 }
3285532666
32856 // Note that even if `nav.status == .resolved`, we must still trigger `ensureCauAnalyzed`32667 try sema.declareDependency(switch (kind) {
32857 // to make sure the value is up-to-date on incremental updates.32668 .type => .{ .nav_ty = nav_index },
32669 .fully => .{ .nav_val = nav_index },
32670 });
3285832671
32859 assert(ip.getCau(cau_index).owner.unwrap().nav == nav_index);32672 // Note that even if `nav.status == .resolved`, we must still trigger `ensureNavValUpToDate`
32673 // to make sure the value is up-to-date on incremental updates.
3286032674
32861 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });32675 const anal_unit: AnalUnit = .wrap(switch (kind) {
32676 .type => .{ .nav_ty = nav_index },
32677 .fully => .{ .nav_val = nav_index },
32678 });
32862 try sema.addReferenceEntry(src, anal_unit);32679 try sema.addReferenceEntry(src, anal_unit);
3286332680
32864 if (zcu.analysis_in_progress.contains(anal_unit)) {32681 if (zcu.analysis_in_progress.contains(anal_unit)) {
32865 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{32682 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
32866 .base_node_inst = ip.getCau(cau_index).zir_index,32683 .base_node_inst = nav.analysis.?.zir_index,
32867 .offset = LazySrcLoc.Offset.nodeOffset(0),32684 .offset = LazySrcLoc.Offset.nodeOffset(0),
32868 }, "dependency loop detected", .{}));32685 }, "dependency loop detected", .{}));
32869 }32686 }
3287032687
32871 return pt.ensureCauAnalyzed(cau_index);32688 switch (kind) {
32689 .type => {
32690 try zcu.ensureNavValAnalysisQueued(nav_index);
32691 return pt.ensureNavTypeUpToDate(nav_index);
32692 },
32693 .fully => return pt.ensureNavValUpToDate(nav_index),
32694 }
32872}32695}
3287332696
32874fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {32697fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
...@@ -32887,36 +32710,44 @@ fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index)...@@ -32887,36 +32710,44 @@ fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index)
32887 return sema.analyzeNavRefInner(src, nav_index, true);32710 return sema.analyzeNavRefInner(src, nav_index, true);
32888}32711}
3288932712
32890/// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed, but32713/// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed.
32891/// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a32714/// If this pointer will be used directly, `is_ref` must be `true`.
32892/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeNavRef` wraps32715/// If this pointer will be immediately loaded (i.e. a `decl_val` instruction), `is_ref` must be `false`.
32893/// this function with `analyze_fn_body` set to true.32716fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref {
32894fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref {
32895 const pt = sema.pt;32717 const pt = sema.pt;
32896 const zcu = pt.zcu;32718 const zcu = pt.zcu;
32897 const ip = &zcu.intern_pool;32719 const ip = &zcu.intern_pool;
3289832720
32899 // TODO: if this is a `decl_ref` of a non-variable Nav, only depend on Nav type32721 try sema.ensureNavResolved(src, orig_nav_index, if (is_ref) .type else .fully);
32900 try sema.declareDependency(.{ .nav_val = orig_nav_index });32722
32901 try sema.ensureNavResolved(src, orig_nav_index);32723 const nav_index = nav: {
32724 if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {
32725 // Getting a pointer to this `Nav` might mean we actually get a pointer to something else!
32726 // We need to resolve the value to know for sure.
32727 if (is_ref) try sema.ensureNavResolved(src, orig_nav_index, .fully);
32728 switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
32729 .func => |f| break :nav f.owner_nav,
32730 .@"extern" => |e| break :nav e.owner_nav,
32731 else => {},
32732 }
32733 }
32734 break :nav orig_nav_index;
32735 };
3290232736
32903 const nav_val = zcu.navValue(orig_nav_index);32737 const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_index).status) {
32904 const nav_index, const is_const = switch (ip.indexToKey(nav_val.toIntern())) {32738 .unresolved => unreachable,
32905 .variable => |v| .{ v.owner_nav, false },32739 .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const },
32906 .func => |f| .{ f.owner_nav, true },32740 .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", zcu.navValIsConst(r.val) },
32907 .@"extern" => |e| .{ e.owner_nav, e.is_const },
32908 else => .{ orig_nav_index, true },
32909 };32741 };
32910 const nav_info = ip.getNav(nav_index).status.resolved;
32911 const ptr_ty = try pt.ptrTypeSema(.{32742 const ptr_ty = try pt.ptrTypeSema(.{
32912 .child = nav_val.typeOf(zcu).toIntern(),32743 .child = ty,
32913 .flags = .{32744 .flags = .{
32914 .alignment = nav_info.alignment,32745 .alignment = alignment,
32915 .is_const = is_const,32746 .is_const = is_const,
32916 .address_space = nav_info.@"addrspace",32747 .address_space = @"addrspace",
32917 },32748 },
32918 });32749 });
32919 if (analyze_fn_body) {32750 if (is_ref) {
32920 try sema.maybeQueueFuncBodyAnalysis(src, nav_index);32751 try sema.maybeQueueFuncBodyAnalysis(src, nav_index);
32921 }32752 }
32922 return Air.internedToRef((try pt.intern(.{ .ptr = .{32753 return Air.internedToRef((try pt.intern(.{ .ptr = .{
...@@ -32927,11 +32758,22 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N...@@ -32927,11 +32758,22 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N
32927}32758}
3292832759
32929fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {32760fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {
32930 const zcu = sema.pt.zcu;32761 const pt = sema.pt;
32762 const zcu = pt.zcu;
32931 const ip = &zcu.intern_pool;32763 const ip = &zcu.intern_pool;
32764
32765 // To avoid forcing too much resolution, let's first resolve the type, and check if it's a function.
32766 // If it is, we can resolve the *value*, and queue analysis as needed.
32767
32768 try sema.ensureNavResolved(src, nav_index, .type);
32769 const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip));
32770 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
32771 if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return;
32772
32773 try sema.ensureNavResolved(src, nav_index, .fully);
32932 const nav_val = zcu.navValue(nav_index);32774 const nav_val = zcu.navValue(nav_index);
32933 if (!ip.isFuncBody(nav_val.toIntern())) return;32775 if (!ip.isFuncBody(nav_val.toIntern())) return;
32934 if (!try nav_val.typeOf(zcu).fnHasRuntimeBitsSema(sema.pt)) return;32776
32935 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));32777 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));
32936 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());32778 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
32937}32779}
...@@ -35818,7 +35660,7 @@ pub fn resolveStructAlignment(...@@ -35818,7 +35660,7 @@ pub fn resolveStructAlignment(
35818 const ip = &zcu.intern_pool;35660 const ip = &zcu.intern_pool;
35819 const target = zcu.getTarget();35661 const target = zcu.getTarget();
3582035662
35821 assert(sema.owner.unwrap().cau == struct_type.cau);35663 assert(sema.owner.unwrap().type == ty);
3582235664
35823 assert(struct_type.layout != .@"packed");35665 assert(struct_type.layout != .@"packed");
35824 assert(struct_type.flagsUnordered(ip).alignment == .none);35666 assert(struct_type.flagsUnordered(ip).alignment == .none);
...@@ -35861,7 +35703,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35861,7 +35703,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35861 const ip = &zcu.intern_pool;35703 const ip = &zcu.intern_pool;
35862 const struct_type = zcu.typeToStruct(ty) orelse return;35704 const struct_type = zcu.typeToStruct(ty) orelse return;
3586335705
35864 assert(sema.owner.unwrap().cau == struct_type.cau);35706 assert(sema.owner.unwrap().type == ty.toIntern());
3586535707
35866 if (struct_type.haveLayout(ip))35708 if (struct_type.haveLayout(ip))
35867 return;35709 return;
...@@ -36008,15 +35850,13 @@ fn backingIntType(...@@ -36008,15 +35850,13 @@ fn backingIntType(
36008 const gpa = zcu.gpa;35850 const gpa = zcu.gpa;
36009 const ip = &zcu.intern_pool;35851 const ip = &zcu.intern_pool;
3601035852
36011 const cau_index = struct_type.cau;
36012
36013 var analysis_arena = std.heap.ArenaAllocator.init(gpa);35853 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
36014 defer analysis_arena.deinit();35854 defer analysis_arena.deinit();
3601535855
36016 var block: Block = .{35856 var block: Block = .{
36017 .parent = null,35857 .parent = null,
36018 .sema = sema,35858 .sema = sema,
36019 .namespace = ip.getCau(cau_index).namespace,35859 .namespace = struct_type.namespace,
36020 .instructions = .{},35860 .instructions = .{},
36021 .inlining = null,35861 .inlining = null,
36022 .is_comptime = true,35862 .is_comptime = true,
...@@ -36148,7 +35988,7 @@ pub fn resolveUnionAlignment(...@@ -36148,7 +35988,7 @@ pub fn resolveUnionAlignment(
36148 const ip = &zcu.intern_pool;35988 const ip = &zcu.intern_pool;
36149 const target = zcu.getTarget();35989 const target = zcu.getTarget();
3615035990
36151 assert(sema.owner.unwrap().cau == union_type.cau);35991 assert(sema.owner.unwrap().type == ty.toIntern());
3615235992
36153 assert(!union_type.haveLayout(ip));35993 assert(!union_type.haveLayout(ip));
3615435994
...@@ -36188,7 +36028,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -36188,7 +36028,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
36188 // Load again, since the tag type might have changed due to resolution.36028 // Load again, since the tag type might have changed due to resolution.
36189 const union_type = ip.loadUnionType(ty.ip_index);36029 const union_type = ip.loadUnionType(ty.ip_index);
3619036030
36191 assert(sema.owner.unwrap().cau == union_type.cau);36031 assert(sema.owner.unwrap().type == ty.toIntern());
3619236032
36193 const old_flags = union_type.flagsUnordered(ip);36033 const old_flags = union_type.flagsUnordered(ip);
36194 switch (old_flags.status) {36034 switch (old_flags.status) {
...@@ -36303,7 +36143,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {...@@ -36303,7 +36143,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
36303 const ip = &zcu.intern_pool;36143 const ip = &zcu.intern_pool;
36304 const struct_type = zcu.typeToStruct(ty).?;36144 const struct_type = zcu.typeToStruct(ty).?;
3630536145
36306 assert(sema.owner.unwrap().cau == struct_type.cau);36146 assert(sema.owner.unwrap().type == ty.toIntern());
3630736147
36308 if (struct_type.setFullyResolved(ip)) return;36148 if (struct_type.setFullyResolved(ip)) return;
36309 errdefer struct_type.clearFullyResolved(ip);36149 errdefer struct_type.clearFullyResolved(ip);
...@@ -36326,7 +36166,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {...@@ -36326,7 +36166,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
36326 const ip = &zcu.intern_pool;36166 const ip = &zcu.intern_pool;
36327 const union_obj = zcu.typeToUnion(ty).?;36167 const union_obj = zcu.typeToUnion(ty).?;
3632836168
36329 assert(sema.owner.unwrap().cau == union_obj.cau);36169 assert(sema.owner.unwrap().type == ty.toIntern());
3633036170
36331 switch (union_obj.flagsUnordered(ip).status) {36171 switch (union_obj.flagsUnordered(ip).status) {
36332 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},36172 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
...@@ -36361,7 +36201,7 @@ pub fn resolveStructFieldTypes(...@@ -36361,7 +36201,7 @@ pub fn resolveStructFieldTypes(
36361 const zcu = pt.zcu;36201 const zcu = pt.zcu;
36362 const ip = &zcu.intern_pool;36202 const ip = &zcu.intern_pool;
3636336203
36364 assert(sema.owner.unwrap().cau == struct_type.cau);36204 assert(sema.owner.unwrap().type == ty);
3636536205
36366 if (struct_type.haveFieldTypes(ip)) return;36206 if (struct_type.haveFieldTypes(ip)) return;
3636736207
...@@ -36387,7 +36227,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -36387,7 +36227,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
36387 const ip = &zcu.intern_pool;36227 const ip = &zcu.intern_pool;
36388 const struct_type = zcu.typeToStruct(ty) orelse return;36228 const struct_type = zcu.typeToStruct(ty) orelse return;
3638936229
36390 assert(sema.owner.unwrap().cau == struct_type.cau);36230 assert(sema.owner.unwrap().type == ty.toIntern());
3639136231
36392 // Inits can start as resolved36232 // Inits can start as resolved
36393 if (struct_type.haveFieldInits(ip)) return;36233 if (struct_type.haveFieldInits(ip)) return;
...@@ -36416,7 +36256,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -36416,7 +36256,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
36416 const zcu = pt.zcu;36256 const zcu = pt.zcu;
36417 const ip = &zcu.intern_pool;36257 const ip = &zcu.intern_pool;
3641836258
36419 assert(sema.owner.unwrap().cau == union_type.cau);36259 assert(sema.owner.unwrap().type == ty.toIntern());
3642036260
36421 switch (union_type.flagsUnordered(ip).status) {36261 switch (union_type.flagsUnordered(ip).status) {
36422 .none => {},36262 .none => {},
...@@ -36492,7 +36332,7 @@ fn resolveInferredErrorSet(...@@ -36492,7 +36332,7 @@ fn resolveInferredErrorSet(
36492 // In this case we are dealing with the actual InferredErrorSet object that36332 // In this case we are dealing with the actual InferredErrorSet object that
36493 // corresponds to the function, not one created to track an inline/comptime call.36333 // corresponds to the function, not one created to track an inline/comptime call.
36494 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));36334 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));
36495 try pt.ensureFuncBodyAnalyzed(func_index);36335 try pt.ensureFuncBodyUpToDate(func_index);
36496 }36336 }
3649736337
36498 // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody`36338 // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody`
...@@ -36649,8 +36489,7 @@ fn structFields(...@@ -36649,8 +36489,7 @@ fn structFields(
36649 const zcu = pt.zcu;36489 const zcu = pt.zcu;
36650 const gpa = zcu.gpa;36490 const gpa = zcu.gpa;
36651 const ip = &zcu.intern_pool;36491 const ip = &zcu.intern_pool;
36652 const cau_index = struct_type.cau;36492 const namespace_index = struct_type.namespace;
36653 const namespace_index = ip.getCau(cau_index).namespace;
36654 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36493 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36655 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;36494 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
3665636495
...@@ -36848,8 +36687,7 @@ fn structFieldInits(...@@ -36848,8 +36687,7 @@ fn structFieldInits(
3684836687
36849 assert(!struct_type.haveFieldInits(ip));36688 assert(!struct_type.haveFieldInits(ip));
3685036689
36851 const cau_index = struct_type.cau;36690 const namespace_index = struct_type.namespace;
36852 const namespace_index = ip.getCau(cau_index).namespace;
36853 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36691 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36854 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;36692 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
36855 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);36693 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
...@@ -38650,14 +38488,17 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {...@@ -38650,14 +38488,17 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38650 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would38488 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would
38651 // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve38489 // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve
38652 // the loop.38490 // the loop.
38491 // Note that this also disallows a `nav_val`
38653 switch (sema.owner.unwrap()) {38492 switch (sema.owner.unwrap()) {
38654 .cau => |cau| switch (dependee) {38493 .nav_val => |this_nav| switch (dependee) {
38655 .nav_val => |nav| if (zcu.intern_pool.getNav(nav).analysis_owner == cau.toOptional()) {38494 .nav_val => |other_nav| if (this_nav == other_nav) return,
38656 return;
38657 },
38658 else => {},38495 else => {},
38659 },38496 },
38660 .func => {},38497 .nav_ty => |this_nav| switch (dependee) {
38498 .nav_ty => |other_nav| if (this_nav == other_nav) return,
38499 else => {},
38500 },
38501 else => {},
38661 }38502 }
3866238503
38663 try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee);38504 try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee);
...@@ -38836,45 +38677,6 @@ pub fn flushExports(sema: *Sema) !void {...@@ -38836,45 +38677,6 @@ pub fn flushExports(sema: *Sema) !void {
38836 }38677 }
38837}38678}
3883838679
38839/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38840/// the corresponding `Nav`.
38841fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {
38842 const cau = sema.owner.unwrap().cau;
38843 return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;
38844}
38845
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
38853/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38854/// the `TrackedInst` corresponding to this `declaration` instruction.
38855fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
38856 const ip = &sema.pt.zcu.intern_pool;
38857 const cau = ip.getCau(sema.owner.unwrap().cau);
38858 assert(cau.owner.unwrap() == .nav);
38859 return cau.zir_index;
38860}
38861
38862/// Given that this `Sema` is owned by a runtime function, fetches the
38863/// `TrackedInst` corresponding to its `declaration` instruction.
38864fn getOwnerFuncDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
38865 const zcu = sema.pt.zcu;
38866 const ip = &zcu.intern_pool;
38867 const func = sema.owner.unwrap().func;
38868 const func_info = zcu.funcInfo(func);
38869 const cau = if (func_info.generic_owner == .none) cau: {
38870 break :cau ip.getNav(func_info.owner_nav).analysis_owner.unwrap().?;
38871 } else cau: {
38872 const generic_owner = zcu.funcInfo(func_info.generic_owner);
38873 break :cau ip.getNav(generic_owner.owner_nav).analysis_owner.unwrap().?;
38874 };
38875 return ip.getCau(cau).zir_index;
38876}
38877
38878/// Called as soon as a `declared` enum type is created.38680/// Called as soon as a `declared` enum type is created.
38879/// Resolves the tag type and field inits.38681/// Resolves the tag type and field inits.
38880/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.38682/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.
...@@ -38885,7 +38687,6 @@ pub fn resolveDeclaredEnum(...@@ -38885,7 +38687,6 @@ pub fn resolveDeclaredEnum(
38885 tracked_inst: InternPool.TrackedInst.Index,38687 tracked_inst: InternPool.TrackedInst.Index,
38886 namespace: InternPool.NamespaceIndex,38688 namespace: InternPool.NamespaceIndex,
38887 type_name: InternPool.NullTerminatedString,38689 type_name: InternPool.NullTerminatedString,
38888 enum_cau: InternPool.Cau.Index,
38889 small: Zir.Inst.EnumDecl.Small,38690 small: Zir.Inst.EnumDecl.Small,
38890 body: []const Zir.Inst.Index,38691 body: []const Zir.Inst.Index,
38891 tag_type_ref: Zir.Inst.Ref,38692 tag_type_ref: Zir.Inst.Ref,
...@@ -38903,7 +38704,7 @@ pub fn resolveDeclaredEnum(...@@ -38903,7 +38704,7 @@ pub fn resolveDeclaredEnum(
38903 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };38704 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
38904 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };38705 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
3890538706
38906 const anal_unit = AnalUnit.wrap(.{ .cau = enum_cau });38707 const anal_unit = AnalUnit.wrap(.{ .type = wip_ty.index });
3890738708
38908 var arena = std.heap.ArenaAllocator.init(gpa);38709 var arena = std.heap.ArenaAllocator.init(gpa);
38909 defer arena.deinit();38710 defer arena.deinit();
...@@ -39115,8 +38916,8 @@ fn getBuiltinInnerType(...@@ -39115,8 +38916,8 @@ fn getBuiltinInnerType(
39115 const nav = opt_nav orelse return sema.fail(block, src, "std.builtin.{s} missing {s}", .{38916 const nav = opt_nav orelse return sema.fail(block, src, "std.builtin.{s} missing {s}", .{
39116 compile_error_parent_name, inner_name,38917 compile_error_parent_name, inner_name,
39117 });38918 });
39118 try sema.ensureNavResolved(src, nav);38919 try sema.ensureNavResolved(src, nav, .fully);
39119 const val = Value.fromInterned(ip.getNav(nav).status.resolved.val);38920 const val = Value.fromInterned(ip.getNav(nav).status.fully_resolved.val);
39120 const ty = val.toType();38921 const ty = val.toType();
39121 try ty.resolveFully(pt);38922 try ty.resolveFully(pt);
39122 return ty;38923 return ty;
...@@ -39127,6 +38928,74 @@ fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {...@@ -39127,6 +38928,74 @@ fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {
39127 const zcu = pt.zcu;38928 const zcu = pt.zcu;
39128 const ip = &zcu.intern_pool;38929 const ip = &zcu.intern_pool;
39129 const nav = try pt.getBuiltinNav(name);38930 const nav = try pt.getBuiltinNav(name);
39130 try pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?);38931 try pt.ensureNavValUpToDate(nav);
39131 return Air.internedToRef(ip.getNav(nav).status.resolved.val);38932 return Air.internedToRef(ip.getNav(nav).status.fully_resolved.val);
38933}
38934
38935pub const NavPtrModifiers = struct {
38936 alignment: Alignment,
38937 @"linksection": InternPool.OptionalNullTerminatedString,
38938 @"addrspace": std.builtin.AddressSpace,
38939};
38940
38941pub fn resolveNavPtrModifiers(
38942 sema: *Sema,
38943 block: *Block,
38944 zir_decl: Zir.Inst.Declaration.Unwrapped,
38945 decl_inst: Zir.Inst.Index,
38946 nav_ty: Type,
38947) CompileError!NavPtrModifiers {
38948 const pt = sema.pt;
38949 const zcu = pt.zcu;
38950 const gpa = zcu.gpa;
38951 const ip = &zcu.intern_pool;
38952
38953 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
38954 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
38955 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
38956
38957 const alignment: InternPool.Alignment = a: {
38958 const align_body = zir_decl.align_body orelse break :a .none;
38959 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);
38960 break :a try sema.analyzeAsAlign(block, align_src, align_ref);
38961 };
38962
38963 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
38964 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
38965 const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst);
38966 const bytes = try sema.toConstString(block, section_src, linksection_ref, .{
38967 .needed_comptime_reason = "linksection must be comptime-known",
38968 });
38969 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
38970 return sema.fail(block, section_src, "linksection cannot contain null bytes", .{});
38971 } else if (bytes.len == 0) {
38972 return sema.fail(block, section_src, "linksection cannot be empty", .{});
38973 }
38974 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
38975 };
38976
38977 const @"addrspace": std.builtin.AddressSpace = as: {
38978 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {
38979 .@"var" => .variable,
38980 else => switch (nav_ty.zigTypeTag(zcu)) {
38981 .@"fn" => .function,
38982 else => .constant,
38983 },
38984 };
38985 const target = zcu.getTarget();
38986 const addrspace_body = zir_decl.addrspace_body orelse break :as switch (addrspace_ctx) {
38987 .function => target_util.defaultAddressSpace(target, .function),
38988 .variable => target_util.defaultAddressSpace(target, .global_mutable),
38989 .constant => target_util.defaultAddressSpace(target, .global_constant),
38990 else => unreachable,
38991 };
38992 const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst);
38993 break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx);
38994 };
38995
38996 return .{
38997 .alignment = alignment,
38998 .@"linksection" = @"linksection",
38999 .@"addrspace" = @"addrspace",
39000 };
39132}39001}
src/Sema/comptime_ptr_access.zig+2-3
...@@ -219,9 +219,8 @@ fn loadComptimePtrInner(...@@ -219,9 +219,8 @@ fn loadComptimePtrInner(
219219
220 const base_val: MutableValue = switch (ptr.base_addr) {220 const base_val: MutableValue = switch (ptr.base_addr) {
221 .nav => |nav| val: {221 .nav => |nav| val: {
222 try sema.declareDependency(.{ .nav_val = nav });222 try sema.ensureNavResolved(src, nav, .fully);
223 try sema.ensureNavResolved(src, nav);223 const val = ip.getNav(nav).status.fully_resolved.val;
224 const val = ip.getNav(nav).status.resolved.val;
225 switch (ip.indexToKey(val)) {224 switch (ip.indexToKey(val)) {
226 .variable => return .runtime_load,225 .variable => return .runtime_load,
227 // We let `.@"extern"` through here if it's a function.226 // We let `.@"extern"` through here if it's a function.
src/Type.zig+2-2
...@@ -3851,7 +3851,7 @@ fn resolveStructInner(...@@ -3851,7 +3851,7 @@ fn resolveStructInner(
3851 const gpa = zcu.gpa;3851 const gpa = zcu.gpa;
38523852
3853 const struct_obj = zcu.typeToStruct(ty).?;3853 const struct_obj = zcu.typeToStruct(ty).?;
3854 const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau });3854 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
38553855
3856 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {3856 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3857 return error.AnalysisFail;3857 return error.AnalysisFail;
...@@ -3905,7 +3905,7 @@ fn resolveUnionInner(...@@ -3905,7 +3905,7 @@ fn resolveUnionInner(
3905 const gpa = zcu.gpa;3905 const gpa = zcu.gpa;
39063906
3907 const union_obj = zcu.typeToUnion(ty).?;3907 const union_obj = zcu.typeToUnion(ty).?;
3908 const owner = InternPool.AnalUnit.wrap(.{ .cau = union_obj.cau });3908 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
39093909
3910 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {3910 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3911 return error.AnalysisFail;3911 return error.AnalysisFail;
src/Value.zig+6-1
...@@ -1343,7 +1343,12 @@ pub fn isLazySize(val: Value, zcu: *Zcu) bool {...@@ -1343,7 +1343,12 @@ pub fn isLazySize(val: Value, zcu: *Zcu) bool {
1343pub fn isPtrRuntimeValue(val: Value, zcu: *Zcu) bool {1343pub fn isPtrRuntimeValue(val: Value, zcu: *Zcu) bool {
1344 const ip = &zcu.intern_pool;1344 const ip = &zcu.intern_pool;
1345 const nav = ip.getBackingNav(val.toIntern()).unwrap() orelse return false;1345 const nav = ip.getBackingNav(val.toIntern()).unwrap() orelse return false;
1346 return switch (ip.indexToKey(ip.getNav(nav).status.resolved.val)) {1346 const nav_val = switch (ip.getNav(nav).status) {
1347 .unresolved => unreachable,
1348 .type_resolved => |r| return r.is_threadlocal,
1349 .fully_resolved => |r| r.val,
1350 };
1351 return switch (ip.indexToKey(nav_val)) {
1347 .@"extern" => |e| e.is_threadlocal or e.is_dll_import,1352 .@"extern" => |e| e.is_threadlocal or e.is_dll_import,
1348 .variable => |v| v.is_threadlocal,1353 .variable => |v| v.is_threadlocal,
1349 else => false,1354 else => false,
src/Zcu.zig+187-147
...@@ -170,6 +170,9 @@ outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty,...@@ -170,6 +170,9 @@ outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty,
170/// it as outdated.170/// it as outdated.
171retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .empty,171retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .empty,
172172
173func_body_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty,
174nav_val_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
175
173/// These are the modules which we initially queue for analysis in `Compilation.update`.176/// These are the modules which we initially queue for analysis in `Compilation.update`.
174/// `resolveReferences` will use these as the root of its reachability traversal.177/// `resolveReferences` will use these as the root of its reachability traversal.
175analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},178analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},
...@@ -192,7 +195,7 @@ compile_log_text: std.ArrayListUnmanaged(u8) = .empty,...@@ -192,7 +195,7 @@ compile_log_text: std.ArrayListUnmanaged(u8) = .empty,
192195
193test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,196test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
194197
195global_assembly: std.AutoArrayHashMapUnmanaged(InternPool.Cau.Index, []u8) = .empty,198global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
196199
197/// Key is the `AnalUnit` *performing* the reference. This representation allows200/// Key is the `AnalUnit` *performing* the reference. This representation allows
198/// incremental updates to quickly delete references caused by a specific `AnalUnit`.201/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
...@@ -282,7 +285,11 @@ pub const Exported = union(enum) {...@@ -282,7 +285,11 @@ pub const Exported = union(enum) {
282285
283 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {286 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {
284 return switch (exported) {287 return switch (exported) {
285 .nav => |nav| zcu.intern_pool.getNav(nav).status.resolved.alignment,288 .nav => |nav| switch (zcu.intern_pool.getNav(nav).status) {
289 .unresolved => unreachable,
290 .type_resolved => |r| r.alignment,
291 .fully_resolved => |r| r.alignment,
292 },
286 .uav => .none,293 .uav => .none,
287 };294 };
288 }295 }
...@@ -344,9 +351,12 @@ pub const Namespace = struct {...@@ -344,9 +351,12 @@ pub const Namespace = struct {
344 pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,351 pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
345 /// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.352 /// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.
346 priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,353 priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
347 /// All `comptime` and `test` declarations in this namespace. We store these purely so that354 /// All `comptime` declarations in this namespace. We store these purely so that incremental
348 /// incremental compilation can re-use the existing `Cau`s when a namespace changes.355 /// compilation can re-use the existing `ComptimeUnit`s when a namespace changes.
349 other_decls: std.ArrayListUnmanaged(InternPool.Cau.Index) = .empty,356 comptime_decls: std.ArrayListUnmanaged(InternPool.ComptimeUnit.Id) = .empty,
357 /// All `test` declarations in this namespace. We store these purely so that incremental
358 /// compilation can re-use the existing `Nav`s when a namespace changes.
359 test_decls: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
350360
351 pub const Index = InternPool.NamespaceIndex;361 pub const Index = InternPool.NamespaceIndex;
352 pub const OptionalIndex = InternPool.OptionalNamespaceIndex;362 pub const OptionalIndex = InternPool.OptionalNamespaceIndex;
...@@ -2238,6 +2248,9 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2238,6 +2248,9 @@ pub fn deinit(zcu: *Zcu) void {
2238 zcu.outdated_ready.deinit(gpa);2248 zcu.outdated_ready.deinit(gpa);
2239 zcu.retryable_failures.deinit(gpa);2249 zcu.retryable_failures.deinit(gpa);
22402250
2251 zcu.func_body_analysis_queued.deinit(gpa);
2252 zcu.nav_val_analysis_queued.deinit(gpa);
2253
2241 zcu.test_functions.deinit(gpa);2254 zcu.test_functions.deinit(gpa);
22422255
2243 for (zcu.global_assembly.values()) |s| {2256 for (zcu.global_assembly.values()) |s| {
...@@ -2436,11 +2449,10 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -2436,11 +2449,10 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
2436 // If this is a Decl, we must recursively mark dependencies on its tyval2449 // If this is a Decl, we must recursively mark dependencies on its tyval
2437 // as no longer PO.2450 // as no longer PO.
2438 switch (depender.unwrap()) {2451 switch (depender.unwrap()) {
2439 .cau => |cau| switch (zcu.intern_pool.getCau(cau).owner.unwrap()) {2452 .@"comptime" => {},
2440 .nav => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),2453 .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
2441 .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),2454 .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }),
2442 .none => {},2455 .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
2443 },
2444 .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),2456 .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),
2445 }2457 }
2446 }2458 }
...@@ -2451,11 +2463,10 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -2451,11 +2463,10 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
2451fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {2463fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {
2452 const ip = &zcu.intern_pool;2464 const ip = &zcu.intern_pool;
2453 const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) {2465 const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) {
2454 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {2466 .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies
2455 .nav => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced2467 .nav_val => |nav| .{ .nav_val = nav },
2456 .type => |ty| .{ .interned = ty },2468 .nav_ty => |nav| .{ .nav_ty = nav },
2457 .none => return, // analysis of this `Cau` can't outdate any dependencies2469 .type => |ty| .{ .interned = ty },
2458 },
2459 .func => |func_index| .{ .interned = func_index }, // IES2470 .func => |func_index| .{ .interned = func_index }, // IES
2460 };2471 };
2461 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});2472 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});
...@@ -2512,14 +2523,14 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2512,14 +2523,14 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2512 }2523 }
25132524
2514 // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some2525 // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some
2515 // Cau with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of2526 // AnalUnit with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of
2516 // A or B. We should select a Cau, since a Cau is definitely responsible for the loop in the2527 // A or B. We should definitely not select a function, since a function can't be responsible for the
2517 // dependency graph (since IES dependencies can't have loops). We should also, of course, not2528 // loop (IES dependencies can't have loops). We should also, of course, not select a `comptime`
2518 // select a Cau owned by a `comptime` declaration, since you can't depend on those!2529 // declaration, since you can't depend on those!
25192530
2520 // The choice of this Cau could have a big impact on how much total analysis we perform, since2531 // The choice of this unit could have a big impact on how much total analysis we perform, since
2521 // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit2532 // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit
2522 // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a Decl2533 // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a unit
2523 // which the most things depend on - the idea is that this will resolve a lot of loops (but this2534 // which the most things depend on - the idea is that this will resolve a lot of loops (but this
2524 // is only a heuristic).2535 // is only a heuristic).
25252536
...@@ -2530,33 +2541,29 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2530,33 +2541,29 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
25302541
2531 const ip = &zcu.intern_pool;2542 const ip = &zcu.intern_pool;
25322543
2533 var chosen_cau: ?InternPool.Cau.Index = null;2544 var chosen_unit: ?AnalUnit = null;
2534 var chosen_cau_dependers: u32 = undefined;2545 var chosen_unit_dependers: u32 = undefined;
25352546
2536 inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {2547 inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {
2537 for (outdated_units) |unit| {2548 for (outdated_units) |unit| {
2538 const cau = switch (unit.unwrap()) {
2539 .cau => |cau| cau,
2540 .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
2541 };
2542 const cau_owner = ip.getCau(cau).owner;
2543
2544 var n: u32 = 0;2549 var n: u32 = 0;
2545 var it = ip.dependencyIterator(switch (cau_owner.unwrap()) {2550 var it = ip.dependencyIterator(switch (unit.unwrap()) {
2546 .none => continue, // there can be no dependencies on this `Cau` so it is a terrible choice2551 .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
2552 .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice
2547 .type => |ty| .{ .interned = ty },2553 .type => |ty| .{ .interned = ty },
2548 .nav => |nav| .{ .nav_val = nav },2554 .nav_val => |nav| .{ .nav_val = nav },
2555 .nav_ty => |nav| .{ .nav_ty = nav },
2549 });2556 });
2550 while (it.next()) |_| n += 1;2557 while (it.next()) |_| n += 1;
25512558
2552 if (chosen_cau == null or n > chosen_cau_dependers) {2559 if (chosen_unit == null or n > chosen_unit_dependers) {
2553 chosen_cau = cau;2560 chosen_unit = unit;
2554 chosen_cau_dependers = n;2561 chosen_unit_dependers = n;
2555 }2562 }
2556 }2563 }
2557 }2564 }
25582565
2559 if (chosen_cau == null) {2566 if (chosen_unit == null) {
2560 for (zcu.outdated.keys(), zcu.outdated.values()) |o, opod| {2567 for (zcu.outdated.keys(), zcu.outdated.values()) |o, opod| {
2561 const func = o.unwrap().func;2568 const func = o.unwrap().func;
2562 const nav = zcu.funcInfo(func).owner_nav;2569 const nav = zcu.funcInfo(func).owner_nav;
...@@ -2570,11 +2577,11 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2570,11 +2577,11 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2570 }2577 }
25712578
2572 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{2579 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{
2573 zcu.fmtAnalUnit(AnalUnit.wrap(.{ .cau = chosen_cau.? })),2580 zcu.fmtAnalUnit(chosen_unit.?),
2574 chosen_cau_dependers,2581 chosen_unit_dependers,
2575 });2582 });
25762583
2577 return AnalUnit.wrap(.{ .cau = chosen_cau.? });2584 return chosen_unit.?;
2578}2585}
25792586
2580/// During an incremental update, before semantic analysis, call this to flush all values from2587/// During an incremental update, before semantic analysis, call this to flush all values from
...@@ -2679,24 +2686,14 @@ pub fn mapOldZirToNew(...@@ -2679,24 +2686,14 @@ pub fn mapOldZirToNew(
2679 {2686 {
2680 var old_decl_it = old_zir.declIterator(match_item.old_inst);2687 var old_decl_it = old_zir.declIterator(match_item.old_inst);
2681 while (old_decl_it.next()) |old_decl_inst| {2688 while (old_decl_it.next()) |old_decl_inst| {
2682 const old_decl, _ = old_zir.getDeclaration(old_decl_inst);2689 const old_decl = old_zir.getDeclaration(old_decl_inst);
2683 switch (old_decl.name) {2690 switch (old_decl.kind) {
2684 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),2691 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
2685 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),2692 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),
2686 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),2693 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
2687 _ => {2694 .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
2688 const name_nts = old_decl.name.toString(old_zir).?;2695 .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
2689 const name = old_zir.nullTerminatedString(name_nts);2696 .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
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 },
2700 }2697 }
2701 }2698 }
2702 }2699 }
...@@ -2707,7 +2704,7 @@ pub fn mapOldZirToNew(...@@ -2707,7 +2704,7 @@ pub fn mapOldZirToNew(
27072704
2708 var new_decl_it = new_zir.declIterator(match_item.new_inst);2705 var new_decl_it = new_zir.declIterator(match_item.new_inst);
2709 while (new_decl_it.next()) |new_decl_inst| {2706 while (new_decl_it.next()) |new_decl_inst| {
2710 const new_decl, _ = new_zir.getDeclaration(new_decl_inst);2707 const new_decl = new_zir.getDeclaration(new_decl_inst);
2711 // Attempt to match this to a declaration in the old ZIR:2708 // Attempt to match this to a declaration in the old ZIR:
2712 // * For named declarations (`const`/`var`/`fn`), we match based on name.2709 // * For named declarations (`const`/`var`/`fn`), we match based on name.
2713 // * For named tests (`test "foo"`) and decltests (`test foo`), we also match based on name.2710 // * For named tests (`test "foo"`) and decltests (`test foo`), we also match based on name.
...@@ -2715,7 +2712,7 @@ pub fn mapOldZirToNew(...@@ -2715,7 +2712,7 @@ pub fn mapOldZirToNew(
2715 // * For comptime blocks, we match based on order.2712 // * For comptime blocks, we match based on order.
2716 // * For usingnamespace decls, we match based on order.2713 // * For usingnamespace decls, we match based on order.
2717 // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`.2714 // 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) {2715 const old_decl_inst = switch (new_decl.kind) {
2719 .@"comptime" => inst: {2716 .@"comptime" => inst: {
2720 if (comptime_decl_idx == comptime_decls.items.len) continue;2717 if (comptime_decl_idx == comptime_decls.items.len) continue;
2721 defer comptime_decl_idx += 1;2718 defer comptime_decl_idx += 1;
...@@ -2731,18 +2728,17 @@ pub fn mapOldZirToNew(...@@ -2731,18 +2728,17 @@ pub fn mapOldZirToNew(
2731 defer unnamed_test_idx += 1;2728 defer unnamed_test_idx += 1;
2732 break :inst unnamed_tests.items[unnamed_test_idx];2729 break :inst unnamed_tests.items[unnamed_test_idx];
2733 },2730 },
2734 _ => inst: {2731 .@"test" => inst: {
2735 const name_nts = new_decl.name.toString(new_zir).?;2732 const name = new_zir.nullTerminatedString(new_decl.name);
2736 const name = new_zir.nullTerminatedString(name_nts);2733 break :inst named_tests.get(name) orelse continue;
2737 if (new_decl.name.isNamedTest(new_zir)) {2734 },
2738 if (new_decl.flags.test_is_decltest) {2735 .decltest => inst: {
2739 break :inst named_decltests.get(name) orelse continue;2736 const name = new_zir.nullTerminatedString(new_decl.name);
2740 } else {2737 break :inst named_decltests.get(name) orelse continue;
2741 break :inst named_tests.get(name) orelse continue;2738 },
2742 }2739 .@"const", .@"var" => inst: {
2743 } else {2740 const name = new_zir.nullTerminatedString(new_decl.name);
2744 break :inst named_decls.get(name) orelse continue;2741 break :inst named_decls.get(name) orelse continue;
2745 }
2746 },2742 },
2747 };2743 };
27482744
...@@ -2797,14 +2793,39 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !vo...@@ -2797,14 +2793,39 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !vo
2797 const ip = &zcu.intern_pool;2793 const ip = &zcu.intern_pool;
2798 const func = zcu.funcInfo(func_index);2794 const func = zcu.funcInfo(func_index);
27992795
2800 switch (func.analysisUnordered(ip).state) {2796 if (zcu.func_body_analysis_queued.contains(func_index)) return;
2801 .unreferenced => {}, // We're the first reference!2797
2802 .queued => return, // Analysis is already queued.2798 if (func.analysisUnordered(ip).is_analyzed) {
2803 .analyzed => return, // Analysis is complete; if it's out-of-date, it'll be re-analyzed later this update.2799 if (!zcu.outdated.contains(.wrap(.{ .func = func_index })) and
2800 !zcu.potentially_outdated.contains(.wrap(.{ .func = func_index })))
2801 {
2802 // This function has been analyzed before and is definitely up-to-date.
2803 return;
2804 }
2804 }2805 }
28052806
2807 try zcu.func_body_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1);
2806 try zcu.comp.queueJob(.{ .analyze_func = func_index });2808 try zcu.comp.queueJob(.{ .analyze_func = func_index });
2807 func.setAnalysisState(ip, .queued);2809 zcu.func_body_analysis_queued.putAssumeCapacityNoClobber(func_index, {});
2810}
2811
2812pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void {
2813 const ip = &zcu.intern_pool;
2814
2815 if (zcu.nav_val_analysis_queued.contains(nav_id)) return;
2816
2817 if (ip.getNav(nav_id).status == .fully_resolved) {
2818 if (!zcu.outdated.contains(.wrap(.{ .nav_val = nav_id })) and
2819 !zcu.potentially_outdated.contains(.wrap(.{ .nav_val = nav_id })))
2820 {
2821 // This `Nav` has been analyzed before and is definitely up-to-date.
2822 return;
2823 }
2824 }
2825
2826 try zcu.nav_val_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1);
2827 try zcu.comp.queueJob(.{ .analyze_comptime_unit = .wrap(.{ .nav_val = nav_id }) });
2828 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});
2808}2829}
28092830
2810pub const ImportFileResult = struct {2831pub const ImportFileResult = struct {
...@@ -3030,9 +3051,9 @@ pub fn handleUpdateExports(...@@ -3030,9 +3051,9 @@ pub fn handleUpdateExports(
3030 };3051 };
3031}3052}
30323053
3033pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u8) !void {3054pub fn addGlobalAssembly(zcu: *Zcu, unit: AnalUnit, source: []const u8) !void {
3034 const gpa = zcu.gpa;3055 const gpa = zcu.gpa;
3035 const gop = try zcu.global_assembly.getOrPut(gpa, cau);3056 const gop = try zcu.global_assembly.getOrPut(gpa, unit);
3036 if (gop.found_existing) {3057 if (gop.found_existing) {
3037 const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source });3058 const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source });
3038 gpa.free(gop.value_ptr.*);3059 gpa.free(gop.value_ptr.*);
...@@ -3315,23 +3336,22 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3315,23 +3336,22 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
33153336
3316 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});3337 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
33173338
3318 // If this type has a `Cau` for resolution, it's automatically referenced.3339 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
3319 const resolution_cau: InternPool.Cau.Index.Optional = switch (ip.indexToKey(ty)) {3340 const has_resolution: bool = switch (ip.indexToKey(ty)) {
3320 .struct_type => ip.loadStructType(ty).cau.toOptional(),3341 .struct_type, .union_type => true,
3321 .union_type => ip.loadUnionType(ty).cau.toOptional(),3342 .enum_type => |k| k != .generated_tag,
3322 .enum_type => ip.loadEnumType(ty).cau,3343 .opaque_type => false,
3323 .opaque_type => .none,
3324 else => unreachable,3344 else => unreachable,
3325 };3345 };
3326 if (resolution_cau.unwrap()) |cau| {3346 if (has_resolution) {
3327 // this should only be referenced by the type3347 // this should only be referenced by the type
3328 const unit = AnalUnit.wrap(.{ .cau = cau });3348 const unit: AnalUnit = .wrap(.{ .type = ty });
3329 assert(!result.contains(unit));3349 assert(!result.contains(unit));
3330 try unit_queue.putNoClobber(gpa, unit, referencer);3350 try unit_queue.putNoClobber(gpa, unit, referencer);
3331 }3351 }
33323352
3333 // If this is a union with a generated tag, its tag type is automatically referenced.3353 // If this is a union with a generated tag, its tag type is automatically referenced.
3334 // We don't add this reference for non-generated tags, as those will already be referenced via the union's `Cau`, with a better source location.3354 // We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location.
3335 if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {3355 if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {
3336 const tag_ty = union_obj.enum_tag_ty;3356 const tag_ty = union_obj.enum_tag_ty;
3337 if (tag_ty != .none) {3357 if (tag_ty != .none) {
...@@ -3346,53 +3366,61 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3346,53 +3366,61 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3346 // Queue any decls within this type which would be automatically analyzed.3366 // Queue any decls within this type which would be automatically analyzed.
3347 // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`.3367 // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`.
3348 const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?;3368 const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?;
3349 for (zcu.namespacePtr(ns).other_decls.items) |cau| {3369 for (zcu.namespacePtr(ns).comptime_decls.items) |cu| {
3350 // These are `comptime` and `test` declarations.3370 // `comptime` decls are always analyzed.
3351 // `comptime` decls are always analyzed; `test` declarations are analyzed depending on the test filter.3371 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
3352 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;3372 if (!result.contains(unit)) {
3373 log.debug("type '{}': ref comptime %{}", .{
3374 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3375 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
3376 });
3377 try unit_queue.put(gpa, unit, referencer);
3378 }
3379 }
3380 for (zcu.namespacePtr(ns).test_decls.items) |nav_id| {
3381 const nav = ip.getNav(nav_id);
3382 // `test` declarations are analyzed depending on the test filter.
3383 const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue;
3353 const file = zcu.fileByIndex(inst_info.file);3384 const file = zcu.fileByIndex(inst_info.file);
3354 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3385 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3355 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3386 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3356 const declaration = zir.getDeclaration(inst_info.inst)[0];3387 const decl = zir.getDeclaration(inst_info.inst);
3357 const want_analysis = switch (declaration.name) {3388
3389 if (!comp.config.is_test or file.mod != zcu.main_mod) continue;
3390
3391 const want_analysis = switch (decl.kind) {
3358 .@"usingnamespace" => unreachable,3392 .@"usingnamespace" => unreachable,
3359 .@"comptime" => true,3393 .@"const", .@"var" => unreachable,
3360 else => a: {3394 .@"comptime" => unreachable,
3361 if (!comp.config.is_test) break :a false;3395 .unnamed_test => true,
3362 if (file.mod != zcu.main_mod) break :a false;3396 .@"test", .decltest => a: {
3363 if (declaration.name.isNamedTest(zir)) {3397 const fqn_slice = nav.fqn.toSlice(ip);
3364 const nav = ip.getCau(cau).owner.unwrap().nav;3398 for (comp.test_filters) |test_filter| {
3365 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);3399 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3366 for (comp.test_filters) |test_filter| {3400 } else break :a false;
3367 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3368 } else break :a false;
3369 }
3370 break :a true;3401 break :a true;
3371 },3402 },
3372 };3403 };
3373 if (want_analysis) {3404 if (want_analysis) {
3374 const unit = AnalUnit.wrap(.{ .cau = cau });3405 log.debug("type '{}': ref test %{}", .{
3375 if (!result.contains(unit)) {3406 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3376 log.debug("type '{}': ref cau %{}", .{3407 @intFromEnum(inst_info.inst),
3377 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3408 });
3378 @intFromEnum(inst_info.inst),3409 const unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
3379 });3410 try unit_queue.put(gpa, unit, referencer);
3380 try unit_queue.put(gpa, unit, referencer);
3381 }
3382 }3411 }
3383 }3412 }
3384 for (zcu.namespacePtr(ns).pub_decls.keys()) |nav| {3413 for (zcu.namespacePtr(ns).pub_decls.keys()) |nav| {
3385 // These are named declarations. They are analyzed only if marked `export`.3414 // These are named declarations. They are analyzed only if marked `export`.
3386 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3415 const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
3387 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
3388 const file = zcu.fileByIndex(inst_info.file);3416 const file = zcu.fileByIndex(inst_info.file);
3389 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3417 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3390 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3418 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3391 const declaration = zir.getDeclaration(inst_info.inst)[0];3419 const decl = zir.getDeclaration(inst_info.inst);
3392 if (declaration.flags.is_export) {3420 if (decl.linkage == .@"export") {
3393 const unit = AnalUnit.wrap(.{ .cau = cau });3421 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3394 if (!result.contains(unit)) {3422 if (!result.contains(unit)) {
3395 log.debug("type '{}': ref cau %{}", .{3423 log.debug("type '{}': ref named %{}", .{
3396 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3424 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3397 @intFromEnum(inst_info.inst),3425 @intFromEnum(inst_info.inst),
3398 });3426 });
...@@ -3402,16 +3430,15 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3402,16 +3430,15 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3402 }3430 }
3403 for (zcu.namespacePtr(ns).priv_decls.keys()) |nav| {3431 for (zcu.namespacePtr(ns).priv_decls.keys()) |nav| {
3404 // These are named declarations. They are analyzed only if marked `export`.3432 // These are named declarations. They are analyzed only if marked `export`.
3405 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3433 const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
3406 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
3407 const file = zcu.fileByIndex(inst_info.file);3434 const file = zcu.fileByIndex(inst_info.file);
3408 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3435 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3409 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3436 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3410 const declaration = zir.getDeclaration(inst_info.inst)[0];3437 const decl = zir.getDeclaration(inst_info.inst);
3411 if (declaration.flags.is_export) {3438 if (decl.linkage == .@"export") {
3412 const unit = AnalUnit.wrap(.{ .cau = cau });3439 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3413 if (!result.contains(unit)) {3440 if (!result.contains(unit)) {
3414 log.debug("type '{}': ref cau %{}", .{3441 log.debug("type '{}': ref named %{}", .{
3415 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3442 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3416 @intFromEnum(inst_info.inst),3443 @intFromEnum(inst_info.inst),
3417 });3444 });
...@@ -3422,13 +3449,11 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3422,13 +3449,11 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3422 // Incremental compilation does not support `usingnamespace`.3449 // Incremental compilation does not support `usingnamespace`.
3423 // These are only included to keep good reference traces in non-incremental updates.3450 // These are only included to keep good reference traces in non-incremental updates.
3424 for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {3451 for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {
3425 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3452 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3426 const unit = AnalUnit.wrap(.{ .cau = cau });
3427 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);3453 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
3428 }3454 }
3429 for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {3455 for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {
3430 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3456 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3431 const unit = AnalUnit.wrap(.{ .cau = cau });
3432 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);3457 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
3433 }3458 }
3434 continue;3459 continue;
...@@ -3437,6 +3462,17 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3437,6 +3462,17 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3437 const unit = kv.key;3462 const unit = kv.key;
3438 try result.putNoClobber(gpa, unit, kv.value);3463 try result.putNoClobber(gpa, unit, kv.value);
34393464
3465 // `nav_val` and `nav_ty` reference each other *implicitly* to save memory.
3466 queue_paired: {
3467 const other: AnalUnit = .wrap(switch (unit.unwrap()) {
3468 .nav_val => |n| .{ .nav_ty = n },
3469 .nav_ty => |n| .{ .nav_val = n },
3470 .@"comptime", .type, .func => break :queue_paired,
3471 });
3472 if (result.contains(other)) break :queue_paired;
3473 try unit_queue.put(gpa, other, kv.value); // same reference location
3474 }
3475
3440 log.debug("handle unit '{}'", .{zcu.fmtAnalUnit(unit)});3476 log.debug("handle unit '{}'", .{zcu.fmtAnalUnit(unit)});
34413477
3442 if (zcu.reference_table.get(unit)) |first_ref_idx| {3478 if (zcu.reference_table.get(unit)) |first_ref_idx| {
...@@ -3522,13 +3558,11 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {...@@ -3522,13 +3558,11 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
3522 const ip = &zcu.intern_pool;3558 const ip = &zcu.intern_pool;
3523 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;3559 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;
3524 const zir = zcu.fileByIndex(inst_info.file).zir;3560 const zir = zcu.fileByIndex(inst_info.file).zir;
3525 const inst = zir.instructions.get(@intFromEnum(inst_info.inst));3561 return zir.getDeclaration(inst_info.inst).src_line;
3526 assert(inst.tag == .declaration);
3527 return zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line;
3528}3562}
35293563
3530pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {3564pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {
3531 return Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.resolved.val);3565 return Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.fully_resolved.val);
3532}3566}
35333567
3534pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index {3568pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index {
...@@ -3540,12 +3574,6 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {...@@ -3540,12 +3574,6 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
3540 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));3574 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
3541}3575}
35423576
3543pub fn cauFileScope(zcu: *Zcu, cau: InternPool.Cau.Index) *File {
3544 const ip = &zcu.intern_pool;
3545 const file_index = ip.getCau(cau).zir_index.resolveFile(ip);
3546 return zcu.fileByIndex(file_index);
3547}
3548
3549pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {3577pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {
3550 return .{ .data = .{ .unit = unit, .zcu = zcu } };3578 return .{ .data = .{ .unit = unit, .zcu = zcu } };
3551}3579}
...@@ -3558,19 +3586,18 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -3558,19 +3586,18 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
3558 const zcu = data.zcu;3586 const zcu = data.zcu;
3559 const ip = &zcu.intern_pool;3587 const ip = &zcu.intern_pool;
3560 switch (data.unit.unwrap()) {3588 switch (data.unit.unwrap()) {
3561 .cau => |cau_index| {3589 .@"comptime" => |cu_id| {
3562 const cau = ip.getCau(cau_index);3590 const cu = ip.getComptimeUnit(cu_id);
3563 switch (cau.owner.unwrap()) {3591 if (cu.zir_index.resolveFull(ip)) |resolved| {
3564 .nav => |nav| return writer.print("cau(decl='{}')", .{ip.getNav(nav).fqn.fmt(ip)}),3592 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;
3565 .type => |ty| return writer.print("cau(ty='{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),3593 return writer.print("comptime(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
3566 .none => if (cau.zir_index.resolveFull(ip)) |resolved| {3594 } else {
3567 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;3595 return writer.writeAll("comptime(inst=<list>)");
3568 return writer.print("cau(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
3569 } else {
3570 return writer.writeAll("cau(inst=<lost>)");
3571 },
3572 }3596 }
3573 },3597 },
3598 .nav_val => |nav| return writer.print("nav_val('{}')", .{ip.getNav(nav).fqn.fmt(ip)}),
3599 .nav_ty => |nav| return writer.print("nav_ty('{}')", .{ip.getNav(nav).fqn.fmt(ip)}),
3600 .type => |ty| return writer.print("ty('{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),
3574 .func => |func| {3601 .func => |func| {
3575 const nav = zcu.funcInfo(func).owner_nav;3602 const nav = zcu.funcInfo(func).owner_nav;
3576 return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)});3603 return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)});
...@@ -3595,7 +3622,11 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -3595,7 +3622,11 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
3595 },3622 },
3596 .nav_val => |nav| {3623 .nav_val => |nav| {
3597 const fqn = ip.getNav(nav).fqn;3624 const fqn = ip.getNav(nav).fqn;
3598 return writer.print("nav('{}')", .{fqn.fmt(ip)});3625 return writer.print("nav_val('{}')", .{fqn.fmt(ip)});
3626 },
3627 .nav_ty => |nav| {
3628 const fqn = ip.getNav(nav).fqn;
3629 return writer.print("nav_ty('{}')", .{fqn.fmt(ip)});
3599 },3630 },
3600 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {3631 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
3601 .struct_type, .union_type, .enum_type => return writer.print("type('{}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),3632 .struct_type, .union_type, .enum_type => return writer.print("type('{}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),
...@@ -3772,3 +3803,12 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu...@@ -3772,3 +3803,12 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu
3772 if (!backend_ok) return .{ .bad_backend = backend };3803 if (!backend_ok) return .{ .bad_backend = backend };
3773 return .ok;3804 return .ok;
3774}3805}
3806
3807/// Given that a `Nav` has value `val`, determine if a ref of that `Nav` gives a `const` pointer.
3808pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool {
3809 return switch (zcu.intern_pool.indexToKey(val)) {
3810 .variable => false,
3811 .@"extern" => |e| e.is_const,
3812 else => true,
3813 };
3814}
src/Zcu/PerThread.zig+942-703
...@@ -469,12 +469,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -469,12 +469,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
469 {469 {
470 var it = old_zir.declIterator(old_inst);470 var it = old_zir.declIterator(old_inst);
471 while (it.next()) |decl_inst| {471 while (it.next()) |decl_inst| {
472 const decl_name = old_zir.getDeclaration(decl_inst)[0].name;472 const name_zir = old_zir.getDeclaration(decl_inst).name;
473 switch (decl_name) {473 if (name_zir == .empty) continue;
474 .@"comptime", .@"usingnamespace", .unnamed_test => continue,
475 _ => if (decl_name.isNamedTest(old_zir)) continue,
476 }
477 const name_zir = decl_name.toString(old_zir).?;
478 const name_ip = try zcu.intern_pool.getOrPutString(474 const name_ip = try zcu.intern_pool.getOrPutString(
479 zcu.gpa,475 zcu.gpa,
480 pt.tid,476 pt.tid,
...@@ -488,12 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -488,12 +484,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
488 {484 {
489 var it = new_zir.declIterator(new_inst);485 var it = new_zir.declIterator(new_inst);
490 while (it.next()) |decl_inst| {486 while (it.next()) |decl_inst| {
491 const decl_name = new_zir.getDeclaration(decl_inst)[0].name;487 const name_zir = new_zir.getDeclaration(decl_inst).name;
492 switch (decl_name) {488 if (name_zir == .empty) continue;
493 .@"comptime", .@"usingnamespace", .unnamed_test => continue,
494 _ => if (decl_name.isNamedTest(new_zir)) continue,
495 }
496 const name_zir = decl_name.toString(new_zir).?;
497 const name_ip = try zcu.intern_pool.getOrPutString(489 const name_ip = try zcu.intern_pool.getOrPutString(
498 zcu.gpa,490 zcu.gpa,
499 pt.tid,491 pt.tid,
...@@ -553,118 +545,643 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -553,118 +545,643 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
553pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {545pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
554 const file_root_type = pt.zcu.fileRootType(file_index);546 const file_root_type = pt.zcu.fileRootType(file_index);
555 if (file_root_type != .none) {547 if (file_root_type != .none) {
556 _ = try pt.ensureTypeUpToDate(file_root_type, false);548 _ = try pt.ensureTypeUpToDate(file_root_type);
557 } else {549 } else {
558 return pt.semaFile(file_index);550 return pt.semaFile(file_index);
559 }551 }
560}552}
561553
562/// This ensures that the state of the `Cau`, and of its corresponding `Nav` or type,554/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
563/// is fully up-to-date. Note that the type of the `Nav` may not be fully resolved.555/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
564/// Returns `error.AnalysisFail` if the `Cau` has an error.556/// free to ignore this, since the error is already registered.
565pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu.SemaError!void {557pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void {
566 const tracy = trace(@src());558 const tracy = trace(@src());
567 defer tracy.end();559 defer tracy.end();
568560
569 const zcu = pt.zcu;561 const zcu = pt.zcu;
570 const gpa = zcu.gpa;562 const gpa = zcu.gpa;
571 const ip = &zcu.intern_pool;
572563
573 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });564 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
574 const cau = ip.getCau(cau_index);
575565
576 log.debug("ensureCauAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)});566 log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
577567
578 assert(!zcu.analysis_in_progress.contains(anal_unit));568 assert(!zcu.analysis_in_progress.contains(anal_unit));
579569
580 // Determine whether or not this Cau is outdated, i.e. requires re-analysis570 // Determine whether or not this `ComptimeUnit` is outdated. For this kind of `AnalUnit`, that's
581 // even if `complete`. If a Cau is PO, we pessismistically assume that it571 // the only indicator as to whether or not analysis is required; when a `ComptimeUnit` is first
582 // *does* require re-analysis, to ensure that the Cau is definitely572 // created, it's marked as outdated.
583 // up-to-date when this function returns.573 //
584574 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
585 // If analysis occurs in a poor order, this could result in over-analysis.575 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
586 // We do our best to avoid this by the other dependency logic in this file576 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by
587 // which tries to limit re-analysis to Caus whose previously listed577 // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`.
588 // dependencies are all up-to-date.
589578
590 const cau_outdated = zcu.outdated.swapRemove(anal_unit) or579 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
591 zcu.potentially_outdated.swapRemove(anal_unit);580 zcu.potentially_outdated.swapRemove(anal_unit);
592581
593 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);582 if (was_outdated) {
594
595 if (cau_outdated) {
596 _ = zcu.outdated_ready.swapRemove(anal_unit);583 _ = zcu.outdated_ready.swapRemove(anal_unit);
584 // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.
585 if (dev.env.supports(.incremental)) {
586 zcu.deleteUnitExports(anal_unit);
587 zcu.deleteUnitReferences(anal_unit);
588 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
589 kv.value.destroy(gpa);
590 }
591 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
592 }
597 } else {593 } else {
598 // We can trust the current information about this `Cau`.594 // We can trust the current information about this unit.
599 if (prev_failed) {595 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
596 if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
597 return;
598 }
599
600 const unit_prog_node = zcu.sema_prog_node.start("comptime", 0);
601 defer unit_prog_node.end();
602
603 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
604 error.AnalysisFail => {
605 if (!zcu.failed_analysis.contains(anal_unit)) {
606 // If this unit caused the error, it would have an entry in `failed_analysis`.
607 // Since it does not, this must be a transitive failure.
608 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
609 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
610 }
600 return error.AnalysisFail;611 return error.AnalysisFail;
612 },
613 error.OutOfMemory => {
614 // TODO: it's unclear how to gracefully handle this.
615 // To report the error cleanly, we need to add a message to `failed_analysis` and a
616 // corresponding entry to `retryable_failures`; but either of these things is quite
617 // likely to OOM at this point.
618 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
619 // for reporting OOM errors without allocating.
620 return error.OutOfMemory;
621 },
622 error.GenericPoison => unreachable,
623 error.ComptimeReturn => unreachable,
624 error.ComptimeBreak => unreachable,
625 };
626}
627
628/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
629/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this
630/// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry
631/// to `transitive_failed_analysis` if necessary.
632fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
633 const zcu = pt.zcu;
634 const gpa = zcu.gpa;
635 const ip = &zcu.intern_pool;
636
637 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
638 const comptime_unit = ip.getComptimeUnit(cu_id);
639
640 log.debug("analyzeComptimeUnit {}", .{zcu.fmtAnalUnit(anal_unit)});
641
642 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
643 const file = zcu.fileByIndex(inst_resolved.file);
644 // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is
645 // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends
646 // in `ensureComptimeUnitUpToDate`.
647 if (file.status != .success_zir) return error.AnalysisFail;
648 const zir = file.zir;
649
650 // We are about to re-analyze this unit; drop its depenndencies.
651 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
652
653 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
654 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
655
656 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
657 defer analysis_arena.deinit();
658
659 var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
660 defer comptime_err_ret_trace.deinit();
661
662 var sema: Sema = .{
663 .pt = pt,
664 .gpa = gpa,
665 .arena = analysis_arena.allocator(),
666 .code = zir,
667 .owner = anal_unit,
668 .func_index = .none,
669 .func_is_naked = false,
670 .fn_ret_ty = .void,
671 .fn_ret_ty_ies = null,
672 .comptime_err_ret_trace = &comptime_err_ret_trace,
673 };
674 defer sema.deinit();
675
676 // The comptime unit declares on the source of the corresponding `comptime` declaration.
677 try sema.declareDependency(.{ .src_hash = comptime_unit.zir_index });
678
679 var block: Sema.Block = .{
680 .parent = null,
681 .sema = &sema,
682 .namespace = comptime_unit.namespace,
683 .instructions = .{},
684 .inlining = null,
685 .is_comptime = true,
686 .src_base_inst = comptime_unit.zir_index,
687 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
688 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
689 }, .no_embedded_nulls),
690 };
691 defer block.instructions.deinit(gpa);
692
693 const zir_decl = zir.getDeclaration(inst_resolved.inst);
694 assert(zir_decl.kind == .@"comptime");
695 assert(zir_decl.type_body == null);
696 assert(zir_decl.align_body == null);
697 assert(zir_decl.linksection_body == null);
698 assert(zir_decl.addrspace_body == null);
699 const value_body = zir_decl.value_body.?;
700
701 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
702 assert(result_ref == .void_value); // AstGen should always uphold this
703
704 // Nothing else to do -- for a comptime decl, all we care about are the side effects.
705 // Just make sure to `flushExports`.
706 try sema.flushExports();
707}
708
709/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
710/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
711/// free to ignore this, since the error is already registered.
712pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void {
713 const tracy = trace(@src());
714 defer tracy.end();
715
716 // TODO: document this elsewhere mlugg!
717 // For my own benefit, here's how a namespace update for a normal (non-file-root) type works:
718 // `const S = struct { ... };`
719 // We are adding or removing a declaration within this `struct`.
720 // * `S` registers a dependency on `.{ .src_hash = (declaration of S) }`
721 // * Any change to the `struct` body -- including changing a declaration -- invalidates this
722 // * `S` is re-analyzed, but notes:
723 // * there is an existing struct instance (at this `TrackedInst` with these captures)
724 // * the struct's resolution is up-to-date (because nothing about the fields changed)
725 // * so, it uses the same `struct`
726 // * but this doesn't stop it from updating the namespace!
727 // * we basically do `scanDecls`, updating the namespace as needed
728 // * so everyone lived happily ever after
729
730 const zcu = pt.zcu;
731 const gpa = zcu.gpa;
732 const ip = &zcu.intern_pool;
733
734 _ = zcu.nav_val_analysis_queued.swapRemove(nav_id);
735
736 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
737 const nav = ip.getNav(nav_id);
738
739 log.debug("ensureNavValUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
740
741 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the
742 // status is `.unresolved`, which indicates that the value is outdated because it has *never*
743 // been analyzed so far.
744 //
745 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
746 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
747 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by
748 // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`.
749
750 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
751 zcu.potentially_outdated.swapRemove(anal_unit);
752
753 const prev_failed = zcu.failed_analysis.contains(anal_unit) or
754 zcu.transitive_failed_analysis.contains(anal_unit);
755
756 if (was_outdated) {
757 dev.check(.incremental);
758 _ = zcu.outdated_ready.swapRemove(anal_unit);
759 zcu.deleteUnitExports(anal_unit);
760 zcu.deleteUnitReferences(anal_unit);
761 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
762 kv.value.destroy(gpa);
601 }763 }
602 // If it wasn't failed and wasn't marked outdated, then either...764 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
603 // * it is a type and is up-to-date, or765 } else {
604 // * it is a `comptime` decl and is up-to-date, or766 // We can trust the current information about this unit.
605 // * it is another decl and is EITHER up-to-date OR never-referenced (so unresolved)767 if (prev_failed) return error.AnalysisFail;
606 // We just need to check for that last case.768 switch (nav.status) {
607 switch (cau.owner.unwrap()) {769 .unresolved, .type_resolved => {},
608 .type, .none => return,770 .fully_resolved => return,
609 .nav => |nav| if (ip.getNav(nav).status == .resolved) return,
610 }771 }
611 }772 }
612773
613 const sema_result: SemaCauResult, const analysis_fail = if (pt.ensureCauAnalyzedInner(cau_index, cau_outdated)) |result|774 const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
614 // This `Cau` has gone from failed to success, so even if the value of the owner `Nav` didn't actually775 defer unit_prog_node.end();
615 // change, we need to invalidate the dependencies anyway.776
616 .{ .{777 const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: {
617 .invalidate_decl_val = result.invalidate_decl_val or prev_failed,778 break :res .{
618 .invalidate_decl_ref = result.invalidate_decl_ref or prev_failed,779 // If the unit has gone from failed to success, we still need to invalidate the dependencies.
619 }, false }780 result.val_changed or prev_failed,
620 else |err| switch (err) {781 false,
782 };
783 } else |err| switch (err) {
621 error.AnalysisFail => res: {784 error.AnalysisFail => res: {
622 if (!zcu.failed_analysis.contains(anal_unit)) {785 if (!zcu.failed_analysis.contains(anal_unit)) {
623 // If this `Cau` caused the error, it would have an entry in `failed_analysis`.786 // If this unit caused the error, it would have an entry in `failed_analysis`.
624 // Since it does not, this must be a transitive failure.787 // Since it does not, this must be a transitive failure.
625 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});788 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
626 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});789 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
627 }790 }
628 // We consider this `Cau` to be outdated if:791 break :res .{ !prev_failed, true };
629 // * Previous analysis succeeded; in this case, we need to re-analyze dependants to ensure
630 // they hit a transitive error here, rather than reporting a different error later (which
631 // may now be invalid).
632 // * The `Cau` is a type; in this case, the declaration site may require re-analysis to
633 // construct a valid type.
634 const outdated = !prev_failed or cau.owner.unwrap() == .type;
635 break :res .{ .{
636 .invalidate_decl_val = outdated,
637 .invalidate_decl_ref = outdated,
638 }, true };
639 },792 },
640 error.OutOfMemory => res: {793 error.OutOfMemory => {
641 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);794 // TODO: it's unclear how to gracefully handle this.
642 try zcu.retryable_failures.ensureUnusedCapacity(gpa, 1);795 // To report the error cleanly, we need to add a message to `failed_analysis` and a
643 const msg = try Zcu.ErrorMsg.create(796 // corresponding entry to `retryable_failures`; but either of these things is quite
644 gpa,797 // likely to OOM at this point.
645 .{ .base_node_inst = cau.zir_index, .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0) },798 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
646 "unable to analyze: OutOfMemory",799 // for reporting OOM errors without allocating.
647 .{},800 return error.OutOfMemory;
648 );801 },
649 zcu.retryable_failures.appendAssumeCapacity(anal_unit);802 error.GenericPoison => unreachable,
650 zcu.failed_analysis.putAssumeCapacityNoClobber(anal_unit, msg);803 error.ComptimeReturn => unreachable,
651 break :res .{ .{804 error.ComptimeBreak => unreachable,
652 .invalidate_decl_val = true,805 };
653 .invalidate_decl_ref = true,806
654 }, true };807 if (was_outdated) {
808 const dependee: InternPool.Dependee = .{ .nav_val = nav_id };
809 if (invalidate_value) {
810 // This dependency was marked as PO, meaning dependees were waiting
811 // on its analysis result, and it has turned out to be outdated.
812 // Update dependees accordingly.
813 try zcu.markDependeeOutdated(.marked_po, dependee);
814 } else {
815 // This dependency was previously PO, but turned out to be up-to-date.
816 // We do not need to queue successive analysis.
817 try zcu.markPoDependeeUpToDate(dependee);
818 }
819 }
820
821 if (new_failed) return error.AnalysisFail;
822}
823
824fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } {
825 const zcu = pt.zcu;
826 const gpa = zcu.gpa;
827 const ip = &zcu.intern_pool;
828
829 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
830 const old_nav = ip.getNav(nav_id);
831
832 log.debug("analyzeNavVal {}", .{zcu.fmtAnalUnit(anal_unit)});
833
834 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
835 const file = zcu.fileByIndex(inst_resolved.file);
836 // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is
837 // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends
838 // in `ensureComptimeUnitUpToDate`.
839 if (file.status != .success_zir) return error.AnalysisFail;
840 const zir = file.zir;
841
842 // We are about to re-analyze this unit; drop its depenndencies.
843 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
844
845 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
846 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
847
848 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
849 defer analysis_arena.deinit();
850
851 var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
852 defer comptime_err_ret_trace.deinit();
853
854 var sema: Sema = .{
855 .pt = pt,
856 .gpa = gpa,
857 .arena = analysis_arena.allocator(),
858 .code = zir,
859 .owner = anal_unit,
860 .func_index = .none,
861 .func_is_naked = false,
862 .fn_ret_ty = .void,
863 .fn_ret_ty_ies = null,
864 .comptime_err_ret_trace = &comptime_err_ret_trace,
865 };
866 defer sema.deinit();
867
868 // Every `Nav` declares a dependency on the source of the corresponding declaration.
869 try sema.declareDependency(.{ .src_hash = old_nav.analysis.?.zir_index });
870
871 // In theory, we would also add a reference to the corresponding `nav_val` unit here: there are
872 // always references in both directions between a `nav_val` and `nav_ty`. However, to save memory,
873 // these references are known implicitly. See logic in `Zcu.resolveReferences`.
874
875 var block: Sema.Block = .{
876 .parent = null,
877 .sema = &sema,
878 .namespace = old_nav.analysis.?.namespace,
879 .instructions = .{},
880 .inlining = null,
881 .is_comptime = true,
882 .src_base_inst = old_nav.analysis.?.zir_index,
883 .type_name_ctx = old_nav.fqn,
884 };
885 defer block.instructions.deinit(gpa);
886
887 const zir_decl = zir.getDeclaration(inst_resolved.inst);
888 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
889
890 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
891 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
892 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
893 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
894 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
895
896 const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {
897 // Since we have a type body, the type is resolved separately!
898 // Of course, we need to make sure we depend on it properly.
899 try sema.declareDependency(.{ .nav_ty = nav_id });
900 try pt.ensureNavTypeUpToDate(nav_id);
901 break :ty .fromInterned(ip.getNav(nav_id).status.type_resolved.type);
902 } else null;
903
904 const final_val: ?Value = if (zir_decl.value_body) |value_body| val: {
905 if (maybe_ty) |ty| {
906 // Put the resolved type into `inst_map` to be used as the result type of the init.
907 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{inst_resolved.inst});
908 sema.inst_map.putAssumeCapacity(inst_resolved.inst, Air.internedToRef(ty.toIntern()));
909 const uncoerced_result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
910 assert(sema.inst_map.remove(inst_resolved.inst));
911
912 const result_ref = try sema.coerce(&block, ty, uncoerced_result_ref, init_src);
913 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);
914 } else {
915 // Just analyze the value; we have no type to offer.
916 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
917 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);
918 }
919 } else null;
920
921 const nav_ty: Type = maybe_ty orelse final_val.?.typeOf(zcu);
922
923 // First, we must resolve the declaration's type. To do this, we analyze the type body if available,
924 // or otherwise, we analyze the value body, populating `early_val` in the process.
925
926 switch (zir_decl.kind) {
927 .@"comptime" => unreachable, // this is not a Nav
928 .unnamed_test, .@"test", .decltest => assert(nav_ty.zigTypeTag(zcu) == .@"fn"),
929 .@"usingnamespace" => {},
930 .@"const" => {},
931 .@"var" => try sema.validateVarType(
932 &block,
933 if (zir_decl.type_body != null) ty_src else init_src,
934 nav_ty,
935 zir_decl.linkage == .@"extern",
936 ),
937 }
938
939 // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine
940 // the full pointer type of this declaration.
941
942 const modifiers: Sema.NavPtrModifiers = if (zir_decl.type_body != null) m: {
943 // `analyzeNavType` (from the `ensureNavTypeUpToDate` call above) has already populated this data into
944 // the `Nav`. Load the new one, and pull the modifiers out.
945 switch (ip.getNav(nav_id).status) {
946 .unresolved => unreachable, // `analyzeNavType` will never leave us in this state
947 inline .type_resolved, .fully_resolved => |r| break :m .{
948 .alignment = r.alignment,
949 .@"linksection" = r.@"linksection",
950 .@"addrspace" = r.@"addrspace",
951 },
952 }
953 } else m: {
954 // `analyzeNavType` is essentially a stub which calls us. We are responsible for resolving this data.
955 break :m try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, nav_ty);
956 };
957
958 // Lastly, we must figure out the actual interned value to store to the `Nav`.
959 // This isn't necessarily the same as `final_val`!
960
961 const nav_val: Value = switch (zir_decl.linkage) {
962 .normal, .@"export" => switch (zir_decl.kind) {
963 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{
964 .ty = nav_ty.toIntern(),
965 .init = final_val.?.toIntern(),
966 .owner_nav = nav_id,
967 .is_threadlocal = zir_decl.is_threadlocal,
968 .is_weak_linkage = false,
969 } })),
970 else => final_val.?,
971 },
972 .@"extern" => val: {
973 assert(final_val == null); // extern decls do not have a value body
974 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
975 break :l zir.nullTerminatedString(zir_decl.lib_name);
976 } else null;
977 if (lib_name) |l| {
978 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });
979 try sema.handleExternLibName(&block, lib_name_src, l);
980 }
981 break :val .fromInterned(try pt.getExtern(.{
982 .name = old_nav.name,
983 .ty = nav_ty.toIntern(),
984 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),
985 .is_const = zir_decl.kind == .@"const",
986 .is_threadlocal = zir_decl.is_threadlocal,
987 .is_weak_linkage = false,
988 .is_dll_import = false,
989 .alignment = modifiers.alignment,
990 .@"addrspace" = modifiers.@"addrspace",
991 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction
992 .owner_nav = undefined, // ignored by `getExtern`
993 }));
655 },994 },
656 };995 };
657996
658 if (cau_outdated) {997 switch (nav_val.toIntern()) {
659 // TODO: we do not yet have separate dependencies for decl values vs types.998 .generic_poison => unreachable, // assertion failure
660 const invalidate = sema_result.invalidate_decl_val or sema_result.invalidate_decl_ref;999 .unreachable_value => unreachable, // assertion failure
661 const dependee: InternPool.Dependee = switch (cau.owner.unwrap()) {1000 else => {},
662 .none => return, // there are no dependencies on a `comptime` decl!1001 }
663 .nav => |nav_index| .{ .nav_val = nav_index },1002
664 .type => |ty| .{ .interned = ty },1003 // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type,
1004 // this resolves the type `type` (which needs no resolution), not the struct itself.
1005 try nav_ty.resolveLayout(pt);
1006
1007 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.
1008 if (zir_decl.kind == .@"usingnamespace") {
1009 if (nav_ty.toIntern() != .type_type) {
1010 return sema.fail(&block, ty_src, "expected type, found {}", .{nav_ty.fmt(pt)});
1011 }
1012 if (nav_val.toType().getNamespace(zcu) == .none) {
1013 return sema.fail(&block, ty_src, "type {} has no namespace", .{nav_val.toType().fmt(pt)});
1014 }
1015 ip.resolveNavValue(nav_id, .{
1016 .val = nav_val.toIntern(),
1017 .alignment = .none,
1018 .@"linksection" = .none,
1019 .@"addrspace" = .generic,
1020 });
1021 // TODO: usingnamespace cannot participate in incremental compilation
1022 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1023 return .{ .val_changed = true };
1024 }
1025
1026 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
1027 .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen
1028 .variable => |v| .{ v.owner_nav == nav_id, false },
1029 .@"extern" => |e| .{
1030 false,
1031 Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern",
1032 },
1033 else => .{ true, false },
1034 };
1035
1036 if (is_owned_fn) {
1037 // linksection etc are legal, except some targets do not support function alignment.
1038 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
1039 return sema.fail(&block, align_src, "target does not support function alignment", .{});
1040 }
1041 } else if (try nav_ty.comptimeOnlySema(pt)) {
1042 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
1043 const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) {
1044 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
1045 else => "comptime-only type",
1046 };
1047 if (zir_decl.align_body != null) {
1048 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
1049 }
1050 if (zir_decl.linksection_body != null) {
1051 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
1052 }
1053 if (zir_decl.addrspace_body != null) {
1054 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1055 }
1056 }
1057
1058 ip.resolveNavValue(nav_id, .{
1059 .val = nav_val.toIntern(),
1060 .alignment = modifiers.alignment,
1061 .@"linksection" = modifiers.@"linksection",
1062 .@"addrspace" = modifiers.@"addrspace",
1063 });
1064
1065 // Mark the unit as completed before evaluating the export!
1066 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1067
1068 if (zir_decl.type_body == null) {
1069 // In this situation, it's possible that we were triggered by `analyzeNavType` up the stack. In that
1070 // case, we must also signal that the *type* is now populated to make this export behave correctly.
1071 // An alternative strategy would be to just put something on the job queue to perform the export, but
1072 // this is a little more straightforward, if perhaps less elegant.
1073 _ = zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id }));
1074 }
1075
1076 if (zir_decl.linkage == .@"export") {
1077 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1078 const name_slice = zir.nullTerminatedString(zir_decl.name);
1079 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
1080 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);
1081 }
1082
1083 try sema.flushExports();
1084
1085 queue_codegen: {
1086 if (!queue_linker_work) break :queue_codegen;
1087
1088 if (!try nav_ty.hasRuntimeBitsSema(pt)) {
1089 if (zcu.comp.config.use_llvm) break :queue_codegen;
1090 if (file.mod.strip) break :queue_codegen;
1091 }
1092
1093 // This job depends on any resolve_type_fully jobs queued up before it.
1094 try zcu.comp.queueJob(.{ .codegen_nav = nav_id });
1095 }
1096
1097 switch (old_nav.status) {
1098 .unresolved, .type_resolved => return .{ .val_changed = true },
1099 .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() },
1100 }
1101}
1102
1103pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void {
1104 const tracy = trace(@src());
1105 defer tracy.end();
1106
1107 const zcu = pt.zcu;
1108 const gpa = zcu.gpa;
1109 const ip = &zcu.intern_pool;
1110
1111 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1112 const nav = ip.getNav(nav_id);
1113
1114 log.debug("ensureNavTypeUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
1115
1116 // Determine whether or not this `Nav`'s type is outdated. This also includes checking if the
1117 // status is `.unresolved`, which indicates that the value is outdated because it has *never*
1118 // been analyzed so far.
1119 //
1120 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
1121 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
1122 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by
1123 // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`.
1124
1125 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
1126 zcu.potentially_outdated.swapRemove(anal_unit);
1127
1128 const prev_failed = zcu.failed_analysis.contains(anal_unit) or
1129 zcu.transitive_failed_analysis.contains(anal_unit);
1130
1131 if (was_outdated) {
1132 dev.check(.incremental);
1133 _ = zcu.outdated_ready.swapRemove(anal_unit);
1134 zcu.deleteUnitExports(anal_unit);
1135 zcu.deleteUnitReferences(anal_unit);
1136 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1137 kv.value.destroy(gpa);
1138 }
1139 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
1140 } else {
1141 // We can trust the current information about this unit.
1142 if (prev_failed) return error.AnalysisFail;
1143 switch (nav.status) {
1144 .unresolved => {},
1145 .type_resolved, .fully_resolved => return,
1146 }
1147 }
1148
1149 const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
1150 defer unit_prog_node.end();
1151
1152 const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: {
1153 break :res .{
1154 // If the unit has gone from failed to success, we still need to invalidate the dependencies.
1155 result.type_changed or prev_failed,
1156 false,
665 };1157 };
1158 } else |err| switch (err) {
1159 error.AnalysisFail => res: {
1160 if (!zcu.failed_analysis.contains(anal_unit)) {
1161 // If this unit caused the error, it would have an entry in `failed_analysis`.
1162 // Since it does not, this must be a transitive failure.
1163 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1164 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
1165 }
1166 break :res .{ !prev_failed, true };
1167 },
1168 error.OutOfMemory => {
1169 // TODO: it's unclear how to gracefully handle this.
1170 // To report the error cleanly, we need to add a message to `failed_analysis` and a
1171 // corresponding entry to `retryable_failures`; but either of these things is quite
1172 // likely to OOM at this point.
1173 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
1174 // for reporting OOM errors without allocating.
1175 return error.OutOfMemory;
1176 },
1177 error.GenericPoison => unreachable,
1178 error.ComptimeReturn => unreachable,
1179 error.ComptimeBreak => unreachable,
1180 };
6661181
667 if (invalidate) {1182 if (was_outdated) {
1183 const dependee: InternPool.Dependee = .{ .nav_ty = nav_id };
1184 if (invalidate_type) {
668 // This dependency was marked as PO, meaning dependees were waiting1185 // This dependency was marked as PO, meaning dependees were waiting
669 // on its analysis result, and it has turned out to be outdated.1186 // on its analysis result, and it has turned out to be outdated.
670 // Update dependees accordingly.1187 // Update dependees accordingly.
...@@ -676,67 +1193,151 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu...@@ -676,67 +1193,151 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu
676 }1193 }
677 }1194 }
6781195
679 if (analysis_fail) return error.AnalysisFail;1196 if (new_failed) return error.AnalysisFail;
680}1197}
1198
1199fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } {
1200 const zcu = pt.zcu;
1201 const gpa = zcu.gpa;
1202 const ip = &zcu.intern_pool;
1203
1204 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1205 const old_nav = ip.getNav(nav_id);
1206
1207 log.debug("analyzeNavType {}", .{zcu.fmtAnalUnit(anal_unit)});
1208
1209 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1210 const file = zcu.fileByIndex(inst_resolved.file);
1211 // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is
1212 // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends
1213 // in `ensureComptimeUnitUpToDate`.
1214 if (file.status != .success_zir) return error.AnalysisFail;
1215 const zir = file.zir;
1216
1217 // We are about to re-analyze this unit; drop its depenndencies.
1218 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
1219
1220 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
1221 defer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
1222
1223 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
1224 defer analysis_arena.deinit();
1225
1226 var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
1227 defer comptime_err_ret_trace.deinit();
1228
1229 var sema: Sema = .{
1230 .pt = pt,
1231 .gpa = gpa,
1232 .arena = analysis_arena.allocator(),
1233 .code = zir,
1234 .owner = anal_unit,
1235 .func_index = .none,
1236 .func_is_naked = false,
1237 .fn_ret_ty = .void,
1238 .fn_ret_ty_ies = null,
1239 .comptime_err_ret_trace = &comptime_err_ret_trace,
1240 };
1241 defer sema.deinit();
1242
1243 // Every `Nav` declares a dependency on the source of the corresponding declaration.
1244 try sema.declareDependency(.{ .src_hash = old_nav.analysis.?.zir_index });
1245
1246 // In theory, we would also add a reference to the corresponding `nav_val` unit here: there are
1247 // always references in both directions between a `nav_val` and `nav_ty`. However, to save memory,
1248 // these references are known implicitly. See logic in `Zcu.resolveReferences`.
1249
1250 var block: Sema.Block = .{
1251 .parent = null,
1252 .sema = &sema,
1253 .namespace = old_nav.analysis.?.namespace,
1254 .instructions = .{},
1255 .inlining = null,
1256 .is_comptime = true,
1257 .src_base_inst = old_nav.analysis.?.zir_index,
1258 .type_name_ctx = old_nav.fqn,
1259 };
1260 defer block.instructions.deinit(gpa);
1261
1262 const zir_decl = zir.getDeclaration(inst_resolved.inst);
1263 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
1264
1265 const type_body = zir_decl.type_body orelse {
1266 // The type of this `Nav` is inferred from the value.
1267 // In other words, this `nav_ty` depends on the corresponding `nav_val`.
1268 try sema.declareDependency(.{ .nav_val = nav_id });
1269 try pt.ensureNavValUpToDate(nav_id);
1270 // Note that the above call, if it did any work, has removed our `analysis_in_progress` entry for us.
1271 // (Our `defer` will run anyway, but it does nothing in this case.)
1272
1273 // There's not a great way for us to know whether the type actually changed.
1274 // For instance, perhaps the `nav_val` was already up-to-date, but this `nav_ty` is being
1275 // analyzed because this declaration had a type annotation on the *previous* update.
1276 // However, such cases are rare, and it's not unreasonable to re-analyze in them; and in
1277 // other cases where we get here, it's because the `nav_val` was already re-analyzed and
1278 // is outdated.
1279 return .{ .type_changed = true };
1280 };
6811281
682fn ensureCauAnalyzedInner(1282 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
683 pt: Zcu.PerThread,
684 cau_index: InternPool.Cau.Index,
685 cau_outdated: bool,
686) Zcu.SemaError!SemaCauResult {
687 const zcu = pt.zcu;
688 const ip = &zcu.intern_pool;
6891283
690 const cau = ip.getCau(cau_index);1284 const resolved_ty: Type = ty: {
691 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });1285 const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_resolved.inst);
1286 const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
1287 break :ty .fromInterned(type_ref.toInterned().?);
1288 };
6921289
693 const inst_info = cau.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1290 // In the case where the type is specified, this function is also responsible for resolving
1291 // the pointer modifiers, i.e. alignment, linksection, addrspace.
1292 const modifiers = try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, resolved_ty);
6941293
695 // TODO: document this elsewhere mlugg!1294 // Usually, we can infer this information from the resolved `Nav` value; see `Zcu.navValIsConst`.
696 // For my own benefit, here's how a namespace update for a normal (non-file-root) type works:1295 // However, since we don't have one, we need to quickly check the ZIR to figure this out.
697 // `const S = struct { ... };`1296 const is_const = switch (zir_decl.kind) {
698 // We are adding or removing a declaration within this `struct`.1297 .@"comptime" => unreachable,
699 // * `S` registers a dependency on `.{ .src_hash = (declaration of S) }`1298 .unnamed_test, .@"test", .decltest, .@"usingnamespace", .@"const" => true,
700 // * Any change to the `struct` body -- including changing a declaration -- invalidates this1299 .@"var" => false,
701 // * `S` is re-analyzed, but notes:1300 };
702 // * there is an existing struct instance (at this `TrackedInst` with these captures)
703 // * the struct's `Cau` is up-to-date (because nothing about the fields changed)
704 // * so, it uses the same `struct`
705 // * but this doesn't stop it from updating the namespace!
706 // * we basically do `scanDecls`, updating the namespace as needed
707 // * so everyone lived happily ever after
7081301
709 if (zcu.fileByIndex(inst_info.file).status != .success_zir) {1302 const is_extern_decl = zir_decl.linkage == .@"extern";
710 return error.AnalysisFail;1303
711 }1304 // Now for the question of the day: are the type and modifiers the same as before?
1305 // If they are, then we should actually keep the `Nav` as `fully_resolved` if it currently is.
1306 // That's because `analyzeNavVal` will later want to look at the resolved value to figure out
1307 // whether it's changed: if we threw that data away now, it would have to assume that the value
1308 // had changed, potentially spinning off loads of unnecessary re-analysis!
1309 const changed = switch (old_nav.status) {
1310 .unresolved => true,
1311 .type_resolved => |r| r.type != resolved_ty.toIntern() or
1312 r.alignment != modifiers.alignment or
1313 r.@"linksection" != modifiers.@"linksection" or
1314 r.@"addrspace" != modifiers.@"addrspace" or
1315 r.is_const != is_const or
1316 r.is_extern_decl != is_extern_decl,
1317 .fully_resolved => |r| ip.typeOf(r.val) != resolved_ty.toIntern() or
1318 r.alignment != modifiers.alignment or
1319 r.@"linksection" != modifiers.@"linksection" or
1320 r.@"addrspace" != modifiers.@"addrspace" or
1321 zcu.navValIsConst(r.val) != is_const or
1322 (old_nav.getExtern(ip) != null) != is_extern_decl,
1323 };
7121324
713 // `cau_outdated` can be true in the initial update for `comptime` declarations,1325 if (!changed) return .{ .type_changed = false };
714 // so this isn't a `dev.check`.
715 if (cau_outdated and dev.env.supports(.incremental)) {
716 // The exports this `Cau` performs will be re-discovered, so we remove them here
717 // prior to re-analysis.
718 zcu.deleteUnitExports(anal_unit);
719 zcu.deleteUnitReferences(anal_unit);
720 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
721 kv.value.destroy(zcu.gpa);
722 }
723 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
724 }
7251326
726 const decl_prog_node = zcu.sema_prog_node.start(switch (cau.owner.unwrap()) {1327 ip.resolveNavType(nav_id, .{
727 .nav => |nav| ip.getNav(nav).fqn.toSlice(ip),1328 .type = resolved_ty.toIntern(),
728 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),1329 .alignment = modifiers.alignment,
729 .none => "comptime",1330 .@"linksection" = modifiers.@"linksection",
730 }, 0);1331 .@"addrspace" = modifiers.@"addrspace",
731 defer decl_prog_node.end();1332 .is_const = is_const,
1333 .is_threadlocal = zir_decl.is_threadlocal,
1334 .is_extern_decl = is_extern_decl,
1335 });
7321336
733 return pt.semaCau(cau_index) catch |err| switch (err) {1337 return .{ .type_changed = true };
734 error.GenericPoison, error.ComptimeBreak, error.ComptimeReturn => unreachable,
735 error.AnalysisFail, error.OutOfMemory => |e| return e,
736 };
737}1338}
7381339
739pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {1340pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {
740 dev.check(.sema);1341 dev.check(.sema);
7411342
742 const tracy = trace(@src());1343 const tracy = trace(@src());
...@@ -746,35 +1347,43 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -746,35 +1347,43 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
746 const gpa = zcu.gpa;1347 const gpa = zcu.gpa;
747 const ip = &zcu.intern_pool;1348 const ip = &zcu.intern_pool;
7481349
1350 _ = zcu.func_body_analysis_queued.swapRemove(maybe_coerced_func_index);
1351
749 // We only care about the uncoerced function.1352 // We only care about the uncoerced function.
750 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);1353 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);
751 const anal_unit = AnalUnit.wrap(.{ .func = func_index });1354 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });
7521355
753 log.debug("ensureFuncBodyAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)});1356 log.debug("ensureFuncBodyUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
7541357
755 const func = zcu.funcInfo(maybe_coerced_func_index);1358 const func = zcu.funcInfo(maybe_coerced_func_index);
7561359
757 const func_outdated = zcu.outdated.swapRemove(anal_unit) or1360 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
758 zcu.potentially_outdated.swapRemove(anal_unit);1361 zcu.potentially_outdated.swapRemove(anal_unit);
7591362
760 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);1363 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);
7611364
762 if (func_outdated) {1365 if (was_outdated) {
1366 dev.check(.incremental);
763 _ = zcu.outdated_ready.swapRemove(anal_unit);1367 _ = zcu.outdated_ready.swapRemove(anal_unit);
1368 zcu.deleteUnitExports(anal_unit);
1369 zcu.deleteUnitReferences(anal_unit);
1370 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1371 kv.value.destroy(gpa);
1372 }
1373 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
764 } else {1374 } else {
765 // We can trust the current information about this function.1375 // We can trust the current information about this function.
766 if (prev_failed) {1376 if (prev_failed) {
767 return error.AnalysisFail;1377 return error.AnalysisFail;
768 }1378 }
769 switch (func.analysisUnordered(ip).state) {1379 if (func.analysisUnordered(ip).is_analyzed) return;
770 .unreferenced => {}, // this is the first reference
771 .queued => {}, // we're waiting on first-time analysis
772 .analyzed => return, // up-to-date
773 }
774 }1380 }
7751381
776 const ies_outdated, const analysis_fail = if (pt.ensureFuncBodyAnalyzedInner(func_index, func_outdated)) |result|1382 const func_prog_node = zcu.sema_prog_node.start(ip.getNav(func.owner_nav).fqn.toSlice(ip), 0);
777 .{ result.ies_outdated, false }1383 defer func_prog_node.end();
1384
1385 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result|
1386 .{ prev_failed or result.ies_outdated, false }
778 else |err| switch (err) {1387 else |err| switch (err) {
779 error.AnalysisFail => res: {1388 error.AnalysisFail => res: {
780 if (!zcu.failed_analysis.contains(anal_unit)) {1389 if (!zcu.failed_analysis.contains(anal_unit)) {
...@@ -788,10 +1397,18 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -788,10 +1397,18 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
788 // a different error later (which may now be invalid).1397 // a different error later (which may now be invalid).
789 break :res .{ !prev_failed, true };1398 break :res .{ !prev_failed, true };
790 },1399 },
791 error.OutOfMemory => return error.OutOfMemory, // TODO: graceful handling like `ensureCauAnalyzed`1400 error.OutOfMemory => {
1401 // TODO: it's unclear how to gracefully handle this.
1402 // To report the error cleanly, we need to add a message to `failed_analysis` and a
1403 // corresponding entry to `retryable_failures`; but either of these things is quite
1404 // likely to OOM at this point.
1405 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
1406 // for reporting OOM errors without allocating.
1407 return error.OutOfMemory;
1408 },
792 };1409 };
7931410
794 if (func_outdated) {1411 if (was_outdated) {
795 if (ies_outdated) {1412 if (ies_outdated) {
796 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index });1413 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index });
797 } else {1414 } else {
...@@ -799,13 +1416,12 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -799,13 +1416,12 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
799 }1416 }
800 }1417 }
8011418
802 if (analysis_fail) return error.AnalysisFail;1419 if (new_failed) return error.AnalysisFail;
803}1420}
8041421
805fn ensureFuncBodyAnalyzedInner(1422fn analyzeFuncBody(
806 pt: Zcu.PerThread,1423 pt: Zcu.PerThread,
807 func_index: InternPool.Index,1424 func_index: InternPool.Index,
808 func_outdated: bool,
809) Zcu.SemaError!struct { ies_outdated: bool } {1425) Zcu.SemaError!struct { ies_outdated: bool } {
810 const zcu = pt.zcu;1426 const zcu = pt.zcu;
811 const gpa = zcu.gpa;1427 const gpa = zcu.gpa;
...@@ -820,8 +1436,8 @@ fn ensureFuncBodyAnalyzedInner(...@@ -820,8 +1436,8 @@ fn ensureFuncBodyAnalyzedInner(
8201436
821 if (func.generic_owner == .none) {1437 if (func.generic_owner == .none) {
822 // Among another things, this ensures that the function's `zir_body_inst` is correct.1438 // Among another things, this ensures that the function's `zir_body_inst` is correct.
823 try pt.ensureCauAnalyzed(ip.getNav(func.owner_nav).analysis_owner.unwrap().?);1439 try pt.ensureNavValUpToDate(func.owner_nav);
824 if (ip.getNav(func.owner_nav).status.resolved.val != func_index) {1440 if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) {
825 // This function is no longer referenced! There's no point in re-analyzing it.1441 // This function is no longer referenced! There's no point in re-analyzing it.
826 // Just mark a transitive failure and move on.1442 // Just mark a transitive failure and move on.
827 return error.AnalysisFail;1443 return error.AnalysisFail;
...@@ -829,8 +1445,8 @@ fn ensureFuncBodyAnalyzedInner(...@@ -829,8 +1445,8 @@ fn ensureFuncBodyAnalyzedInner(
829 } else {1445 } else {
830 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;1446 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
831 // Among another things, this ensures that the function's `zir_body_inst` is correct.1447 // Among another things, this ensures that the function's `zir_body_inst` is correct.
832 try pt.ensureCauAnalyzed(ip.getNav(go_nav).analysis_owner.unwrap().?);1448 try pt.ensureNavValUpToDate(go_nav);
833 if (ip.getNav(go_nav).status.resolved.val != func.generic_owner) {1449 if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) {
834 // The generic owner is no longer referenced, so this function is also unreferenced.1450 // The generic owner is no longer referenced, so this function is also unreferenced.
835 // There's no point in re-analyzing it. Just mark a transitive failure and move on.1451 // There's no point in re-analyzing it. Just mark a transitive failure and move on.
836 return error.AnalysisFail;1452 return error.AnalysisFail;
...@@ -844,38 +1460,13 @@ fn ensureFuncBodyAnalyzedInner(...@@ -844,38 +1460,13 @@ fn ensureFuncBodyAnalyzedInner(
844 else1460 else
845 .none;1461 .none;
8461462
847 if (func_outdated) {1463 log.debug("analyze and generate fn body {}", .{zcu.fmtAnalUnit(anal_unit)});
848 dev.check(.incremental);
849 zcu.deleteUnitExports(anal_unit);
850 zcu.deleteUnitReferences(anal_unit);
851 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
852 kv.value.destroy(gpa);
853 }
854 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
855 }
856
857 if (!func_outdated) {
858 // We can trust the current information about this function.
859 if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) {
860 return error.AnalysisFail;
861 }
862 switch (func.analysisUnordered(ip).state) {
863 .unreferenced => {}, // this is the first reference
864 .queued => {}, // we're waiting on first-time analysis
865 .analyzed => return .{ .ies_outdated = false }, // up-to-date
866 }
867 }
868
869 log.debug("analyze and generate fn body {}; reason='{s}'", .{
870 zcu.fmtAnalUnit(anal_unit),
871 if (func_outdated) "outdated" else "never analyzed",
872 });
8731464
874 var air = try pt.analyzeFnBody(func_index);1465 var air = try pt.analyzeFnBodyInner(func_index);
875 errdefer air.deinit(gpa);1466 errdefer air.deinit(gpa);
8761467
877 const ies_outdated = func_outdated and1468 const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or
878 (!func.analysisUnordered(ip).inferred_error_set or func.resolvedErrorSetUnordered(ip) != old_resolved_ies);1469 func.resolvedErrorSetUnordered(ip) != old_resolved_ies;
8791470
880 const comp = zcu.comp;1471 const comp = zcu.comp;
8811472
...@@ -1043,12 +1634,11 @@ fn createFileRootStruct(...@@ -1043,12 +1634,11 @@ fn createFileRootStruct(
10431634
1044 wip_ty.setName(ip, try file.internFullyQualifiedName(pt));1635 wip_ty.setName(ip, try file.internFullyQualifiedName(pt));
1045 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;1636 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
1046 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, namespace_index, wip_ty.index);
10471637
1048 if (zcu.comp.incremental) {1638 if (zcu.comp.incremental) {
1049 try ip.addDependency(1639 try ip.addDependency(
1050 gpa,1640 gpa,
1051 AnalUnit.wrap(.{ .cau = new_cau_index }),1641 .wrap(.{ .type = wip_ty.index }),
1052 .{ .src_hash = tracked_inst },1642 .{ .src_hash = tracked_inst },
1053 );1643 );
1054 }1644 }
...@@ -1062,7 +1652,7 @@ fn createFileRootStruct(...@@ -1062,7 +1652,7 @@ fn createFileRootStruct(
1062 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });1652 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
1063 }1653 }
1064 zcu.setFileRootType(file_index, wip_ty.index);1654 zcu.setFileRootType(file_index, wip_ty.index);
1065 return wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index);1655 return wip_ty.finish(ip, namespace_index);
1066}1656}
10671657
1068/// Re-scan the namespace of a file's root struct type on an incremental update.1658/// Re-scan the namespace of a file's root struct type on an incremental update.
...@@ -1155,294 +1745,6 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {...@@ -1155,294 +1745,6 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
1155 }1745 }
1156}1746}
11571747
1158const SemaCauResult = packed struct {
1159 /// Whether the value of a `decl_val` of the corresponding Nav changed.
1160 invalidate_decl_val: bool,
1161 /// Whether the type of a `decl_ref` of the corresponding Nav changed.
1162 invalidate_decl_ref: bool,
1163};
1164
1165/// Performs semantic analysis on the given `Cau`, storing results to its owner `Nav` if needed.
1166/// If analysis fails, returns `error.AnalysisFail`, storing an error in `zcu.failed_analysis` unless
1167/// the error is transitive.
1168/// On success, returns information about whether the `Nav` value changed.
1169fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1170 const zcu = pt.zcu;
1171 const gpa = zcu.gpa;
1172 const ip = &zcu.intern_pool;
1173
1174 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });
1175
1176 const cau = ip.getCau(cau_index);
1177 const inst_info = cau.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1178 const file = zcu.fileByIndex(inst_info.file);
1179 const zir = file.zir;
1180
1181 if (file.status != .success_zir) {
1182 return error.AnalysisFail;
1183 }
1184
1185 // We are about to re-analyze this `Cau`; drop its depenndencies.
1186 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
1187
1188 switch (cau.owner.unwrap()) {
1189 .none => {}, // `comptime` decl -- we will re-analyze its body.
1190 .nav => {}, // Other decl -- we will re-analyze its value.
1191 .type => |ty| {
1192 // This is an incremental update, and this type is being re-analyzed because it is outdated.
1193 // Create a new type in its place, and mark the old one as outdated so that use sites will
1194 // be re-analyzed and discover an up-to-date type.
1195 const new_ty = try pt.ensureTypeUpToDate(ty, true);
1196 assert(new_ty != ty);
1197 return .{
1198 .invalidate_decl_val = true,
1199 .invalidate_decl_ref = true,
1200 };
1201 },
1202 }
1203
1204 const is_usingnamespace = switch (cau.owner.unwrap()) {
1205 .nav => |nav| ip.getNav(nav).is_usingnamespace,
1206 .none, .type => false,
1207 };
1208
1209 log.debug("semaCau {}", .{zcu.fmtAnalUnit(anal_unit)});
1210
1211 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
1212 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
1213
1214 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
1215 defer analysis_arena.deinit();
1216
1217 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);
1218 defer comptime_err_ret_trace.deinit();
1219
1220 var sema: Sema = .{
1221 .pt = pt,
1222 .gpa = gpa,
1223 .arena = analysis_arena.allocator(),
1224 .code = zir,
1225 .owner = anal_unit,
1226 .func_index = .none,
1227 .func_is_naked = false,
1228 .fn_ret_ty = Type.void,
1229 .fn_ret_ty_ies = null,
1230 .comptime_err_ret_trace = &comptime_err_ret_trace,
1231 };
1232 defer sema.deinit();
1233
1234 // Every `Cau` has a dependency on the source of its own ZIR instruction.
1235 try sema.declareDependency(.{ .src_hash = cau.zir_index });
1236
1237 var block: Sema.Block = .{
1238 .parent = null,
1239 .sema = &sema,
1240 .namespace = cau.namespace,
1241 .instructions = .{},
1242 .inlining = null,
1243 .is_comptime = true,
1244 .src_base_inst = cau.zir_index,
1245 .type_name_ctx = switch (cau.owner.unwrap()) {
1246 .nav => |nav| ip.getNav(nav).fqn,
1247 .type => |ty| Type.fromInterned(ty).containerTypeName(ip),
1248 .none => try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
1249 Type.fromInterned(zcu.namespacePtr(cau.namespace).owner_type).containerTypeName(ip).fmt(ip),
1250 }, .no_embedded_nulls),
1251 },
1252 };
1253 defer block.instructions.deinit(gpa);
1254
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 };
1259
1260 // We have to fetch this state before resolving the body because of the `nav_already_populated`
1261 // case below. We might change the language in future so that align/linksection/etc for functions
1262 // work in a way more in line with other declarations, in which case that logic will go away.
1263 const old_nav_info = switch (cau.owner.unwrap()) {
1264 .none, .type => undefined, // we'll never use `old_nav_info`
1265 .nav => |nav| ip.getNav(nav),
1266 };
1267
1268 const result_ref = try sema.resolveInlineBody(&block, decl_bodies.value_body, inst_info.inst);
1269
1270 const nav_index = switch (cau.owner.unwrap()) {
1271 .none => {
1272 // This is a `comptime` decl, so we are done -- the side effects are all we care about.
1273 // Just make sure to `flushExports`.
1274 try sema.flushExports();
1275 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1276 return .{
1277 .invalidate_decl_val = false,
1278 .invalidate_decl_ref = false,
1279 };
1280 },
1281 .nav => |nav| nav, // We will resolve this `Nav` below.
1282 .type => unreachable, // Handled at top of function.
1283 };
1284
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
1294 switch (decl_val.toIntern()) {
1295 .generic_poison => unreachable, // assertion failure
1296 .unreachable_value => unreachable, // assertion failure
1297 else => {},
1298 }
1299
1300 // This resolves the type of the resolved value, not that value itself. If `decl_val` is a struct type,
1301 // this resolves the type `type` (which needs no resolution), not the struct itself.
1302 try decl_ty.resolveLayout(pt);
1303
1304 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.
1305 if (is_usingnamespace) {
1306 if (decl_ty.toIntern() != .type_type) {
1307 return sema.fail(&block, ty_src, "expected type, found {}", .{decl_ty.fmt(pt)});
1308 }
1309 if (decl_val.toType().getNamespace(zcu) == .none) {
1310 return sema.fail(&block, ty_src, "type {} has no namespace", .{decl_val.toType().fmt(pt)});
1311 }
1312 ip.resolveNavValue(nav_index, .{
1313 .val = decl_val.toIntern(),
1314 .alignment = .none,
1315 .@"linksection" = .none,
1316 .@"addrspace" = .generic,
1317 });
1318 // TODO: usingnamespace cannot participate in incremental compilation
1319 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1320 return .{
1321 .invalidate_decl_val = true,
1322 .invalidate_decl_ref = true,
1323 };
1324 }
1325
1326 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(decl_val.toIntern())) {
1327 .func => |f| .{ true, f.owner_nav == nav_index }, // note that this lets function aliases reach codegen
1328 .variable => |v| .{ v.owner_nav == nav_index, false },
1329 .@"extern" => |e| .{ false, Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" },
1330 else => .{ true, false },
1331 };
1332
1333 // 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 };
1374
1375 if (is_owned_fn) {
1376 // 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())) {
1378 return sema.fail(&block, align_src, "target does not support function alignment", .{});
1379 }
1380 } else if (try decl_ty.comptimeOnlySema(pt)) {
1381 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
1382 const reason: []const u8 = switch (ip.indexToKey(decl_val.toIntern())) {
1383 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
1384 else => "comptime-only type",
1385 };
1386 if (decl_bodies.align_body != null) {
1387 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
1388 }
1389 if (decl_bodies.linksection_body != null) {
1390 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
1391 }
1392 if (decl_bodies.addrspace_body != null) {
1393 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1394 }
1395 }
1396
1397 ip.resolveNavValue(nav_index, .{
1398 .val = decl_val.toIntern(),
1399 .alignment = alignment,
1400 .@"linksection" = @"linksection",
1401 .@"addrspace" = @"addrspace",
1402 });
1403
1404 // Mark the `Cau` as completed before evaluating the export!
1405 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1406
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).?);
1410 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
1411 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_index);
1412 }
1413
1414 try sema.flushExports();
1415
1416 queue_codegen: {
1417 if (!queue_linker_work) break :queue_codegen;
1418
1419 if (!try decl_ty.hasRuntimeBitsSema(pt)) {
1420 if (zcu.comp.config.use_llvm) break :queue_codegen;
1421 if (file.mod.strip) break :queue_codegen;
1422 }
1423
1424 // This job depends on any resolve_type_fully jobs queued up before it.
1425 try zcu.comp.queueJob(.{ .codegen_nav = nav_index });
1426 }
1427
1428 switch (old_nav_info.status) {
1429 .unresolved => return .{
1430 .invalidate_decl_val = true,
1431 .invalidate_decl_ref = true,
1432 },
1433 .resolved => |old| {
1434 const new = ip.getNav(nav_index).status.resolved;
1435 return .{
1436 .invalidate_decl_val = new.val != old.val,
1437 .invalidate_decl_ref = ip.typeOf(new.val) != ip.typeOf(old.val) or
1438 new.alignment != old.alignment or
1439 new.@"linksection" != old.@"linksection" or
1440 new.@"addrspace" != old.@"addrspace",
1441 };
1442 },
1443 }
1444}
1445
1446pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {1748pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
1447 const zcu = pt.zcu;1749 const zcu = pt.zcu;
1448 const gpa = zcu.gpa;1750 const gpa = zcu.gpa;
...@@ -1813,45 +2115,42 @@ pub fn scanNamespace(...@@ -1813,45 +2115,42 @@ pub fn scanNamespace(
18132115
1814 // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather2116 // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather
1815 // than their name. We'll build an efficient mapping now, then discard the current `decls`.2117 // than their name. We'll build an efficient mapping now, then discard the current `decls`.
1816 // We map to the `Cau`, since not every declaration has a `Nav`.2118 // We map to the `AnalUnit`, since not every declaration has a `Nav`.
1817 var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index) = .empty;2119 var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.AnalUnit) = .empty;
1818 defer existing_by_inst.deinit(gpa);2120 defer existing_by_inst.deinit(gpa);
18192121
1820 try existing_by_inst.ensureTotalCapacity(gpa, @intCast(2122 try existing_by_inst.ensureTotalCapacity(gpa, @intCast(
1821 namespace.pub_decls.count() + namespace.priv_decls.count() +2123 namespace.pub_decls.count() + namespace.priv_decls.count() +
1822 namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len +2124 namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len +
1823 namespace.other_decls.items.len,2125 namespace.comptime_decls.items.len +
2126 namespace.test_decls.items.len,
1824 ));2127 ));
18252128
1826 for (namespace.pub_decls.keys()) |nav| {2129 for (namespace.pub_decls.keys()) |nav| {
1827 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;2130 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1828 const zir_index = ip.getCau(cau_index).zir_index;2131 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1829 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1830 }2132 }
1831 for (namespace.priv_decls.keys()) |nav| {2133 for (namespace.priv_decls.keys()) |nav| {
1832 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;2134 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1833 const zir_index = ip.getCau(cau_index).zir_index;2135 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1834 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1835 }2136 }
1836 for (namespace.pub_usingnamespace.items) |nav| {2137 for (namespace.pub_usingnamespace.items) |nav| {
1837 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;2138 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1838 const zir_index = ip.getCau(cau_index).zir_index;2139 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1839 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1840 }2140 }
1841 for (namespace.priv_usingnamespace.items) |nav| {2141 for (namespace.priv_usingnamespace.items) |nav| {
1842 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;2142 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1843 const zir_index = ip.getCau(cau_index).zir_index;2143 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1844 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);2144 }
1845 }2145 for (namespace.comptime_decls.items) |cu| {
1846 for (namespace.other_decls.items) |cau_index| {2146 const zir_index = ip.getComptimeUnit(cu).zir_index;
1847 const cau = ip.getCau(cau_index);2147 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .@"comptime" = cu }));
1848 existing_by_inst.putAssumeCapacityNoClobber(cau.zir_index, cau_index);2148 }
1849 // If this is a test, it'll be re-added to `test_functions` later on2149 for (namespace.test_decls.items) |nav| {
1850 // if still alive. Remove it for now.2150 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1851 switch (cau.owner.unwrap()) {2151 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1852 .none, .type => {},2152 // This test will be re-added to `test_functions` later on if it's still alive. Remove it for now.
1853 .nav => |nav| _ = zcu.test_functions.swapRemove(nav),2153 _ = zcu.test_functions.swapRemove(nav);
1854 }
1855 }2154 }
18562155
1857 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;2156 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
...@@ -1861,7 +2160,8 @@ pub fn scanNamespace(...@@ -1861,7 +2160,8 @@ pub fn scanNamespace(
1861 namespace.priv_decls.clearRetainingCapacity();2160 namespace.priv_decls.clearRetainingCapacity();
1862 namespace.pub_usingnamespace.clearRetainingCapacity();2161 namespace.pub_usingnamespace.clearRetainingCapacity();
1863 namespace.priv_usingnamespace.clearRetainingCapacity();2162 namespace.priv_usingnamespace.clearRetainingCapacity();
1864 namespace.other_decls.clearRetainingCapacity();2163 namespace.comptime_decls.clearRetainingCapacity();
2164 namespace.test_decls.clearRetainingCapacity();
18652165
1866 var scan_decl_iter: ScanDeclIter = .{2166 var scan_decl_iter: ScanDeclIter = .{
1867 .pt = pt,2167 .pt = pt,
...@@ -1883,7 +2183,7 @@ const ScanDeclIter = struct {...@@ -1883,7 +2183,7 @@ const ScanDeclIter = struct {
1883 pt: Zcu.PerThread,2183 pt: Zcu.PerThread,
1884 namespace_index: Zcu.Namespace.Index,2184 namespace_index: Zcu.Namespace.Index,
1885 seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),2185 seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
1886 existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index),2186 existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.AnalUnit),
1887 /// Decl scanning is run in two passes, so that we can detect when a generated2187 /// Decl scanning is run in two passes, so that we can detect when a generated
1888 /// name would clash with an explicit name and use a different one.2188 /// name would clash with an explicit name and use a different one.
1889 pass: enum { named, unnamed },2189 pass: enum { named, unnamed },
...@@ -1919,64 +2219,41 @@ const ScanDeclIter = struct {...@@ -1919,64 +2219,41 @@ const ScanDeclIter = struct {
1919 const zir = file.zir;2219 const zir = file.zir;
1920 const ip = &zcu.intern_pool;2220 const ip = &zcu.intern_pool;
19212221
1922 const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;2222 const decl = zir.getDeclaration(decl_inst);
1923 const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
1924 const declaration = extra.data;
19252223
1926 const Kind = enum { @"comptime", @"usingnamespace", @"test", named };2224 const maybe_name: InternPool.OptionalNullTerminatedString = switch (decl.kind) {
19272225 .@"comptime" => name: {
1928 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (declaration.name) {
1929 .@"comptime" => info: {
1930 if (iter.pass != .unnamed) return;2226 if (iter.pass != .unnamed) return;
1931 break :info .{2227 break :name .none;
1932 .none,
1933 .@"comptime",
1934 false,
1935 };
1936 },2228 },
1937 .@"usingnamespace" => info: {2229 .@"usingnamespace" => name: {
1938 if (iter.pass != .unnamed) return;2230 if (iter.pass != .unnamed) return;
1939 const i = iter.usingnamespace_index;2231 const i = iter.usingnamespace_index;
1940 iter.usingnamespace_index += 1;2232 iter.usingnamespace_index += 1;
1941 break :info .{2233 break :name (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional();
1942 (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional(),
1943 .@"usingnamespace",
1944 false,
1945 };
1946 },2234 },
1947 .unnamed_test => info: {2235 .unnamed_test => name: {
1948 if (iter.pass != .unnamed) return;2236 if (iter.pass != .unnamed) return;
1949 const i = iter.unnamed_test_index;2237 const i = iter.unnamed_test_index;
1950 iter.unnamed_test_index += 1;2238 iter.unnamed_test_index += 1;
1951 break :info .{2239 break :name (try iter.avoidNameConflict("test_{d}", .{i})).toOptional();
1952 (try iter.avoidNameConflict("test_{d}", .{i})).toOptional(),
1953 .@"test",
1954 false,
1955 };
1956 },2240 },
1957 _ => if (declaration.name.isNamedTest(zir)) info: {2241 .@"test", .decltest => |kind| name: {
1958 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.2242 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
1959 if (iter.pass != .unnamed) return;2243 if (iter.pass != .unnamed) return;
1960 const prefix = if (declaration.flags.test_is_decltest) "decltest" else "test";2244 const prefix = @tagName(kind);
1961 break :info .{2245 break :name (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(decl.name) })).toOptional();
1962 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(declaration.name.toString(zir).?) })).toOptional(),2246 },
1963 .@"test",2247 .@"const", .@"var" => name: {
1964 true,
1965 };
1966 } else info: {
1967 if (iter.pass != .named) return;2248 if (iter.pass != .named) return;
1968 const name = try ip.getOrPutString(2249 const name = try ip.getOrPutString(
1969 gpa,2250 gpa,
1970 pt.tid,2251 pt.tid,
1971 zir.nullTerminatedString(declaration.name.toString(zir).?),2252 zir.nullTerminatedString(decl.name),
1972 .no_embedded_nulls,2253 .no_embedded_nulls,
1973 );2254 );
1974 try iter.seen_decls.putNoClobber(gpa, name, {});2255 try iter.seen_decls.putNoClobber(gpa, name, {});
1975 break :info .{2256 break :name name.toOptional();
1976 name.toOptional(),
1977 .named,
1978 false,
1979 };
1980 },2257 },
1981 };2258 };
19822259
...@@ -1985,60 +2262,59 @@ const ScanDeclIter = struct {...@@ -1985,60 +2262,59 @@ const ScanDeclIter = struct {
1985 .inst = decl_inst,2262 .inst = decl_inst,
1986 });2263 });
19872264
1988 const existing_cau = iter.existing_by_inst.get(tracked_inst);2265 const existing_unit = iter.existing_by_inst.get(tracked_inst);
2266
2267 const unit, const want_analysis = switch (decl.kind) {
2268 .@"comptime" => unit: {
2269 const cu = if (existing_unit) |eu|
2270 eu.unwrap().@"comptime"
2271 else
2272 try ip.createComptimeUnit(gpa, pt.tid, tracked_inst, namespace_index);
19892273
1990 const cau, const want_analysis = switch (kind) {2274 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
1991 .@"comptime" => cau: {
1992 const cau = existing_cau orelse try ip.createComptimeCau(gpa, pt.tid, tracked_inst, namespace_index);
19932275
1994 try namespace.other_decls.append(gpa, cau);2276 try namespace.comptime_decls.append(gpa, cu);
19952277
1996 if (existing_cau == null) {2278 if (existing_unit == null) {
1997 // For a `comptime` declaration, whether to analyze is based solely on whether the2279 // For a `comptime` declaration, whether to analyze is based solely on whether the unit
1998 // `Cau` is outdated. So, add this one to `outdated` and `outdated_ready` if not already.2280 // is outdated. So, add this fresh one to `outdated` and `outdated_ready`.
1999 const unit = AnalUnit.wrap(.{ .cau = cau });2281 try zcu.outdated.ensureUnusedCapacity(gpa, 1);
2000 if (zcu.potentially_outdated.fetchSwapRemove(unit)) |kv| {2282 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);
2001 try zcu.outdated.ensureUnusedCapacity(gpa, 1);2283 zcu.outdated.putAssumeCapacityNoClobber(unit, 0);
2002 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);2284 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2003 zcu.outdated.putAssumeCapacityNoClobber(unit, kv.value);
2004 if (kv.value == 0) { // no PO deps
2005 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2006 }
2007 } else if (!zcu.outdated.contains(unit)) {
2008 try zcu.outdated.ensureUnusedCapacity(gpa, 1);
2009 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);
2010 zcu.outdated.putAssumeCapacityNoClobber(unit, 0);
2011 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2012 }
2013 }2285 }
20142286
2015 break :cau .{ cau, true };2287 break :unit .{ unit, true };
2016 },2288 },
2017 else => cau: {2289 else => unit: {
2018 const name = maybe_name.unwrap().?;2290 const name = maybe_name.unwrap().?;
2019 const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);2291 const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);
2020 const cau, const nav = if (existing_cau) |cau_index| cau_nav: {2292 const nav = if (existing_unit) |eu|
2021 const nav_index = ip.getCau(cau_index).owner.unwrap().nav;2293 eu.unwrap().nav_val
2022 const nav = ip.getNav(nav_index);2294 else
2023 assert(nav.name == name);2295 try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, decl.kind == .@"usingnamespace");
2024 assert(nav.fqn == fqn);2296
2025 break :cau_nav .{ cau_index, nav_index };2297 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
2026 } else try ip.createPairedCauNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, kind == .@"usingnamespace");2298
2027 const want_analysis = switch (kind) {2299 assert(ip.getNav(nav).name == name);
2300 assert(ip.getNav(nav).fqn == fqn);
2301
2302 const want_analysis = switch (decl.kind) {
2028 .@"comptime" => unreachable,2303 .@"comptime" => unreachable,
2029 .@"usingnamespace" => a: {2304 .@"usingnamespace" => a: {
2030 if (comp.incremental) {2305 if (comp.incremental) {
2031 @panic("'usingnamespace' is not supported by incremental compilation");2306 @panic("'usingnamespace' is not supported by incremental compilation");
2032 }2307 }
2033 if (declaration.flags.is_pub) {2308 if (decl.is_pub) {
2034 try namespace.pub_usingnamespace.append(gpa, nav);2309 try namespace.pub_usingnamespace.append(gpa, nav);
2035 } else {2310 } else {
2036 try namespace.priv_usingnamespace.append(gpa, nav);2311 try namespace.priv_usingnamespace.append(gpa, nav);
2037 }2312 }
2038 break :a true;2313 break :a true;
2039 },2314 },
2040 .@"test" => a: {2315 .unnamed_test, .@"test", .decltest => a: {
2041 try namespace.other_decls.append(gpa, cau);2316 const is_named = decl.kind != .unnamed_test;
2317 try namespace.test_decls.append(gpa, nav);
2042 // TODO: incremental compilation!2318 // TODO: incremental compilation!
2043 // * remove from `test_functions` if no longer matching filter2319 // * remove from `test_functions` if no longer matching filter
2044 // * add to `test_functions` if newly passing filter2320 // * add to `test_functions` if newly passing filter
...@@ -2046,7 +2322,7 @@ const ScanDeclIter = struct {...@@ -2046,7 +2322,7 @@ const ScanDeclIter = struct {
2046 // Perhaps we should add all test indiscriminately and filter at the end of the update.2322 // Perhaps we should add all test indiscriminately and filter at the end of the update.
2047 if (!comp.config.is_test) break :a false;2323 if (!comp.config.is_test) break :a false;
2048 if (file.mod != zcu.main_mod) break :a false;2324 if (file.mod != zcu.main_mod) break :a false;
2049 if (is_named_test and comp.test_filters.len > 0) {2325 if (is_named and comp.test_filters.len > 0) {
2050 const fqn_slice = fqn.toSlice(ip);2326 const fqn_slice = fqn.toSlice(ip);
2051 for (comp.test_filters) |test_filter| {2327 for (comp.test_filters) |test_filter| {
2052 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;2328 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
...@@ -2055,8 +2331,8 @@ const ScanDeclIter = struct {...@@ -2055,8 +2331,8 @@ const ScanDeclIter = struct {
2055 try zcu.test_functions.put(gpa, nav, {});2331 try zcu.test_functions.put(gpa, nav, {});
2056 break :a true;2332 break :a true;
2057 },2333 },
2058 .named => a: {2334 .@"const", .@"var" => a: {
2059 if (declaration.flags.is_pub) {2335 if (decl.is_pub) {
2060 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });2336 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
2061 } else {2337 } else {
2062 try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });2338 try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
...@@ -2064,23 +2340,23 @@ const ScanDeclIter = struct {...@@ -2064,23 +2340,23 @@ const ScanDeclIter = struct {
2064 break :a false;2340 break :a false;
2065 },2341 },
2066 };2342 };
2067 break :cau .{ cau, want_analysis };2343 break :unit .{ unit, want_analysis };
2068 },2344 },
2069 };2345 };
20702346
2071 if (existing_cau == null and (want_analysis or declaration.flags.is_export)) {2347 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {
2072 log.debug(2348 log.debug(
2073 "scanDecl queue analyze_cau file='{s}' cau_index={d}",2349 "scanDecl queue analyze_comptime_unit file='{s}' unit={}",
2074 .{ namespace.fileScope(zcu).sub_file_path, cau },2350 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },
2075 );2351 );
2076 try comp.queueJob(.{ .analyze_cau = cau });2352 try comp.queueJob(.{ .analyze_comptime_unit = unit });
2077 }2353 }
20782354
2079 // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live.2355 // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live.
2080 }2356 }
2081};2357};
20822358
2083fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {2359fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {
2084 const tracy = trace(@src());2360 const tracy = trace(@src());
2085 defer tracy.end();2361 defer tracy.end();
20862362
...@@ -2097,26 +2373,19 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2097,26 +2373,19 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2097 try zcu.analysis_in_progress.put(gpa, anal_unit, {});2373 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
2098 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);2374 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
20992375
2100 func.setAnalysisState(ip, .analyzed);2376 func.setAnalyzed(ip);
2101 if (func.analysisUnordered(ip).inferred_error_set) {2377 if (func.analysisUnordered(ip).inferred_error_set) {
2102 func.setResolvedErrorSet(ip, .none);2378 func.setResolvedErrorSet(ip, .none);
2103 }2379 }
21042380
2105 // This is the `Cau` corresponding to the `declaration` instruction which the function or its generic owner originates from.2381 // This is the `Nau` corresponding to the `declaration` instruction which the function or its generic owner originates from.
2106 const decl_cau = ip.getCau(cau: {2382 const decl_nav = ip.getNav(if (func.generic_owner == .none)
2107 const orig_nav = if (func.generic_owner == .none)2383 func.owner_nav
2108 func.owner_nav2384 else
2109 else2385 zcu.funcInfo(func.generic_owner).owner_nav);
2110 zcu.funcInfo(func.generic_owner).owner_nav;
2111
2112 break :cau ip.getNav(orig_nav).analysis_owner.unwrap().?;
2113 });
21142386
2115 const func_nav = ip.getNav(func.owner_nav);2387 const func_nav = ip.getNav(func.owner_nav);
21162388
2117 const decl_prog_node = zcu.sema_prog_node.start(func_nav.fqn.toSlice(ip), 0);
2118 defer decl_prog_node.end();
2119
2120 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);2389 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
21212390
2122 var analysis_arena = std.heap.ArenaAllocator.init(gpa);2391 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
...@@ -2150,7 +2419,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2150,7 +2419,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
21502419
2151 // Every runtime function has a dependency on the source of the Decl it originates from.2420 // Every runtime function has a dependency on the source of the Decl it originates from.
2152 // It also depends on the value of its owner Decl.2421 // It also depends on the value of its owner Decl.
2153 try sema.declareDependency(.{ .src_hash = decl_cau.zir_index });2422 try sema.declareDependency(.{ .src_hash = decl_nav.analysis.?.zir_index });
2154 try sema.declareDependency(.{ .nav_val = func.owner_nav });2423 try sema.declareDependency(.{ .nav_val = func.owner_nav });
21552424
2156 if (func.analysisUnordered(ip).inferred_error_set) {2425 if (func.analysisUnordered(ip).inferred_error_set) {
...@@ -2170,11 +2439,11 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2170,11 +2439,11 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2170 var inner_block: Sema.Block = .{2439 var inner_block: Sema.Block = .{
2171 .parent = null,2440 .parent = null,
2172 .sema = &sema,2441 .sema = &sema,
2173 .namespace = decl_cau.namespace,2442 .namespace = decl_nav.analysis.?.namespace,
2174 .instructions = .{},2443 .instructions = .{},
2175 .inlining = null,2444 .inlining = null,
2176 .is_comptime = false,2445 .is_comptime = false,
2177 .src_base_inst = decl_cau.zir_index,2446 .src_base_inst = decl_nav.analysis.?.zir_index,
2178 .type_name_ctx = func_nav.fqn,2447 .type_name_ctx = func_nav.fqn,
2179 };2448 };
2180 defer inner_block.instructions.deinit(gpa);2449 defer inner_block.instructions.deinit(gpa);
...@@ -2476,14 +2745,14 @@ fn processExportsInner(...@@ -2476,14 +2745,14 @@ fn processExportsInner(
2476 .nav => |nav_index| if (failed: {2745 .nav => |nav_index| if (failed: {
2477 const nav = ip.getNav(nav_index);2746 const nav = ip.getNav(nav_index);
2478 if (zcu.failed_codegen.contains(nav_index)) break :failed true;2747 if (zcu.failed_codegen.contains(nav_index)) break :failed true;
2479 if (nav.analysis_owner.unwrap()) |cau| {2748 if (nav.analysis != null) {
2480 const cau_unit = AnalUnit.wrap(.{ .cau = cau });2749 const unit: AnalUnit = .wrap(.{ .nav_val = nav_index });
2481 if (zcu.failed_analysis.contains(cau_unit)) break :failed true;2750 if (zcu.failed_analysis.contains(unit)) break :failed true;
2482 if (zcu.transitive_failed_analysis.contains(cau_unit)) break :failed true;2751 if (zcu.transitive_failed_analysis.contains(unit)) break :failed true;
2483 }2752 }
2484 const val = switch (nav.status) {2753 const val = switch (nav.status) {
2485 .unresolved => break :failed true,2754 .unresolved, .type_resolved => break :failed true,
2486 .resolved => |r| Value.fromInterned(r.val),2755 .fully_resolved => |r| Value.fromInterned(r.val),
2487 };2756 };
2488 // If the value is a function, we also need to check if that function succeeded analysis.2757 // If the value is a function, we also need to check if that function succeeded analysis.
2489 if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") {2758 if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") {
...@@ -2527,15 +2796,14 @@ pub fn populateTestFunctions(...@@ -2527,15 +2796,14 @@ pub fn populateTestFunctions(
2527 Zcu.Namespace.NameAdapter{ .zcu = zcu },2796 Zcu.Namespace.NameAdapter{ .zcu = zcu },
2528 ).?;2797 ).?;
2529 {2798 {
2530 // We have to call `ensureCauAnalyzed` here in case `builtin.test_functions`2799 // We have to call `ensureNavValUpToDate` here in case `builtin.test_functions`
2531 // was not referenced by start code.2800 // was not referenced by start code.
2532 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);2801 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
2533 defer {2802 defer {
2534 zcu.sema_prog_node.end();2803 zcu.sema_prog_node.end();
2535 zcu.sema_prog_node = std.Progress.Node.none;2804 zcu.sema_prog_node = std.Progress.Node.none;
2536 }2805 }
2537 const cau_index = ip.getNav(nav_index).analysis_owner.unwrap().?;2806 pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) {
2538 pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) {
2539 error.AnalysisFail => return,2807 error.AnalysisFail => return,
2540 error.OutOfMemory => return error.OutOfMemory,2808 error.OutOfMemory => return error.OutOfMemory,
2541 };2809 };
...@@ -2556,8 +2824,7 @@ pub fn populateTestFunctions(...@@ -2556,8 +2824,7 @@ pub fn populateTestFunctions(
2556 {2824 {
2557 // The test declaration might have failed; if that's the case, just return, as we'll2825 // The test declaration might have failed; if that's the case, just return, as we'll
2558 // be emitting a compile error anyway.2826 // be emitting a compile error anyway.
2559 const cau = test_nav.analysis_owner.unwrap().?;2827 const anal_unit: AnalUnit = .wrap(.{ .nav_val = test_nav_index });
2560 const anal_unit: AnalUnit = .wrap(.{ .cau = cau });
2561 if (zcu.failed_analysis.contains(anal_unit) or2828 if (zcu.failed_analysis.contains(anal_unit) or
2562 zcu.transitive_failed_analysis.contains(anal_unit))2829 zcu.transitive_failed_analysis.contains(anal_unit))
2563 {2830 {
...@@ -2682,8 +2949,8 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error...@@ -2682,8 +2949,8 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error
2682 "unable to codegen: {s}",2949 "unable to codegen: {s}",
2683 .{@errorName(err)},2950 .{@errorName(err)},
2684 ));2951 ));
2685 if (nav.analysis_owner.unwrap()) |cau| {2952 if (nav.analysis != null) {
2686 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .cau = cau }));2953 try zcu.retryable_failures.append(zcu.gpa, .wrap(.{ .nav_val = nav_index }));
2687 } else {2954 } else {
2688 // TODO: we don't have a way to indicate that this failure is retryable!2955 // TODO: we don't have a way to indicate that this failure is retryable!
2689 // Since these are really rare, we could as a cop-out retry the whole build next update.2956 // Since these are really rare, we could as a cop-out retry the whole build next update.
...@@ -3189,31 +3456,30 @@ pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Intern...@@ -3189,31 +3456,30 @@ pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Intern
3189 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);3456 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
3190 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse3457 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse
3191 @panic("lib/std.zig is corrupt and missing 'builtin'");3458 @panic("lib/std.zig is corrupt and missing 'builtin'");
3192 pt.ensureCauAnalyzed(ip.getNav(builtin_nav).analysis_owner.unwrap().?) catch @panic("std.builtin is corrupt");3459 pt.ensureNavValUpToDate(builtin_nav) catch @panic("std.builtin is corrupt");
3193 const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.resolved.val);3460 const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.fully_resolved.val);
3194 const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt"));3461 const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt"));
3195 const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);3462 const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
3196 return builtin_namespace.pub_decls.getKeyAdapted(name_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");3463 return builtin_namespace.pub_decls.getKeyAdapted(name_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");
3197}3464}
31983465
3199pub fn navPtrType(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Allocator.Error!Type {3466pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {
3200 const zcu = pt.zcu;3467 const zcu = pt.zcu;
3201 const ip = &zcu.intern_pool;3468 const ip = &zcu.intern_pool;
3202 const r = ip.getNav(nav_index).status.resolved;3469 const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) {
3203 const ty = Value.fromInterned(r.val).typeOf(zcu);3470 .unresolved => unreachable,
3471 .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const },
3472 .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", zcu.navValIsConst(r.val) },
3473 };
3204 return pt.ptrType(.{3474 return pt.ptrType(.{
3205 .child = ty.toIntern(),3475 .child = ty,
3206 .flags = .{3476 .flags = .{
3207 .alignment = if (r.alignment == ty.abiAlignment(zcu))3477 .alignment = if (alignment == Type.fromInterned(ty).abiAlignment(zcu))
3208 .none3478 .none
3209 else3479 else
3210 r.alignment,3480 alignment,
3211 .address_space = r.@"addrspace",3481 .address_space = @"addrspace",
3212 .is_const = switch (ip.indexToKey(r.val)) {3482 .is_const = is_const,
3213 .variable => false,
3214 .@"extern" => |e| e.is_const,
3215 else => true,
3216 },
3217 },3483 },
3218 });3484 });
3219}3485}
...@@ -3233,76 +3499,57 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!...@@ -3233,76 +3499,57 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!
3233// TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`.3499// TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`.
3234pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment {3500pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment {
3235 const zcu = pt.zcu;3501 const zcu = pt.zcu;
3236 const r = zcu.intern_pool.getNav(nav_index).status.resolved;3502 const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) {
3237 if (r.alignment != .none) return r.alignment;3503 .unresolved => unreachable,
3238 return Value.fromInterned(r.val).typeOf(zcu).abiAlignment(zcu);3504 .type_resolved => |r| .{ .fromInterned(r.type), r.alignment },
3505 .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment },
3506 };
3507 if (alignment != .none) return alignment;
3508 return ty.abiAlignment(zcu);
3239}3509}
32403510
3241/// Given a container type requiring resolution, ensures that it is up-to-date.3511/// Given a container type requiring resolution, ensures that it is up-to-date.
3242/// If not, the type is recreated at a new `InternPool.Index`.3512/// If not, the type is recreated at a new `InternPool.Index`.
3243/// The new index is returned. This is the same as the old index if the fields were up-to-date.3513/// The new index is returned. This is the same as the old index if the fields were up-to-date.
3244/// If `already_updating` is set, assumes the type is already outdated and undergoing re-analysis rather than checking `zcu.outdated`.3514pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index {
3245pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updating: bool) Zcu.SemaError!InternPool.Index {
3246 const zcu = pt.zcu;3515 const zcu = pt.zcu;
3516 const gpa = zcu.gpa;
3247 const ip = &zcu.intern_pool;3517 const ip = &zcu.intern_pool;
3518
3519 const anal_unit: AnalUnit = .wrap(.{ .type = ty });
3520 const outdated = zcu.outdated.swapRemove(anal_unit) or
3521 zcu.potentially_outdated.swapRemove(anal_unit);
3522
3523 if (!outdated) return ty;
3524
3525 // We will recreate the type at a new `InternPool.Index`.
3526
3527 _ = zcu.outdated_ready.swapRemove(anal_unit);
3528 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3529
3530 // Delete old state which is no longer in use. Technically, this is not necessary: these exports,
3531 // references, etc, will be ignored because the type itself is unreferenced. However, it allows
3532 // reusing the memory which is currently being used to track this state.
3533 zcu.deleteUnitExports(anal_unit);
3534 zcu.deleteUnitReferences(anal_unit);
3535 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
3536 kv.value.destroy(gpa);
3537 }
3538 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
3539 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
3540
3248 switch (ip.indexToKey(ty)) {3541 switch (ip.indexToKey(ty)) {
3249 .struct_type => |key| {3542 .struct_type => |key| return pt.recreateStructType(ty, key),
3250 const struct_obj = ip.loadStructType(ty);3543 .union_type => |key| return pt.recreateUnionType(ty, key),
3251 const outdated = already_updating or o: {3544 .enum_type => |key| return pt.recreateEnumType(ty, key),
3252 const anal_unit = AnalUnit.wrap(.{ .cau = struct_obj.cau });
3253 const o = zcu.outdated.swapRemove(anal_unit) or
3254 zcu.potentially_outdated.swapRemove(anal_unit);
3255 if (o) {
3256 _ = zcu.outdated_ready.swapRemove(anal_unit);
3257 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3258 }
3259 break :o o;
3260 };
3261 if (!outdated) return ty;
3262 return pt.recreateStructType(key, struct_obj);
3263 },
3264 .union_type => |key| {
3265 const union_obj = ip.loadUnionType(ty);
3266 const outdated = already_updating or o: {
3267 const anal_unit = AnalUnit.wrap(.{ .cau = union_obj.cau });
3268 const o = zcu.outdated.swapRemove(anal_unit) or
3269 zcu.potentially_outdated.swapRemove(anal_unit);
3270 if (o) {
3271 _ = zcu.outdated_ready.swapRemove(anal_unit);
3272 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3273 }
3274 break :o o;
3275 };
3276 if (!outdated) return ty;
3277 return pt.recreateUnionType(key, union_obj);
3278 },
3279 .enum_type => |key| {
3280 const enum_obj = ip.loadEnumType(ty);
3281 const outdated = already_updating or o: {
3282 const anal_unit = AnalUnit.wrap(.{ .cau = enum_obj.cau.unwrap().? });
3283 const o = zcu.outdated.swapRemove(anal_unit) or
3284 zcu.potentially_outdated.swapRemove(anal_unit);
3285 if (o) {
3286 _ = zcu.outdated_ready.swapRemove(anal_unit);
3287 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3288 }
3289 break :o o;
3290 };
3291 if (!outdated) return ty;
3292 return pt.recreateEnumType(key, enum_obj);
3293 },
3294 .opaque_type => {
3295 assert(!already_updating);
3296 return ty;
3297 },
3298 else => unreachable,3545 else => unreachable,
3299 }3546 }
3300}3547}
33013548
3302fn recreateStructType(3549fn recreateStructType(
3303 pt: Zcu.PerThread,3550 pt: Zcu.PerThread,
3551 old_ty: InternPool.Index,
3304 full_key: InternPool.Key.NamespaceType,3552 full_key: InternPool.Key.NamespaceType,
3305 struct_obj: InternPool.LoadedStructType,
3306) Zcu.SemaError!InternPool.Index {3553) Zcu.SemaError!InternPool.Index {
3307 const zcu = pt.zcu;3554 const zcu = pt.zcu;
3308 const gpa = zcu.gpa;3555 const gpa = zcu.gpa;
...@@ -3339,8 +3586,7 @@ fn recreateStructType(...@@ -3339,8 +3586,7 @@ fn recreateStructType(
33393586
3340 if (captures_len != key.captures.owned.len) return error.AnalysisFail;3587 if (captures_len != key.captures.owned.len) return error.AnalysisFail;
33413588
3342 // The old type will be unused, so drop its dependency information.3589 const struct_obj = ip.loadStructType(old_ty);
3343 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = struct_obj.cau }));
33443590
3345 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{3591 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
3346 .layout = small.layout,3592 .layout = small.layout,
...@@ -3362,17 +3608,16 @@ fn recreateStructType(...@@ -3362,17 +3608,16 @@ fn recreateStructType(
3362 errdefer wip_ty.cancel(ip, pt.tid);3608 errdefer wip_ty.cancel(ip, pt.tid);
33633609
3364 wip_ty.setName(ip, struct_obj.name);3610 wip_ty.setName(ip, struct_obj.name);
3365 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, struct_obj.namespace, wip_ty.index);
3366 try ip.addDependency(3611 try ip.addDependency(
3367 gpa,3612 gpa,
3368 AnalUnit.wrap(.{ .cau = new_cau_index }),3613 .wrap(.{ .type = wip_ty.index }),
3369 .{ .src_hash = key.zir_index },3614 .{ .src_hash = key.zir_index },
3370 );3615 );
3371 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;3616 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
3372 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.3617 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
3373 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });3618 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
33743619
3375 const new_ty = wip_ty.finish(ip, new_cau_index.toOptional(), struct_obj.namespace);3620 const new_ty = wip_ty.finish(ip, struct_obj.namespace);
3376 if (inst_info.inst == .main_struct_inst) {3621 if (inst_info.inst == .main_struct_inst) {
3377 // This is the root type of a file! Update the reference.3622 // This is the root type of a file! Update the reference.
3378 zcu.setFileRootType(inst_info.file, new_ty);3623 zcu.setFileRootType(inst_info.file, new_ty);
...@@ -3382,8 +3627,8 @@ fn recreateStructType(...@@ -3382,8 +3627,8 @@ fn recreateStructType(
33823627
3383fn recreateUnionType(3628fn recreateUnionType(
3384 pt: Zcu.PerThread,3629 pt: Zcu.PerThread,
3630 old_ty: InternPool.Index,
3385 full_key: InternPool.Key.NamespaceType,3631 full_key: InternPool.Key.NamespaceType,
3386 union_obj: InternPool.LoadedUnionType,
3387) Zcu.SemaError!InternPool.Index {3632) Zcu.SemaError!InternPool.Index {
3388 const zcu = pt.zcu;3633 const zcu = pt.zcu;
3389 const gpa = zcu.gpa;3634 const gpa = zcu.gpa;
...@@ -3422,8 +3667,7 @@ fn recreateUnionType(...@@ -3422,8 +3667,7 @@ fn recreateUnionType(
34223667
3423 if (captures_len != key.captures.owned.len) return error.AnalysisFail;3668 if (captures_len != key.captures.owned.len) return error.AnalysisFail;
34243669
3425 // The old type will be unused, so drop its dependency information.3670 const union_obj = ip.loadUnionType(old_ty);
3426 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = union_obj.cau }));
34273671
3428 const namespace_index = union_obj.namespace;3672 const namespace_index = union_obj.namespace;
34293673
...@@ -3460,22 +3704,21 @@ fn recreateUnionType(...@@ -3460,22 +3704,21 @@ fn recreateUnionType(
3460 errdefer wip_ty.cancel(ip, pt.tid);3704 errdefer wip_ty.cancel(ip, pt.tid);
34613705
3462 wip_ty.setName(ip, union_obj.name);3706 wip_ty.setName(ip, union_obj.name);
3463 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, namespace_index, wip_ty.index);
3464 try ip.addDependency(3707 try ip.addDependency(
3465 gpa,3708 gpa,
3466 AnalUnit.wrap(.{ .cau = new_cau_index }),3709 .wrap(.{ .type = wip_ty.index }),
3467 .{ .src_hash = key.zir_index },3710 .{ .src_hash = key.zir_index },
3468 );3711 );
3469 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;3712 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
3470 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.3713 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.
3471 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });3714 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
3472 return wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index);3715 return wip_ty.finish(ip, namespace_index);
3473}3716}
34743717
3475fn recreateEnumType(3718fn recreateEnumType(
3476 pt: Zcu.PerThread,3719 pt: Zcu.PerThread,
3720 old_ty: InternPool.Index,
3477 full_key: InternPool.Key.NamespaceType,3721 full_key: InternPool.Key.NamespaceType,
3478 enum_obj: InternPool.LoadedEnumType,
3479) Zcu.SemaError!InternPool.Index {3722) Zcu.SemaError!InternPool.Index {
3480 const zcu = pt.zcu;3723 const zcu = pt.zcu;
3481 const gpa = zcu.gpa;3724 const gpa = zcu.gpa;
...@@ -3544,8 +3787,7 @@ fn recreateEnumType(...@@ -3544,8 +3787,7 @@ fn recreateEnumType(
3544 if (bag != 0) break true;3787 if (bag != 0) break true;
3545 } else false;3788 } else false;
35463789
3547 // The old type will be unused, so drop its dependency information.3790 const enum_obj = ip.loadEnumType(old_ty);
3548 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = enum_obj.cau.unwrap().? }));
35493791
3550 const namespace_index = enum_obj.namespace;3792 const namespace_index = enum_obj.namespace;
35513793
...@@ -3571,12 +3813,10 @@ fn recreateEnumType(...@@ -3571,12 +3813,10 @@ fn recreateEnumType(
35713813
3572 wip_ty.setName(ip, enum_obj.name);3814 wip_ty.setName(ip, enum_obj.name);
35733815
3574 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, namespace_index, wip_ty.index);
3575
3576 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;3816 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
3577 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.3817 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.
35783818
3579 wip_ty.prepare(ip, new_cau_index, namespace_index);3819 wip_ty.prepare(ip, namespace_index);
3580 done = true;3820 done = true;
35813821
3582 Sema.resolveDeclaredEnum(3822 Sema.resolveDeclaredEnum(
...@@ -3586,7 +3826,6 @@ fn recreateEnumType(...@@ -3586,7 +3826,6 @@ fn recreateEnumType(
3586 key.zir_index,3826 key.zir_index,
3587 namespace_index,3827 namespace_index,
3588 enum_obj.name,3828 enum_obj.name,
3589 new_cau_index,
3590 small,3829 small,
3591 body,3830 body,
3592 tag_type_ref,3831 tag_type_ref,
src/arch/wasm/CodeGen.zig+1-9
...@@ -3218,15 +3218,7 @@ fn lowerNavRef(func: *CodeGen, nav_index: InternPool.Nav.Index, offset: u32) Inn...@@ -3218,15 +3218,7 @@ fn lowerNavRef(func: *CodeGen, nav_index: InternPool.Nav.Index, offset: u32) Inn
3218 const zcu = pt.zcu;3218 const zcu = pt.zcu;
3219 const ip = &zcu.intern_pool;3219 const ip = &zcu.intern_pool;
32203220
3221 // check if decl is an alias to a function, in which case we3221 const nav_ty = ip.getNav(nav_index).typeOf(ip);
3222 // want to lower the actual decl, rather than the alias itself.
3223 const owner_nav = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {
3224 .func => |function| function.owner_nav,
3225 .variable => |variable| variable.owner_nav,
3226 .@"extern" => |@"extern"| @"extern".owner_nav,
3227 else => nav_index,
3228 };
3229 const nav_ty = ip.getNav(owner_nav).typeOf(ip);
3230 if (!ip.isFunctionType(nav_ty) and !Type.fromInterned(nav_ty).hasRuntimeBitsIgnoreComptime(zcu)) {3222 if (!ip.isFunctionType(nav_ty) and !Type.fromInterned(nav_ty).hasRuntimeBitsIgnoreComptime(zcu)) {
3231 return .{ .imm32 = 0xaaaaaaaa };3223 return .{ .imm32 = 0xaaaaaaaa };
3232 }3224 }
src/codegen.zig+9-8
...@@ -817,7 +817,7 @@ fn genNavRef(...@@ -817,7 +817,7 @@ fn genNavRef(
817 pt: Zcu.PerThread,817 pt: Zcu.PerThread,
818 src_loc: Zcu.LazySrcLoc,818 src_loc: Zcu.LazySrcLoc,
819 val: Value,819 val: Value,
820 ref_nav_index: InternPool.Nav.Index,820 nav_index: InternPool.Nav.Index,
821 target: std.Target,821 target: std.Target,
822) CodeGenError!GenResult {822) CodeGenError!GenResult {
823 const zcu = pt.zcu;823 const zcu = pt.zcu;
...@@ -851,14 +851,15 @@ fn genNavRef(...@@ -851,14 +851,15 @@ fn genNavRef(
851 }851 }
852 }852 }
853853
854 const nav_index, const is_extern, const lib_name, const is_threadlocal = switch (ip.indexToKey(zcu.navValue(ref_nav_index).toIntern())) {854 const nav = ip.getNav(nav_index);
855 .func => |func| .{ func.owner_nav, false, .none, false },855
856 .variable => |variable| .{ variable.owner_nav, false, variable.lib_name, variable.is_threadlocal },856 const is_extern, const lib_name, const is_threadlocal = if (nav.getExtern(ip)) |e|
857 .@"extern" => |@"extern"| .{ @"extern".owner_nav, true, @"extern".lib_name, @"extern".is_threadlocal },857 .{ true, e.lib_name, e.is_threadlocal }
858 else => .{ ref_nav_index, false, .none, false },858 else
859 };859 .{ false, .none, nav.isThreadlocal(ip) };
860
860 const single_threaded = zcu.navFileScope(nav_index).mod.single_threaded;861 const single_threaded = zcu.navFileScope(nav_index).mod.single_threaded;
861 const name = ip.getNav(nav_index).name;862 const name = nav.name;
862 if (lf.cast(.elf)) |elf_file| {863 if (lf.cast(.elf)) |elf_file| {
863 const zo = elf_file.zigObjectPtr().?;864 const zo = elf_file.zigObjectPtr().?;
864 if (is_extern) {865 if (is_extern) {
src/codegen/c.zig+32-29
...@@ -770,11 +770,14 @@ pub const DeclGen = struct {...@@ -770,11 +770,14 @@ pub const DeclGen = struct {
770 const ctype_pool = &dg.ctype_pool;770 const ctype_pool = &dg.ctype_pool;
771771
772 // Chase function values in order to be able to reference the original function.772 // Chase function values in order to be able to reference the original function.
773 const owner_nav = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {773 const owner_nav = switch (ip.getNav(nav_index).status) {
774 .variable => |variable| variable.owner_nav,774 .unresolved => unreachable,
775 .func => |func| func.owner_nav,775 .type_resolved => nav_index, // this can't be an extern or a function
776 .@"extern" => |@"extern"| @"extern".owner_nav,776 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
777 else => nav_index,777 .func => |f| f.owner_nav,
778 .@"extern" => |e| e.owner_nav,
779 else => nav_index,
780 },
778 };781 };
779782
780 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.783 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
...@@ -2237,7 +2240,7 @@ pub const DeclGen = struct {...@@ -2237,7 +2240,7 @@ pub const DeclGen = struct {
2237 Type.fromInterned(nav.typeOf(ip)),2240 Type.fromInterned(nav.typeOf(ip)),
2238 .{ .nav = nav_index },2241 .{ .nav = nav_index },
2239 CQualifiers.init(.{ .@"const" = flags.is_const }),2242 CQualifiers.init(.{ .@"const" = flags.is_const }),
2240 nav.status.resolved.alignment,2243 nav.getAlignment(),
2241 .complete,2244 .complete,
2242 );2245 );
2243 try fwd.writeAll(";\n");2246 try fwd.writeAll(";\n");
...@@ -2246,19 +2249,19 @@ pub const DeclGen = struct {...@@ -2246,19 +2249,19 @@ pub const DeclGen = struct {
2246 fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void {2249 fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void {
2247 const zcu = dg.pt.zcu;2250 const zcu = dg.pt.zcu;
2248 const ip = &zcu.intern_pool;2251 const ip = &zcu.intern_pool;
2249 switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {2252 const nav = ip.getNav(nav_index);
2250 .@"extern" => |@"extern"| try writer.print("{ }", .{2253 if (nav.getExtern(ip)) |@"extern"| {
2254 try writer.print("{ }", .{
2251 fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),2255 fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),
2252 }),2256 });
2253 else => {2257 } else {
2254 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2258 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2255 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2259 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
2256 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);2260 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
2257 try writer.print("{}__{d}", .{2261 try writer.print("{}__{d}", .{
2258 fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),2262 fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
2259 @intFromEnum(nav_index),2263 @intFromEnum(nav_index),
2260 });2264 });
2261 },
2262 }2265 }
2263 }2266 }
22642267
...@@ -2826,7 +2829,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2826,7 +2829,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
28262829
2827 const fwd = o.dg.fwdDeclWriter();2830 const fwd = o.dg.fwdDeclWriter();
2828 try fwd.print("static zig_{s} ", .{@tagName(key)});2831 try fwd.print("static zig_{s} ", .{@tagName(key)});
2829 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).status.resolved.alignment, .forward, .{2832 try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
2830 .fmt_ctype_pool_string = fn_name,2833 .fmt_ctype_pool_string = fn_name,
2831 });2834 });
2832 try fwd.writeAll(";\n");2835 try fwd.writeAll(";\n");
...@@ -2867,13 +2870,13 @@ pub fn genFunc(f: *Function) !void {...@@ -2867,13 +2870,13 @@ pub fn genFunc(f: *Function) !void {
2867 try o.dg.renderFunctionSignature(2870 try o.dg.renderFunctionSignature(
2868 fwd,2871 fwd,
2869 nav_val,2872 nav_val,
2870 nav.status.resolved.alignment,2873 nav.status.fully_resolved.alignment,
2871 .forward,2874 .forward,
2872 .{ .nav = nav_index },2875 .{ .nav = nav_index },
2873 );2876 );
2874 try fwd.writeAll(";\n");2877 try fwd.writeAll(";\n");
28752878
2876 if (nav.status.resolved.@"linksection".toSlice(ip)) |s|2879 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|
2877 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});2880 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
2878 try o.dg.renderFunctionSignature(2881 try o.dg.renderFunctionSignature(
2879 o.writer(),2882 o.writer(),
...@@ -2952,7 +2955,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2952,7 +2955,7 @@ pub fn genDecl(o: *Object) !void {
2952 const nav_ty = Type.fromInterned(nav.typeOf(ip));2955 const nav_ty = Type.fromInterned(nav.typeOf(ip));
29532956
2954 if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;2957 if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
2955 switch (ip.indexToKey(nav.status.resolved.val)) {2958 switch (ip.indexToKey(nav.status.fully_resolved.val)) {
2956 .@"extern" => |@"extern"| {2959 .@"extern" => |@"extern"| {
2957 if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{2960 if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{
2958 .is_extern = true,2961 .is_extern = true,
...@@ -2965,8 +2968,8 @@ pub fn genDecl(o: *Object) !void {...@@ -2965,8 +2968,8 @@ pub fn genDecl(o: *Object) !void {
2965 try fwd.writeAll("zig_extern ");2968 try fwd.writeAll("zig_extern ");
2966 try o.dg.renderFunctionSignature(2969 try o.dg.renderFunctionSignature(
2967 fwd,2970 fwd,
2968 Value.fromInterned(nav.status.resolved.val),2971 Value.fromInterned(nav.status.fully_resolved.val),
2969 nav.status.resolved.alignment,2972 nav.status.fully_resolved.alignment,
2970 .forward,2973 .forward,
2971 .{ .@"export" = .{2974 .{ .@"export" = .{
2972 .main_name = nav.name,2975 .main_name = nav.name,
...@@ -2985,14 +2988,14 @@ pub fn genDecl(o: *Object) !void {...@@ -2985,14 +2988,14 @@ pub fn genDecl(o: *Object) !void {
2985 const w = o.writer();2988 const w = o.writer();
2986 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2989 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
2987 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");2990 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
2988 if (nav.status.resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|2991 if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
2989 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});2992 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
2990 try o.dg.renderTypeAndName(2993 try o.dg.renderTypeAndName(
2991 w,2994 w,
2992 nav_ty,2995 nav_ty,
2993 .{ .nav = o.dg.pass.nav },2996 .{ .nav = o.dg.pass.nav },
2994 .{},2997 .{},
2995 nav.status.resolved.alignment,2998 nav.status.fully_resolved.alignment,
2996 .complete,2999 .complete,
2997 );3000 );
2998 try w.writeAll(" = ");3001 try w.writeAll(" = ");
...@@ -3002,10 +3005,10 @@ pub fn genDecl(o: *Object) !void {...@@ -3002,10 +3005,10 @@ pub fn genDecl(o: *Object) !void {
3002 },3005 },
3003 else => try genDeclValue(3006 else => try genDeclValue(
3004 o,3007 o,
3005 Value.fromInterned(nav.status.resolved.val),3008 Value.fromInterned(nav.status.fully_resolved.val),
3006 .{ .nav = o.dg.pass.nav },3009 .{ .nav = o.dg.pass.nav },
3007 nav.status.resolved.alignment,3010 nav.status.fully_resolved.alignment,
3008 nav.status.resolved.@"linksection",3011 nav.status.fully_resolved.@"linksection",
3009 ),3012 ),
3010 }3013 }
3011}3014}
src/codegen/llvm.zig+29-38
...@@ -1476,7 +1476,7 @@ pub const Object = struct {...@@ -1476,7 +1476,7 @@ pub const Object = struct {
1476 } }, &o.builder);1476 } }, &o.builder);
1477 }1477 }
14781478
1479 if (nav.status.resolved.@"linksection".toSlice(ip)) |section|1479 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |section|
1480 function_index.setSection(try o.builder.string(section), &o.builder);1480 function_index.setSection(try o.builder.string(section), &o.builder);
14811481
1482 var deinit_wip = true;1482 var deinit_wip = true;
...@@ -1684,7 +1684,7 @@ pub const Object = struct {...@@ -1684,7 +1684,7 @@ pub const Object = struct {
1684 const file = try o.getDebugFile(file_scope);1684 const file = try o.getDebugFile(file_scope);
16851685
1686 const line_number = zcu.navSrcLine(func.owner_nav) + 1;1686 const line_number = zcu.navSrcLine(func.owner_nav) + 1;
1687 const is_internal_linkage = ip.indexToKey(nav.status.resolved.val) != .@"extern";1687 const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern";
1688 const debug_decl_type = try o.lowerDebugType(fn_ty);1688 const debug_decl_type = try o.lowerDebugType(fn_ty);
16891689
1690 const subprogram = try o.builder.debugSubprogram(1690 const subprogram = try o.builder.debugSubprogram(
...@@ -2928,9 +2928,7 @@ pub const Object = struct {...@@ -2928,9 +2928,7 @@ pub const Object = struct {
2928 const gpa = o.gpa;2928 const gpa = o.gpa;
2929 const nav = ip.getNav(nav_index);2929 const nav = ip.getNav(nav_index);
2930 const owner_mod = zcu.navFileScope(nav_index).mod;2930 const owner_mod = zcu.navFileScope(nav_index).mod;
2931 const resolved = nav.status.resolved;2931 const ty: Type = .fromInterned(nav.typeOf(ip));
2932 const val = Value.fromInterned(resolved.val);
2933 const ty = val.typeOf(zcu);
2934 const gop = try o.nav_map.getOrPut(gpa, nav_index);2932 const gop = try o.nav_map.getOrPut(gpa, nav_index);
2935 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;2933 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
29362934
...@@ -2938,15 +2936,14 @@ pub const Object = struct {...@@ -2938,15 +2936,14 @@ pub const Object = struct {
2938 const target = owner_mod.resolved_target.result;2936 const target = owner_mod.resolved_target.result;
2939 const sret = firstParamSRet(fn_info, zcu, target);2937 const sret = firstParamSRet(fn_info, zcu, target);
29402938
2941 const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) {2939 const is_extern, const lib_name = if (nav.getExtern(ip)) |@"extern"|
2942 .variable => |variable| .{ false, variable.lib_name },2940 .{ true, @"extern".lib_name }
2943 .@"extern" => |@"extern"| .{ true, @"extern".lib_name },2941 else
2944 else => .{ false, .none },2942 .{ false, .none };
2945 };
2946 const function_index = try o.builder.addFunction(2943 const function_index = try o.builder.addFunction(
2947 try o.lowerType(ty),2944 try o.lowerType(ty),
2948 try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),2945 try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),
2949 toLlvmAddressSpace(resolved.@"addrspace", target),2946 toLlvmAddressSpace(nav.getAddrspace(), target),
2950 );2947 );
2951 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;2948 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
29522949
...@@ -3064,8 +3061,8 @@ pub const Object = struct {...@@ -3064,8 +3061,8 @@ pub const Object = struct {
3064 }3061 }
3065 }3062 }
30663063
3067 if (resolved.alignment != .none)3064 if (nav.getAlignment() != .none)
3068 function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder);3065 function_index.setAlignment(nav.getAlignment().toLlvm(), &o.builder);
30693066
3070 // Function attributes that are independent of analysis results of the function body.3067 // Function attributes that are independent of analysis results of the function body.
3071 try o.addCommonFnAttributes(3068 try o.addCommonFnAttributes(
...@@ -3250,17 +3247,21 @@ pub const Object = struct {...@@ -3250,17 +3247,21 @@ pub const Object = struct {
3250 const zcu = pt.zcu;3247 const zcu = pt.zcu;
3251 const ip = &zcu.intern_pool;3248 const ip = &zcu.intern_pool;
3252 const nav = ip.getNav(nav_index);3249 const nav = ip.getNav(nav_index);
3253 const resolved = nav.status.resolved;3250 const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (nav.status) {
3254 const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (ip.indexToKey(resolved.val)) {3251 .unresolved => unreachable,
3255 .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false },3252 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
3256 .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import },3253 .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false },
3257 else => .{ false, false, false, false },3254 .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import },
3255 else => .{ false, false, false, false },
3256 },
3257 // This means it's a source declaration which is not `extern`!
3258 .type_resolved => |r| .{ false, r.is_threadlocal, false, false },
3258 };3259 };
32593260
3260 const variable_index = try o.builder.addVariable(3261 const variable_index = try o.builder.addVariable(
3261 try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),3262 try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),
3262 try o.lowerType(Type.fromInterned(nav.typeOf(ip))),3263 try o.lowerType(Type.fromInterned(nav.typeOf(ip))),
3263 toLlvmGlobalAddressSpace(resolved.@"addrspace", zcu.getTarget()),3264 toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()),
3264 );3265 );
3265 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;3266 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
32663267
...@@ -4529,20 +4530,10 @@ pub const Object = struct {...@@ -4529,20 +4530,10 @@ pub const Object = struct {
4529 const zcu = pt.zcu;4530 const zcu = pt.zcu;
4530 const ip = &zcu.intern_pool;4531 const ip = &zcu.intern_pool;
45314532
4532 // In the case of something like:4533 const nav = ip.getNav(nav_index);
4533 // fn foo() void {}
4534 // const bar = foo;
4535 // ... &bar;
4536 // `bar` is just an alias and we actually want to lower a reference to `foo`.
4537 const owner_nav_index = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {
4538 .func => |func| func.owner_nav,
4539 .@"extern" => |@"extern"| @"extern".owner_nav,
4540 else => nav_index,
4541 };
4542 const owner_nav = ip.getNav(owner_nav_index);
45434534
4544 const nav_ty = Type.fromInterned(owner_nav.typeOf(ip));4535 const nav_ty = Type.fromInterned(nav.typeOf(ip));
4545 const ptr_ty = try pt.navPtrType(owner_nav_index);4536 const ptr_ty = try pt.navPtrType(nav_index);
45464537
4547 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";4538 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
4548 if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or4539 if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or
...@@ -4552,13 +4543,13 @@ pub const Object = struct {...@@ -4552,13 +4543,13 @@ pub const Object = struct {
4552 }4543 }
45534544
4554 const llvm_global = if (is_fn_body)4545 const llvm_global = if (is_fn_body)
4555 (try o.resolveLlvmFunction(owner_nav_index)).ptrConst(&o.builder).global4546 (try o.resolveLlvmFunction(nav_index)).ptrConst(&o.builder).global
4556 else4547 else
4557 (try o.resolveGlobalNav(owner_nav_index)).ptrConst(&o.builder).global;4548 (try o.resolveGlobalNav(nav_index)).ptrConst(&o.builder).global;
45584549
4559 const llvm_val = try o.builder.convConst(4550 const llvm_val = try o.builder.convConst(
4560 llvm_global.toConst(),4551 llvm_global.toConst(),
4561 try o.builder.ptrType(toLlvmAddressSpace(owner_nav.status.resolved.@"addrspace", zcu.getTarget())),4552 try o.builder.ptrType(toLlvmAddressSpace(nav.getAddrspace(), zcu.getTarget())),
4562 );4553 );
45634554
4564 return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));4555 return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
...@@ -4800,10 +4791,10 @@ pub const NavGen = struct {...@@ -4800,10 +4791,10 @@ pub const NavGen = struct {
4800 const ip = &zcu.intern_pool;4791 const ip = &zcu.intern_pool;
4801 const nav_index = ng.nav_index;4792 const nav_index = ng.nav_index;
4802 const nav = ip.getNav(nav_index);4793 const nav = ip.getNav(nav_index);
4803 const resolved = nav.status.resolved;4794 const resolved = nav.status.fully_resolved;
48044795
4805 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)) {4796 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 },4797 .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
4807 .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav },4798 .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav },
4808 else => .{ false, .none, false, false, false, true, resolved.val, nav_index },4799 else => .{ false, .none, false, false, false, true, resolved.val, nav_index },
4809 };4800 };
...@@ -5766,7 +5757,7 @@ pub const FuncGen = struct {...@@ -5766,7 +5757,7 @@ pub const FuncGen = struct {
5766 const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;5757 const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
5767 const msg_nav = ip.getNav(msg_nav_index);5758 const msg_nav = ip.getNav(msg_nav_index);
5768 const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);5759 const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
5769 const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);5760 const msg_ptr = try o.lowerValue(msg_nav.status.fully_resolved.val);
5770 const null_opt_addr_global = try fg.resolveNullOptUsize();5761 const null_opt_addr_global = try fg.resolveNullOptUsize();
5771 const target = zcu.getTarget();5762 const target = zcu.getTarget();
5772 const llvm_usize = try o.lowerType(Type.usize);5763 const llvm_usize = try o.lowerType(Type.usize);
src/codegen/spirv.zig+16-13
...@@ -268,7 +268,7 @@ pub const Object = struct {...@@ -268,7 +268,7 @@ pub const Object = struct {
268 // TODO: Extern fn?268 // TODO: Extern fn?
269 const kind: SpvModule.Decl.Kind = if (ip.isFunctionType(nav.typeOf(ip)))269 const kind: SpvModule.Decl.Kind = if (ip.isFunctionType(nav.typeOf(ip)))
270 .func270 .func
271 else switch (nav.status.resolved.@"addrspace") {271 else switch (nav.getAddrspace()) {
272 .generic => .invocation_global,272 .generic => .invocation_global,
273 else => .global,273 else => .global,
274 };274 };
...@@ -1279,17 +1279,20 @@ const NavGen = struct {...@@ -1279,17 +1279,20 @@ const NavGen = struct {
1279 const ip = &zcu.intern_pool;1279 const ip = &zcu.intern_pool;
1280 const ty_id = try self.resolveType(ty, .direct);1280 const ty_id = try self.resolveType(ty, .direct);
1281 const nav = ip.getNav(nav_index);1281 const nav = ip.getNav(nav_index);
1282 const nav_val = zcu.navValue(nav_index);1282 const nav_ty: Type = .fromInterned(nav.typeOf(ip));
1283 const nav_ty = nav_val.typeOf(zcu);1283
12841284 switch (nav.status) {
1285 switch (ip.indexToKey(nav_val.toIntern())) {1285 .unresolved => unreachable,
1286 .func => {1286 .type_resolved => {}, // this is not a function or extern
1287 // TODO: Properly lower function pointers. For now we are going to hack around it and1287 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
1288 // just generate an empty pointer. Function pointers are represented by a pointer to usize.1288 .func => {
1289 return try self.spv.constUndef(ty_id);1289 // TODO: Properly lower function pointers. For now we are going to hack around it and
1290 // just generate an empty pointer. Function pointers are represented by a pointer to usize.
1291 return try self.spv.constUndef(ty_id);
1292 },
1293 .@"extern" => if (ip.isFunctionType(nav_ty.toIntern())) @panic("TODO"),
1294 else => {},
1290 },1295 },
1291 .@"extern" => assert(!ip.isFunctionType(nav_ty.toIntern())), // TODO
1292 else => {},
1293 }1296 }
12941297
1295 if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {1298 if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
...@@ -1305,7 +1308,7 @@ const NavGen = struct {...@@ -1305,7 +1308,7 @@ const NavGen = struct {
1305 .global, .invocation_global => spv_decl.result_id,1308 .global, .invocation_global => spv_decl.result_id,
1306 };1309 };
13071310
1308 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");1311 const storage_class = self.spvStorageClass(nav.getAddrspace());
1309 try self.addFunctionDep(spv_decl_index, storage_class);1312 try self.addFunctionDep(spv_decl_index, storage_class);
13101313
1311 const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class);1314 const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class);
...@@ -3182,7 +3185,7 @@ const NavGen = struct {...@@ -3182,7 +3185,7 @@ const NavGen = struct {
3182 };3185 };
3183 assert(maybe_init_val == null); // TODO3186 assert(maybe_init_val == null); // TODO
31843187
3185 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");3188 const storage_class = self.spvStorageClass(nav.getAddrspace());
3186 assert(storage_class != .Generic); // These should be instance globals3189 assert(storage_class != .Generic); // These should be instance globals
31873190
3188 const ptr_ty_id = try self.ptrType(ty, storage_class);3191 const ptr_ty_id = try self.ptrType(ty, storage_class);
src/link.zig+1-1
...@@ -692,7 +692,7 @@ pub const File = struct {...@@ -692,7 +692,7 @@ pub const File = struct {
692 /// May be called before or after updateExports for any given Nav.692 /// May be called before or after updateExports for any given Nav.
693 pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {693 pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
694 const nav = pt.zcu.intern_pool.getNav(nav_index);694 const nav = pt.zcu.intern_pool.getNav(nav_index);
695 assert(nav.status == .resolved);695 assert(nav.status == .fully_resolved);
696 switch (base.tag) {696 switch (base.tag) {
697 inline else => |tag| {697 inline else => |tag| {
698 dev.check(tag.devFeature());698 dev.check(tag.devFeature());
src/link/C.zig+9-11
...@@ -217,7 +217,7 @@ pub fn updateFunc(...@@ -217,7 +217,7 @@ pub fn updateFunc(
217 .mod = zcu.navFileScope(func.owner_nav).mod,217 .mod = zcu.navFileScope(func.owner_nav).mod,
218 .error_msg = null,218 .error_msg = null,
219 .pass = .{ .nav = func.owner_nav },219 .pass = .{ .nav = func.owner_nav },
220 .is_naked_fn = zcu.navValue(func.owner_nav).typeOf(zcu).fnCallingConvention(zcu) == .naked,220 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
221 .fwd_decl = fwd_decl.toManaged(gpa),221 .fwd_decl = fwd_decl.toManaged(gpa),
222 .ctype_pool = ctype_pool.*,222 .ctype_pool = ctype_pool.*,
223 .scratch = .{},223 .scratch = .{},
...@@ -320,11 +320,11 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !...@@ -320,11 +320,11 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !
320 const ip = &zcu.intern_pool;320 const ip = &zcu.intern_pool;
321321
322 const nav = ip.getNav(nav_index);322 const nav = ip.getNav(nav_index);
323 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {323 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
324 .func => return,324 .func => return,
325 .@"extern" => .none,325 .@"extern" => .none,
326 .variable => |variable| variable.init,326 .variable => |variable| variable.init,
327 else => nav.status.resolved.val,327 else => nav.status.fully_resolved.val,
328 };328 };
329 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) return;329 if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) return;
330330
...@@ -499,7 +499,7 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -499,7 +499,7 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
499 av_block,499 av_block,
500 self.exported_navs.getPtr(nav),500 self.exported_navs.getPtr(nav),
501 export_names,501 export_names,
502 if (ip.indexToKey(zcu.navValue(nav).toIntern()) == .@"extern")502 if (ip.getNav(nav).getExtern(ip) != null)
503 ip.getNav(nav).name.toOptional()503 ip.getNav(nav).name.toOptional()
504 else504 else
505 .none,505 .none,
...@@ -544,13 +544,11 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -544,13 +544,11 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
544 },544 },
545 self.getString(av_block.code),545 self.getString(av_block.code),
546 );546 );
547 for (self.navs.keys(), self.navs.values()) |nav, av_block| f.appendCodeAssumeCapacity(547 for (self.navs.keys(), self.navs.values()) |nav, av_block| f.appendCodeAssumeCapacity(storage: {
548 if (self.exported_navs.contains(nav)) .default else switch (ip.indexToKey(zcu.navValue(nav).toIntern())) {548 if (self.exported_navs.contains(nav)) break :storage .default;
549 .@"extern" => .zig_extern,549 if (ip.getNav(nav).getExtern(ip) != null) break :storage .zig_extern;
550 else => .static,550 break :storage .static;
551 },551 }, self.getString(av_block.code));
552 self.getString(av_block.code),
553 );
554552
555 const file = self.base.file.?;553 const file = self.base.file.?;
556 try file.setEndPos(f.file_size);554 try file.setEndPos(f.file_size);
src/link/Coff.zig+11-6
...@@ -1110,6 +1110,8 @@ pub fn updateFunc(coff: *Coff, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -1110,6 +1110,8 @@ pub fn updateFunc(coff: *Coff, pt: Zcu.PerThread, func_index: InternPool.Index,
1110 const atom_index = try coff.getOrCreateAtomForNav(func.owner_nav);1110 const atom_index = try coff.getOrCreateAtomForNav(func.owner_nav);
1111 coff.freeRelocations(atom_index);1111 coff.freeRelocations(atom_index);
11121112
1113 coff.navs.getPtr(func.owner_nav).?.section = coff.text_section_index.?;
1114
1113 var code_buffer = std.ArrayList(u8).init(gpa);1115 var code_buffer = std.ArrayList(u8).init(gpa);
1114 defer code_buffer.deinit();1116 defer code_buffer.deinit();
11151117
...@@ -1223,6 +1225,8 @@ pub fn updateNav(...@@ -1223,6 +1225,8 @@ pub fn updateNav(
1223 coff.freeRelocations(atom_index);1225 coff.freeRelocations(atom_index);
1224 const atom = coff.getAtom(atom_index);1226 const atom = coff.getAtom(atom_index);
12251227
1228 coff.navs.getPtr(nav_index).?.section = coff.getNavOutputSection(nav_index);
1229
1226 var code_buffer = std.ArrayList(u8).init(gpa);1230 var code_buffer = std.ArrayList(u8).init(gpa);
1227 defer code_buffer.deinit();1231 defer code_buffer.deinit();
12281232
...@@ -1342,7 +1346,8 @@ pub fn getOrCreateAtomForNav(coff: *Coff, nav_index: InternPool.Nav.Index) !Atom...@@ -1342,7 +1346,8 @@ pub fn getOrCreateAtomForNav(coff: *Coff, nav_index: InternPool.Nav.Index) !Atom
1342 if (!gop.found_existing) {1346 if (!gop.found_existing) {
1343 gop.value_ptr.* = .{1347 gop.value_ptr.* = .{
1344 .atom = try coff.createAtom(),1348 .atom = try coff.createAtom(),
1345 .section = coff.getNavOutputSection(nav_index),1349 // If necessary, this will be modified by `updateNav` or `updateFunc`.
1350 .section = coff.rdata_section_index.?,
1346 .exports = .{},1351 .exports = .{},
1347 };1352 };
1348 }1353 }
...@@ -1355,7 +1360,7 @@ fn getNavOutputSection(coff: *Coff, nav_index: InternPool.Nav.Index) u16 {...@@ -1355,7 +1360,7 @@ fn getNavOutputSection(coff: *Coff, nav_index: InternPool.Nav.Index) u16 {
1355 const nav = ip.getNav(nav_index);1360 const nav = ip.getNav(nav_index);
1356 const ty = Type.fromInterned(nav.typeOf(ip));1361 const ty = Type.fromInterned(nav.typeOf(ip));
1357 const zig_ty = ty.zigTypeTag(zcu);1362 const zig_ty = ty.zigTypeTag(zcu);
1358 const val = Value.fromInterned(nav.status.resolved.val);1363 const val = Value.fromInterned(nav.status.fully_resolved.val);
1359 const index: u16 = blk: {1364 const index: u16 = blk: {
1360 if (val.isUndefDeep(zcu)) {1365 if (val.isUndefDeep(zcu)) {
1361 // TODO in release-fast and release-small, we should put undef in .bss1366 // TODO in release-fast and release-small, we should put undef in .bss
...@@ -2348,10 +2353,10 @@ pub fn getNavVAddr(...@@ -2348,10 +2353,10 @@ pub fn getNavVAddr(
2348 const ip = &zcu.intern_pool;2353 const ip = &zcu.intern_pool;
2349 const nav = ip.getNav(nav_index);2354 const nav = ip.getNav(nav_index);
2350 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });2355 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });
2351 const sym_index = switch (ip.indexToKey(nav.status.resolved.val)) {2356 const sym_index = if (nav.getExtern(ip)) |e|
2352 .@"extern" => |@"extern"| try coff.getGlobalSymbol(nav.name.toSlice(ip), @"extern".lib_name.toSlice(ip)),2357 try coff.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip))
2353 else => coff.getAtom(try coff.getOrCreateAtomForNav(nav_index)).getSymbolIndex().?,2358 else
2354 };2359 coff.getAtom(try coff.getOrCreateAtomForNav(nav_index)).getSymbolIndex().?;
2355 const atom_index = coff.getAtomIndexForSymbol(.{2360 const atom_index = coff.getAtomIndexForSymbol(.{
2356 .sym_index = reloc_info.parent.atom_index,2361 .sym_index = reloc_info.parent.atom_index,
2357 .file = null,2362 .file = null,
src/link/Dwarf.zig+25-61
...@@ -2259,24 +2259,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2259,24 +2259,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2259 switch (ip.indexToKey(nav_val.toIntern())) {2259 switch (ip.indexToKey(nav_val.toIntern())) {
2260 else => {2260 else => {
2261 assert(file.zir_loaded);2261 assert(file.zir_loaded);
2262 const decl = file.zir.getDeclaration(inst_info.inst)[0];2262 const decl = file.zir.getDeclaration(inst_info.inst);
22632263
2264 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2264 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2265 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2265 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2266 break :parent .{2266 break :parent .{
2267 parent_namespace_ptr.owner_type,2267 parent_namespace_ptr.owner_type,
2268 switch (decl.name) {2268 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
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 },
2280 };2269 };
2281 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };2270 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
22822271
...@@ -2292,7 +2281,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2292,7 +2281,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2292 const nav_ty = nav_val.typeOf(zcu);2281 const nav_ty = nav_val.typeOf(zcu);
2293 const nav_ty_reloc_index = try wip_nav.refForward();2282 const nav_ty_reloc_index = try wip_nav.refForward();
2294 try wip_nav.infoExprloc(.{ .addr = .{ .sym = sym_index } });2283 try wip_nav.infoExprloc(.{ .addr = .{ .sym = sym_index } });
2295 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse2284 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
2296 nav_ty.abiAlignment(zcu).toByteUnits().?);2285 nav_ty.abiAlignment(zcu).toByteUnits().?);
2297 try diw.writeByte(@intFromBool(false));2286 try diw.writeByte(@intFromBool(false));
2298 wip_nav.finishForward(nav_ty_reloc_index);2287 wip_nav.finishForward(nav_ty_reloc_index);
...@@ -2301,24 +2290,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2301,24 +2290,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2301 },2290 },
2302 .variable => |variable| {2291 .variable => |variable| {
2303 assert(file.zir_loaded);2292 assert(file.zir_loaded);
2304 const decl = file.zir.getDeclaration(inst_info.inst)[0];2293 const decl = file.zir.getDeclaration(inst_info.inst);
23052294
2306 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2295 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2307 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2296 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2308 break :parent .{2297 break :parent .{
2309 parent_namespace_ptr.owner_type,2298 parent_namespace_ptr.owner_type,
2310 switch (decl.name) {2299 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
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 },
2322 };2300 };
2323 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };2301 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
23242302
...@@ -2335,30 +2313,19 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2335,30 +2313,19 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2335 try wip_nav.refType(ty);2313 try wip_nav.refType(ty);
2336 const addr: Loc = .{ .addr = .{ .sym = sym_index } };2314 const addr: Loc = .{ .addr = .{ .sym = sym_index } };
2337 try wip_nav.infoExprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);2315 try wip_nav.infoExprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);
2338 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse2316 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
2339 ty.abiAlignment(zcu).toByteUnits().?);2317 ty.abiAlignment(zcu).toByteUnits().?);
2340 try diw.writeByte(@intFromBool(false));2318 try diw.writeByte(@intFromBool(false));
2341 },2319 },
2342 .func => |func| {2320 .func => |func| {
2343 assert(file.zir_loaded);2321 assert(file.zir_loaded);
2344 const decl = file.zir.getDeclaration(inst_info.inst)[0];2322 const decl = file.zir.getDeclaration(inst_info.inst);
23452323
2346 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2324 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2347 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2325 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2348 break :parent .{2326 break :parent .{
2349 parent_namespace_ptr.owner_type,2327 parent_namespace_ptr.owner_type,
2350 switch (decl.name) {2328 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
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 },
2362 };2329 };
2363 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };2330 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
23642331
...@@ -2421,7 +2388,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2421,7 +2388,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2421 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);2388 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);
2422 try diw.writeInt(u32, 0, dwarf.endian);2389 try diw.writeInt(u32, 0, dwarf.endian);
2423 const target = file.mod.resolved_target.result;2390 const target = file.mod.resolved_target.result;
2424 try uleb128(diw, switch (nav.status.resolved.alignment) {2391 try uleb128(diw, switch (nav.status.fully_resolved.alignment) {
2425 .none => target_info.defaultFunctionAlignment(target),2392 .none => target_info.defaultFunctionAlignment(target),
2426 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),2393 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
2427 }.toByteUnits().?);2394 }.toByteUnits().?);
...@@ -2585,23 +2552,22 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2585,23 +2552,22 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2585 const inst_info = nav.srcInst(ip).resolveFull(ip).?;2552 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
2586 const file = zcu.fileByIndex(inst_info.file);2553 const file = zcu.fileByIndex(inst_info.file);
2587 assert(file.zir_loaded);2554 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) {2557 const is_test = switch (decl.kind) {
2591 .unnamed_test => true,2558 .unnamed_test, .@"test", .decltest => true,
2592 .@"comptime", .@"usingnamespace" => false,2559 .@"comptime", .@"usingnamespace", .@"const", .@"var" => false,
2593 _ => decl.name.isNamedTest(file.zir),
2594 };2560 };
2595 if (is_test) {2561 if (is_test) {
2596 // This isn't actually a comptime Nav! It's a test, so it'll definitely never be referenced at comptime.2562 // This isn't actually a comptime Nav! It's a test, so it'll definitely never be referenced at comptime.
2597 return;2563 return;
2598 }2564 }
25992565
2600 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2566 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2601 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2567 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2602 break :parent .{2568 break :parent .{
2603 parent_namespace_ptr.owner_type,2569 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,
2605 };2571 };
2606 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };2572 } else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
26072573
...@@ -2986,7 +2952,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2986,7 +2952,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2986 const nav_ty = nav_val.typeOf(zcu);2952 const nav_ty = nav_val.typeOf(zcu);
2987 try wip_nav.refType(nav_ty);2953 try wip_nav.refType(nav_ty);
2988 try wip_nav.blockValue(nav_src_loc, nav_val);2954 try wip_nav.blockValue(nav_src_loc, nav_val);
2989 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse2955 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
2990 nav_ty.abiAlignment(zcu).toByteUnits().?);2956 nav_ty.abiAlignment(zcu).toByteUnits().?);
2991 try diw.writeByte(@intFromBool(false));2957 try diw.writeByte(@intFromBool(false));
2992 },2958 },
...@@ -3011,7 +2977,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -3011,7 +2977,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
3011 try wip_nav.strp(nav.name.toSlice(ip));2977 try wip_nav.strp(nav.name.toSlice(ip));
3012 try wip_nav.strp(nav.fqn.toSlice(ip));2978 try wip_nav.strp(nav.fqn.toSlice(ip));
3013 const nav_ty_reloc_index = try wip_nav.refForward();2979 const nav_ty_reloc_index = try wip_nav.refForward();
3014 try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse2980 try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
3015 nav_ty.abiAlignment(zcu).toByteUnits().?);2981 nav_ty.abiAlignment(zcu).toByteUnits().?);
3016 try diw.writeByte(@intFromBool(false));2982 try diw.writeByte(@intFromBool(false));
3017 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);2983 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);
...@@ -4198,9 +4164,7 @@ pub fn updateNavLineNumber(dwarf: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.I...@@ -4198,9 +4164,7 @@ pub fn updateNavLineNumber(dwarf: *Dwarf, zcu: *Zcu, nav_index: InternPool.Nav.I
4198 assert(inst_info.inst != .main_struct_inst);4164 assert(inst_info.inst != .main_struct_inst);
4199 const file = zcu.fileByIndex(inst_info.file);4165 const file = zcu.fileByIndex(inst_info.file);
42004166
4201 const inst = file.zir.instructions.get(@intFromEnum(inst_info.inst));4167 const line = file.zir.getDeclaration(inst_info.inst).src_line;
4202 assert(inst.tag == .declaration);
4203 const line = file.zir.extraData(Zir.Inst.Declaration, inst.data.declaration.payload_index).data.src_line;
4204 var line_buf: [4]u8 = undefined;4168 var line_buf: [4]u8 = undefined;
4205 std.mem.writeInt(u32, &line_buf, line, dwarf.endian);4169 std.mem.writeInt(u32, &line_buf, line, dwarf.endian);
42064170
src/link/Elf/ZigObject.zig+10-15
...@@ -925,14 +925,11 @@ pub fn getNavVAddr(...@@ -925,14 +925,11 @@ pub fn getNavVAddr(
925 const ip = &zcu.intern_pool;925 const ip = &zcu.intern_pool;
926 const nav = ip.getNav(nav_index);926 const nav = ip.getNav(nav_index);
927 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });927 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });
928 const this_sym_index = switch (ip.indexToKey(nav.status.resolved.val)) {928 const this_sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
929 .@"extern" => |@"extern"| try self.getGlobalSymbol(929 elf_file,
930 elf_file,930 nav.name.toSlice(ip),
931 nav.name.toSlice(ip),931 @"extern".lib_name.toSlice(ip),
932 @"extern".lib_name.toSlice(ip),932 ) else try self.getOrCreateMetadataForNav(zcu, nav_index);
933 ),
934 else => try self.getOrCreateMetadataForNav(zcu, nav_index),
935 };
936 const this_sym = self.symbol(this_sym_index);933 const this_sym = self.symbol(this_sym_index);
937 const vaddr = this_sym.address(.{}, elf_file);934 const vaddr = this_sym.address(.{}, elf_file);
938 switch (reloc_info.parent) {935 switch (reloc_info.parent) {
...@@ -1107,15 +1104,13 @@ pub fn freeNav(self: *ZigObject, elf_file: *Elf, nav_index: InternPool.Nav.Index...@@ -1107,15 +1104,13 @@ pub fn freeNav(self: *ZigObject, elf_file: *Elf, nav_index: InternPool.Nav.Index
11071104
1108pub fn getOrCreateMetadataForNav(self: *ZigObject, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {1105pub fn getOrCreateMetadataForNav(self: *ZigObject, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
1109 const gpa = zcu.gpa;1106 const gpa = zcu.gpa;
1107 const ip = &zcu.intern_pool;
1110 const gop = try self.navs.getOrPut(gpa, nav_index);1108 const gop = try self.navs.getOrPut(gpa, nav_index);
1111 if (!gop.found_existing) {1109 if (!gop.found_existing) {
1112 const symbol_index = try self.newSymbolWithAtom(gpa, 0);1110 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
1113 const nav_val = Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.resolved.val);
1114 const sym = self.symbol(symbol_index);1111 const sym = self.symbol(symbol_index);
1115 if (nav_val.getVariable(zcu)) |variable| {1112 if (ip.getNav(nav_index).isThreadlocal(ip) and zcu.comp.config.any_non_single_threaded) {
1116 if (variable.is_threadlocal and zcu.comp.config.any_non_single_threaded) {1113 sym.flags.is_tls = true;
1117 sym.flags.is_tls = true;
1118 }
1119 }1114 }
1120 gop.value_ptr.* = .{ .symbol_index = symbol_index };1115 gop.value_ptr.* = .{ .symbol_index = symbol_index };
1121 }1116 }
...@@ -1547,7 +1542,7 @@ pub fn updateNav(...@@ -1547,7 +1542,7 @@ pub fn updateNav(
15471542
1548 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });1543 log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });
15491544
1550 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {1545 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
1551 .func => .none,1546 .func => .none,
1552 .variable => |variable| variable.init,1547 .variable => |variable| variable.init,
1553 .@"extern" => |@"extern"| {1548 .@"extern" => |@"extern"| {
...@@ -1560,7 +1555,7 @@ pub fn updateNav(...@@ -1560,7 +1555,7 @@ pub fn updateNav(
1560 self.symbol(sym_index).flags.is_extern_ptr = true;1555 self.symbol(sym_index).flags.is_extern_ptr = true;
1561 return;1556 return;
1562 },1557 },
1563 else => nav.status.resolved.val,1558 else => nav.status.fully_resolved.val,
1564 };1559 };
15651560
1566 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {1561 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
src/link/MachO/ZigObject.zig+8-15
...@@ -608,14 +608,11 @@ pub fn getNavVAddr(...@@ -608,14 +608,11 @@ pub fn getNavVAddr(
608 const ip = &zcu.intern_pool;608 const ip = &zcu.intern_pool;
609 const nav = ip.getNav(nav_index);609 const nav = ip.getNav(nav_index);
610 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });610 log.debug("getNavVAddr {}({d})", .{ nav.fqn.fmt(ip), nav_index });
611 const sym_index = switch (ip.indexToKey(nav.status.resolved.val)) {611 const sym_index = if (nav.getExtern(ip)) |@"extern"| try self.getGlobalSymbol(
612 .@"extern" => |@"extern"| try self.getGlobalSymbol(612 macho_file,
613 macho_file,613 nav.name.toSlice(ip),
614 nav.name.toSlice(ip),614 @"extern".lib_name.toSlice(ip),
615 @"extern".lib_name.toSlice(ip),615 ) else try self.getOrCreateMetadataForNav(macho_file, nav_index);
616 ),
617 else => try self.getOrCreateMetadataForNav(macho_file, nav_index),
618 };
619 const sym = self.symbols.items[sym_index];616 const sym = self.symbols.items[sym_index];
620 const vaddr = sym.getAddress(.{}, macho_file);617 const vaddr = sym.getAddress(.{}, macho_file);
621 switch (reloc_info.parent) {618 switch (reloc_info.parent) {
...@@ -882,7 +879,7 @@ pub fn updateNav(...@@ -882,7 +879,7 @@ pub fn updateNav(
882 const ip = &zcu.intern_pool;879 const ip = &zcu.intern_pool;
883 const nav = ip.getNav(nav_index);880 const nav = ip.getNav(nav_index);
884881
885 const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {882 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
886 .func => .none,883 .func => .none,
887 .variable => |variable| variable.init,884 .variable => |variable| variable.init,
888 .@"extern" => |@"extern"| {885 .@"extern" => |@"extern"| {
...@@ -895,7 +892,7 @@ pub fn updateNav(...@@ -895,7 +892,7 @@ pub fn updateNav(
895 sym.flags.is_extern_ptr = true;892 sym.flags.is_extern_ptr = true;
896 return;893 return;
897 },894 },
898 else => nav.status.resolved.val,895 else => nav.status.fully_resolved.val,
899 };896 };
900897
901 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {898 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
...@@ -1561,11 +1558,7 @@ fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool {...@@ -1561,11 +1558,7 @@ fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool {
1561 if (!macho_file.base.comp.config.any_non_single_threaded)1558 if (!macho_file.base.comp.config.any_non_single_threaded)
1562 return false;1559 return false;
1563 const ip = &macho_file.base.comp.zcu.?.intern_pool;1560 const ip = &macho_file.base.comp.zcu.?.intern_pool;
1564 return switch (ip.indexToKey(ip.getNav(nav_index).status.resolved.val)) {1561 return ip.getNav(nav_index).isThreadlocal(ip);
1565 .variable => |variable| variable.is_threadlocal,
1566 .@"extern" => |@"extern"| @"extern".is_threadlocal,
1567 else => false,
1568 };
1569}1562}
15701563
1571fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {1564fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
src/link/Plan9.zig+2-2
...@@ -1021,7 +1021,7 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -1021,7 +1021,7 @@ pub fn seeNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
1021 const atom_idx = gop.value_ptr.index;1021 const atom_idx = gop.value_ptr.index;
1022 // handle externs here because they might not get updateDecl called on them1022 // handle externs here because they might not get updateDecl called on them
1023 const nav = ip.getNav(nav_index);1023 const nav = ip.getNav(nav_index);
1024 if (ip.indexToKey(nav.status.resolved.val) == .@"extern") {1024 if (nav.getExtern(ip) != null) {
1025 // this is a "phantom atom" - it is never actually written to disk, just convenient for us to store stuff about externs1025 // this is a "phantom atom" - it is never actually written to disk, just convenient for us to store stuff about externs
1026 if (nav.name.eqlSlice("etext", ip)) {1026 if (nav.name.eqlSlice("etext", ip)) {
1027 self.etext_edata_end_atom_indices[0] = atom_idx;1027 self.etext_edata_end_atom_indices[0] = atom_idx;
...@@ -1370,7 +1370,7 @@ pub fn getNavVAddr(...@@ -1370,7 +1370,7 @@ pub fn getNavVAddr(
1370 const ip = &pt.zcu.intern_pool;1370 const ip = &pt.zcu.intern_pool;
1371 const nav = ip.getNav(nav_index);1371 const nav = ip.getNav(nav_index);
1372 log.debug("getDeclVAddr for {}", .{nav.name.fmt(ip)});1372 log.debug("getDeclVAddr for {}", .{nav.name.fmt(ip)});
1373 if (ip.indexToKey(nav.status.resolved.val) == .@"extern") {1373 if (nav.getExtern(ip) != null) {
1374 if (nav.name.eqlSlice("etext", ip)) {1374 if (nav.name.eqlSlice("etext", ip)) {
1375 try self.addReloc(reloc_info.parent.atom_index, .{1375 try self.addReloc(reloc_info.parent.atom_index, .{
1376 .target = undefined,1376 .target = undefined,
src/link/Wasm/ZigObject.zig+7-8
...@@ -241,7 +241,7 @@ pub fn updateNav(...@@ -241,7 +241,7 @@ pub fn updateNav(
241241
242 const nav_val = zcu.navValue(nav_index);242 const nav_val = zcu.navValue(nav_index);
243 const is_extern, const lib_name, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {243 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) },
245 .func => return,245 .func => return,
246 .@"extern" => |@"extern"| if (ip.isFunctionType(nav.typeOf(ip)))246 .@"extern" => |@"extern"| if (ip.isFunctionType(nav.typeOf(ip)))
247 return247 return
...@@ -734,15 +734,14 @@ pub fn getNavVAddr(...@@ -734,15 +734,14 @@ pub fn getNavVAddr(
734 const target_atom_index = try zig_object.getOrCreateAtomForNav(wasm, pt, nav_index);734 const target_atom_index = try zig_object.getOrCreateAtomForNav(wasm, pt, nav_index);
735 const target_atom = wasm.getAtom(target_atom_index);735 const target_atom = wasm.getAtom(target_atom_index);
736 const target_symbol_index = @intFromEnum(target_atom.sym_index);736 const target_symbol_index = @intFromEnum(target_atom.sym_index);
737 switch (ip.indexToKey(nav.status.resolved.val)) {737 if (nav.getExtern(ip)) |@"extern"| {
738 .@"extern" => |@"extern"| try zig_object.addOrUpdateImport(738 try zig_object.addOrUpdateImport(
739 wasm,739 wasm,
740 nav.name.toSlice(ip),740 nav.name.toSlice(ip),
741 target_atom.sym_index,741 target_atom.sym_index,
742 @"extern".lib_name.toSlice(ip),742 @"extern".lib_name.toSlice(ip),
743 null,743 null,
744 ),744 );
745 else => {},
746 }745 }
747746
748 std.debug.assert(reloc_info.parent.atom_index != 0);747 std.debug.assert(reloc_info.parent.atom_index != 0);
...@@ -945,8 +944,8 @@ pub fn freeNav(zig_object: *ZigObject, wasm: *Wasm, nav_index: InternPool.Nav.In...@@ -945,8 +944,8 @@ pub fn freeNav(zig_object: *ZigObject, wasm: *Wasm, nav_index: InternPool.Nav.In
945 segment.name = &.{}; // Ensure no accidental double free944 segment.name = &.{}; // Ensure no accidental double free
946 }945 }
947946
948 const nav_val = zcu.navValue(nav_index).toIntern();947 const nav = ip.getNav(nav_index);
949 if (ip.indexToKey(nav_val) == .@"extern") {948 if (nav.getExtern(ip) != null) {
950 std.debug.assert(zig_object.imports.remove(atom.sym_index));949 std.debug.assert(zig_object.imports.remove(atom.sym_index));
951 }950 }
952 std.debug.assert(wasm.symbol_atom.remove(atom.symbolLoc()));951 std.debug.assert(wasm.symbol_atom.remove(atom.symbolLoc()));
...@@ -960,7 +959,7 @@ pub fn freeNav(zig_object: *ZigObject, wasm: *Wasm, nav_index: InternPool.Nav.In...@@ -960,7 +959,7 @@ pub fn freeNav(zig_object: *ZigObject, wasm: *Wasm, nav_index: InternPool.Nav.In
960 if (sym.isGlobal()) {959 if (sym.isGlobal()) {
961 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));960 std.debug.assert(zig_object.global_syms.remove(atom.sym_index));
962 }961 }
963 if (ip.isFunctionType(ip.typeOf(nav_val))) {962 if (ip.isFunctionType(nav.typeOf(ip))) {
964 zig_object.functions_free_list.append(gpa, sym.index) catch {};963 zig_object.functions_free_list.append(gpa, sym.index) catch {};
965 std.debug.assert(zig_object.atom_types.remove(atom_index));964 std.debug.assert(zig_object.atom_types.remove(atom_index));
966 } else {965 } else {
src/print_zir.zig+29-69
...@@ -542,7 +542,6 @@ const Writer = struct {...@@ -542,7 +542,6 @@ const Writer = struct {
542542
543 .@"asm" => try self.writeAsm(stream, extended, false),543 .@"asm" => try self.writeAsm(stream, extended, false),
544 .asm_expr => try self.writeAsm(stream, extended, true),544 .asm_expr => try self.writeAsm(stream, extended, true),
545 .variable => try self.writeVarExtended(stream, extended),
546 .alloc => try self.writeAllocExtended(stream, extended),545 .alloc => try self.writeAllocExtended(stream, extended),
547546
548 .compile_log => try self.writeNodeMultiOp(stream, extended),547 .compile_log => try self.writeNodeMultiOp(stream, extended),
...@@ -2347,7 +2346,6 @@ const Writer = struct {...@@ -2347,7 +2346,6 @@ const Writer = struct {
2347 inferred_error_set,2346 inferred_error_set,
2348 false,2347 false,
2349 false,2348 false,
2350 false,
23512349
2352 .none,2350 .none,
2353 &.{},2351 &.{},
...@@ -2371,13 +2369,6 @@ const Writer = struct {...@@ -2371,13 +2369,6 @@ const Writer = struct {
2371 var ret_ty_ref: Zir.Inst.Ref = .none;2369 var ret_ty_ref: Zir.Inst.Ref = .none;
2372 var ret_ty_body: []const Zir.Inst.Index = &.{};2370 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
2381 if (extra.data.bits.has_cc_body) {2372 if (extra.data.bits.has_cc_body) {
2382 const body_len = self.code.extra[extra_index];2373 const body_len = self.code.extra[extra_index];
2383 extra_index += 1;2374 extra_index += 1;
...@@ -2414,7 +2405,6 @@ const Writer = struct {...@@ -2414,7 +2405,6 @@ const Writer = struct {
2414 stream,2405 stream,
2415 extra.data.bits.is_inferred_error,2406 extra.data.bits.is_inferred_error,
2416 extra.data.bits.is_var_args,2407 extra.data.bits.is_var_args,
2417 extra.data.bits.is_extern,
2418 extra.data.bits.is_noinline,2408 extra.data.bits.is_noinline,
2419 cc_ref,2409 cc_ref,
2420 cc_body,2410 cc_body,
...@@ -2427,36 +2417,6 @@ const Writer = struct {...@@ -2427,36 +2417,6 @@ const Writer = struct {
2427 );2417 );
2428 }2418 }
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
2460 fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2420 fn writeAllocExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
2461 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);2421 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2462 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));2422 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
...@@ -2604,7 +2564,6 @@ const Writer = struct {...@@ -2604,7 +2564,6 @@ const Writer = struct {
2604 stream: anytype,2564 stream: anytype,
2605 inferred_error_set: bool,2565 inferred_error_set: bool,
2606 var_args: bool,2566 var_args: bool,
2607 is_extern: bool,
2608 is_noinline: bool,2567 is_noinline: bool,
2609 cc_ref: Zir.Inst.Ref,2568 cc_ref: Zir.Inst.Ref,
2610 cc_body: []const Zir.Inst.Index,2569 cc_body: []const Zir.Inst.Index,
...@@ -2618,7 +2577,6 @@ const Writer = struct {...@@ -2618,7 +2577,6 @@ const Writer = struct {
2618 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);2577 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2619 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);2578 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2620 try self.writeFlag(stream, "vargs, ", var_args);2579 try self.writeFlag(stream, "vargs, ", var_args);
2621 try self.writeFlag(stream, "extern, ", is_extern);
2622 try self.writeFlag(stream, "inferror, ", inferred_error_set);2580 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2623 try self.writeFlag(stream, "noinline, ", is_noinline);2581 try self.writeFlag(stream, "noinline, ", is_noinline);
26242582
...@@ -2664,56 +2622,58 @@ const Writer = struct {...@@ -2664,56 +2622,58 @@ const Writer = struct {
2664 }2622 }
26652623
2666 fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2624 fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2667 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].declaration;2625 const decl = self.code.getDeclaration(inst);
2668 const extra = self.code.extraData(Zir.Inst.Declaration, inst_data.payload_index);
26692626
2670 const prev_parent_decl_node = self.parent_decl_node;2627 const prev_parent_decl_node = self.parent_decl_node;
2671 defer self.parent_decl_node = prev_parent_decl_node;2628 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 ");2631 if (decl.is_pub) try stream.writeAll("pub ");
2675 if (extra.data.flags.is_export) try stream.writeAll("export ");2632 switch (decl.linkage) {
2676 switch (extra.data.name) {2633 .normal => {},
2634 .@"export" => try stream.writeAll("export "),
2635 .@"extern" => try stream.writeAll("extern "),
2636 }
2637 switch (decl.kind) {
2677 .@"comptime" => try stream.writeAll("comptime"),2638 .@"comptime" => try stream.writeAll("comptime"),
2678 .@"usingnamespace" => try stream.writeAll("usingnamespace"),2639 .@"usingnamespace" => try stream.writeAll("usingnamespace"),
2679 .unnamed_test => try stream.writeAll("test"),2640 .unnamed_test => try stream.writeAll("test"),
2680 _ => {2641 .@"test", .decltest, .@"const", .@"var" => {
2681 const name = extra.data.name.toString(self.code).?;2642 try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
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) });
2686 },2643 },
2687 }2644 }
2688 const src_hash_arr: [4]u32 = .{2645 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2689 extra.data.src_hash_0,2646 try stream.print(" line({d}) column({d}) hash({})", .{
2690 extra.data.src_hash_1,2647 decl.src_line,
2691 extra.data.src_hash_2,2648 decl.src_column,
2692 extra.data.src_hash_3,2649 std.fmt.fmtSliceHexLower(&src_hash),
2693 };2650 });
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) });
26962651
2697 {2652 {
2698 const bodies = extra.data.getBodies(@intCast(extra.end), self.code);2653 if (decl.type_body) |b| {
26992654 try stream.writeAll(" type=");
2700 try stream.writeAll(" value=");2655 try self.writeBracedDecl(stream, b);
2701 try self.writeBracedDecl(stream, bodies.value_body);2656 }
27022657
2703 if (bodies.align_body) |b| {2658 if (decl.align_body) |b| {
2704 try stream.writeAll(" align=");2659 try stream.writeAll(" align=");
2705 try self.writeBracedDecl(stream, b);2660 try self.writeBracedDecl(stream, b);
2706 }2661 }
27072662
2708 if (bodies.linksection_body) |b| {2663 if (decl.linksection_body) |b| {
2709 try stream.writeAll(" linksection=");2664 try stream.writeAll(" linksection=");
2710 try self.writeBracedDecl(stream, b);2665 try self.writeBracedDecl(stream, b);
2711 }2666 }
27122667
2713 if (bodies.addrspace_body) |b| {2668 if (decl.addrspace_body) |b| {
2714 try stream.writeAll(" addrspace=");2669 try stream.writeAll(" addrspace=");
2715 try self.writeBracedDecl(stream, b);2670 try self.writeBracedDecl(stream, b);
2716 }2671 }
2672
2673 if (decl.value_body) |b| {
2674 try stream.writeAll(" value=");
2675 try self.writeBracedDecl(stream, b);
2676 }
2717 }2677 }
27182678
2719 try stream.writeAll(") ");2679 try stream.writeAll(") ");
test/behavior/globals.zig+96
...@@ -66,3 +66,99 @@ test "global loads can affect liveness" {...@@ -66,3 +66,99 @@ test "global loads can affect liveness" {
66 S.f();66 S.f();
67 try std.testing.expect(y.a == 1);67 try std.testing.expect(y.a == 1);
68}68}
69
70test "global const can be self-referential" {
71 const S = struct {
72 self: *const @This(),
73 x: u32,
74
75 const foo: @This() = .{ .self = &foo, .x = 123 };
76 };
77
78 try std.testing.expect(S.foo.x == 123);
79 try std.testing.expect(S.foo.self.x == 123);
80 try std.testing.expect(S.foo.self.self.x == 123);
81 try std.testing.expect(S.foo.self == &S.foo);
82 try std.testing.expect(S.foo.self.self == &S.foo);
83}
84
85test "global var can be self-referential" {
86 const S = struct {
87 self: *@This(),
88 x: u32,
89
90 var foo: @This() = .{ .self = &foo, .x = undefined };
91 };
92
93 S.foo.x = 123;
94
95 try std.testing.expect(S.foo.x == 123);
96 try std.testing.expect(S.foo.self.x == 123);
97 try std.testing.expect(S.foo.self == &S.foo);
98
99 S.foo.self.x = 456;
100
101 try std.testing.expect(S.foo.x == 456);
102 try std.testing.expect(S.foo.self.x == 456);
103 try std.testing.expect(S.foo.self == &S.foo);
104
105 S.foo.self.self.x = 789;
106
107 try std.testing.expect(S.foo.x == 789);
108 try std.testing.expect(S.foo.self.x == 789);
109 try std.testing.expect(S.foo.self == &S.foo);
110}
111
112test "global const can be indirectly self-referential" {
113 const S = struct {
114 other: *const @This(),
115 x: u32,
116
117 const foo: @This() = .{ .other = &bar, .x = 123 };
118 const bar: @This() = .{ .other = &foo, .x = 456 };
119 };
120
121 try std.testing.expect(S.foo.x == 123);
122 try std.testing.expect(S.foo.other.x == 456);
123 try std.testing.expect(S.foo.other.other.x == 123);
124 try std.testing.expect(S.foo.other.other.other.x == 456);
125 try std.testing.expect(S.foo.other == &S.bar);
126 try std.testing.expect(S.foo.other.other == &S.foo);
127
128 try std.testing.expect(S.bar.x == 456);
129 try std.testing.expect(S.bar.other.x == 123);
130 try std.testing.expect(S.bar.other.other.x == 456);
131 try std.testing.expect(S.bar.other.other.other.x == 123);
132 try std.testing.expect(S.bar.other == &S.foo);
133 try std.testing.expect(S.bar.other.other == &S.bar);
134}
135
136test "global var can be indirectly self-referential" {
137 const S = struct {
138 other: *@This(),
139 x: u32,
140
141 var foo: @This() = .{ .other = &bar, .x = undefined };
142 var bar: @This() = .{ .other = &foo, .x = undefined };
143 };
144
145 S.foo.other.x = 123; // bar.x
146 S.foo.other.other.x = 456; // foo.x
147
148 try std.testing.expect(S.foo.x == 456);
149 try std.testing.expect(S.foo.other.x == 123);
150 try std.testing.expect(S.foo.other.other.x == 456);
151 try std.testing.expect(S.foo.other.other.other.x == 123);
152 try std.testing.expect(S.foo.other == &S.bar);
153 try std.testing.expect(S.foo.other.other == &S.foo);
154
155 S.bar.other.x = 111; // foo.x
156 S.bar.other.other.x = 222; // bar.x
157
158 try std.testing.expect(S.bar.x == 222);
159 try std.testing.expect(S.bar.other.x == 111);
160 try std.testing.expect(S.bar.other.other.x == 222);
161 try std.testing.expect(S.bar.other.other.other.x == 111);
162 try std.testing.expect(S.bar.other == &S.foo);
163 try std.testing.expect(S.bar.other.other == &S.bar);
164}
test/cases/compile_errors/address_of_threadlocal_not_comptime_known.zig+2-1
...@@ -10,4 +10,5 @@ pub export fn entry() void {...@@ -10,4 +10,5 @@ pub export fn entry() void {
10// target=native10// target=native
11//11//
12// :2:36: error: unable to resolve comptime value12// :2:36: error: unable to resolve comptime value
13// :2:36: note: container level variable initializers must be comptime-known13// :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/self_reference_missing_const.zig created+11
...@@ -0,0 +1,11 @@
1const S = struct { self: *S, x: u32 };
2const s: S = .{ .self = &s, .x = 123 };
3
4comptime {
5 _ = s;
6}
7
8// error
9//
10// :2:18: error: expected type '*tmp.S', found '*const tmp.S'
11// :2:18: note: cast discards const qualifier
test/cases/compile_errors/type_variables_must_be_constant.zig+2-2
...@@ -7,5 +7,5 @@ export fn entry() foo {...@@ -7,5 +7,5 @@ export fn entry() foo {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :1:5: error: variable of type 'type' must be const or comptime10// :1:11: error: variable of type 'type' must be const or comptime
11// :1:5: note: types are not available at runtime11// :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 {...@@ -8,5 +8,5 @@ export fn entry() void {
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :1:5: error: variable of type 'comptime_int' must be const or comptime11// :1:9: 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 type12// :1:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type