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

Zir: refactor `declaration` instruction representation

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

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

lib/std/zig/AstGen.zig+582-536
...@@ -106,7 +106,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -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/InternPool.zig-7
...@@ -2018,7 +2018,6 @@ pub const Key = union(enum) {...@@ -2018,7 +2018,6 @@ pub const Key = union(enum) {
2018 ty: Index,2018 ty: Index,
2019 init: Index,2019 init: Index,
2020 owner_nav: Nav.Index,2020 owner_nav: Nav.Index,
2021 lib_name: OptionalNullTerminatedString,
2022 is_threadlocal: bool,2021 is_threadlocal: bool,
2023 is_weak_linkage: bool,2022 is_weak_linkage: bool,
2024 };2023 };
...@@ -2741,7 +2740,6 @@ pub const Key = union(enum) {...@@ -2741,7 +2740,6 @@ pub const Key = union(enum) {
2741 return a_info.owner_nav == b_info.owner_nav and2740 return a_info.owner_nav == b_info.owner_nav and
2742 a_info.ty == b_info.ty and2741 a_info.ty == b_info.ty and
2743 a_info.init == b_info.init and2742 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 and2743 a_info.is_threadlocal == b_info.is_threadlocal and
2746 a_info.is_weak_linkage == b_info.is_weak_linkage;2744 a_info.is_weak_linkage == b_info.is_weak_linkage;
2747 },2745 },
...@@ -5573,9 +5571,6 @@ pub const Tag = enum(u8) {...@@ -5573,9 +5571,6 @@ pub const Tag = enum(u8) {
5573 /// May be `none`.5571 /// May be `none`.
5574 init: Index,5572 init: Index,
5575 owner_nav: Nav.Index,5573 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,5574 flags: Flags,
55805575
5581 pub const Flags = packed struct(u32) {5576 pub const Flags = packed struct(u32) {
...@@ -6928,7 +6923,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6928,7 +6923,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6928 .ty = extra.ty,6923 .ty = extra.ty,
6929 .init = extra.init,6924 .init = extra.init,
6930 .owner_nav = extra.owner_nav,6925 .owner_nav = extra.owner_nav,
6931 .lib_name = extra.lib_name,
6932 .is_threadlocal = extra.flags.is_threadlocal,6926 .is_threadlocal = extra.flags.is_threadlocal,
6933 .is_weak_linkage = extra.flags.is_weak_linkage,6927 .is_weak_linkage = extra.flags.is_weak_linkage,
6934 } };6928 } };
...@@ -7575,7 +7569,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7575,7 +7569,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7575 .ty = variable.ty,7569 .ty = variable.ty,
7576 .init = variable.init,7570 .init = variable.init,
7577 .owner_nav = variable.owner_nav,7571 .owner_nav = variable.owner_nav,
7578 .lib_name = variable.lib_name,
7579 .flags = .{7572 .flags = .{
7580 .is_const = false,7573 .is_const = false,
7581 .is_threadlocal = variable.is_threadlocal,7574 .is_threadlocal = variable.is_threadlocal,
src/Sema.zig+40-224
...@@ -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
...@@ -9525,8 +9518,8 @@ fn zirFunc(...@@ -9525,8 +9518,8 @@ fn zirFunc(
9525 } else sema.owner.unwrap().cau;9518 } else sema.owner.unwrap().cau;
9526 const fn_is_exported = exported: {9519 const fn_is_exported = exported: {
9527 const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;9520 const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;
9528 const zir_decl = sema.code.getDeclaration(decl_inst)[0];9521 const zir_decl = sema.code.getDeclaration(decl_inst);
9529 break :exported zir_decl.flags.is_export;9522 break :exported zir_decl.linkage == .@"export";
9530 };9523 };
9531 if (fn_is_exported) {9524 if (fn_is_exported) {
9532 break :cc target.cCallingConvention() orelse {9525 break :cc target.cCallingConvention() orelse {
...@@ -9557,10 +9550,8 @@ fn zirFunc(...@@ -9557,10 +9550,8 @@ fn zirFunc(
9557 ret_ty,9550 ret_ty,
9558 false,9551 false,
9559 inferred_error_set,9552 inferred_error_set,
9560 false,
9561 has_body,9553 has_body,
9562 src_locs,9554 src_locs,
9563 null,
9564 0,9555 0,
9565 false,9556 false,
9566 );9557 );
...@@ -9619,7 +9610,7 @@ fn resolveGenericBody(...@@ -9619,7 +9610,7 @@ fn resolveGenericBody(
9619/// respective `Decl` (either `ExternFn` or `Var`).9610/// respective `Decl` (either `ExternFn` or `Var`).
9620/// The liveness of the duped library name is tied to liveness of `Zcu`.9611/// 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`).9612/// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`).
9622fn handleExternLibName(9613pub fn handleExternLibName(
9623 sema: *Sema,9614 sema: *Sema,
9624 block: *Block,9615 block: *Block,
9625 src_loc: LazySrcLoc,9616 src_loc: LazySrcLoc,
...@@ -9843,10 +9834,8 @@ fn funcCommon(...@@ -9843,10 +9834,8 @@ fn funcCommon(
9843 bare_return_type: Type,9834 bare_return_type: Type,
9844 var_args: bool,9835 var_args: bool,
9845 inferred_error_set: bool,9836 inferred_error_set: bool,
9846 is_extern: bool,
9847 has_body: bool,9837 has_body: bool,
9848 src_locs: Zir.Inst.Func.SrcLocs,9838 src_locs: Zir.Inst.Func.SrcLocs,
9849 opt_lib_name: ?[]const u8,
9850 noalias_bits: u32,9839 noalias_bits: u32,
9851 is_noinline: bool,9840 is_noinline: bool,
9852) CompileError!Air.Inst.Ref {9841) CompileError!Air.Inst.Ref {
...@@ -9998,7 +9987,6 @@ fn funcCommon(...@@ -9998,7 +9987,6 @@ fn funcCommon(
9998 }9987 }
99999988
10000 if (inferred_error_set) {9989 if (inferred_error_set) {
10001 assert(!is_extern);
10002 assert(has_body);9990 assert(has_body);
10003 if (!ret_poison)9991 if (!ret_poison)
10004 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9992 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
...@@ -10050,32 +10038,6 @@ fn funcCommon(...@@ -10050,32 +10038,6 @@ fn funcCommon(
10050 .is_noinline = is_noinline,10038 .is_noinline = is_noinline,
10051 });10039 });
1005210040
10053 if (is_extern) {
10054 assert(comptime_bits == 0);
10055 assert(!is_generic);
10056 if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, block.src(.{
10057 .node_offset_lib_name = src_node_offset,
10058 }), lib_name);
10059 const extern_func_index = try sema.resolveExternDecl(block, .fromInterned(func_ty), opt_lib_name, true, false);
10060 return finishFunc(
10061 sema,
10062 block,
10063 extern_func_index,
10064 func_ty,
10065 ret_poison,
10066 bare_return_type,
10067 ret_ty_src,
10068 cc,
10069 is_source_decl,
10070 ret_ty_requires_comptime,
10071 func_inst,
10072 cc_src,
10073 is_noinline,
10074 is_generic,
10075 final_is_generic,
10076 );
10077 }
10078
10079 if (has_body) {10041 if (has_body) {
10080 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{10042 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
10081 .owner_nav = sema.getOwnerCauNav(),10043 .owner_nav = sema.getOwnerCauNav(),
...@@ -26711,135 +26673,6 @@ fn zirAwaitNosuspend(...@@ -26711,135 +26673,6 @@ fn zirAwaitNosuspend(
26711 return sema.failWithUseOfAsync(block, src);26673 return sema.failWithUseOfAsync(block, src);
26712}26674}
2671326675
26714fn zirVarExtended(
26715 sema: *Sema,
26716 block: *Block,
26717 extended: Zir.Inst.Extended.InstData,
26718) CompileError!Air.Inst.Ref {
26719 const pt = sema.pt;
26720 const zcu = pt.zcu;
26721 const ip = &zcu.intern_pool;
26722 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
26723 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
26724 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
26725 const small: Zir.Inst.ExtendedVar.Small = @bitCast(extended.small);
26726
26727 var extra_index: usize = extra.end;
26728
26729 const lib_name = if (small.has_lib_name) lib_name: {
26730 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
26731 const lib_name = sema.code.nullTerminatedString(lib_name_index);
26732 extra_index += 1;
26733 try sema.handleExternLibName(block, ty_src, lib_name);
26734 break :lib_name lib_name;
26735 } else null;
26736
26737 // ZIR supports encoding this information but it is not used; the information
26738 // is encoded via the Decl entry.
26739 assert(!small.has_align);
26740
26741 const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: {
26742 const init_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
26743 extra_index += 1;
26744 break :blk try sema.resolveInst(init_ref);
26745 } else .none;
26746
26747 const have_ty = extra.data.var_type != .none;
26748 const var_ty = if (have_ty)
26749 try sema.resolveType(block, ty_src, extra.data.var_type)
26750 else
26751 sema.typeOf(uncasted_init);
26752
26753 const init_val = if (uncasted_init != .none) blk: {
26754 const init = if (have_ty)
26755 try sema.coerce(block, var_ty, uncasted_init, init_src)
26756 else
26757 uncasted_init;
26758
26759 break :blk ((try sema.resolveValue(init)) orelse {
26760 return sema.failWithNeededComptime(block, init_src, .{
26761 .needed_comptime_reason = "container level variable initializers must be comptime-known",
26762 });
26763 }).toIntern();
26764 } else .none;
26765
26766 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
26767
26768 if (small.is_extern) {
26769 const extern_val = try sema.resolveExternDecl(block, var_ty, lib_name, small.is_const, small.is_threadlocal);
26770 return Air.internedToRef(extern_val);
26771 }
26772 assert(!small.is_const); // non-const non-extern variable is not legal
26773 return Air.internedToRef(try pt.intern(.{ .variable = .{
26774 .ty = var_ty.toIntern(),
26775 .init = init_val,
26776 .owner_nav = sema.getOwnerCauNav(),
26777 .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls),
26778 .is_threadlocal = small.is_threadlocal,
26779 .is_weak_linkage = false,
26780 } }));
26781}
26782
26783fn resolveExternDecl(
26784 sema: *Sema,
26785 block: *Block,
26786 ty: Type,
26787 opt_lib_name: ?[]const u8,
26788 is_const: bool,
26789 is_threadlocal: bool,
26790) CompileError!InternPool.Index {
26791 const pt = sema.pt;
26792 const zcu = pt.zcu;
26793 const ip = &zcu.intern_pool;
26794
26795 // We need to resolve the alignment and addrspace early.
26796 // Keep in sync with logic in `Zcu.PerThread.semaCau`.
26797 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
26798 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
26799
26800 const decl_inst, const decl_bodies = decl: {
26801 const decl_inst = sema.getOwnerCauDeclInst().resolve(ip) orelse return error.AnalysisFail;
26802 const zir_decl, const extra_end = sema.code.getDeclaration(decl_inst);
26803 break :decl .{ decl_inst, zir_decl.getBodies(extra_end, sema.code) };
26804 };
26805
26806 const alignment: InternPool.Alignment = a: {
26807 const align_body = decl_bodies.align_body orelse break :a .none;
26808 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);
26809 break :a try sema.analyzeAsAlign(block, align_src, align_ref);
26810 };
26811
26812 const @"addrspace": std.builtin.AddressSpace = as: {
26813 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(ty.toIntern())) {
26814 .func_type => .function,
26815 else => .variable,
26816 };
26817 const target = zcu.getTarget();
26818 const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
26819 .function => target_util.defaultAddressSpace(target, .function),
26820 .variable => target_util.defaultAddressSpace(target, .global_mutable),
26821 .constant => target_util.defaultAddressSpace(target, .global_constant),
26822 else => unreachable,
26823 };
26824 const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst);
26825 break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx);
26826 };
26827
26828 return pt.getExtern(.{
26829 .name = sema.getOwnerCauNavName(),
26830 .ty = ty.toIntern(),
26831 .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, opt_lib_name, .no_embedded_nulls),
26832 .is_const = is_const,
26833 .is_threadlocal = is_threadlocal,
26834 .is_weak_linkage = false,
26835 .is_dll_import = false,
26836 .alignment = alignment,
26837 .@"addrspace" = @"addrspace",
26838 .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction
26839 .owner_nav = undefined, // ignored by `getExtern`
26840 });
26841}
26842
26843fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {26676fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
26844 const tracy = trace(@src());26677 const tracy = trace(@src());
26845 defer tracy.end();26678 defer tracy.end();
...@@ -26857,13 +26690,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26857,13 +26690,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2685726690
26858 var extra_index: usize = extra.end;26691 var extra_index: usize = extra.end;
2685926692
26860 const lib_name: ?[]const u8 = if (extra.data.bits.has_lib_name) blk: {
26861 const lib_name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
26862 const lib_name = sema.code.nullTerminatedString(lib_name_index);
26863 extra_index += 1;
26864 break :blk lib_name;
26865 } else null;
26866
26867 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {26693 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
26868 const body_len = sema.code.extra[extra_index];26694 const body_len = sema.code.extra[extra_index];
26869 extra_index += 1;26695 extra_index += 1;
...@@ -26895,8 +26721,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26895,8 +26721,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26895 break :decl_inst cau.zir_index;26721 break :decl_inst cau.zir_index;
26896 } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau26722 } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau
2689726723
26898 const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail)[0];26724 const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail);
26899 if (zir_decl.flags.is_export) {26725 if (zir_decl.linkage == .@"export") {
26900 break :cc target.cCallingConvention() orelse {26726 break :cc target.cCallingConvention() orelse {
26901 // This target has no default C calling convention. We sometimes trigger a similar26727 // 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,26728 // error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
...@@ -26958,7 +26784,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26958,7 +26784,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2695826784
26959 const is_var_args = extra.data.bits.is_var_args;26785 const is_var_args = extra.data.bits.is_var_args;
26960 const is_inferred_error = extra.data.bits.is_inferred_error;26786 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;26787 const is_noinline = extra.data.bits.is_noinline;
2696326788
26964 return sema.funcCommon(26789 return sema.funcCommon(
...@@ -26969,10 +26794,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -26969,10 +26794,8 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26969 ret_ty,26794 ret_ty,
26970 is_var_args,26795 is_var_args,
26971 is_inferred_error,26796 is_inferred_error,
26972 is_extern,
26973 has_body,26797 has_body,
26974 src_locs,26798 src_locs,
26975 lib_name,
26976 noalias_bits,26799 noalias_bits,
26977 is_noinline,26800 is_noinline,
26978 );26801 );
...@@ -27467,7 +27290,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:...@@ -27467,7 +27290,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
27467}27290}
2746827291
27469/// Emit a compile error if type cannot be used for a runtime variable.27292/// Emit a compile error if type cannot be used for a runtime variable.
27470fn validateVarType(27293pub fn validateVarType(
27471 sema: *Sema,27294 sema: *Sema,
27472 block: *Block,27295 block: *Block,
27473 src: LazySrcLoc,27296 src: LazySrcLoc,
...@@ -29881,7 +29704,7 @@ fn elemPtrSlice(...@@ -29881,7 +29704,7 @@ fn elemPtrSlice(
29881 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);29704 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
29882}29705}
2988329706
29884fn coerce(29707pub fn coerce(
29885 sema: *Sema,29708 sema: *Sema,
29886 block: *Block,29709 block: *Block,
29887 dest_ty_unresolved: Type,29710 dest_ty_unresolved: Type,
...@@ -38843,13 +38666,6 @@ fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {...@@ -38843,13 +38666,6 @@ fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {
38843 return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;38666 return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;
38844}38667}
3884538668
38846/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38847/// the declaration name from its corresponding `Nav`.
38848fn getOwnerCauNavName(sema: *Sema) InternPool.NullTerminatedString {
38849 const nav = sema.getOwnerCauNav();
38850 return sema.pt.zcu.intern_pool.getNav(nav).name;
38851}
38852
38853/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches38669/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38854/// the `TrackedInst` corresponding to this `declaration` instruction.38670/// the `TrackedInst` corresponding to this `declaration` instruction.
38855fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {38671fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
src/Zcu.zig+33-46
...@@ -2679,24 +2679,14 @@ pub fn mapOldZirToNew(...@@ -2679,24 +2679,14 @@ pub fn mapOldZirToNew(
2679 {2679 {
2680 var old_decl_it = old_zir.declIterator(match_item.old_inst);2680 var old_decl_it = old_zir.declIterator(match_item.old_inst);
2681 while (old_decl_it.next()) |old_decl_inst| {2681 while (old_decl_it.next()) |old_decl_inst| {
2682 const old_decl, _ = old_zir.getDeclaration(old_decl_inst);2682 const old_decl = old_zir.getDeclaration(old_decl_inst);
2683 switch (old_decl.name) {2683 switch (old_decl.kind) {
2684 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),2684 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
2685 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),2685 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),
2686 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),2686 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
2687 _ => {2687 .@"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).?;2688 .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
2689 const name = old_zir.nullTerminatedString(name_nts);2689 .@"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 }2690 }
2701 }2691 }
2702 }2692 }
...@@ -2707,7 +2697,7 @@ pub fn mapOldZirToNew(...@@ -2707,7 +2697,7 @@ pub fn mapOldZirToNew(
27072697
2708 var new_decl_it = new_zir.declIterator(match_item.new_inst);2698 var new_decl_it = new_zir.declIterator(match_item.new_inst);
2709 while (new_decl_it.next()) |new_decl_inst| {2699 while (new_decl_it.next()) |new_decl_inst| {
2710 const new_decl, _ = new_zir.getDeclaration(new_decl_inst);2700 const new_decl = new_zir.getDeclaration(new_decl_inst);
2711 // Attempt to match this to a declaration in the old ZIR:2701 // Attempt to match this to a declaration in the old ZIR:
2712 // * For named declarations (`const`/`var`/`fn`), we match based on name.2702 // * 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.2703 // * For named tests (`test "foo"`) and decltests (`test foo`), we also match based on name.
...@@ -2715,7 +2705,7 @@ pub fn mapOldZirToNew(...@@ -2715,7 +2705,7 @@ pub fn mapOldZirToNew(
2715 // * For comptime blocks, we match based on order.2705 // * For comptime blocks, we match based on order.
2716 // * For usingnamespace decls, we match based on order.2706 // * 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`.2707 // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`.
2718 const old_decl_inst = switch (new_decl.name) {2708 const old_decl_inst = switch (new_decl.kind) {
2719 .@"comptime" => inst: {2709 .@"comptime" => inst: {
2720 if (comptime_decl_idx == comptime_decls.items.len) continue;2710 if (comptime_decl_idx == comptime_decls.items.len) continue;
2721 defer comptime_decl_idx += 1;2711 defer comptime_decl_idx += 1;
...@@ -2731,18 +2721,17 @@ pub fn mapOldZirToNew(...@@ -2731,18 +2721,17 @@ pub fn mapOldZirToNew(
2731 defer unnamed_test_idx += 1;2721 defer unnamed_test_idx += 1;
2732 break :inst unnamed_tests.items[unnamed_test_idx];2722 break :inst unnamed_tests.items[unnamed_test_idx];
2733 },2723 },
2734 _ => inst: {2724 .@"test" => inst: {
2735 const name_nts = new_decl.name.toString(new_zir).?;2725 const name = new_zir.nullTerminatedString(new_decl.name);
2736 const name = new_zir.nullTerminatedString(name_nts);2726 break :inst named_tests.get(name) orelse continue;
2737 if (new_decl.name.isNamedTest(new_zir)) {2727 },
2738 if (new_decl.flags.test_is_decltest) {2728 .decltest => inst: {
2739 break :inst named_decltests.get(name) orelse continue;2729 const name = new_zir.nullTerminatedString(new_decl.name);
2740 } else {2730 break :inst named_decltests.get(name) orelse continue;
2741 break :inst named_tests.get(name) orelse continue;2731 },
2742 }2732 .@"const", .@"var" => inst: {
2743 } else {2733 const name = new_zir.nullTerminatedString(new_decl.name);
2744 break :inst named_decls.get(name) orelse continue;2734 break :inst named_decls.get(name) orelse continue;
2745 }
2746 },2735 },
2747 };2736 };
27482737
...@@ -3353,20 +3342,20 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3353,20 +3342,20 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3353 const file = zcu.fileByIndex(inst_info.file);3342 const file = zcu.fileByIndex(inst_info.file);
3354 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3343 // 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.?.*;3344 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3356 const declaration = zir.getDeclaration(inst_info.inst)[0];3345 const decl = zir.getDeclaration(inst_info.inst);
3357 const want_analysis = switch (declaration.name) {3346 const want_analysis = switch (decl.kind) {
3358 .@"usingnamespace" => unreachable,3347 .@"usingnamespace" => unreachable,
3348 .@"const", .@"var" => unreachable,
3359 .@"comptime" => true,3349 .@"comptime" => true,
3360 else => a: {3350 .unnamed_test => comp.config.is_test and file.mod == zcu.main_mod,
3351 .@"test", .decltest => a: {
3361 if (!comp.config.is_test) break :a false;3352 if (!comp.config.is_test) break :a false;
3362 if (file.mod != zcu.main_mod) break :a false;3353 if (file.mod != zcu.main_mod) break :a false;
3363 if (declaration.name.isNamedTest(zir)) {3354 const nav = ip.getCau(cau).owner.unwrap().nav;
3364 const nav = ip.getCau(cau).owner.unwrap().nav;3355 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
3365 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);3356 for (comp.test_filters) |test_filter| {
3366 for (comp.test_filters) |test_filter| {3357 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3367 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;3358 } else break :a false;
3368 } else break :a false;
3369 }
3370 break :a true;3359 break :a true;
3371 },3360 },
3372 };3361 };
...@@ -3388,8 +3377,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3388,8 +3377,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3388 const file = zcu.fileByIndex(inst_info.file);3377 const file = zcu.fileByIndex(inst_info.file);
3389 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3378 // 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.?.*;3379 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3391 const declaration = zir.getDeclaration(inst_info.inst)[0];3380 const decl = zir.getDeclaration(inst_info.inst);
3392 if (declaration.flags.is_export) {3381 if (decl.linkage == .@"export") {
3393 const unit = AnalUnit.wrap(.{ .cau = cau });3382 const unit = AnalUnit.wrap(.{ .cau = cau });
3394 if (!result.contains(unit)) {3383 if (!result.contains(unit)) {
3395 log.debug("type '{}': ref cau %{}", .{3384 log.debug("type '{}': ref cau %{}", .{
...@@ -3407,8 +3396,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3407,8 +3396,8 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3407 const file = zcu.fileByIndex(inst_info.file);3396 const file = zcu.fileByIndex(inst_info.file);
3408 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3397 // 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.?.*;3398 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3410 const declaration = zir.getDeclaration(inst_info.inst)[0];3399 const decl = zir.getDeclaration(inst_info.inst);
3411 if (declaration.flags.is_export) {3400 if (decl.linkage == .@"export") {
3412 const unit = AnalUnit.wrap(.{ .cau = cau });3401 const unit = AnalUnit.wrap(.{ .cau = cau });
3413 if (!result.contains(unit)) {3402 if (!result.contains(unit)) {
3414 log.debug("type '{}': ref cau %{}", .{3403 log.debug("type '{}': ref cau %{}", .{
...@@ -3522,9 +3511,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {...@@ -3522,9 +3511,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
3522 const ip = &zcu.intern_pool;3511 const ip = &zcu.intern_pool;
3523 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;3512 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;
3524 const zir = zcu.fileByIndex(inst_info.file).zir;3513 const zir = zcu.fileByIndex(inst_info.file).zir;
3525 const inst = zir.instructions.get(@intFromEnum(inst_info.inst));3514 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}3515}
35293516
3530pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {3517pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {
src/Zcu/PerThread.zig+151-85
...@@ -469,12 +469,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -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,
...@@ -1252,10 +1244,7 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1252,10 +1244,7 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1252 };1244 };
1253 defer block.instructions.deinit(gpa);1245 defer block.instructions.deinit(gpa);
12541246
1255 const zir_decl: Zir.Inst.Declaration, const decl_bodies: Zir.Inst.Declaration.Bodies = decl: {1247 const zir_decl = zir.getDeclaration(inst_info.inst);
1256 const decl, const extra_end = zir.getDeclaration(inst_info.inst);
1257 break :decl .{ decl, decl.getBodies(extra_end, zir) };
1258 };
12591248
1260 // We have to fetch this state before resolving the body because of the `nav_already_populated`1249 // 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 functions1250 // case below. We might change the language in future so that align/linksection/etc for functions
...@@ -1265,7 +1254,134 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1265,7 +1254,134 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1265 .nav => |nav| ip.getNav(nav),1254 .nav => |nav| ip.getNav(nav),
1266 };1255 };
12671256
1268 const result_ref = try sema.resolveInlineBody(&block, decl_bodies.value_body, inst_info.inst);1257 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
1258 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
1259 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
1260 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1261 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
1262
1263 // First, we must resolve the declaration's type. To do this, we analyze the type body if available,
1264 // or otherwise, we analyze the value body, populating `early_val` in the process.
1265
1266 const decl_ty: Type, const early_val: ?Value = if (zir_decl.type_body) |type_body| ty: {
1267 // We evaluate only the type now; no need for the value yet.
1268 const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_info.inst);
1269 const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
1270 break :ty .{ .fromInterned(type_ref.toInterned().?), null };
1271 } else ty: {
1272 // We don't have a type body, so we need to evaluate the value immediately.
1273 const value_body = zir_decl.value_body.?;
1274 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1275 const val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1276 break :ty .{ val.typeOf(zcu), val };
1277 };
1278
1279 switch (zir_decl.kind) {
1280 .unnamed_test, .@"test", .decltest => assert(decl_ty.zigTypeTag(zcu) == .@"fn"),
1281 .@"comptime" => assert(decl_ty.toIntern() == .void_type),
1282 .@"usingnamespace" => {},
1283 .@"const" => {},
1284 .@"var" => try sema.validateVarType(
1285 &block,
1286 if (zir_decl.type_body != null) ty_src else init_src,
1287 decl_ty,
1288 zir_decl.linkage == .@"extern",
1289 ),
1290 }
1291
1292 // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine
1293 // the full pointer type of this declaration.
1294
1295 const alignment: InternPool.Alignment = a: {
1296 const align_body = zir_decl.align_body orelse break :a .none;
1297 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
1298 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
1299 };
1300
1301 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
1302 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
1303 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
1304 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
1305 .needed_comptime_reason = "linksection must be comptime-known",
1306 });
1307 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
1308 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
1309 } else if (bytes.len == 0) {
1310 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
1311 }
1312 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
1313 };
1314
1315 const @"addrspace": std.builtin.AddressSpace = as: {
1316 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {
1317 .@"var" => .variable,
1318 else => switch (decl_ty.zigTypeTag(zcu)) {
1319 .@"fn" => .function,
1320 else => .constant,
1321 },
1322 };
1323 const target = zcu.getTarget();
1324 const addrspace_body = zir_decl.addrspace_body orelse break :as switch (addrspace_ctx) {
1325 .function => target_util.defaultAddressSpace(target, .function),
1326 .variable => target_util.defaultAddressSpace(target, .global_mutable),
1327 .constant => target_util.defaultAddressSpace(target, .global_constant),
1328 else => unreachable,
1329 };
1330 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
1331 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
1332 };
1333
1334 // Lastly, we must evaluate the value if we have not already done so. Note, however, that extern declarations
1335 // don't have an associated value body.
1336
1337 const final_val: ?Value = early_val orelse if (zir_decl.value_body) |value_body| val: {
1338 // Put the resolved type into `inst_map` to be used as the result type of the init.
1339 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{inst_info.inst});
1340 sema.inst_map.putAssumeCapacity(inst_info.inst, Air.internedToRef(decl_ty.toIntern()));
1341 const uncoerced_result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1342 assert(sema.inst_map.remove(inst_info.inst));
1343
1344 const result_ref = try sema.coerce(&block, decl_ty, uncoerced_result_ref, init_src);
1345 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1346 } else null;
1347
1348 // TODO: missing validation?
1349
1350 const decl_val: Value = switch (zir_decl.linkage) {
1351 .normal, .@"export" => switch (zir_decl.kind) {
1352 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{
1353 .ty = decl_ty.toIntern(),
1354 .init = final_val.?.toIntern(),
1355 .owner_nav = cau.owner.unwrap().nav,
1356 .is_threadlocal = zir_decl.is_threadlocal,
1357 .is_weak_linkage = false,
1358 } })),
1359 else => final_val.?,
1360 },
1361 .@"extern" => val: {
1362 assert(final_val == null); // extern decls do not have a value body
1363 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
1364 break :l zir.nullTerminatedString(zir_decl.lib_name);
1365 } else null;
1366 if (lib_name) |l| {
1367 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });
1368 try sema.handleExternLibName(&block, lib_name_src, l);
1369 }
1370 break :val .fromInterned(try pt.getExtern(.{
1371 .name = old_nav_info.name,
1372 .ty = decl_ty.toIntern(),
1373 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),
1374 .is_const = zir_decl.kind == .@"const",
1375 .is_threadlocal = zir_decl.is_threadlocal,
1376 .is_weak_linkage = false,
1377 .is_dll_import = false,
1378 .alignment = alignment,
1379 .@"addrspace" = @"addrspace",
1380 .zir_index = cau.zir_index, // `declaration` instruction
1381 .owner_nav = undefined, // ignored by `getExtern`
1382 }));
1383 },
1384 };
12691385
1270 const nav_index = switch (cau.owner.unwrap()) {1386 const nav_index = switch (cau.owner.unwrap()) {
1271 .none => {1387 .none => {
...@@ -1282,15 +1398,6 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1282,15 +1398,6 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1282 .type => unreachable, // Handled at top of function.1398 .type => unreachable, // Handled at top of function.
1283 };1399 };
12841400
1285 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
1286 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
1287 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
1288 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1289 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
1290
1291 const decl_val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1292 const decl_ty = decl_val.typeOf(zcu);
1293
1294 switch (decl_val.toIntern()) {1401 switch (decl_val.toIntern()) {
1295 .generic_poison => unreachable, // assertion failure1402 .generic_poison => unreachable, // assertion failure
1296 .unreachable_value => unreachable, // assertion failure1403 .unreachable_value => unreachable, // assertion failure
...@@ -1331,50 +1438,10 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1331,50 +1438,10 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1331 };1438 };
13321439
1333 // Keep in sync with logic in `Sema.zirVarExtended`.1440 // Keep in sync with logic in `Sema.zirVarExtended`.
1334 const alignment: InternPool.Alignment = a: {
1335 const align_body = decl_bodies.align_body orelse break :a .none;
1336 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);
1337 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
1338 };
1339
1340 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
1341 const linksection_body = decl_bodies.linksection_body orelse break :ls .none;
1342 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
1343 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
1344 .needed_comptime_reason = "linksection must be comptime-known",
1345 });
1346 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
1347 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
1348 } else if (bytes.len == 0) {
1349 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
1350 }
1351 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
1352 };
1353
1354 const @"addrspace": std.builtin.AddressSpace = as: {
1355 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
1356 .func => .function,
1357 .variable => .variable,
1358 .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type)
1359 .function
1360 else
1361 .variable,
1362 else => .constant,
1363 };
1364 const target = zcu.getTarget();
1365 const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) {
1366 .function => target_util.defaultAddressSpace(target, .function),
1367 .variable => target_util.defaultAddressSpace(target, .global_mutable),
1368 .constant => target_util.defaultAddressSpace(target, .global_constant),
1369 else => unreachable,
1370 };
1371 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);
1372 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
1373 };
13741441
1375 if (is_owned_fn) {1442 if (is_owned_fn) {
1376 // linksection etc are legal, except some targets do not support function alignment.1443 // linksection etc are legal, except some targets do not support function alignment.
1377 if (decl_bodies.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {1444 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
1378 return sema.fail(&block, align_src, "target does not support function alignment", .{});1445 return sema.fail(&block, align_src, "target does not support function alignment", .{});
1379 }1446 }
1380 } else if (try decl_ty.comptimeOnlySema(pt)) {1447 } else if (try decl_ty.comptimeOnlySema(pt)) {
...@@ -1383,13 +1450,13 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1383,13 +1450,13 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1383 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*1450 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
1384 else => "comptime-only type",1451 else => "comptime-only type",
1385 };1452 };
1386 if (decl_bodies.align_body != null) {1453 if (zir_decl.align_body != null) {
1387 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});1454 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
1388 }1455 }
1389 if (decl_bodies.linksection_body != null) {1456 if (zir_decl.linksection_body != null) {
1390 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});1457 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
1391 }1458 }
1392 if (decl_bodies.addrspace_body != null) {1459 if (zir_decl.addrspace_body != null) {
1393 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});1460 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1394 }1461 }
1395 }1462 }
...@@ -1404,9 +1471,9 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {...@@ -1404,9 +1471,9 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1404 // Mark the `Cau` as completed before evaluating the export!1471 // Mark the `Cau` as completed before evaluating the export!
1405 assert(zcu.analysis_in_progress.swapRemove(anal_unit));1472 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
14061473
1407 if (zir_decl.flags.is_export) {1474 if (zir_decl.linkage == .@"export") {
1408 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.flags.is_pub) });1475 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1409 const name_slice = zir.nullTerminatedString(zir_decl.name.toString(zir).?);1476 const name_slice = zir.nullTerminatedString(zir_decl.name);
1410 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);1477 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);1478 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_index);
1412 }1479 }
...@@ -1919,13 +1986,11 @@ const ScanDeclIter = struct {...@@ -1919,13 +1986,11 @@ const ScanDeclIter = struct {
1919 const zir = file.zir;1986 const zir = file.zir;
1920 const ip = &zcu.intern_pool;1987 const ip = &zcu.intern_pool;
19211988
1922 const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;1989 const decl = zir.getDeclaration(decl_inst);
1923 const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
1924 const declaration = extra.data;
19251990
1926 const Kind = enum { @"comptime", @"usingnamespace", @"test", named };1991 const Kind = enum { @"comptime", @"usingnamespace", @"test", named };
19271992
1928 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (declaration.name) {1993 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (decl.kind) {
1929 .@"comptime" => info: {1994 .@"comptime" => info: {
1930 if (iter.pass != .unnamed) return;1995 if (iter.pass != .unnamed) return;
1931 break :info .{1996 break :info .{
...@@ -1954,21 +2019,22 @@ const ScanDeclIter = struct {...@@ -1954,21 +2019,22 @@ const ScanDeclIter = struct {
1954 false,2019 false,
1955 };2020 };
1956 },2021 },
1957 _ => if (declaration.name.isNamedTest(zir)) info: {2022 .@"test", .decltest => |kind| info: {
1958 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.2023 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
1959 if (iter.pass != .unnamed) return;2024 if (iter.pass != .unnamed) return;
1960 const prefix = if (declaration.flags.test_is_decltest) "decltest" else "test";2025 const prefix = @tagName(kind);
1961 break :info .{2026 break :info .{
1962 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(declaration.name.toString(zir).?) })).toOptional(),2027 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(decl.name) })).toOptional(),
1963 .@"test",2028 .@"test",
1964 true,2029 true,
1965 };2030 };
1966 } else info: {2031 },
2032 .@"const", .@"var" => info: {
1967 if (iter.pass != .named) return;2033 if (iter.pass != .named) return;
1968 const name = try ip.getOrPutString(2034 const name = try ip.getOrPutString(
1969 gpa,2035 gpa,
1970 pt.tid,2036 pt.tid,
1971 zir.nullTerminatedString(declaration.name.toString(zir).?),2037 zir.nullTerminatedString(decl.name),
1972 .no_embedded_nulls,2038 .no_embedded_nulls,
1973 );2039 );
1974 try iter.seen_decls.putNoClobber(gpa, name, {});2040 try iter.seen_decls.putNoClobber(gpa, name, {});
...@@ -2030,7 +2096,7 @@ const ScanDeclIter = struct {...@@ -2030,7 +2096,7 @@ const ScanDeclIter = struct {
2030 if (comp.incremental) {2096 if (comp.incremental) {
2031 @panic("'usingnamespace' is not supported by incremental compilation");2097 @panic("'usingnamespace' is not supported by incremental compilation");
2032 }2098 }
2033 if (declaration.flags.is_pub) {2099 if (decl.is_pub) {
2034 try namespace.pub_usingnamespace.append(gpa, nav);2100 try namespace.pub_usingnamespace.append(gpa, nav);
2035 } else {2101 } else {
2036 try namespace.priv_usingnamespace.append(gpa, nav);2102 try namespace.priv_usingnamespace.append(gpa, nav);
...@@ -2056,7 +2122,7 @@ const ScanDeclIter = struct {...@@ -2056,7 +2122,7 @@ const ScanDeclIter = struct {
2056 break :a true;2122 break :a true;
2057 },2123 },
2058 .named => a: {2124 .named => a: {
2059 if (declaration.flags.is_pub) {2125 if (decl.is_pub) {
2060 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });2126 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
2061 } else {2127 } else {
2062 try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });2128 try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
...@@ -2068,7 +2134,7 @@ const ScanDeclIter = struct {...@@ -2068,7 +2134,7 @@ const ScanDeclIter = struct {
2068 },2134 },
2069 };2135 };
20702136
2071 if (existing_cau == null and (want_analysis or declaration.flags.is_export)) {2137 if (existing_cau == null and (want_analysis or decl.linkage == .@"export")) {
2072 log.debug(2138 log.debug(
2073 "scanDecl queue analyze_cau file='{s}' cau_index={d}",2139 "scanDecl queue analyze_cau file='{s}' cau_index={d}",
2074 .{ namespace.fileScope(zcu).sub_file_path, cau },2140 .{ namespace.fileScope(zcu).sub_file_path, cau },
src/codegen.zig+1-1
...@@ -853,7 +853,7 @@ fn genNavRef(...@@ -853,7 +853,7 @@ fn genNavRef(
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_index, const is_extern, const lib_name, const is_threadlocal = switch (ip.indexToKey(zcu.navValue(ref_nav_index).toIntern())) {
855 .func => |func| .{ func.owner_nav, false, .none, false },855 .func => |func| .{ func.owner_nav, false, .none, false },
856 .variable => |variable| .{ variable.owner_nav, false, variable.lib_name, variable.is_threadlocal },856 .variable => |variable| .{ variable.owner_nav, false, .none, variable.is_threadlocal },
857 .@"extern" => |@"extern"| .{ @"extern".owner_nav, true, @"extern".lib_name, @"extern".is_threadlocal },857 .@"extern" => |@"extern"| .{ @"extern".owner_nav, true, @"extern".lib_name, @"extern".is_threadlocal },
858 else => .{ ref_nav_index, false, .none, false },858 else => .{ ref_nav_index, false, .none, false },
859 };859 };
src/codegen/llvm.zig+1-2
...@@ -2939,7 +2939,6 @@ pub const Object = struct {...@@ -2939,7 +2939,6 @@ pub const Object = struct {
2939 const sret = firstParamSRet(fn_info, zcu, target);2939 const sret = firstParamSRet(fn_info, zcu, target);
29402940
2941 const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) {2941 const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) {
2942 .variable => |variable| .{ false, variable.lib_name },
2943 .@"extern" => |@"extern"| .{ true, @"extern".lib_name },2942 .@"extern" => |@"extern"| .{ true, @"extern".lib_name },
2944 else => .{ false, .none },2943 else => .{ false, .none },
2945 };2944 };
...@@ -4803,7 +4802,7 @@ pub const NavGen = struct {...@@ -4803,7 +4802,7 @@ pub const NavGen = struct {
4803 const resolved = nav.status.resolved;4802 const resolved = nav.status.resolved;
48044803
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)) {4804 const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) {
4806 .variable => |variable| .{ false, variable.lib_name, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },4805 .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
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 },4806 .@"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 },4807 else => .{ false, .none, false, false, false, true, resolved.val, nav_index },
4809 };4808 };
src/link/Dwarf.zig+12-48
...@@ -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_owner.unwrap()) |cau| parent: {
2265 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2265 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).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
...@@ -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_owner.unwrap()) |cau| parent: {
2307 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2296 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).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
...@@ -2341,24 +2319,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2341,24 +2319,13 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
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_owner.unwrap()) |cau| parent: {
2347 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2325 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).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
...@@ -2585,12 +2552,11 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2585,12 +2552,11 @@ 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.
...@@ -2601,7 +2567,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2601,7 +2567,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2601 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2567 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).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
...@@ -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/Wasm/ZigObject.zig+1-1
...@@ -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
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/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/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