authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-02-11 15:05:33+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:11+00:00
logbcb1a6bdf3ef1f39784298deaf2adfb91ea5c5c1
treebddb4e32baf31c2be1f50ed8154a6f74885eac04
parent7170e0f02043d157cb4e10c6333e125c10395a63
signaturelock-open Commit is signed but in an unrecognized format.

compiler: make Dwarf and self-hosted x86_64 happy

Introduces a small abstraction, `link.DebugConstPool`, to deal with lowering type/value information into debug info when it may not be known until type resolution (which in some cases will *never* happen). It is currently only used by self-hosted DWARF logic, but it will also be of use to the LLVM backend (which is my next focus).

8 files changed, 1033 insertions(+), 1468 deletions(-)

src/Compilation.zig+3-72
......@@ -956,8 +956,7 @@ pub const RcSourceFile = struct {
956956
957957const Job = union(enum) {
958958 /// Given the generated AIR for a function, put it onto the code generation queue.
959 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
960 /// all types are resolved before the linker task is queued.
959 /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now
961960 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.
962961 /// Before queueing this `Job`, increase the estimated total item count for both
963962 /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.
......@@ -967,17 +966,10 @@ const Job = union(enum) {
967966 air: Air,
968967 },
969968 /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary.
970 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
971 /// all types are resolved before the linker task is queued.
969 /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now
972970 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
973971 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
974972 link_nav: InternPool.Nav.Index,
975 /// Queue a `link.ZcuTask` to emit debug information for this container type.
976 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
977 /// all types are resolved before the linker task is queued.
978 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
979 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
980 link_type: InternPool.Index,
981973 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
982974 update_line_number: InternPool.TrackedInst.Index,
983975 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
......@@ -5058,26 +5050,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
50585050 var owned_air: ?Air = func.air;
50595051 defer if (owned_air) |*air| air.deinit(gpa);
50605052
5061 {
5062 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5063 defer pt.deactivate();
5064 pt.resolveAirTypesForCodegen(&owned_air.?) catch |err| switch (err) {
5065 error.OutOfMemory,
5066 error.Canceled,
5067 => |e| return e,
5068
5069 error.AnalysisFail => {
5070 // Type resolution failed, making codegen of this function impossible. This
5071 // is a transitive failure, but it doesn't need recording, because this
5072 // function semantically depends on the failed type, so when it is changed
5073 // the function will be updated.
5074 zcu.codegen_prog_node.completeOne();
5075 comp.link_prog_node.completeOne();
5076 return;
5077 },
5078 };
5079 }
5080
50815053 // Some linkers need to refer to the AIR. In that case, the linker is not running
50825054 // concurrently, so we'll just keep ownership of the AIR for ourselves instead of
50835055 // letting the codegen job destroy it.
......@@ -5101,51 +5073,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
51015073 }
51025074 }
51035075 assert(nav.status == .fully_resolved);
5104 {
5105 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5106 defer pt.deactivate();
5107 pt.resolveValueTypesForCodegen(zcu.navValue(nav_index)) catch |err| switch (err) {
5108 error.OutOfMemory,
5109 error.Canceled,
5110 => |e| return e,
5111
5112 error.AnalysisFail => {
5113 // Type resolution failed, making codegen of this `Nav` impossible. This is
5114 // a transitive failure, but it doesn't need recording, because this `Nav`
5115 // semantically depends on the failed type, so when it is changed the value
5116 // of the `Nav` will be updated.
5117 comp.link_prog_node.completeOne();
5118 return;
5119 },
5120 };
5121 }
51225076 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index });
51235077 },
5124 .link_type => |ty| {
5125 const zcu = comp.zcu.?;
5126 if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa);
5127 {
5128 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5129 defer pt.deactivate();
5130 pt.resolveTypeForCodegen(.fromInterned(ty)) catch |err| switch (err) {
5131 error.OutOfMemory,
5132 error.Canceled,
5133 => |e| return e,
5134
5135 error.AnalysisFail => {
5136 // Type resolution failed, making codegen of this type impossible. This is
5137 // a transitive failure, but it doesn't need recording, because this type
5138 // semantically depends on the failed type, so when it is changed the type
5139 // will be updated appropriately.
5140 comp.link_prog_node.completeOne();
5141 return;
5142 },
5143 };
5144 }
5145 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty });
5146 },
51475078 .update_line_number => |tracked_inst| {
5148 try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst });
5079 try comp.link_queue.enqueueZcu(comp, tid, .{ .debug_update_line_number = tracked_inst });
51495080 },
51505081 .analyze_unit => |unit| {
51515082 const tracy_trace = traceNamed(@src(), "analyze_unit");
src/Zcu/PerThread.zig+22-470
......@@ -998,10 +998,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
998998 try sema.flushExports();
999999}
10001000
1001/// Ensures that the layout of the given `struct` or `union` type is fully up-to-date, performing
1002/// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns
1003/// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is
1004/// free to ignore this, since the error is already registered.
1001/// Ensures that the layout of the given `struct`, `union`, or `enum` type is fully up-to-date,
1002/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!), union, or
1003/// enum type. Returns `error.AnalysisFail` if an analysis error is encountered during type
1004/// resolution; the caller is free to ignore this, since the error is already registered.
10051005pub fn ensureTypeLayoutUpToDate(
10061006 pt: Zcu.PerThread,
10071007 ty: Type,
......@@ -1012,7 +1012,8 @@ pub fn ensureTypeLayoutUpToDate(
10121012 defer tracy.end();
10131013
10141014 const zcu = pt.zcu;
1015 const gpa = zcu.gpa;
1015 const comp = zcu.comp;
1016 const gpa = comp.gpa;
10161017
10171018 const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() });
10181019
......@@ -1021,7 +1022,7 @@ pub fn ensureTypeLayoutUpToDate(
10211022 assert(!zcu.analysis_in_progress.contains(anal_unit));
10221023
10231024 const was_outdated = zcu.clearOutdatedState(anal_unit) or
1024 zcu.intern_pool.setWantTypeLayout(zcu.comp.io, ty.toIntern());
1025 zcu.intern_pool.setWantTypeLayout(comp.io, ty.toIntern());
10251026
10261027 if (was_outdated) {
10271028 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.
......@@ -1038,7 +1039,7 @@ pub fn ensureTypeLayoutUpToDate(
10381039 return;
10391040 }
10401041
1041 if (zcu.comp.debugIncremental()) {
1042 if (comp.debugIncremental()) {
10421043 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
10431044 info.last_update_gen = zcu.generation;
10441045 info.deps.clearRetainingCapacity();
......@@ -1078,15 +1079,17 @@ pub fn ensureTypeLayoutUpToDate(
10781079 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),
10791080 else => unreachable,
10801081 };
1081 result catch |err| switch (err) {
1082 error.AnalysisFail => {
1082 const new_success: bool = if (result) s: {
1083 break :s true;
1084 } else |err| switch (err) {
1085 error.AnalysisFail => success: {
10831086 if (!zcu.failed_analysis.contains(anal_unit)) {
10841087 // If this unit caused the error, it would have an entry in `failed_analysis`.
10851088 // Since it does not, this must be a transitive failure.
10861089 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
10871090 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
10881091 }
1089 return error.AnalysisFail;
1092 break :success false;
10901093 },
10911094 error.OutOfMemory,
10921095 error.Canceled,
......@@ -1098,6 +1101,15 @@ pub fn ensureTypeLayoutUpToDate(
10981101 sema.flushExports() catch |err| switch (err) {
10991102 error.OutOfMemory => |e| return e,
11001103 };
1104
1105 // We don't need to `markDependeeOutdated`/`markPoDependeeUpToDate` here, because we already
1106 // marked the layout as outdated at the top of this function. However, we do need to tell the
1107 // debug info logic in the backend about this type.
1108 comp.link_prog_node.increaseEstimatedTotalItems(1);
1109 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{
1110 .ty = ty.toIntern(),
1111 .success = new_success,
1112 } });
11011113}
11021114
11031115/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
......@@ -4102,463 +4114,3 @@ fn printVerboseAir(
41024114 try air.write(w, pt, liveness);
41034115 try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});
41044116}
4105
4106// MLUGG TODO: these functions are all blatant hacks. See if I can remove them!
4107pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
4108 const zcu = pt.zcu;
4109 const ip = &zcu.intern_pool;
4110 if (ty.isGenericPoison()) return;
4111 switch (ty.zigTypeTag(zcu)) {
4112 .type,
4113 .void,
4114 .bool,
4115 .noreturn,
4116 .int,
4117 .float,
4118 .error_set,
4119 .@"opaque",
4120 .comptime_float,
4121 .comptime_int,
4122 .undefined,
4123 .null,
4124 .enum_literal,
4125 => {},
4126
4127 .frame, .@"anyframe" => @panic("TODO resolveTypeForCodegen async frames"),
4128
4129 .optional => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4130 .error_union => try pt.resolveTypeForCodegen(ty.errorUnionPayload(zcu)),
4131 .pointer => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4132 .array => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4133 .vector => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4134
4135 .@"fn" => {
4136 const info = zcu.typeToFunc(ty).?;
4137 for (0..info.param_types.len) |i| {
4138 const param_ty = info.param_types.get(ip)[i];
4139 try pt.resolveTypeForCodegen(.fromInterned(param_ty));
4140 }
4141 try pt.resolveTypeForCodegen(.fromInterned(info.return_type));
4142 },
4143
4144 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
4145 .struct_type => try pt.ensureTypeLayoutUpToDate(ty, null),
4146 .tuple_type => |tuple| for (0..tuple.types.len) |i| {
4147 const field_is_comptime = tuple.values.get(ip)[i] != .none;
4148 if (field_is_comptime) continue;
4149 const field_ty = tuple.types.get(ip)[i];
4150 try pt.resolveTypeForCodegen(.fromInterned(field_ty));
4151 },
4152 else => unreachable,
4153 },
4154
4155 .@"union" => try pt.ensureTypeLayoutUpToDate(ty, null),
4156 .@"enum" => try pt.ensureTypeLayoutUpToDate(ty, null),
4157 }
4158}
4159pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void {
4160 const zcu = pt.zcu;
4161 const ty: Type = switch (val.typeOf(zcu).toIntern()) {
4162 .type_type => if (val.isUndef(zcu)) {
4163 return;
4164 } else val.toType(),
4165 else => |ty| .fromInterned(ty),
4166 };
4167 return pt.resolveTypeForCodegen(ty);
4168}
4169pub fn resolveAirTypesForCodegen(pt: Zcu.PerThread, air: *const Air) Zcu.SemaError!void {
4170 return pt.resolveBodyTypesForCodegen(air, air.getMainBody());
4171}
4172fn resolveBodyTypesForCodegen(pt: Zcu.PerThread, air: *const Air, body: []const Air.Inst.Index) Zcu.SemaError!void {
4173 const zcu = pt.zcu;
4174 const tags = air.instructions.items(.tag);
4175 const datas = air.instructions.items(.data);
4176 for (body) |inst| {
4177 const data = datas[@intFromEnum(inst)];
4178 switch (tags[@intFromEnum(inst)]) {
4179 .inferred_alloc, .inferred_alloc_comptime => unreachable,
4180
4181 .arg => try pt.resolveTypeForCodegen(data.arg.ty.toType()),
4182
4183 .add,
4184 .add_safe,
4185 .add_optimized,
4186 .add_wrap,
4187 .add_sat,
4188 .sub,
4189 .sub_safe,
4190 .sub_optimized,
4191 .sub_wrap,
4192 .sub_sat,
4193 .mul,
4194 .mul_safe,
4195 .mul_optimized,
4196 .mul_wrap,
4197 .mul_sat,
4198 .div_float,
4199 .div_float_optimized,
4200 .div_trunc,
4201 .div_trunc_optimized,
4202 .div_floor,
4203 .div_floor_optimized,
4204 .div_exact,
4205 .div_exact_optimized,
4206 .rem,
4207 .rem_optimized,
4208 .mod,
4209 .mod_optimized,
4210 .max,
4211 .min,
4212 .bit_and,
4213 .bit_or,
4214 .shr,
4215 .shr_exact,
4216 .shl,
4217 .shl_exact,
4218 .shl_sat,
4219 .xor,
4220 .cmp_lt,
4221 .cmp_lt_optimized,
4222 .cmp_lte,
4223 .cmp_lte_optimized,
4224 .cmp_eq,
4225 .cmp_eq_optimized,
4226 .cmp_gte,
4227 .cmp_gte_optimized,
4228 .cmp_gt,
4229 .cmp_gt_optimized,
4230 .cmp_neq,
4231 .cmp_neq_optimized,
4232 .bool_and,
4233 .bool_or,
4234 .store,
4235 .store_safe,
4236 .set_union_tag,
4237 .array_elem_val,
4238 .slice_elem_val,
4239 .ptr_elem_val,
4240 .memset,
4241 .memset_safe,
4242 .memcpy,
4243 .memmove,
4244 .atomic_store_unordered,
4245 .atomic_store_monotonic,
4246 .atomic_store_release,
4247 .atomic_store_seq_cst,
4248 .legalize_vec_elem_val,
4249 => {
4250 try pt.resolveRefTypesForCodegen(data.bin_op.lhs);
4251 try pt.resolveRefTypesForCodegen(data.bin_op.rhs);
4252 },
4253
4254 .not,
4255 .bitcast,
4256 .clz,
4257 .ctz,
4258 .popcount,
4259 .byte_swap,
4260 .bit_reverse,
4261 .abs,
4262 .load,
4263 .fptrunc,
4264 .fpext,
4265 .intcast,
4266 .intcast_safe,
4267 .trunc,
4268 .optional_payload,
4269 .optional_payload_ptr,
4270 .optional_payload_ptr_set,
4271 .wrap_optional,
4272 .unwrap_errunion_payload,
4273 .unwrap_errunion_err,
4274 .unwrap_errunion_payload_ptr,
4275 .unwrap_errunion_err_ptr,
4276 .errunion_payload_ptr_set,
4277 .wrap_errunion_payload,
4278 .wrap_errunion_err,
4279 .struct_field_ptr_index_0,
4280 .struct_field_ptr_index_1,
4281 .struct_field_ptr_index_2,
4282 .struct_field_ptr_index_3,
4283 .get_union_tag,
4284 .slice_len,
4285 .slice_ptr,
4286 .ptr_slice_len_ptr,
4287 .ptr_slice_ptr_ptr,
4288 .array_to_slice,
4289 .int_from_float,
4290 .int_from_float_optimized,
4291 .int_from_float_safe,
4292 .int_from_float_optimized_safe,
4293 .float_from_int,
4294 .splat,
4295 .error_set_has_value,
4296 .addrspace_cast,
4297 .c_va_arg,
4298 .c_va_copy,
4299 => {
4300 try pt.resolveTypeForCodegen(data.ty_op.ty.toType());
4301 try pt.resolveRefTypesForCodegen(data.ty_op.operand);
4302 },
4303
4304 .alloc,
4305 .ret_ptr,
4306 .c_va_start,
4307 => try pt.resolveTypeForCodegen(data.ty),
4308
4309 .ptr_add,
4310 .ptr_sub,
4311 .add_with_overflow,
4312 .sub_with_overflow,
4313 .mul_with_overflow,
4314 .shl_with_overflow,
4315 .slice,
4316 .slice_elem_ptr,
4317 .ptr_elem_ptr,
4318 => {
4319 const bin = air.extraData(Air.Bin, data.ty_pl.payload).data;
4320 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4321 try pt.resolveRefTypesForCodegen(bin.lhs);
4322 try pt.resolveRefTypesForCodegen(bin.rhs);
4323 },
4324
4325 .block,
4326 .loop,
4327 => {
4328 const block = air.unwrapBlock(inst);
4329 try pt.resolveTypeForCodegen(block.ty);
4330 try pt.resolveBodyTypesForCodegen(air, block.body);
4331 },
4332
4333 .dbg_inline_block => {
4334 const block = air.unwrapDbgBlock(inst);
4335 try pt.resolveTypeForCodegen(block.ty);
4336 try pt.resolveBodyTypesForCodegen(air, block.body);
4337 },
4338
4339 .sqrt,
4340 .sin,
4341 .cos,
4342 .tan,
4343 .exp,
4344 .exp2,
4345 .log,
4346 .log2,
4347 .log10,
4348 .floor,
4349 .ceil,
4350 .round,
4351 .trunc_float,
4352 .neg,
4353 .neg_optimized,
4354 .is_null,
4355 .is_non_null,
4356 .is_null_ptr,
4357 .is_non_null_ptr,
4358 .is_err,
4359 .is_non_err,
4360 .is_err_ptr,
4361 .is_non_err_ptr,
4362 .ret,
4363 .ret_safe,
4364 .ret_load,
4365 .is_named_enum_value,
4366 .tag_name,
4367 .error_name,
4368 .cmp_lt_errors_len,
4369 .c_va_end,
4370 .set_err_return_trace,
4371 => try pt.resolveRefTypesForCodegen(data.un_op),
4372
4373 .br, .switch_dispatch => try pt.resolveRefTypesForCodegen(data.br.operand),
4374
4375 .cmp_vector,
4376 .cmp_vector_optimized,
4377 => {
4378 const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data;
4379 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4380 try pt.resolveRefTypesForCodegen(extra.lhs);
4381 try pt.resolveRefTypesForCodegen(extra.rhs);
4382 },
4383
4384 .reduce,
4385 .reduce_optimized,
4386 => try pt.resolveRefTypesForCodegen(data.reduce.operand),
4387
4388 .struct_field_ptr,
4389 .struct_field_val,
4390 => {
4391 const extra = air.extraData(Air.StructField, data.ty_pl.payload).data;
4392 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4393 try pt.resolveRefTypesForCodegen(extra.struct_operand);
4394 },
4395
4396 .shuffle_one => {
4397 const unwrapped = air.unwrapShuffleOne(zcu, inst);
4398 try pt.resolveTypeForCodegen(unwrapped.result_ty);
4399 try pt.resolveRefTypesForCodegen(unwrapped.operand);
4400 for (unwrapped.mask) |m| switch (m.unwrap()) {
4401 .elem => {},
4402 .value => |val| try pt.resolveValueTypesForCodegen(.fromInterned(val)),
4403 };
4404 },
4405
4406 .shuffle_two => {
4407 const unwrapped = air.unwrapShuffleTwo(zcu, inst);
4408 try pt.resolveTypeForCodegen(unwrapped.result_ty);
4409 try pt.resolveRefTypesForCodegen(unwrapped.operand_a);
4410 try pt.resolveRefTypesForCodegen(unwrapped.operand_b);
4411 // No values to check because there are no comptime-known values other than undef
4412 },
4413
4414 .cmpxchg_weak,
4415 .cmpxchg_strong,
4416 => {
4417 const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data;
4418 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4419 try pt.resolveRefTypesForCodegen(extra.ptr);
4420 try pt.resolveRefTypesForCodegen(extra.expected_value);
4421 try pt.resolveRefTypesForCodegen(extra.new_value);
4422 },
4423
4424 .aggregate_init => {
4425 const ty = data.ty_pl.ty.toType();
4426 const elems_len: usize = @intCast(ty.arrayLen(zcu));
4427 const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]);
4428 try pt.resolveTypeForCodegen(ty);
4429 if (ty.zigTypeTag(zcu) == .@"struct") {
4430 for (elems, 0..) |elem, elem_idx| {
4431 if (ty.structFieldIsComptime(elem_idx, zcu)) continue;
4432 try pt.resolveRefTypesForCodegen(elem);
4433 }
4434 } else {
4435 for (elems) |elem| {
4436 try pt.resolveRefTypesForCodegen(elem);
4437 }
4438 }
4439 },
4440
4441 .union_init => {
4442 const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data;
4443 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4444 try pt.resolveRefTypesForCodegen(extra.init);
4445 },
4446
4447 .field_parent_ptr => {
4448 const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data;
4449 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4450 try pt.resolveRefTypesForCodegen(extra.field_ptr);
4451 },
4452
4453 .atomic_load => try pt.resolveRefTypesForCodegen(data.atomic_load.ptr),
4454
4455 .prefetch => try pt.resolveRefTypesForCodegen(data.prefetch.ptr),
4456
4457 .runtime_nav_ptr => try pt.resolveTypeForCodegen(.fromInterned(data.ty_nav.ty)),
4458
4459 .select,
4460 .mul_add,
4461 .legalize_vec_store_elem,
4462 => {
4463 const bin = air.extraData(Air.Bin, data.pl_op.payload).data;
4464 try pt.resolveRefTypesForCodegen(data.pl_op.operand);
4465 try pt.resolveRefTypesForCodegen(bin.lhs);
4466 try pt.resolveRefTypesForCodegen(bin.rhs);
4467 },
4468
4469 .atomic_rmw => {
4470 const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data;
4471 try pt.resolveRefTypesForCodegen(data.pl_op.operand);
4472 try pt.resolveRefTypesForCodegen(extra.operand);
4473 },
4474
4475 .call,
4476 .call_always_tail,
4477 .call_never_tail,
4478 .call_never_inline,
4479 => {
4480 const call = air.unwrapCall(inst);
4481 try pt.resolveRefTypesForCodegen(call.callee);
4482 for (call.args) |arg| try pt.resolveRefTypesForCodegen(arg);
4483 },
4484
4485 .dbg_var_ptr,
4486 .dbg_var_val,
4487 .dbg_arg_inline,
4488 => try pt.resolveRefTypesForCodegen(data.pl_op.operand),
4489
4490 .@"try", .try_cold => {
4491 const @"try" = air.unwrapTry(inst);
4492 try pt.resolveRefTypesForCodegen(@"try".error_union);
4493 try pt.resolveBodyTypesForCodegen(air, @"try".else_body);
4494 },
4495
4496 .try_ptr, .try_ptr_cold => {
4497 const try_ptr = air.unwrapTryPtr(inst);
4498 try pt.resolveTypeForCodegen(try_ptr.error_union_payload_ptr_ty.toType());
4499 try pt.resolveRefTypesForCodegen(try_ptr.error_union_ptr);
4500 try pt.resolveBodyTypesForCodegen(air, try_ptr.else_body);
4501 },
4502
4503 .cond_br => {
4504 const cond_br = air.unwrapCondBr(inst);
4505 try pt.resolveRefTypesForCodegen(cond_br.condition);
4506 try pt.resolveBodyTypesForCodegen(air, cond_br.then_body);
4507 try pt.resolveBodyTypesForCodegen(air, cond_br.else_body);
4508 },
4509
4510 .switch_br, .loop_switch_br => {
4511 const switch_br = air.unwrapSwitch(inst);
4512 try pt.resolveRefTypesForCodegen(switch_br.operand);
4513 var it = switch_br.iterateCases();
4514 while (it.next()) |case| {
4515 for (case.items) |item| {
4516 try pt.resolveRefTypesForCodegen(item);
4517 }
4518 for (case.ranges) |range| {
4519 try pt.resolveRefTypesForCodegen(range[0]);
4520 try pt.resolveRefTypesForCodegen(range[1]);
4521 }
4522 try pt.resolveBodyTypesForCodegen(air, case.body);
4523 }
4524 try pt.resolveBodyTypesForCodegen(air, it.elseBody());
4525 },
4526
4527 .assembly => {
4528 const @"asm" = air.unwrapAsm(inst);
4529 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4530 for (@"asm".outputs) |output| if (output != .none) try pt.resolveRefTypesForCodegen(output);
4531 for (@"asm".inputs) |input| if (input != .none) try pt.resolveRefTypesForCodegen(input);
4532 },
4533
4534 .legalize_compiler_rt_call => {
4535 const compiler_rt_call = air.unwrapCompilerRtCall(inst);
4536 for (compiler_rt_call.args) |arg| try pt.resolveRefTypesForCodegen(arg);
4537 },
4538
4539 .trap,
4540 .breakpoint,
4541 .ret_addr,
4542 .frame_addr,
4543 .unreach,
4544 .wasm_memory_size,
4545 .wasm_memory_grow,
4546 .work_item_id,
4547 .work_group_size,
4548 .work_group_id,
4549 .dbg_stmt,
4550 .dbg_empty_stmt,
4551 .err_return_trace,
4552 .save_err_return_trace_index,
4553 .repeat,
4554 => {},
4555 }
4556 }
4557}
4558fn resolveRefTypesForCodegen(pt: Zcu.PerThread, ref: Air.Inst.Ref) Zcu.SemaError!void {
4559 const ip_index = ref.toInterned() orelse {
4560 // `ref` refers to a prior instruction, which we already did the resolution for.
4561 return;
4562 };
4563 return pt.resolveValueTypesForCodegen(.fromInterned(ip_index));
4564}
src/codegen.zig+23-14
......@@ -700,7 +700,14 @@ fn lowerPtr(
700700 };
701701 return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);
702702 },
703 .arr_elem, .comptime_field, .comptime_alloc => unreachable,
703 .arr_elem => |arr_elem| {
704 const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu);
705 assert(base_ptr_ty.ptrSize(zcu) == .many);
706 const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu);
707 return lowerPtr(bin_file, pt, src_loc, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index);
708 },
709 .comptime_alloc => unreachable,
710 .comptime_field => unreachable,
704711 };
705712}
706713
......@@ -781,9 +788,8 @@ fn lowerNavRef(
781788 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
782789 const is_obj = lf.comp.config.output_mode == .Obj;
783790 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));
784 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
785791
786 if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) {
792 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {
787793 try w.splatByteAll(0xaa, ptr_width_bytes);
788794 return;
789795 }
......@@ -795,7 +801,7 @@ fn lowerNavRef(
795801 dev.check(link.File.Tag.wasm.devFeature());
796802 const wasm = lf.cast(.wasm).?;
797803 assert(reloc_parent == .none);
798 if (is_fn_body) {
804 if (nav_ty.zigTypeTag(zcu) == .@"fn") {
799805 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);
800806 if (!gop.found_existing) gop.value_ptr.* = {};
801807 if (is_obj) {
......@@ -1025,23 +1031,26 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
10251031 .pointer => switch (ty.ptrSize(zcu)) {
10261032 .slice => {},
10271033 .one, .many, .c => {
1028 const elem_ty = ty.childType(zcu);
10291034 const ptr = ip.indexToKey(val.toIntern()).ptr;
10301035 if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
10311036 if (ptr.byte_offset == 0) switch (ptr.base_addr) {
10321037 .int => unreachable, // handled above
10331038
1034 .nav => |nav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
1035 return .{ .lea_nav = nav };
1036 } else {
1037 // Create the 0xaa bit pattern...
1038 const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
1039 // ...but align the pointer
1040 const alignment = zcu.navAlignment(nav);
1041 return .{ .immediate = alignment.forward(undef_ptr_bits) };
1039 .nav => |nav_index| {
1040 const nav = ip.getNav(nav_index);
1041 const nav_ty: Type = .fromInterned(nav.typeOf(ip));
1042 if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
1043 return .{ .lea_nav = nav_index };
1044 } else {
1045 // Create the 0xaa bit pattern...
1046 const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
1047 // ...but align the pointer
1048 const alignment = zcu.navAlignment(nav_index);
1049 return .{ .immediate = alignment.forward(undef_ptr_bits) };
1050 }
10421051 },
10431052
1044 .uav => |uav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
1053 .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
10451054 return .{ .lea_uav = uav };
10461055 } else {
10471056 // Create the 0xaa bit pattern...
src/link.zig+34-12
......@@ -798,14 +798,27 @@ pub const File = struct {
798798 };
799799
800800 /// Never called when LLVM is codegenning the ZCU.
801 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
801 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) UpdateContainerTypeError!void {
802802 assert(base.comp.zcu.?.llvm_object == null);
803803 switch (base.tag) {
804804 .lld => unreachable,
805805 else => {},
806806 inline .elf => |tag| {
807807 dev.check(tag.devFeature());
808 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty);
808 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success);
809 },
810 }
811 }
812
813 /// Never called when LLVM is codegenning the ZCU.
814 fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
815 assert(base.comp.zcu.?.llvm_object == null);
816 switch (base.tag) {
817 .lld => unreachable,
818 else => {},
819 inline .elf => |tag| {
820 dev.check(tag.devFeature());
821 return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty);
809822 },
810823 }
811824 }
......@@ -1375,8 +1388,14 @@ pub const ZcuTask = union(enum) {
13751388 link_nav: InternPool.Nav.Index,
13761389 /// Write the machine code for a function to the output file.
13771390 link_func: Zcu.CodegenTaskPool.Index,
1378 link_type: InternPool.Index,
1379 update_line_number: InternPool.TrackedInst.Index,
1391 /// This struct/union/enum type has finished type resolution (successfully or otherwise), so the
1392 /// linker can now lower debug information for this type (and any structural types which depend
1393 /// on it, such as `?T`, `struct { T }`, `[2]T`, etc).
1394 debug_update_container_type: struct {
1395 ty: InternPool.Index,
1396 success: bool,
1397 },
1398 debug_update_line_number: InternPool.TrackedInst.Index,
13801399};
13811400
13821401pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
......@@ -1563,21 +1582,24 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
15631582 }
15641583 break :nav ip.indexToKey(func).func.owner_nav;
15651584 },
1566 .link_type => |ty| nav: {
1567 const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);
1568 const nav_prog_node = comp.link_prog_node.start(name, 0);
1569 defer nav_prog_node.end();
1570 if (zcu.llvm_object == null) {
1585 .debug_update_container_type => |container_update| nav: {
1586 const name = Type.fromInterned(container_update.ty).containerTypeName(ip).toSlice(ip);
1587 const ty_prog_node = comp.link_prog_node.start(name, 0);
1588 defer ty_prog_node.end();
1589 if (zcu.llvm_object) |llvm_object| {
1590 _ = llvm_object;
1591 @compileError("MLUGG TODO");
1592 } else {
15711593 if (comp.bin_file) |lf| {
1572 lf.updateContainerType(pt, ty) catch |err| switch (err) {
1594 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
15731595 error.OutOfMemory => diags.setAllocFailure(),
1574 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
1596 error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)),
15751597 };
15761598 }
15771599 }
15781600 break :nav null;
15791601 },
1580 .update_line_number => |ti| nav: {
1602 .debug_update_line_number => |ti| nav: {
15811603 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);
15821604 defer nav_prog_node.end();
15831605 if (pt.zcu.llvm_object == null) {
src/link/DebugConstPool.zig created+287
......@@ -0,0 +1,287 @@
1/// Helper type for debug information implementations (such as `link.Dwarf`) to help them emit
2/// information about comptime-known values (constants), including types.
3///
4/// Every constant with associated debug information is assigned an `Index` by calling `get`. The
5/// pool will track which container types do and do not have a resolved layout, as well as which
6/// constants in the pool depend on which types, and call into the implementation to emit debug
7/// information for a constant only when all information is available.
8///
9/// Indices into the pool are dense, and constants are never removed from the pool, so the debug
10/// info implementation can store information for each one with a simple `ArrayList`.
11///
12/// To use `DebugConstPool`, the debug info implementation is required to:
13/// * forward `updateContainerType` calls to its `DebugConstPool`
14/// * expose some callback functions---see functions in `DebugInfo`
15/// * ensure that any `get` call is eventually followed by a `flushPending` call
16const DebugConstPool = @This();
17
18values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
19pending: std.ArrayList(Index),
20complete_containers: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
21container_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, ContainerDepEntry.Index),
22container_dep_entries: std.ArrayList(ContainerDepEntry),
23
24pub const empty: DebugConstPool = .{
25 .values = .empty,
26 .pending = .empty,
27 .complete_containers = .empty,
28 .container_deps = .empty,
29 .container_dep_entries = .empty,
30};
31
32pub fn deinit(pool: *DebugConstPool, gpa: Allocator) void {
33 pool.values.deinit(gpa);
34 pool.pending.deinit(gpa);
35 pool.complete_containers.deinit(gpa);
36 pool.container_deps.deinit(gpa);
37 pool.container_dep_entries.deinit(gpa);
38}
39
40pub const Index = enum(u32) {
41 _,
42 pub fn val(i: Index, pool: *const DebugConstPool) InternPool.Index {
43 return pool.values.keys()[@intFromEnum(i)];
44 }
45};
46
47pub const DebugInfo = union(enum) {
48 dwarf: *@import("Dwarf.zig"),
49 llvm: @import("../codegen/llvm.zig").Object.Ptr,
50
51 /// Inform the debug info implementation that the new constant `val` was added to the pool at
52 /// the given index (which equals the current pool length) due to a `get` call. It is guaranteed
53 /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete`
54 /// following the `addConst` call, to actually populate the constant's debug info.
55 fn addConst(
56 di: DebugInfo,
57 pt: Zcu.PerThread,
58 index: Index,
59 val: InternPool.Index,
60 ) !void {
61 switch (di) {
62 inline else => |impl| return impl.addConst(pt, index, val),
63 }
64 }
65
66 /// Tell the debug info implementation to emit information for the constant `val`, which is in
67 /// the pool at the given index. `val` is "complete", which means:
68 /// * If it is a type, its layout is known.
69 /// * Otherwise, the layout of its type is known.
70 fn updateConst(
71 di: DebugInfo,
72 pt: Zcu.PerThread,
73 index: Index,
74 val: InternPool.Index,
75 ) !void {
76 switch (di) {
77 inline else => |impl| return impl.updateConst(pt, index, val),
78 }
79 }
80
81 /// Tell the debug info implementation to emit information for the constant `val`, which is in
82 /// the pool at the given index. `val` is "incomplete", meaning the implementation cannot emit
83 /// full information for it (for instance, perhaps it is a struct type which was never actually
84 /// initialized so never had its layout resolved). Instead, the implementation must emit some
85 /// form of placeholder entry representing an incomplete/unknown constant.
86 fn updateConstIncomplete(
87 di: DebugInfo,
88 pt: Zcu.PerThread,
89 index: Index,
90 val: InternPool.Index,
91 ) !void {
92 switch (di) {
93 inline else => |impl| return impl.updateConstIncomplete(pt, index, val),
94 }
95 }
96};
97
98const ContainerDepEntry = extern struct {
99 next: ContainerDepEntry.Index.Optional,
100 depender: DebugConstPool.Index,
101 const Index = enum(u32) {
102 _,
103 const Optional = enum(u32) {
104 none = std.math.maxInt(u32),
105 _,
106 fn unwrap(o: Optional) ?ContainerDepEntry.Index {
107 return switch (o) {
108 .none => null,
109 else => @enumFromInt(@intFromEnum(o)),
110 };
111 }
112 };
113 fn toOptional(i: ContainerDepEntry.Index) Optional {
114 return @enumFromInt(@intFromEnum(i));
115 }
116 fn ptr(i: ContainerDepEntry.Index, pool: *DebugConstPool) *ContainerDepEntry {
117 return &pool.container_dep_entries.items[@intFromEnum(i)];
118 }
119 };
120};
121
122/// Calls to `link.File.updateContainerType` must be forwarded to this function so that the debug
123/// constant pool has up-to-date information about the resolution status of types.
124pub fn updateContainerType(
125 pool: *DebugConstPool,
126 pt: Zcu.PerThread,
127 di: DebugInfo,
128 container_ty: InternPool.Index,
129 success: bool,
130) !void {
131 if (success) {
132 const gpa = pt.zcu.comp.gpa;
133 try pool.complete_containers.put(gpa, container_ty, {});
134 } else {
135 _ = pool.complete_containers.fetchSwapRemove(container_ty);
136 }
137 var opt_dep = pool.container_deps.get(container_ty);
138 while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) {
139 try pool.update(pt, di, dep.ptr(pool).depender);
140 }
141}
142
143/// After this is called, there may be a constant for which debug information (complete or not) has
144/// not yet been emitted, so the user must call `flushPending` at some point after this call.
145pub fn get(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, val: InternPool.Index) !DebugConstPool.Index {
146 const zcu = pt.zcu;
147 const ip = &zcu.intern_pool;
148 const gpa = zcu.comp.gpa;
149 const gop = try pool.values.getOrPut(gpa, val);
150 const index: DebugConstPool.Index = @enumFromInt(gop.index);
151 if (!gop.found_existing) {
152 const ty: Type = switch (ip.typeOf(val)) {
153 .type_type => if (ip.isUndef(val)) .type else .fromInterned(val),
154 else => |ty| .fromInterned(ty),
155 };
156 try pool.registerTypeDeps(index, ty, zcu);
157 try pool.pending.append(gpa, index);
158 try di.addConst(pt, index, val);
159 }
160 return index;
161}
162pub fn flushPending(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo) !void {
163 while (pool.pending.pop()) |pending_ty| {
164 try pool.update(pt, di, pending_ty);
165 }
166}
167
168fn update(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, index: DebugConstPool.Index) !void {
169 const zcu = pt.zcu;
170 const ip = &zcu.intern_pool;
171 const val = index.val(pool);
172 const ty: Type = switch (ip.typeOf(val)) {
173 .type_type => if (ip.isUndef(val)) .type else .fromInterned(val),
174 else => |ty| .fromInterned(ty),
175 };
176 if (pool.checkType(ty, zcu)) {
177 try di.updateConst(pt, index, val);
178 } else {
179 try di.updateConstIncomplete(pt, index, val);
180 }
181}
182fn checkType(pool: *const DebugConstPool, ty: Type, zcu: *const Zcu) bool {
183 if (ty.isGenericPoison()) return true;
184 return switch (ty.zigTypeTag(zcu)) {
185 .type,
186 .void,
187 .bool,
188 .noreturn,
189 .int,
190 .float,
191 .pointer,
192 .comptime_float,
193 .comptime_int,
194 .undefined,
195 .null,
196 .error_set,
197 .@"opaque",
198 .frame,
199 .@"anyframe",
200 .enum_literal,
201 => true,
202
203 .array, .vector => pool.checkType(ty.childType(zcu), zcu),
204 .optional => pool.checkType(ty.optionalChild(zcu), zcu),
205 .error_union => pool.checkType(ty.errorUnionPayload(zcu), zcu),
206 .@"fn" => {
207 const ip = &zcu.intern_pool;
208 const func = ip.indexToKey(ty.toIntern()).func_type;
209 for (func.param_types.get(ip)) |param_ty_ip| {
210 if (!pool.checkType(.fromInterned(param_ty_ip), zcu)) return false;
211 }
212 return pool.checkType(.fromInterned(func.return_type), zcu);
213 },
214 .@"struct" => if (ty.isTuple(zcu)) {
215 for (0..ty.structFieldCount(zcu)) |field_index| {
216 if (!pool.checkType(ty.fieldType(field_index, zcu), zcu)) return false;
217 }
218 return true;
219 } else {
220 return pool.complete_containers.contains(ty.toIntern());
221 },
222 .@"union", .@"enum" => {
223 return pool.complete_containers.contains(ty.toIntern());
224 },
225 };
226}
227fn registerTypeDeps(pool: *DebugConstPool, root: Index, ty: Type, zcu: *const Zcu) Allocator.Error!void {
228 if (ty.isGenericPoison()) return;
229 switch (ty.zigTypeTag(zcu)) {
230 .type,
231 .void,
232 .bool,
233 .noreturn,
234 .int,
235 .float,
236 .pointer,
237 .comptime_float,
238 .comptime_int,
239 .undefined,
240 .null,
241 .error_set,
242 .@"opaque",
243 .frame,
244 .@"anyframe",
245 .enum_literal,
246 => {},
247
248 .array, .vector => try pool.registerTypeDeps(root, ty.childType(zcu), zcu),
249 .optional => try pool.registerTypeDeps(root, ty.optionalChild(zcu), zcu),
250 .error_union => try pool.registerTypeDeps(root, ty.errorUnionPayload(zcu), zcu),
251 .@"fn" => {
252 const ip = &zcu.intern_pool;
253 const func = ip.indexToKey(ty.toIntern()).func_type;
254 for (func.param_types.get(ip)) |param_ty_ip| {
255 try pool.registerTypeDeps(root, .fromInterned(param_ty_ip), zcu);
256 }
257 try pool.registerTypeDeps(root, .fromInterned(func.return_type), zcu);
258 },
259 .@"struct", .@"union", .@"enum" => if (ty.isTuple(zcu)) {
260 for (0..ty.structFieldCount(zcu)) |field_index| {
261 try pool.registerTypeDeps(root, ty.fieldType(field_index, zcu), zcu);
262 }
263 } else {
264 // `ty` is a container; register the dependency.
265
266 const gpa = zcu.comp.gpa;
267 try pool.container_deps.ensureUnusedCapacity(gpa, 1);
268 try pool.container_dep_entries.ensureUnusedCapacity(gpa, 1);
269 errdefer comptime unreachable;
270
271 const gop = pool.container_deps.getOrPutAssumeCapacity(ty.toIntern());
272 const entry: ContainerDepEntry.Index = @enumFromInt(pool.container_dep_entries.items.len);
273 pool.container_dep_entries.appendAssumeCapacity(.{
274 .next = if (gop.found_existing) gop.value_ptr.toOptional() else .none,
275 .depender = root,
276 });
277 gop.value_ptr.* = entry;
278 },
279 }
280}
281
282const std = @import("std");
283const Allocator = std.mem.Allocator;
284
285const InternPool = @import("../InternPool.zig");
286const Type = @import("../Type.zig");
287const Zcu = @import("../Zcu.zig");
src/link/Dwarf.zig+660-898
......@@ -18,6 +18,7 @@ const codegen = @import("../codegen.zig");
1818const dev = @import("../dev.zig");
1919const link = @import("../link.zig");
2020const target_info = @import("../target.zig");
21const DebugConstPool = @import("DebugConstPool.zig");
2122
2223gpa: Allocator,
2324bin_file: *link.File,
......@@ -25,9 +26,11 @@ format: DW.Format,
2526endian: std.builtin.Endian,
2627address_size: AddressSize,
2728
29const_pool: DebugConstPool,
30
2831mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo),
29types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index),
30values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index),
32/// Indices are `DebugConstPool.Index`.
33values: std.ArrayList(struct { Unit.Index, Entry.Index }),
3134navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index),
3235decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index),
3336
......@@ -1034,15 +1037,14 @@ const Entry = struct {
10341037 });
10351038 const zcu = dwarf.bin_file.comp.zcu.?;
10361039 const ip = &zcu.intern_pool;
1037 for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| {
1038 const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index|
1039 dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?) catch unreachable
1040 else
1041 .main;
1042 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)
1043 log.err("missing Type({f}({d}))", .{
1044 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),
1045 @intFromEnum(ty),
1040 for (0.., dwarf.values.items) |raw_index, unit_and_entry| {
1041 const index: DebugConstPool.Index = @enumFromInt(raw_index);
1042 const val = index.val(&dwarf.const_pool);
1043 const val_unit, const val_entry = unit_and_entry;
1044 if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry)
1045 log.err("missing Value({f}({d}))", .{
1046 Value.fromInterned(val).fmtValue(.{ .tid = .main, .zcu = zcu }),
1047 @intFromEnum(val),
10461048 });
10471049 }
10481050 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {
......@@ -1520,7 +1522,6 @@ pub const WipNav = struct {
15201522 debug_info: Writer.Allocating,
15211523 debug_line: Writer.Allocating,
15221524 debug_loclists: Writer.Allocating,
1523 pending_lazy: PendingLazy,
15241525
15251526 pub fn deinit(wip_nav: *WipNav) void {
15261527 const gpa = wip_nav.dwarf.gpa;
......@@ -1529,8 +1530,6 @@ pub const WipNav = struct {
15291530 wip_nav.debug_info.deinit();
15301531 wip_nav.debug_line.deinit();
15311532 wip_nav.debug_loclists.deinit();
1532 wip_nav.pending_lazy.types.deinit(gpa);
1533 wip_nav.pending_lazy.values.deinit(gpa);
15341533 }
15351534
15361535 pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void {
......@@ -1945,6 +1944,12 @@ pub const WipNav = struct {
19451944 try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0);
19461945 }
19471946
1947 fn strpFmt(wip_nav: *WipNav, comptime fmt: []const u8, args: anytype) (UpdateError || Writer.Error)!void {
1948 const str = try std.fmt.allocPrint(wip_nav.dwarf.gpa, fmt, args);
1949 defer wip_nav.dwarf.gpa.free(str);
1950 return wip_nav.strp(str);
1951 }
1952
19481953 const ExprLocCounter = struct {
19491954 dw: Writer.Discarding,
19501955 section_offset_bytes: u32,
......@@ -2054,74 +2059,16 @@ pub const WipNav = struct {
20542059 try dfw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size));
20552060 }
20562061
2057 fn getNavEntry(
2058 wip_nav: *WipNav,
2059 nav_index: InternPool.Nav.Index,
2060 ) UpdateError!struct { Unit.Index, Entry.Index } {
2061 const zcu = wip_nav.pt.zcu;
2062 const ip = &zcu.intern_pool;
2063 const nav = ip.getNav(nav_index);
2064 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?);
2065 const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
2066 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
2067 const entry = try wip_nav.dwarf.addCommonEntry(unit);
2068 gop.value_ptr.* = entry;
2069 return .{ unit, entry };
2070 }
2071
20722062 fn refNav(
20732063 wip_nav: *WipNav,
20742064 nav_index: InternPool.Nav.Index,
20752065 ) (UpdateError || Writer.Error)!void {
2076 const unit, const entry = try wip_nav.getNavEntry(nav_index);
2066 const unit, const entry = try wip_nav.dwarf.getNavEntry(nav_index);
20772067 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
20782068 }
20792069
2080 fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } {
2081 const zcu = wip_nav.pt.zcu;
2082 const ip = &zcu.intern_pool;
2083 const maybe_inst_index = ty.typeDeclInst(zcu);
2084 const unit = if (maybe_inst_index) |inst_index| switch (switch (ip.indexToKey(ty.toIntern())) {
2085 else => unreachable,
2086 .struct_type => ip.loadStructType(ty.toIntern()).name_nav,
2087 .union_type => ip.loadUnionType(ty.toIntern()).name_nav,
2088 .enum_type => ip.loadEnumType(ty.toIntern()).name_nav,
2089 .opaque_type => ip.loadOpaqueType(ty.toIntern()).name_nav,
2090 }) {
2091 .none => try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?),
2092 else => |name_nav| return wip_nav.getNavEntry(name_nav.unwrap().?),
2093 } else .main;
2094 const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern());
2095 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
2096 const entry = try wip_nav.dwarf.addCommonEntry(unit);
2097 gop.value_ptr.* = entry;
2098 if (maybe_inst_index == null) try wip_nav.pending_lazy.types.append(wip_nav.dwarf.gpa, ty.toIntern());
2099 return .{ unit, entry };
2100 }
2101
21022070 fn refType(wip_nav: *WipNav, ty: Type) (UpdateError || Writer.Error)!void {
2103 const unit, const entry = try wip_nav.getTypeEntry(ty);
2104 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
2105 }
2106
2107 fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } {
2108 const zcu = wip_nav.pt.zcu;
2109 const ip = &zcu.intern_pool;
2110 const ty = value.typeOf(zcu);
2111 if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu));
2112 if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType());
2113 if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(switch (ip.indexToKey(value.toIntern())) {
2114 else => unreachable,
2115 .func => |func| func.owner_nav,
2116 .@"extern" => |@"extern"| @"extern".owner_nav,
2117 });
2118 const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern());
2119 const unit: Unit.Index = .main;
2120 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
2121 const entry = try wip_nav.dwarf.addCommonEntry(unit);
2122 gop.value_ptr.* = entry;
2123 try wip_nav.pending_lazy.values.append(wip_nav.dwarf.gpa, value.toIntern());
2124 return .{ unit, entry };
2071 return wip_nav.refValue(ty.toValue());
21252072 }
21262073
21272074 fn refValue(wip_nav: *WipNav, value: Value) (UpdateError || Writer.Error)!void {
......@@ -2129,6 +2076,15 @@ pub const WipNav = struct {
21292076 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
21302077 }
21312078
2079 fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } {
2080 if (value.typeOf(wip_nav.pt.zcu).toIntern() != .type_type) {
2081 assert(value.typeOf(wip_nav.pt.zcu).comptimeOnly(wip_nav.pt.zcu));
2082 }
2083 const dwarf = wip_nav.dwarf;
2084 const index = try dwarf.const_pool.get(wip_nav.pt, .{ .dwarf = dwarf }, value.toIntern());
2085 return dwarf.values.items[@intFromEnum(index)];
2086 }
2087
21322088 fn refForward(wip_nav: *WipNav) (Allocator.Error || Writer.Error)!u32 {
21332089 const dwarf = wip_nav.dwarf;
21342090 const diw = &wip_nav.debug_info.writer;
......@@ -2156,7 +2112,7 @@ pub const WipNav = struct {
21562112 ) (UpdateError || Writer.Error)!void {
21572113 const ty = val.typeOf(wip_nav.pt.zcu);
21582114 const diw = &wip_nav.debug_info.writer;
2159 const size = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0;
2115 const size = ty.abiSize(wip_nav.pt.zcu);
21602116 try diw.writeUleb128(size);
21612117 if (size == 0) return;
21622118 const old_end = wip_nav.debug_info.writer.end;
......@@ -2331,22 +2287,6 @@ pub const WipNav = struct {
23312287 try wip_nav.refType(parent_type.?);
23322288 try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0);
23332289 }
2334
2335 const PendingLazy = struct {
2336 types: std.ArrayList(InternPool.Index),
2337 values: std.ArrayList(InternPool.Index),
2338
2339 const empty: PendingLazy = .{ .types = .empty, .values = .empty };
2340 };
2341
2342 fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) (UpdateError || Writer.Error)!void {
2343 while (true) if (wip_nav.pending_lazy.types.pop()) |pending_ty|
2344 try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, pending_ty, &wip_nav.pending_lazy)
2345 else if (wip_nav.pending_lazy.values.pop()) |pending_val|
2346 try wip_nav.dwarf.updateLazyValue(wip_nav.pt, src_loc, pending_val, &wip_nav.pending_lazy)
2347 else
2348 break;
2349 }
23502290};
23512291
23522292/// When allocating, the ideal_capacity is calculated by
......@@ -2372,8 +2312,9 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
23722312 },
23732313 .endian = target.cpu.arch.endian(),
23742314
2315 .const_pool = .empty,
2316
23752317 .mods = .empty,
2376 .types = .empty,
23772318 .values = .empty,
23782319 .navs = .empty,
23792320 .decls = .empty,
......@@ -2544,9 +2485,9 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void {
25442485
25452486pub fn deinit(dwarf: *Dwarf) void {
25462487 const gpa = dwarf.gpa;
2488 dwarf.const_pool.deinit(gpa);
25472489 for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa);
25482490 dwarf.mods.deinit(gpa);
2549 dwarf.types.deinit(gpa);
25502491 dwarf.values.deinit(gpa);
25512492 dwarf.navs.deinit(gpa);
25522493 dwarf.decls.deinit(gpa);
......@@ -2562,6 +2503,21 @@ pub fn deinit(dwarf: *Dwarf) void {
25622503 dwarf.* = undefined;
25632504}
25642505
2506fn getNavEntry(
2507 dwarf: *Dwarf,
2508 nav_index: InternPool.Nav.Index,
2509) UpdateError!struct { Unit.Index, Entry.Index } {
2510 const zcu = dwarf.bin_file.comp.zcu.?;
2511 const ip = &zcu.intern_pool;
2512 const nav = ip.getNav(nav_index);
2513 const unit = try dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?);
2514 const gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
2515 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
2516 const entry = try dwarf.addCommonEntry(unit);
2517 gop.value_ptr.* = entry;
2518 return .{ unit, entry };
2519}
2520
25652521fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {
25662522 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);
25672523 const unit: Unit.Index = @enumFromInt(mod_gop.index);
......@@ -2622,6 +2578,10 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo {
26222578 return &dwarf.mods.values()[@intFromEnum(unit)];
26232579}
26242580
2581fn getUnitModule(dwarf: *Dwarf, unit: Unit.Index) *Module {
2582 return dwarf.mods.keys()[@intFromEnum(unit)];
2583}
2584
26252585pub fn initWipNav(
26262586 dwarf: *Dwarf,
26272587 pt: Zcu.PerThread,
......@@ -2683,7 +2643,6 @@ fn initWipNavInner(
26832643 .debug_info = .init(dwarf.gpa),
26842644 .debug_line = .init(dwarf.gpa),
26852645 .debug_loclists = .init(dwarf.gpa),
2686 .pending_lazy = .empty,
26872646 };
26882647 errdefer wip_nav.deinit();
26892648
......@@ -3050,7 +3009,7 @@ fn finishWipNavWriterError(
30503009 }
30513010 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written());
30523011
3053 try wip_nav.updateLazy(zcu.navSrcLoc(nav_index));
3012 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
30543013}
30553014
30563015pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {
......@@ -3087,34 +3046,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
30873046 return;
30883047 }
30893048
3090 var wip_nav: WipNav = .{
3091 .dwarf = dwarf,
3092 .pt = pt,
3093 .unit = try dwarf.getUnit(file.mod.?),
3094 .entry = undefined,
3095 .any_children = false,
3096 .func = .none,
3097 .func_sym_index = undefined,
3098 .func_high_pc = undefined,
3099 .blocks = undefined,
3100 .cfi = undefined,
3101 .debug_frame = .init(dwarf.gpa),
3102 .debug_info = .init(dwarf.gpa),
3103 .debug_line = .init(dwarf.gpa),
3104 .debug_loclists = .init(dwarf.gpa),
3105 .pending_lazy = .empty,
3106 };
3107 defer wip_nav.deinit();
3108
3109 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
3110 errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();
3111
31123049 const tag: union(enum) {
3113 done,
3114 decl_alias,
3115 decl_var,
3116 decl_const,
3117 decl_func_alias: InternPool.Nav.Index,
3050 alias,
3051 @"var",
3052 @"const",
3053 func: Type,
3054 func_alias: InternPool.Nav.Index,
31183055 } = switch (ip.indexToKey(nav_val.toIntern())) {
31193056 .int_type,
31203057 .ptr_type,
......@@ -3128,242 +3065,49 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
31283065 .func_type,
31293066 .error_set_type,
31303067 .inferred_error_set_type,
3131 => .decl_alias,
3068 => .alias,
3069
31323070 .struct_type => tag: {
31333071 const loaded_struct = ip.loadStructType(nav_val.toIntern());
3134 if (loaded_struct.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;
3135
3136 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
3137 if (type_gop.found_existing) {
3138 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
3139 assert(!nav_gop.found_existing);
3140 nav_gop.value_ptr.* = type_gop.value_ptr.*;
3141 } else {
3142 if (nav_gop.found_existing)
3143 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
3144 else
3145 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3146 type_gop.value_ptr.* = nav_gop.value_ptr.*;
3147 }
3148 wip_nav.entry = nav_gop.value_ptr.*;
3149
3150 const diw = &wip_nav.debug_info.writer;
3151
3152 switch (loaded_struct.layout) {
3153 .auto, .@"extern" => {
3154 try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{
3155 .decl = .decl_namespace_struct,
3156 .generic_decl = .generic_decl_const,
3157 .decl_instance = .decl_instance_namespace_struct,
3158 } else .{
3159 .decl = .decl_struct,
3160 .generic_decl = .generic_decl_const,
3161 .decl_instance = .decl_instance_struct,
3162 }, &nav, inst_info.file, &decl);
3163 if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else {
3164 try diw.writeUleb128(nav_val.toType().abiSize(zcu));
3165 try diw.writeUleb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?);
3166 for (0..loaded_struct.field_types.len) |field_index| {
3167 const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index);
3168 const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index);
3169 assert(!(is_comptime and field_init == .none));
3170 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
3171 const has_runtime_bits, const has_comptime_state = switch (field_init) {
3172 .none => .{ false, false },
3173 else => .{
3174 field_type.hasRuntimeBits(zcu),
3175 field_type.comptimeOnly(zcu),
3176 },
3177 };
3178 try wip_nav.abbrevCode(if (is_comptime)
3179 if (has_comptime_state)
3180 .struct_field_comptime_comptime_state
3181 else if (has_runtime_bits)
3182 .struct_field_comptime_runtime_bits
3183 else
3184 .struct_field_comptime
3185 else if (field_init != .none)
3186 if (has_comptime_state)
3187 .struct_field_default_comptime_state
3188 else if (has_runtime_bits)
3189 .struct_field_default_runtime_bits
3190 else
3191 .struct_field
3192 else
3193 .struct_field);
3194 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
3195 try wip_nav.refType(field_type);
3196 if (!is_comptime) {
3197 try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]);
3198 try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3199 field_type.abiAlignment(zcu).toByteUnits().?);
3200 }
3201 if (has_comptime_state)
3202 try wip_nav.refValue(.fromInterned(field_init))
3203 else if (has_runtime_bits)
3204 try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init));
3205 }
3206 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3207 }
3208 },
3209 .@"packed" => {
3210 try wip_nav.declCommon(.{
3211 .decl = .decl_packed_struct,
3212 .generic_decl = .generic_decl_const,
3213 .decl_instance = .decl_instance_packed_struct,
3214 }, &nav, inst_info.file, &decl);
3215 try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type));
3216 var field_bit_offset: u16 = 0;
3217 for (0..loaded_struct.field_types.len) |field_index| {
3218 try wip_nav.abbrevCode(.packed_struct_field);
3219 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
3220 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
3221 try wip_nav.refType(field_type);
3222 try diw.writeUleb128(field_bit_offset);
3223 field_bit_offset += @intCast(field_type.bitSize(zcu));
3224 }
3225 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3226 },
3072 if (nav_index.toOptional() == loaded_struct.name_nav) {
3073 // This Nav's entry is populated by the type, not the actual Nav.
3074 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3075 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3076 return;
32273077 }
3228 break :tag .done;
3078 break :tag .alias;
32293079 },
32303080 .enum_type => tag: {
32313081 const loaded_enum = ip.loadEnumType(nav_val.toIntern());
3232 const type_zir_index = loaded_enum.zir_index.unwrap() orelse break :tag .decl_alias;
3233 if (type_zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;
3234
3235 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
3236 if (type_gop.found_existing) {
3237 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
3238 assert(!nav_gop.found_existing);
3239 nav_gop.value_ptr.* = type_gop.value_ptr.*;
3240 } else {
3241 if (nav_gop.found_existing)
3242 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
3243 else
3244 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3245 type_gop.value_ptr.* = nav_gop.value_ptr.*;
3246 }
3247 wip_nav.entry = nav_gop.value_ptr.*;
3248 const diw = &wip_nav.debug_info.writer;
3249 try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{
3250 .decl = .decl_enum,
3251 .generic_decl = .generic_decl_const,
3252 .decl_instance = .decl_instance_enum,
3253 } else .{
3254 .decl = .decl_empty_enum,
3255 .generic_decl = .generic_decl_const,
3256 .decl_instance = .decl_instance_empty_enum,
3257 }, &nav, inst_info.file, &decl);
3258 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));
3259 for (0..loaded_enum.field_names.len) |field_index| {
3260 try wip_nav.enumConstValue(loaded_enum, .{
3261 .sdata = .signed_enum_field,
3262 .udata = .unsigned_enum_field,
3263 .block = .big_enum_field,
3264 }, field_index);
3265 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
3082 if (nav_index.toOptional() == loaded_enum.name_nav) {
3083 // This Nav's entry is populated by the type, not the actual Nav.
3084 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3085 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3086 return;
32663087 }
3267 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3268 break :tag .done;
3088 break :tag .alias;
32693089 },
32703090 .union_type => tag: {
32713091 const loaded_union = ip.loadUnionType(nav_val.toIntern());
3272 if (loaded_union.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;
3273
3274 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
3275 if (type_gop.found_existing) {
3276 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
3277 assert(!nav_gop.found_existing);
3278 nav_gop.value_ptr.* = type_gop.value_ptr.*;
3279 } else {
3280 if (nav_gop.found_existing)
3281 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
3282 else
3283 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3284 type_gop.value_ptr.* = nav_gop.value_ptr.*;
3285 }
3286 wip_nav.entry = nav_gop.value_ptr.*;
3287 const diw = &wip_nav.debug_info.writer;
3288 try wip_nav.declCommon(.{
3289 .decl = .decl_union,
3290 .generic_decl = .generic_decl_const,
3291 .decl_instance = .decl_instance_union,
3292 }, &nav, inst_info.file, &decl);
3293 const union_layout = Type.getUnionLayout(loaded_union, zcu);
3294 try diw.writeUleb128(union_layout.abi_size);
3295 try diw.writeUleb128(union_layout.abi_align.toByteUnits().?);
3296 const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type);
3297 if (loaded_union.has_runtime_tag) {
3298 try wip_nav.abbrevCode(.tagged_union);
3299 try wip_nav.infoSectionOffset(
3300 .debug_info,
3301 wip_nav.unit,
3302 wip_nav.entry,
3303 @intCast(diw.end + dwarf.sectionOffsetBytes()),
3304 );
3305 {
3306 try wip_nav.abbrevCode(.generated_field);
3307 try wip_nav.strp("tag");
3308 try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type));
3309 try diw.writeUleb128(union_layout.tagOffset());
3310
3311 for (0..loaded_union.field_types.len) |field_index| {
3312 try wip_nav.enumConstValue(loaded_tag, .{
3313 .sdata = .signed_tagged_union_field,
3314 .udata = .unsigned_tagged_union_field,
3315 .block = .big_tagged_union_field,
3316 }, field_index);
3317 {
3318 try wip_nav.abbrevCode(.struct_field);
3319 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
3320 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3321 try wip_nav.refType(field_type);
3322 try diw.writeUleb128(union_layout.payloadOffset());
3323 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3324 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
3325 }
3326 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3327 }
3328 }
3329 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3330 } else for (0..loaded_union.field_types.len) |field_index| {
3331 try wip_nav.abbrevCode(.untagged_union_field);
3332 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
3333 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3334 try wip_nav.refType(field_type);
3335 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3336 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
3092 if (nav_index.toOptional() == loaded_union.name_nav) {
3093 // This Nav's entry is populated by the type, not the actual Nav.
3094 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3095 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3096 return;
33373097 }
3338 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3339 break :tag .done;
3098 break :tag .alias;
33403099 },
33413100 .opaque_type => tag: {
33423101 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());
3343 if (loaded_opaque.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;
3344
3345 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
3346 if (type_gop.found_existing) {
3347 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;
3348 assert(!nav_gop.found_existing);
3349 nav_gop.value_ptr.* = type_gop.value_ptr.*;
3350 } else {
3351 if (nav_gop.found_existing)
3352 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
3353 else
3354 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3355 type_gop.value_ptr.* = nav_gop.value_ptr.*;
3102 if (nav_index.toOptional() == loaded_opaque.name_nav) {
3103 // This Nav's entry is populated by the type, not the actual Nav.
3104 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3105 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3106 return;
33563107 }
3357 wip_nav.entry = nav_gop.value_ptr.*;
3358 const diw = &wip_nav.debug_info.writer;
3359 try wip_nav.declCommon(.{
3360 .decl = .decl_namespace_struct,
3361 .generic_decl = .generic_decl_const,
3362 .decl_instance = .decl_instance_namespace_struct,
3363 }, &nav, inst_info.file, &decl);
3364 try diw.writeByte(@intFromBool(true));
3365 break :tag .done;
3108 break :tag .alias;
33663109 },
3110
33673111 .undef,
33683112 .simple_value,
33693113 .int,
......@@ -3378,72 +3122,77 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
33783122 .aggregate,
33793123 .un,
33803124 .bitpack,
3381 => .decl_const,
3382 .variable => .decl_var,
3125 => .@"const",
3126
3127 .variable => .@"var",
3128
33833129 .@"extern" => unreachable,
3384 .func => |func| tag: {
3385 if (func.owner_nav != nav_index) break :tag .{ .decl_func_alias = func.owner_nav };
3386 if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) {
3387 .null => {},
3388 else => unreachable,
3389 .decl_nullary_func, .decl_func, .decl_instance_nullary_func, .decl_instance_func => return,
3390 .decl_nullary_func_generic,
3391 .decl_func_generic,
3392 .decl_instance_nullary_func_generic,
3393 .decl_instance_func_generic,
3394 => dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(),
3395 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3396 wip_nav.entry = nav_gop.value_ptr.*;
33973130
3398 const func_type = ip.indexToKey(func.ty).func_type;
3399 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {
3400 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;
3401 } else true;
3402 const diw = &wip_nav.debug_info.writer;
3403 try wip_nav.declCommon(if (is_nullary) .{
3404 .decl = .decl_nullary_func_generic,
3405 .generic_decl = .generic_decl_func,
3406 .decl_instance = .decl_instance_nullary_func_generic,
3407 } else .{
3408 .decl = .decl_func_generic,
3409 .generic_decl = .generic_decl_func,
3410 .decl_instance = .decl_instance_func_generic,
3411 }, &nav, inst_info.file, &decl);
3412 try wip_nav.refType(.fromInterned(func_type.return_type));
3413 if (!is_nullary) {
3414 for (0..func_type.param_types.len) |param_index| {
3415 if (std.math.cast(u5, param_index)) |small_param_index|
3416 if (func_type.paramIsComptime(small_param_index)) continue;
3417 try wip_nav.abbrevCode(.func_type_param);
3418 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3419 }
3420 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3421 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3422 }
3423 break :tag .done;
3131 .func => |func| tag: {
3132 if (func.owner_nav != nav_index) break :tag .{ .func_alias = func.owner_nav };
3133 break :tag .{ .func = .fromInterned(func.ty) };
34243134 },
3135
34253136 // memoization, not types
34263137 .memoized_call => unreachable,
34273138 };
3428 if (tag != .done) {
3429 if (nav_gop.found_existing)
3430 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
3431 else
3432 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3433 wip_nav.entry = nav_gop.value_ptr.*;
3139
3140 const unit = try dwarf.getUnit(file.mod.?);
3141
3142 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
3143 errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();
3144
3145 if (nav_gop.found_existing) {
3146 if (tag == .func) switch (try dwarf.debug_info.declAbbrevCode(unit, nav_gop.value_ptr.*)) {
3147 else => unreachable,
3148
3149 .decl_nullary_func,
3150 .decl_func,
3151 .decl_instance_nullary_func,
3152 .decl_instance_func,
3153 => return,
3154
3155 .null,
3156 .decl_nullary_func_generic,
3157 .decl_func_generic,
3158 .decl_instance_nullary_func_generic,
3159 .decl_instance_func_generic,
3160 => {},
3161 };
3162 dwarf.debug_info.section.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear();
3163 } else {
3164 nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
34343165 }
3435 switch (tag) {
3436 .done => {},
3437 .decl_alias => {
3438 try wip_nav.declCommon(.{
3439 .decl = .decl_alias,
3440 .generic_decl = .generic_decl_const,
3441 .decl_instance = .decl_instance_alias,
3442 }, &nav, inst_info.file, &decl);
3443 try wip_nav.refType(nav_val.toType());
3444 },
3445 .decl_var => {
3446 const diw = &wip_nav.debug_info.writer;
3166
3167 var wip_nav: WipNav = .{
3168 .dwarf = dwarf,
3169 .pt = pt,
3170 .unit = unit,
3171 .entry = nav_gop.value_ptr.*,
3172 .any_children = false,
3173 .func = .none,
3174 .func_sym_index = undefined,
3175 .func_high_pc = undefined,
3176 .blocks = undefined,
3177 .cfi = undefined,
3178 .debug_frame = .init(dwarf.gpa),
3179 .debug_info = .init(dwarf.gpa),
3180 .debug_line = .init(dwarf.gpa),
3181 .debug_loclists = .init(dwarf.gpa),
3182 };
3183 defer wip_nav.deinit();
3184 const diw = &wip_nav.debug_info.writer;
3185
3186 switch (tag) {
3187 .alias => {
3188 try wip_nav.declCommon(.{
3189 .decl = .decl_alias,
3190 .generic_decl = .generic_decl_const,
3191 .decl_instance = .decl_instance_alias,
3192 }, &nav, inst_info.file, &decl);
3193 try wip_nav.refType(nav_val.toType());
3194 },
3195 .@"var" => {
34473196 try wip_nav.declCommon(.{
34483197 .decl = .decl_var,
34493198 .generic_decl = .generic_decl_var,
......@@ -3460,8 +3209,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
34603209 nav_ty.abiAlignment(zcu).toByteUnits().?);
34613210 try diw.writeByte(@intFromBool(decl.linkage != .normal));
34623211 },
3463 .decl_const => {
3464 const diw = &wip_nav.debug_info.writer;
3212 .@"const" => {
34653213 const nav_ty = nav_val.typeOf(zcu);
34663214 const has_runtime_bits = nav_ty.hasRuntimeBits(zcu);
34673215 const has_comptime_state = nav_ty.comptimeOnly(zcu);
......@@ -3496,7 +3244,33 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
34963244 try wip_nav.abbrevCode(.is_const);
34973245 try wip_nav.refType(nav_ty);
34983246 },
3499 .decl_func_alias => |owner_nav| {
3247 .func => |func_ty| {
3248 const func_type = ip.indexToKey(func_ty.toIntern()).func_type;
3249 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {
3250 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;
3251 } else true;
3252 try wip_nav.declCommon(if (is_nullary) .{
3253 .decl = .decl_nullary_func_generic,
3254 .generic_decl = .generic_decl_func,
3255 .decl_instance = .decl_instance_nullary_func_generic,
3256 } else .{
3257 .decl = .decl_func_generic,
3258 .generic_decl = .generic_decl_func,
3259 .decl_instance = .decl_instance_func_generic,
3260 }, &nav, inst_info.file, &decl);
3261 try wip_nav.refType(.fromInterned(func_type.return_type));
3262 if (!is_nullary) {
3263 for (0..func_type.param_types.len) |param_index| {
3264 if (std.math.cast(u5, param_index)) |small_param_index|
3265 if (func_type.paramIsComptime(small_param_index)) continue;
3266 try wip_nav.abbrevCode(.func_type_param);
3267 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3268 }
3269 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3270 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3271 }
3272 },
3273 .func_alias => |owner_nav| {
35003274 try wip_nav.declCommon(.{
35013275 .decl = .decl_alias,
35023276 .generic_decl = .generic_decl_const,
......@@ -3505,31 +3279,81 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
35053279 try wip_nav.refNav(owner_nav);
35063280 },
35073281 }
3508 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
3509 try wip_nav.updateLazy(nav_src_loc);
3282 try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
3283 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
35103284}
35113285
3512fn updateLazyType(
3286pub fn updateContainerType(
35133287 dwarf: *Dwarf,
35143288 pt: Zcu.PerThread,
3515 src_loc: Zcu.LazySrcLoc,
3516 type_index: InternPool.Index,
3517 pending_lazy: *WipNav.PendingLazy,
3518) (UpdateError || Writer.Error)!void {
3289 ty: InternPool.Index,
3290 success: bool,
3291) !void {
3292 try dwarf.const_pool.updateContainerType(pt, .{ .dwarf = dwarf }, ty, success);
3293}
3294/// Should only be called by the `DebugConstPool` implementation.
3295pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) !void {
35193296 const zcu = pt.zcu;
35203297 const ip = &zcu.intern_pool;
3521 assert(ip.typeOf(type_index) == .type_type);
3522 const ty: Type = .fromInterned(type_index);
3523 switch (type_index) {
3524 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),
3525 else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}),
3298
3299 const unit: Unit.Index, const entry: Entry.Index = switch (ip.indexToKey(val)) {
3300 else => .{ .main, try dwarf.addCommonEntry(.main) },
3301 .func => |func| try dwarf.getNavEntry(func.owner_nav),
3302 .@"extern" => |@"extern"| try dwarf.getNavEntry(@"extern".owner_nav),
3303 .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| entry: {
3304 const name_nav = switch (tag) {
3305 .struct_type => ip.loadStructType(val).name_nav,
3306 .union_type => ip.loadUnionType(val).name_nav,
3307 .enum_type => ip.loadEnumType(val).name_nav,
3308 .opaque_type => ip.loadOpaqueType(val).name_nav,
3309 else => unreachable,
3310 };
3311 if (name_nav.unwrap()) |nav| {
3312 break :entry try dwarf.getNavEntry(nav);
3313 } else {
3314 const zir_index = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?;
3315 const unit = try dwarf.getUnit(zcu.fileByIndex(zir_index.resolveFile(ip)).mod.?);
3316 break :entry .{ unit, try dwarf.addCommonEntry(unit) };
3317 }
3318 },
3319 };
3320
3321 assert(@intFromEnum(index) == dwarf.values.items.len);
3322 try dwarf.values.append(dwarf.gpa, .{ unit, entry });
3323}
3324/// Should only be called by the `DebugConstPool` implementation.
3325///
3326/// Emits a "dummy" DIE for the given comptime-only value (which may be a type). For types, this is
3327/// an opaque type. Otherwise, it is an undefined value of the value's type.
3328pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void {
3329 const zcu = pt.zcu;
3330
3331 const val: Value = .fromInterned(value_index);
3332
3333 switch (value_index) {
3334 .generic_poison_type => log.debug("updateValueIncomplete(anytype)", .{}),
3335 else => log.debug("updateValueIncomplete(@as({f}, {f}))", .{
3336 val.typeOf(zcu).fmt(pt),
3337 val.fmtValue(pt),
3338 }),
35263339 }
35273340
3341 const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)];
3342
3343 for ([_]*Section{
3344 &dwarf.debug_aranges.section,
3345 &dwarf.debug_aranges.section,
3346 &dwarf.debug_info.section,
3347 &dwarf.debug_line.section,
3348 &dwarf.debug_loclists.section,
3349 &dwarf.debug_rnglists.section,
3350 }) |sec| sec.getUnit(unit).getEntry(entry).clear();
3351
35283352 var wip_nav: WipNav = .{
35293353 .dwarf = dwarf,
35303354 .pt = pt,
3531 .unit = .main,
3532 .entry = dwarf.types.get(type_index).?,
3355 .unit = unit,
3356 .entry = entry,
35333357 .any_children = false,
35343358 .func = .none,
35353359 .func_sym_index = undefined,
......@@ -3540,43 +3364,119 @@ fn updateLazyType(
35403364 .debug_info = .init(dwarf.gpa),
35413365 .debug_line = .init(dwarf.gpa),
35423366 .debug_loclists = .init(dwarf.gpa),
3543 .pending_lazy = pending_lazy.*,
35443367 };
3545 defer {
3546 pending_lazy.* = wip_nav.pending_lazy;
3547 wip_nav.pending_lazy = .empty;
3548 wip_nav.deinit();
3368 defer wip_nav.deinit();
3369 switch (val.typeOf(zcu).toIntern()) {
3370 .type_type => {
3371 try wip_nav.abbrevCode(.generated_empty_struct_type);
3372 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3373 try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
3374 },
3375 else => |ty| {
3376 try wip_nav.abbrevCode(.undefined_comptime_value);
3377 try wip_nav.refType(.fromInterned(ty));
3378 },
35493379 }
3550 const diw = &wip_nav.debug_info.writer;
3551 const name = switch (type_index) {
3552 .generic_poison_type => "",
3553 else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}),
3380 try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());
3381 try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());
3382}
3383/// Should only be called by the `DebugConstPool` implementation.
3384///
3385/// Emits a DIE for the given comptime-only value (which may be a type).
3386pub fn updateConst(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void {
3387 const zcu = pt.zcu;
3388 const ip = &zcu.intern_pool;
3389
3390 const val: Value = .fromInterned(value_index);
3391
3392 if (val.typeOf(zcu).toIntern() == .type_type and !val.isUndef(zcu)) {
3393 val.toType().assertHasLayout(zcu);
3394 } else {
3395 val.typeOf(zcu).assertHasLayout(zcu);
3396 }
3397
3398 const value_ip_key = ip.indexToKey(value_index);
3399 switch (value_ip_key) {
3400 .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`)
3401 .@"extern" => return, // populated by the Nav instead (`initWipNav`)
3402 else => {},
3403 }
3404
3405 switch (value_index) {
3406 .generic_poison_type => log.debug("updateValue(anytype)", .{}),
3407 else => log.debug("updateValue(@as({f}, {f}))", .{
3408 val.typeOf(zcu).fmt(pt),
3409 val.fmtValue(pt),
3410 }),
3411 }
3412
3413 const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)];
3414
3415 for ([_]*Section{
3416 &dwarf.debug_aranges.section,
3417 &dwarf.debug_info.section,
3418 &dwarf.debug_line.section,
3419 &dwarf.debug_loclists.section,
3420 &dwarf.debug_rnglists.section,
3421 }) |sec| sec.getUnit(unit).getEntry(entry).clear();
3422
3423 var wip_nav: WipNav = .{
3424 .dwarf = dwarf,
3425 .pt = pt,
3426 .unit = unit,
3427 .entry = entry,
3428 .any_children = false,
3429 .func = .none,
3430 .func_sym_index = undefined,
3431 .func_high_pc = undefined,
3432 .blocks = undefined,
3433 .cfi = undefined,
3434 .debug_frame = .init(dwarf.gpa),
3435 .debug_info = .init(dwarf.gpa),
3436 .debug_line = .init(dwarf.gpa),
3437 .debug_loclists = .init(dwarf.gpa),
35543438 };
3555 defer dwarf.gpa.free(name);
3439 defer wip_nav.deinit();
3440
3441 // TODO: we really shouldn't need source locations at this point in the pipeline: we've lost
3442 // that information by now. If the linker fundamentally cannot lower certain values, that needs
3443 // to be caught in the frontend; if it can only hit transient failures, they should be reported
3444 // without trying to tie them to a bogus source location.
3445 const src_loc: Zcu.LazySrcLoc = .{
3446 .base_node_inst = inst: {
3447 const mod_root_file_index = zcu.module_roots.get(dwarf.getUnitModule(unit)).?.unwrap().?;
3448 const mod_root_type_index = zcu.fileRootType(mod_root_file_index);
3449 break :inst ip.loadStructType(mod_root_type_index).zir_index;
3450 },
3451 .offset = .{ .byte_abs = 0 },
3452 };
3453
3454 const diw = &wip_nav.debug_info.writer;
3455 var big_int_space: Value.BigIntSpace = undefined;
3456 switch (value_ip_key) {
3457 .func => unreachable, // handled above
3458 .@"extern" => unreachable, // handled above
35563459
3557 switch (ip.indexToKey(type_index)) {
3558 .undef => {
3559 try wip_nav.abbrevCode(.undefined_comptime_value);
3560 try wip_nav.refType(.type);
3561 },
35623460 .int_type => |int_type| {
35633461 try wip_nav.abbrevCode(.numeric_type);
3564 try wip_nav.strp(name);
3462 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
35653463 try diw.writeByte(switch (int_type.signedness) {
35663464 inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),
35673465 });
35683466 try diw.writeUleb128(int_type.bits);
3569 try diw.writeUleb128(ty.abiSize(zcu));
3570 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3467 try diw.writeUleb128(val.toType().abiSize(zcu));
3468 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
35713469 },
35723470 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
35733471 .one, .many, .c => {
35743472 const ptr_child_type: Type = .fromInterned(ptr_type.child);
3575 try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type);
3576 try wip_nav.strp(name);
3473 try wip_nav.abbrevCode(switch (ptr_type.flags.alignment) {
3474 .none => if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type,
3475 else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type,
3476 });
3477 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
35773478 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));
3578 try diw.writeUleb128(ptr_type.flags.alignment.toByteUnits() orelse
3579 ptr_child_type.abiAlignment(zcu).toByteUnits().?);
3479 if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);
35803480 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));
35813481 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(
35823482 .debug_info,
......@@ -3600,12 +3500,12 @@ fn updateLazyType(
36003500 },
36013501 .slice => {
36023502 try wip_nav.abbrevCode(.generated_struct_type);
3603 try wip_nav.strp(name);
3604 try diw.writeUleb128(ty.abiSize(zcu));
3605 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3503 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3504 try diw.writeUleb128(val.toType().abiSize(zcu));
3505 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
36063506 try wip_nav.abbrevCode(.generated_field);
36073507 try wip_nav.strp("ptr");
3608 const ptr_field_type = ty.slicePtrFieldType(zcu);
3508 const ptr_field_type = val.toType().slicePtrFieldType(zcu);
36093509 try wip_nav.refType(ptr_field_type);
36103510 try diw.writeUleb128(0);
36113511 try wip_nav.abbrevCode(.generated_field);
......@@ -3619,7 +3519,7 @@ fn updateLazyType(
36193519 .array_type => |array_type| {
36203520 const array_child_type: Type = .fromInterned(array_type.child);
36213521 try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);
3622 try wip_nav.strp(name);
3522 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
36233523 if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));
36243524 try wip_nav.refType(array_child_type);
36253525 try wip_nav.abbrevCode(.array_len);
......@@ -3629,7 +3529,7 @@ fn updateLazyType(
36293529 },
36303530 .vector_type => |vector_type| {
36313531 try wip_nav.abbrevCode(.vector_type);
3632 try wip_nav.strp(name);
3532 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
36333533 try wip_nav.refType(.fromInterned(vector_type.child));
36343534 try wip_nav.abbrevCode(.array_len);
36353535 try wip_nav.refType(.usize);
......@@ -3640,9 +3540,9 @@ fn updateLazyType(
36403540 const opt_child_type: Type = .fromInterned(opt_child_type_index);
36413541 const opt_repr = optRepr(opt_child_type, zcu);
36423542 try wip_nav.abbrevCode(.generated_union_type);
3643 try wip_nav.strp(name);
3644 try diw.writeUleb128(ty.abiSize(zcu));
3645 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3543 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3544 try diw.writeUleb128(val.toType().abiSize(zcu));
3545 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
36463546 switch (opt_repr) {
36473547 .opv_null => {
36483548 try wip_nav.abbrevCode(.generated_field);
......@@ -3720,12 +3620,12 @@ fn updateLazyType(
37203620 };
37213621
37223622 try wip_nav.abbrevCode(.generated_union_type);
3723 try wip_nav.strp(name);
3623 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
37243624 if (error_union_type.error_set_type != .generic_poison_type and
37253625 error_union_type.payload_type != .generic_poison_type)
37263626 {
3727 try diw.writeUleb128(ty.abiSize(zcu));
3728 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3627 try diw.writeUleb128(val.toType().abiSize(zcu));
3628 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
37293629 } else {
37303630 try diw.writeUleb128(0);
37313631 try diw.writeUleb128(1);
......@@ -3791,20 +3691,24 @@ fn updateLazyType(
37913691 .bool,
37923692 => {
37933693 try wip_nav.abbrevCode(.numeric_type);
3794 try wip_nav.strp(name);
3795 try diw.writeByte(if (type_index == .bool_type)
3694 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3695 try diw.writeByte(if (value_index == .bool_type)
37963696 DW.ATE.boolean
3797 else if (ty.isRuntimeFloat())
3697 else if (val.toType().isRuntimeFloat())
37983698 DW.ATE.float
3799 else if (ty.isSignedInt(zcu))
3699 else if (val.toType().isSignedInt(zcu))
38003700 DW.ATE.signed
3801 else if (ty.isUnsignedInt(zcu))
3701 else if (val.toType().isUnsignedInt(zcu))
38023702 DW.ATE.unsigned
38033703 else
38043704 unreachable);
3805 try diw.writeUleb128(ty.bitSize(zcu));
3806 try diw.writeUleb128(ty.abiSize(zcu));
3807 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3705 try diw.writeUleb128(val.toType().bitSize(zcu));
3706 try diw.writeUleb128(val.toType().abiSize(zcu));
3707 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3708 },
3709 .generic_poison => {
3710 try wip_nav.abbrevCode(.void_type);
3711 try wip_nav.strp("anytype");
38083712 },
38093713 .anyopaque,
38103714 .void,
......@@ -3815,37 +3719,29 @@ fn updateLazyType(
38153719 .null,
38163720 .undefined,
38173721 .enum_literal,
3818 .generic_poison,
38193722 => {
38203723 try wip_nav.abbrevCode(.void_type);
3821 try wip_nav.strp(if (type_index == .generic_poison_type) "anytype" else name);
3724 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
38223725 },
38233726 .anyerror => return, // delay until flush
38243727 .adhoc_inferred_error_set => unreachable,
38253728 },
3826 .struct_type,
3827 .union_type,
3828 .opaque_type,
3829 => unreachable,
38303729 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
38313730 try wip_nav.abbrevCode(.generated_empty_struct_type);
3832 try wip_nav.strp(name);
3731 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
38333732 try diw.writeByte(@intFromBool(false));
38343733 } else {
38353734 try wip_nav.abbrevCode(.generated_struct_type);
3836 try wip_nav.strp(name);
3837 try diw.writeUleb128(ty.abiSize(zcu));
3838 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3735 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3736 try diw.writeUleb128(val.toType().abiSize(zcu));
3737 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
38393738 var field_byte_offset: u64 = 0;
38403739 for (0..tuple_type.types.len) |field_index| {
38413740 const comptime_value = tuple_type.values.get(ip)[field_index];
38423741 const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]);
38433742 const has_runtime_bits, const has_comptime_state = switch (comptime_value) {
38443743 .none => .{ false, false },
3845 else => .{
3846 field_type.hasRuntimeBits(zcu),
3847 field_type.comptimeOnly(zcu),
3848 },
3744 else => .{ field_type.hasRuntimeBits(zcu), field_type.comptimeOnly(zcu) },
38493745 };
38503746 try wip_nav.abbrevCode(if (has_comptime_state)
38513747 .struct_field_comptime_comptime_state
......@@ -3875,25 +3771,259 @@ fn updateLazyType(
38753771 }
38763772 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
38773773 },
3774 .struct_type => {
3775 const loaded_struct = ip.loadStructType(value_index);
3776 const ty = val.toType();
3777 const file = loaded_struct.zir_index.resolveFile(ip);
3778 switch (loaded_struct.layout) {
3779 .auto, .@"extern" => {
3780 const struct_is_file: bool = if (loaded_struct.zir_index.resolve(ip)) |inst| f: {
3781 break :f inst == .main_struct_inst;
3782 } else false;
3783 if (loaded_struct.name_nav.unwrap()) |nav_index| {
3784 assert(!struct_is_file);
3785 const nav = ip.getNav(nav_index);
3786 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3787 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3788 try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{
3789 .decl = .decl_namespace_struct,
3790 .generic_decl = .generic_decl_const,
3791 .decl_instance = .decl_instance_namespace_struct,
3792 } else .{
3793 .decl = .decl_struct,
3794 .generic_decl = .generic_decl_const,
3795 .decl_instance = .decl_instance_struct,
3796 }, &nav, file, &decl);
3797 } else {
3798 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file);
3799 try wip_nav.abbrevCode(switch (loaded_struct.field_types.len) {
3800 0 => if (struct_is_file) .empty_file else .empty_struct_type,
3801 else => if (struct_is_file) .file else .struct_type,
3802 });
3803 try diw.writeUleb128(file_gop.index);
3804 try wip_nav.strp(loaded_struct.name.toSlice(ip));
3805 }
3806 if (loaded_struct.field_types.len == 0) {
3807 if (!struct_is_file) try diw.writeByte(@intFromBool(false));
3808 } else {
3809 try diw.writeUleb128(ty.abiSize(zcu));
3810 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
3811 for (0..loaded_struct.field_types.len) |field_index| {
3812 const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index);
3813 const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index);
3814 assert(!(is_comptime and field_init == .none));
3815 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
3816 const has_runtime_bits, const has_comptime_state = switch (field_init) {
3817 .none => .{ false, false },
3818 else => .{
3819 field_type.hasRuntimeBits(zcu),
3820 field_type.comptimeOnly(zcu),
3821 },
3822 };
3823 try wip_nav.abbrevCode(if (is_comptime)
3824 if (has_comptime_state)
3825 .struct_field_comptime_comptime_state
3826 else if (has_runtime_bits)
3827 .struct_field_comptime_runtime_bits
3828 else
3829 .struct_field_comptime
3830 else if (field_init != .none)
3831 if (has_comptime_state)
3832 .struct_field_default_comptime_state
3833 else if (has_runtime_bits)
3834 .struct_field_default_runtime_bits
3835 else
3836 .struct_field
3837 else
3838 .struct_field);
3839 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
3840 try wip_nav.refType(field_type);
3841 if (!is_comptime) {
3842 try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]);
3843 try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3844 field_type.abiAlignment(zcu).toByteUnits().?);
3845 }
3846 if (has_comptime_state)
3847 try wip_nav.refValue(.fromInterned(field_init))
3848 else if (has_runtime_bits)
3849 try wip_nav.blockValue(ty.srcLoc(zcu), .fromInterned(field_init));
3850 }
3851 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3852 }
3853 },
3854 .@"packed" => {
3855 const need_terminator: bool = if (loaded_struct.name_nav.unwrap()) |nav_index| t: {
3856 const nav = ip.getNav(nav_index);
3857 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3858 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3859 try wip_nav.declCommon(.{
3860 .decl = .decl_packed_struct,
3861 .generic_decl = .generic_decl_const,
3862 .decl_instance = .decl_instance_packed_struct,
3863 }, &nav, file, &decl);
3864 break :t true;
3865 } else t: {
3866 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file);
3867 try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type);
3868 try diw.writeUleb128(file_gop.index);
3869 try wip_nav.strp(loaded_struct.name.toSlice(ip));
3870 break :t loaded_struct.field_types.len > 0;
3871 };
3872 try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type));
3873 var field_bit_offset: u16 = 0;
3874 for (0..loaded_struct.field_types.len) |field_index| {
3875 try wip_nav.abbrevCode(.packed_struct_field);
3876 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
3877 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
3878 try wip_nav.refType(field_type);
3879 try diw.writeUleb128(field_bit_offset);
3880 field_bit_offset += @intCast(field_type.bitSize(zcu));
3881 }
3882 if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3883 },
3884 }
3885 },
3886 .union_type => {
3887 const loaded_union = ip.loadUnionType(value_index);
3888 const file = loaded_union.zir_index.resolveFile(ip);
3889 const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: {
3890 const nav = ip.getNav(nav_index);
3891 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3892 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3893 try wip_nav.declCommon(.{
3894 .decl = .decl_union,
3895 .generic_decl = .generic_decl_const,
3896 .decl_instance = .decl_instance_union,
3897 }, &nav, file, &decl);
3898 break :t true;
3899 } else t: {
3900 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file);
3901 try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type);
3902 try diw.writeUleb128(file_gop.index);
3903 try wip_nav.strp(loaded_union.name.toSlice(ip));
3904 break :t loaded_union.field_types.len > 0;
3905 };
3906 const union_layout = Type.getUnionLayout(loaded_union, zcu);
3907 try diw.writeUleb128(union_layout.abi_size);
3908 try diw.writeUleb128(union_layout.abi_align.toByteUnits().?);
3909 const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type);
3910 if (loaded_union.has_runtime_tag) {
3911 try wip_nav.abbrevCode(.tagged_union);
3912 try wip_nav.infoSectionOffset(
3913 .debug_info,
3914 wip_nav.unit,
3915 wip_nav.entry,
3916 @intCast(diw.end + dwarf.sectionOffsetBytes()),
3917 );
3918 {
3919 try wip_nav.abbrevCode(.generated_field);
3920 try wip_nav.strp("tag");
3921 try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type));
3922 try diw.writeUleb128(union_layout.tagOffset());
3923
3924 for (0..loaded_union.field_types.len) |field_index| {
3925 try wip_nav.enumConstValue(loaded_tag, .{
3926 .sdata = .signed_tagged_union_field,
3927 .udata = .unsigned_tagged_union_field,
3928 .block = .big_tagged_union_field,
3929 }, field_index);
3930 {
3931 try wip_nav.abbrevCode(.struct_field);
3932 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
3933 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3934 try wip_nav.refType(field_type);
3935 try diw.writeUleb128(union_layout.payloadOffset());
3936 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3937 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
3938 }
3939 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3940 }
3941 }
3942 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3943 } else for (0..loaded_union.field_types.len) |field_index| {
3944 try wip_nav.abbrevCode(.untagged_union_field);
3945 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
3946 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
3947 try wip_nav.refType(field_type);
3948 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
3949 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
3950 }
3951 if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3952 },
38783953 .enum_type => {
3879 const loaded_enum = ip.loadEnumType(type_index);
3880 try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type);
3881 try wip_nav.strp(name);
3882 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));
3883 for (0..loaded_enum.field_names.len) |field_index| {
3884 try wip_nav.enumConstValue(loaded_enum, .{
3885 .sdata = .signed_enum_field,
3886 .udata = .unsigned_enum_field,
3887 .block = .big_enum_field,
3888 }, field_index);
3889 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
3954 const loaded_enum = ip.loadEnumType(value_index);
3955 if (loaded_enum.zir_index.unwrap()) |zir_index| {
3956 assert(loaded_enum.owner_union == .none);
3957 const file = zir_index.resolveFile(ip);
3958 if (loaded_enum.name_nav.unwrap()) |nav_index| {
3959 const nav = ip.getNav(nav_index);
3960 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3961 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3962 try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{
3963 .decl = .decl_enum,
3964 .generic_decl = .generic_decl_const,
3965 .decl_instance = .decl_instance_enum,
3966 } else .{
3967 .decl = .decl_empty_enum,
3968 .generic_decl = .generic_decl_const,
3969 .decl_instance = .decl_instance_empty_enum,
3970 }, &nav, file, &decl);
3971 } else {
3972 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file);
3973 try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type);
3974 try diw.writeUleb128(file_gop.index);
3975 try wip_nav.strp(loaded_enum.name.toSlice(ip));
3976 }
3977 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));
3978 for (0..loaded_enum.field_names.len) |field_index| {
3979 try wip_nav.enumConstValue(loaded_enum, .{
3980 .sdata = .signed_enum_field,
3981 .udata = .unsigned_enum_field,
3982 .block = .big_enum_field,
3983 }, field_index);
3984 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
3985 }
3986 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3987 } else {
3988 assert(loaded_enum.owner_union != .none);
3989 try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type);
3990 try wip_nav.strp(loaded_enum.name.toSlice(ip));
3991 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));
3992 for (0..loaded_enum.field_names.len) |field_index| {
3993 try wip_nav.enumConstValue(loaded_enum, .{
3994 .sdata = .signed_enum_field,
3995 .udata = .unsigned_enum_field,
3996 .block = .big_enum_field,
3997 }, field_index);
3998 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
3999 }
4000 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4001 }
4002 },
4003 .opaque_type => {
4004 const loaded_opaque = ip.loadOpaqueType(value_index);
4005 const file = loaded_opaque.zir_index.resolveFile(ip);
4006 if (loaded_opaque.name_nav.unwrap()) |nav_index| {
4007 const nav = ip.getNav(nav_index);
4008 const decl_inst = nav.srcInst(ip).resolve(ip).?;
4009 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
4010 try wip_nav.declCommon(.{
4011 .decl = .decl_namespace_struct,
4012 .generic_decl = .generic_decl_const,
4013 .decl_instance = .decl_instance_namespace_struct,
4014 }, &nav, file, &decl);
4015 } else {
4016 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file);
4017 try wip_nav.abbrevCode(.empty_struct_type);
4018 try diw.writeUleb128(file_gop.index);
4019 try wip_nav.strp(loaded_opaque.name.toSlice(ip));
38904020 }
3891 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4021 try diw.writeByte(@intFromBool(true));
38924022 },
38934023 .func_type => |func_type| {
38944024 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
38954025 try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);
3896 try wip_nav.strp(name);
4026 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
38974027 const cc: DW.CC = cc: {
38984028 if (zcu.getTarget().cCallingConvention()) |cc| {
38994029 if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) {
......@@ -3975,7 +4105,7 @@ fn updateLazyType(
39754105 },
39764106 .error_set_type => |error_set_type| {
39774107 try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);
3978 try wip_nav.strp(name);
4108 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
39794109 try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
39804110 .signedness = .unsigned,
39814111 .bits = zcu.errorSetBits(),
......@@ -3990,100 +4120,28 @@ fn updateLazyType(
39904120 },
39914121 .inferred_error_set_type => |func| {
39924122 try wip_nav.abbrevCode(.inferred_error_set_type);
3993 try wip_nav.strp(name);
4123 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
39944124 try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) {
39954125 .none => .anyerror_type,
39964126 else => |ies| ies,
39974127 }));
39984128 },
39994129
4000 // values, not types
4001 .simple_value,
4002 .variable,
4003 .@"extern",
4004 .func,
4005 .int,
4006 .err,
4007 .error_union,
4008 .enum_literal,
4009 .enum_tag,
4010 .float,
4011 .ptr,
4012 .slice,
4013 .opt,
4014 .aggregate,
4015 .un,
4016 .bitpack,
4017 // memoization, not types
4018 .memoized_call,
4019 => unreachable,
4020 }
4021 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
4022}
4023
4024fn updateLazyValue(
4025 dwarf: *Dwarf,
4026 pt: Zcu.PerThread,
4027 src_loc: Zcu.LazySrcLoc,
4028 value_index: InternPool.Index,
4029 pending_lazy: *WipNav.PendingLazy,
4030) (UpdateError || Writer.Error)!void {
4031 const zcu = pt.zcu;
4032 const ip = &zcu.intern_pool;
4033 assert(ip.typeOf(value_index) != .type_type);
4034 log.debug("updateLazyValue(@as({f}, {f}))", .{
4035 Value.fromInterned(value_index).typeOf(zcu).fmt(pt),
4036 Value.fromInterned(value_index).fmtValue(pt),
4037 });
4038 var wip_nav: WipNav = .{
4039 .dwarf = dwarf,
4040 .pt = pt,
4041 .unit = .main,
4042 .entry = dwarf.values.get(value_index).?,
4043 .any_children = false,
4044 .func = .none,
4045 .func_sym_index = undefined,
4046 .func_high_pc = undefined,
4047 .blocks = undefined,
4048 .cfi = undefined,
4049 .debug_frame = .init(dwarf.gpa),
4050 .debug_info = .init(dwarf.gpa),
4051 .debug_line = .init(dwarf.gpa),
4052 .debug_loclists = .init(dwarf.gpa),
4053 .pending_lazy = pending_lazy.*,
4054 };
4055 defer {
4056 pending_lazy.* = wip_nav.pending_lazy;
4057 wip_nav.pending_lazy = .empty;
4058 wip_nav.deinit();
4059 }
4060 const diw = &wip_nav.debug_info.writer;
4061 var big_int_space: Value.BigIntSpace = undefined;
4062 switch (ip.indexToKey(value_index)) {
4063 .int_type,
4064 .ptr_type,
4065 .array_type,
4066 .vector_type,
4067 .opt_type,
4068 .anyframe_type,
4069 .error_union_type,
4070 .simple_type,
4071 .struct_type,
4072 .tuple_type,
4073 .union_type,
4074 .opaque_type,
4075 .enum_type,
4076 .func_type,
4077 .error_set_type,
4078 .inferred_error_set_type,
4079 => unreachable, // already handled
40804130 .undef => |ty| {
40814131 try wip_nav.abbrevCode(.undefined_comptime_value);
40824132 try wip_nav.refType(.fromInterned(ty));
40834133 },
4084 .simple_value => unreachable, // opv state
4085 .variable, .@"extern" => unreachable, // not a value
4086 .func => unreachable, // already handled
4134 .simple_value => |simple_value| switch (simple_value) {
4135 .void => unreachable, // opv state
4136 .true, .false => unreachable, // runtime bits
4137 .@"unreachable" => unreachable, // not a value
4138 .null => {
4139 // TODO: proper representation for this
4140 try wip_nav.abbrevCode(.undefined_comptime_value);
4141 try wip_nav.refType(.null);
4142 },
4143 },
4144 .variable => unreachable, // not a value
40874145 .int => |int| {
40884146 try wip_nav.bigIntConstValue(.{
40894147 .sdata = .sdata_comptime_value,
......@@ -4202,7 +4260,7 @@ fn updateLazyValue(
42024260 var byte_offset = ptr.byte_offset;
42034261 const base_unit, const base_entry = while (true) {
42044262 const base_ptr, const access: Access = base_ptr_access: switch (base_addr) {
4205 .nav => |nav_index| break try wip_nav.getNavEntry(nav_index),
4263 .nav => |nav_index| break try dwarf.getNavEntry(nav_index),
42064264 .comptime_alloc, .comptime_field => unreachable,
42074265 .uav => |uav| {
42084266 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
......@@ -4319,17 +4377,7 @@ fn updateLazyValue(
43194377 switch (optRepr(opt_child_type, zcu)) {
43204378 .opv_null => try diw.writeUleb128(0),
43214379 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
4322 .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
4323 .pointer => if (opt_child_type.comptimeOnly(zcu)) {
4324 var buf: [8]u8 = undefined;
4325 const bytes = buf[0..@divExact(zcu.getTarget().ptrBitWidth(), 8)];
4326 dwarf.writeInt(bytes, switch (opt.val) {
4327 .none => 0,
4328 else => opt_child_type.ptrAlignment(zcu).toByteUnits().?,
4329 });
4330 try diw.writeUleb128(bytes.len);
4331 try diw.writeAll(bytes);
4332 } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
4380 .error_set, .pointer => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
43334381 }
43344382 }
43354383 if (opt.val != .none) child_field: {
......@@ -4457,7 +4505,8 @@ fn updateLazyValue(
44574505 },
44584506 .memoized_call => unreachable, // not a value
44594507 }
4460 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
4508 try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());
4509 try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());
44614510}
44624511
44634512fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } {
......@@ -4472,312 +4521,6 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err
44724521 };
44734522}
44744523
4475pub fn updateContainerType(
4476 dwarf: *Dwarf,
4477 pt: Zcu.PerThread,
4478 type_index: InternPool.Index,
4479) UpdateError!void {
4480 return dwarf.updateContainerTypeWriterError(pt, type_index) catch |err| switch (err) {
4481 error.WriteFailed => error.OutOfMemory,
4482 else => |e| e,
4483 };
4484}
4485fn updateContainerTypeWriterError(
4486 dwarf: *Dwarf,
4487 pt: Zcu.PerThread,
4488 type_index: InternPool.Index,
4489) (UpdateError || Writer.Error)!void {
4490 const zcu = pt.zcu;
4491 const ip = &zcu.intern_pool;
4492 const ty: Type = .fromInterned(type_index);
4493 const ty_src_loc = ty.srcLoc(zcu);
4494 log.debug("updateContainerType({f})", .{ty.fmt(pt)});
4495
4496 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;
4497 const file = zcu.fileByIndex(inst_info.file);
4498 const unit = try dwarf.getUnit(file.mod.?);
4499 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);
4500 if (inst_info.inst == .main_struct_inst) {
4501 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);
4502 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
4503 var wip_nav: WipNav = .{
4504 .dwarf = dwarf,
4505 .pt = pt,
4506 .unit = unit,
4507 .entry = type_gop.value_ptr.*,
4508 .any_children = false,
4509 .func = .none,
4510 .func_sym_index = undefined,
4511 .func_high_pc = undefined,
4512 .blocks = undefined,
4513 .cfi = undefined,
4514 .debug_frame = .init(dwarf.gpa),
4515 .debug_info = .init(dwarf.gpa),
4516 .debug_line = .init(dwarf.gpa),
4517 .debug_loclists = .init(dwarf.gpa),
4518 .pending_lazy = .empty,
4519 };
4520 defer wip_nav.deinit();
4521
4522 const loaded_struct = ip.loadStructType(type_index);
4523
4524 const diw = &wip_nav.debug_info.writer;
4525 try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_file else .file);
4526 try diw.writeUleb128(file_gop.index);
4527 try wip_nav.strp(loaded_struct.name.toSlice(ip));
4528 if (loaded_struct.field_types.len > 0) {
4529 try diw.writeUleb128(ty.abiSize(zcu));
4530 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
4531 for (0..loaded_struct.field_types.len) |field_index| {
4532 const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index);
4533 const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index);
4534 assert(!(is_comptime and field_init == .none));
4535 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
4536 const has_runtime_bits, const has_comptime_state = switch (field_init) {
4537 .none => .{ false, false },
4538 else => .{
4539 field_type.hasRuntimeBits(zcu),
4540 field_type.comptimeOnly(zcu),
4541 },
4542 };
4543 try wip_nav.abbrevCode(if (is_comptime)
4544 if (has_comptime_state)
4545 .struct_field_comptime_comptime_state
4546 else if (has_runtime_bits)
4547 .struct_field_comptime_runtime_bits
4548 else
4549 .struct_field_comptime
4550 else if (field_init != .none)
4551 if (has_comptime_state)
4552 .struct_field_default_comptime_state
4553 else if (has_runtime_bits)
4554 .struct_field_default_runtime_bits
4555 else
4556 .struct_field
4557 else
4558 .struct_field);
4559 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
4560 try wip_nav.refType(field_type);
4561 if (!is_comptime) {
4562 try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]);
4563 try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
4564 field_type.abiAlignment(zcu).toByteUnits().?);
4565 }
4566 if (has_comptime_state)
4567 try wip_nav.refValue(.fromInterned(field_init))
4568 else if (has_runtime_bits)
4569 try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init));
4570 }
4571 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4572 }
4573
4574 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
4575 try wip_nav.updateLazy(ty_src_loc);
4576 } else {
4577 {
4578 // Note that changes to ZIR instruction tracking only need to update this code
4579 // if a newly-tracked instruction can be a type's owner `zir_index`.
4580 comptime assert(Zir.inst_tracking_version == 0);
4581
4582 const decl_inst = file.zir.?.instructions.get(@intFromEnum(inst_info.inst));
4583 const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) {
4584 .struct_init, .struct_init_ref, .struct_init_anon => .anon,
4585 .extended => switch (decl_inst.data.extended.opcode) {
4586 .struct_decl => file.zir.?.getStructDecl(inst_info.inst).name_strategy,
4587 .union_decl => file.zir.?.getUnionDecl(inst_info.inst).name_strategy,
4588 .enum_decl => file.zir.?.getEnumDecl(inst_info.inst).name_strategy,
4589 .opaque_decl => file.zir.?.getOpaqueDecl(inst_info.inst).name_strategy,
4590
4591 .reify_enum,
4592 .reify_struct,
4593 .reify_union,
4594 => @enumFromInt(decl_inst.data.extended.small),
4595
4596 else => unreachable,
4597 },
4598 else => unreachable,
4599 };
4600 if (name_strat == .parent) return;
4601 }
4602
4603 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);
4604 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
4605 var wip_nav: WipNav = .{
4606 .dwarf = dwarf,
4607 .pt = pt,
4608 .unit = unit,
4609 .entry = type_gop.value_ptr.*,
4610 .any_children = false,
4611 .func = .none,
4612 .func_sym_index = undefined,
4613 .func_high_pc = undefined,
4614 .blocks = undefined,
4615 .cfi = undefined,
4616 .debug_frame = .init(dwarf.gpa),
4617 .debug_info = .init(dwarf.gpa),
4618 .debug_line = .init(dwarf.gpa),
4619 .debug_loclists = .init(dwarf.gpa),
4620 .pending_lazy = .empty,
4621 };
4622 defer wip_nav.deinit();
4623 const diw = &wip_nav.debug_info.writer;
4624 const name = try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)});
4625 defer dwarf.gpa.free(name);
4626
4627 switch (ip.indexToKey(type_index)) {
4628 .struct_type => {
4629 const loaded_struct = ip.loadStructType(type_index);
4630 switch (loaded_struct.layout) {
4631 .auto, .@"extern" => {
4632 try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_struct_type else .struct_type);
4633 try diw.writeUleb128(file_gop.index);
4634 try wip_nav.strp(name);
4635 if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else {
4636 try diw.writeUleb128(ty.abiSize(zcu));
4637 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);
4638 for (0..loaded_struct.field_types.len) |field_index| {
4639 const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index);
4640 const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index);
4641 assert(!(is_comptime and field_init == .none));
4642 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
4643 const has_runtime_bits, const has_comptime_state = switch (field_init) {
4644 .none => .{ false, false },
4645 else => .{
4646 field_type.hasRuntimeBits(zcu),
4647 field_type.comptimeOnly(zcu),
4648 },
4649 };
4650 try wip_nav.abbrevCode(if (is_comptime)
4651 if (has_comptime_state)
4652 .struct_field_comptime_comptime_state
4653 else if (has_runtime_bits)
4654 .struct_field_comptime_runtime_bits
4655 else
4656 .struct_field_comptime
4657 else if (field_init != .none)
4658 if (has_comptime_state)
4659 .struct_field_default_comptime_state
4660 else if (has_runtime_bits)
4661 .struct_field_default_runtime_bits
4662 else
4663 .struct_field
4664 else
4665 .struct_field);
4666 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
4667 try wip_nav.refType(field_type);
4668 if (!is_comptime) {
4669 try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]);
4670 try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
4671 field_type.abiAlignment(zcu).toByteUnits().?);
4672 }
4673 if (has_comptime_state)
4674 try wip_nav.refValue(.fromInterned(field_init))
4675 else if (has_runtime_bits)
4676 try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init));
4677 }
4678 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4679 }
4680 },
4681 .@"packed" => {
4682 try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type);
4683 try diw.writeUleb128(file_gop.index);
4684 try wip_nav.strp(name);
4685 try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type));
4686 var field_bit_offset: u16 = 0;
4687 for (0..loaded_struct.field_types.len) |field_index| {
4688 try wip_nav.abbrevCode(.packed_struct_field);
4689 try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip));
4690 const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
4691 try wip_nav.refType(field_type);
4692 try diw.writeUleb128(field_bit_offset);
4693 field_bit_offset += @intCast(field_type.bitSize(zcu));
4694 }
4695 if (loaded_struct.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4696 },
4697 }
4698 },
4699 .enum_type => {
4700 const loaded_enum = ip.loadEnumType(type_index);
4701 try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type);
4702 try diw.writeUleb128(file_gop.index);
4703 try wip_nav.strp(name);
4704 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));
4705 for (0..loaded_enum.field_names.len) |field_index| {
4706 try wip_nav.enumConstValue(loaded_enum, .{
4707 .sdata = .signed_enum_field,
4708 .udata = .unsigned_enum_field,
4709 .block = .big_enum_field,
4710 }, field_index);
4711 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));
4712 }
4713 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4714 },
4715 .union_type => {
4716 const loaded_union = ip.loadUnionType(type_index);
4717 try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type);
4718 try diw.writeUleb128(file_gop.index);
4719 try wip_nav.strp(name);
4720 const union_layout = Type.getUnionLayout(loaded_union, zcu);
4721 try diw.writeUleb128(union_layout.abi_size);
4722 try diw.writeUleb128(union_layout.abi_align.toByteUnits().?);
4723 const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type);
4724 if (loaded_union.has_runtime_tag) {
4725 try wip_nav.abbrevCode(.tagged_union);
4726 try wip_nav.infoSectionOffset(
4727 .debug_info,
4728 wip_nav.unit,
4729 wip_nav.entry,
4730 @intCast(diw.end + dwarf.sectionOffsetBytes()),
4731 );
4732 {
4733 try wip_nav.abbrevCode(.generated_field);
4734 try wip_nav.strp("tag");
4735 try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type));
4736 try diw.writeUleb128(union_layout.tagOffset());
4737
4738 for (0..loaded_union.field_types.len) |field_index| {
4739 try wip_nav.enumConstValue(loaded_tag, .{
4740 .sdata = .signed_tagged_union_field,
4741 .udata = .unsigned_tagged_union_field,
4742 .block = .big_tagged_union_field,
4743 }, field_index);
4744 {
4745 try wip_nav.abbrevCode(.struct_field);
4746 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
4747 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
4748 try wip_nav.refType(field_type);
4749 try diw.writeUleb128(union_layout.payloadOffset());
4750 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
4751 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
4752 }
4753 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4754 }
4755 }
4756 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4757 } else for (0..loaded_union.field_types.len) |field_index| {
4758 try wip_nav.abbrevCode(.untagged_union_field);
4759 try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip));
4760 const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
4761 try wip_nav.refType(field_type);
4762 try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse
4763 if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?);
4764 }
4765 if (loaded_union.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4766 },
4767 .opaque_type => {
4768 try wip_nav.abbrevCode(.empty_struct_type);
4769 try diw.writeUleb128(file_gop.index);
4770 try wip_nav.strp(name);
4771 try diw.writeByte(@intFromBool(true));
4772 },
4773 else => unreachable,
4774 }
4775 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
4776 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written());
4777 try wip_nav.updateLazy(ty_src_loc);
4778 }
4779}
4780
47814524pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void {
47824525 const comp = dwarf.bin_file.comp;
47834526 const io = comp.io;
......@@ -4840,14 +4583,15 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
48404583 const comp = dwarf.bin_file.comp;
48414584 const io = comp.io;
48424585
4586 // Update `anyerror` based on the finished global error set.
48434587 {
4844 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type);
4845 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main);
4588 const index = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, .anyerror_type);
4589 const unit, const entry = dwarf.values.items[@intFromEnum(index)];
48464590 var wip_nav: WipNav = .{
48474591 .dwarf = dwarf,
48484592 .pt = pt,
4849 .unit = .main,
4850 .entry = type_gop.value_ptr.*,
4593 .unit = unit,
4594 .entry = entry,
48514595 .any_children = false,
48524596 .func = .none,
48534597 .func_sym_index = undefined,
......@@ -4858,7 +4602,6 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
48584602 .debug_info = .init(dwarf.gpa),
48594603 .debug_line = .init(dwarf.gpa),
48604604 .debug_loclists = .init(dwarf.gpa),
4861 .pending_lazy = .empty,
48624605 };
48634606 defer wip_nav.deinit();
48644607 const diw = &wip_nav.debug_info.writer;
......@@ -4876,7 +4619,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
48764619 }
48774620 if (global_error_set_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
48784621 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
4879 try wip_nav.updateLazy(.unneeded);
4622 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
48804623 }
48814624
48824625 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {
......@@ -5324,6 +5067,8 @@ const AbbrevCode = enum {
53245067 inferred_error_set_type,
53255068 ptr_type,
53265069 ptr_sentinel_type,
5070 ptr_aligned_type,
5071 ptr_aligned_sentinel_type,
53275072 is_const,
53285073 is_volatile,
53295074 array_type,
......@@ -5960,12 +5705,29 @@ const AbbrevCode = enum {
59605705 .tag = .pointer_type,
59615706 .attrs = &.{
59625707 .{ .name, .strp },
5963 .{ .alignment, .udata },
59645708 .{ .address_class, .data1 },
59655709 .{ .type, .ref_addr },
59665710 },
59675711 },
59685712 .ptr_sentinel_type = .{
5713 .tag = .pointer_type,
5714 .attrs = &.{
5715 .{ .name, .strp },
5716 .{ .ZIG_sentinel, .block },
5717 .{ .address_class, .data1 },
5718 .{ .type, .ref_addr },
5719 },
5720 },
5721 .ptr_aligned_type = .{
5722 .tag = .pointer_type,
5723 .attrs = &.{
5724 .{ .name, .strp },
5725 .{ .alignment, .udata },
5726 .{ .address_class, .data1 },
5727 .{ .type, .ref_addr },
5728 },
5729 },
5730 .ptr_aligned_sentinel_type = .{
59695731 .tag = .pointer_type,
59705732 .attrs = &.{
59715733 .{ .name, .strp },
src/link/Elf.zig+2-1
......@@ -1711,13 +1711,14 @@ pub fn updateContainerType(
17111711 self: *Elf,
17121712 pt: Zcu.PerThread,
17131713 ty: InternPool.Index,
1714 success: bool,
17141715) link.File.UpdateContainerTypeError!void {
17151716 if (build_options.skip_non_native and builtin.object_format != .elf) {
17161717 @panic("Attempted to compile for object format that was disabled by build configuration");
17171718 }
17181719 const zcu = pt.zcu;
17191720 const gpa = zcu.gpa;
1720 return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {
1721 return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) {
17211722 error.OutOfMemory => return error.OutOfMemory,
17221723 else => |e| {
17231724 try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create(
src/link/Elf/ZigObject.zig+2-1
......@@ -1719,11 +1719,12 @@ pub fn updateContainerType(
17191719 self: *ZigObject,
17201720 pt: Zcu.PerThread,
17211721 ty: InternPool.Index,
1722 success: bool,
17221723) !void {
17231724 const tracy = trace(@src());
17241725 defer tracy.end();
17251726
1726 if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty);
1727 if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty, success);
17271728}
17281729
17291730fn updateLazySymbol(