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 {...@@ -956,8 +956,7 @@ pub const RcSourceFile = struct {
956956
957const Job = union(enum) {957const Job = union(enum) {
958 /// Given the generated AIR for a function, put it onto the code generation queue.958 /// 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 that959 /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now
960 /// all types are resolved before the linker task is queued.
961 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.960 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.
962 /// Before queueing this `Job`, increase the estimated total item count for both961 /// Before queueing this `Job`, increase the estimated total item count for both
963 /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.962 /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.
...@@ -967,17 +966,10 @@ const Job = union(enum) {...@@ -967,17 +966,10 @@ const Job = union(enum) {
967 air: Air,966 air: Air,
968 },967 },
969 /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary.968 /// 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 that969 /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now
971 /// all types are resolved before the linker task is queued.
972 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.970 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
973 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.971 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
974 link_nav: InternPool.Nav.Index,972 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,
981 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.973 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
982 update_line_number: InternPool.TrackedInst.Index,974 update_line_number: InternPool.TrackedInst.Index,
983 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.975 /// 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...@@ -5058,26 +5050,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
5058 var owned_air: ?Air = func.air;5050 var owned_air: ?Air = func.air;
5059 defer if (owned_air) |*air| air.deinit(gpa);5051 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
5081 // Some linkers need to refer to the AIR. In that case, the linker is not running5053 // Some linkers need to refer to the AIR. In that case, the linker is not running
5082 // concurrently, so we'll just keep ownership of the AIR for ourselves instead of5054 // concurrently, so we'll just keep ownership of the AIR for ourselves instead of
5083 // letting the codegen job destroy it.5055 // letting the codegen job destroy it.
...@@ -5101,51 +5073,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v...@@ -5101,51 +5073,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
5101 }5073 }
5102 }5074 }
5103 assert(nav.status == .fully_resolved);5075 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 }
5122 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index });5076 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index });
5123 },5077 },
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 },
5147 .update_line_number => |tracked_inst| {5078 .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 });
5149 },5080 },
5150 .analyze_unit => |unit| {5081 .analyze_unit => |unit| {
5151 const tracy_trace = traceNamed(@src(), "analyze_unit");5082 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...@@ -998,10 +998,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
998 try sema.flushExports();998 try sema.flushExports();
999}999}
10001000
1001/// Ensures that the layout of the given `struct` or `union` type is fully up-to-date, performing1001/// Ensures that the layout of the given `struct`, `union`, or `enum` type is fully up-to-date,
1002/// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns1002/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!), union, or
1003/// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is1003/// enum type. Returns `error.AnalysisFail` if an analysis error is encountered during type
1004/// free to ignore this, since the error is already registered.1004/// resolution; the caller is free to ignore this, since the error is already registered.
1005pub fn ensureTypeLayoutUpToDate(1005pub fn ensureTypeLayoutUpToDate(
1006 pt: Zcu.PerThread,1006 pt: Zcu.PerThread,
1007 ty: Type,1007 ty: Type,
...@@ -1012,7 +1012,8 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1012,7 +1012,8 @@ pub fn ensureTypeLayoutUpToDate(
1012 defer tracy.end();1012 defer tracy.end();
10131013
1014 const zcu = pt.zcu;1014 const zcu = pt.zcu;
1015 const gpa = zcu.gpa;1015 const comp = zcu.comp;
1016 const gpa = comp.gpa;
10161017
1017 const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() });1018 const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() });
10181019
...@@ -1021,7 +1022,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1021,7 +1022,7 @@ pub fn ensureTypeLayoutUpToDate(
1021 assert(!zcu.analysis_in_progress.contains(anal_unit));1022 assert(!zcu.analysis_in_progress.contains(anal_unit));
10221023
1023 const was_outdated = zcu.clearOutdatedState(anal_unit) or1024 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
1026 if (was_outdated) {1027 if (was_outdated) {
1027 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.1028 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.
...@@ -1038,7 +1039,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1038,7 +1039,7 @@ pub fn ensureTypeLayoutUpToDate(
1038 return;1039 return;
1039 }1040 }
10401041
1041 if (zcu.comp.debugIncremental()) {1042 if (comp.debugIncremental()) {
1042 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);1043 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
1043 info.last_update_gen = zcu.generation;1044 info.last_update_gen = zcu.generation;
1044 info.deps.clearRetainingCapacity();1045 info.deps.clearRetainingCapacity();
...@@ -1078,15 +1079,17 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1078,15 +1079,17 @@ pub fn ensureTypeLayoutUpToDate(
1078 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),1079 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),
1079 else => unreachable,1080 else => unreachable,
1080 };1081 };
1081 result catch |err| switch (err) {1082 const new_success: bool = if (result) s: {
1082 error.AnalysisFail => {1083 break :s true;
1084 } else |err| switch (err) {
1085 error.AnalysisFail => success: {
1083 if (!zcu.failed_analysis.contains(anal_unit)) {1086 if (!zcu.failed_analysis.contains(anal_unit)) {
1084 // If this unit caused the error, it would have an entry in `failed_analysis`.1087 // If this unit caused the error, it would have an entry in `failed_analysis`.
1085 // Since it does not, this must be a transitive failure.1088 // Since it does not, this must be a transitive failure.
1086 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1089 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1087 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});1090 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1088 }1091 }
1089 return error.AnalysisFail;1092 break :success false;
1090 },1093 },
1091 error.OutOfMemory,1094 error.OutOfMemory,
1092 error.Canceled,1095 error.Canceled,
...@@ -1098,6 +1101,15 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1098,6 +1101,15 @@ pub fn ensureTypeLayoutUpToDate(
1098 sema.flushExports() catch |err| switch (err) {1101 sema.flushExports() catch |err| switch (err) {
1099 error.OutOfMemory => |e| return e,1102 error.OutOfMemory => |e| return e,
1100 };1103 };
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 } });
1101}1113}
11021114
1103/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis1115/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
...@@ -4102,463 +4114,3 @@ fn printVerboseAir(...@@ -4102,463 +4114,3 @@ fn printVerboseAir(
4102 try air.write(w, pt, liveness);4114 try air.write(w, pt, liveness);
4103 try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});4115 try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});
4104}4116}
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(...@@ -700,7 +700,14 @@ fn lowerPtr(
700 };700 };
701 return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);701 return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off);
702 },702 },
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,
704 };711 };
705}712}
706713
...@@ -781,9 +788,8 @@ fn lowerNavRef(...@@ -781,9 +788,8 @@ fn lowerNavRef(
781 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);788 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
782 const is_obj = lf.comp.config.output_mode == .Obj;789 const is_obj = lf.comp.config.output_mode == .Obj;
783 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));790 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) {
787 try w.splatByteAll(0xaa, ptr_width_bytes);793 try w.splatByteAll(0xaa, ptr_width_bytes);
788 return;794 return;
789 }795 }
...@@ -795,7 +801,7 @@ fn lowerNavRef(...@@ -795,7 +801,7 @@ fn lowerNavRef(
795 dev.check(link.File.Tag.wasm.devFeature());801 dev.check(link.File.Tag.wasm.devFeature());
796 const wasm = lf.cast(.wasm).?;802 const wasm = lf.cast(.wasm).?;
797 assert(reloc_parent == .none);803 assert(reloc_parent == .none);
798 if (is_fn_body) {804 if (nav_ty.zigTypeTag(zcu) == .@"fn") {
799 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);805 const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index);
800 if (!gop.found_existing) gop.value_ptr.* = {};806 if (!gop.found_existing) gop.value_ptr.* = {};
801 if (is_obj) {807 if (is_obj) {
...@@ -1025,23 +1031,26 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo...@@ -1025,23 +1031,26 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
1025 .pointer => switch (ty.ptrSize(zcu)) {1031 .pointer => switch (ty.ptrSize(zcu)) {
1026 .slice => {},1032 .slice => {},
1027 .one, .many, .c => {1033 .one, .many, .c => {
1028 const elem_ty = ty.childType(zcu);
1029 const ptr = ip.indexToKey(val.toIntern()).ptr;1034 const ptr = ip.indexToKey(val.toIntern()).ptr;
1030 if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };1035 if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
1031 if (ptr.byte_offset == 0) switch (ptr.base_addr) {1036 if (ptr.byte_offset == 0) switch (ptr.base_addr) {
1032 .int => unreachable, // handled above1037 .int => unreachable, // handled above
10331038
1034 .nav => |nav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {1039 .nav => |nav_index| {
1035 return .{ .lea_nav = nav };1040 const nav = ip.getNav(nav_index);
1036 } else {1041 const nav_ty: Type = .fromInterned(nav.typeOf(ip));
1037 // Create the 0xaa bit pattern...1042 if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
1038 const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);1043 return .{ .lea_nav = nav_index };
1039 // ...but align the pointer1044 } else {
1040 const alignment = zcu.navAlignment(nav);1045 // Create the 0xaa bit pattern...
1041 return .{ .immediate = alignment.forward(undef_ptr_bits) };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 }
1042 },1051 },
10431052
1044 .uav => |uav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {1053 .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
1045 return .{ .lea_uav = uav };1054 return .{ .lea_uav = uav };
1046 } else {1055 } else {
1047 // Create the 0xaa bit pattern...1056 // Create the 0xaa bit pattern...
src/link.zig+34-12
...@@ -798,14 +798,27 @@ pub const File = struct {...@@ -798,14 +798,27 @@ pub const File = struct {
798 };798 };
799799
800 /// Never called when LLVM is codegenning the ZCU.800 /// 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 {
802 assert(base.comp.zcu.?.llvm_object == null);802 assert(base.comp.zcu.?.llvm_object == null);
803 switch (base.tag) {803 switch (base.tag) {
804 .lld => unreachable,804 .lld => unreachable,
805 else => {},805 else => {},
806 inline .elf => |tag| {806 inline .elf => |tag| {
807 dev.check(tag.devFeature());807 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);
809 },822 },
810 }823 }
811 }824 }
...@@ -1375,8 +1388,14 @@ pub const ZcuTask = union(enum) {...@@ -1375,8 +1388,14 @@ pub const ZcuTask = union(enum) {
1375 link_nav: InternPool.Nav.Index,1388 link_nav: InternPool.Nav.Index,
1376 /// Write the machine code for a function to the output file.1389 /// Write the machine code for a function to the output file.
1377 link_func: Zcu.CodegenTaskPool.Index,1390 link_func: Zcu.CodegenTaskPool.Index,
1378 link_type: InternPool.Index,1391 /// This struct/union/enum type has finished type resolution (successfully or otherwise), so the
1379 update_line_number: InternPool.TrackedInst.Index,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,
1380};1399};
13811400
1382pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {1401pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
...@@ -1563,21 +1582,24 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1563,21 +1582,24 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1563 }1582 }
1564 break :nav ip.indexToKey(func).func.owner_nav;1583 break :nav ip.indexToKey(func).func.owner_nav;
1565 },1584 },
1566 .link_type => |ty| nav: {1585 .debug_update_container_type => |container_update| nav: {
1567 const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);1586 const name = Type.fromInterned(container_update.ty).containerTypeName(ip).toSlice(ip);
1568 const nav_prog_node = comp.link_prog_node.start(name, 0);1587 const ty_prog_node = comp.link_prog_node.start(name, 0);
1569 defer nav_prog_node.end();1588 defer ty_prog_node.end();
1570 if (zcu.llvm_object == null) {1589 if (zcu.llvm_object) |llvm_object| {
1590 _ = llvm_object;
1591 @compileError("MLUGG TODO");
1592 } else {
1571 if (comp.bin_file) |lf| {1593 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) {
1573 error.OutOfMemory => diags.setAllocFailure(),1595 error.OutOfMemory => diags.setAllocFailure(),
1574 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),1596 error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)),
1575 };1597 };
1576 }1598 }
1577 }1599 }
1578 break :nav null;1600 break :nav null;
1579 },1601 },
1580 .update_line_number => |ti| nav: {1602 .debug_update_line_number => |ti| nav: {
1581 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);1603 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);
1582 defer nav_prog_node.end();1604 defer nav_prog_node.end();
1583 if (pt.zcu.llvm_object == null) {1605 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");...@@ -18,6 +18,7 @@ const codegen = @import("../codegen.zig");
18const dev = @import("../dev.zig");18const dev = @import("../dev.zig");
19const link = @import("../link.zig");19const link = @import("../link.zig");
20const target_info = @import("../target.zig");20const target_info = @import("../target.zig");
21const DebugConstPool = @import("DebugConstPool.zig");
2122
22gpa: Allocator,23gpa: Allocator,
23bin_file: *link.File,24bin_file: *link.File,
...@@ -25,9 +26,11 @@ format: DW.Format,...@@ -25,9 +26,11 @@ format: DW.Format,
25endian: std.builtin.Endian,26endian: std.builtin.Endian,
26address_size: AddressSize,27address_size: AddressSize,
2728
29const_pool: DebugConstPool,
30
28mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo),31mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo),
29types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index),32/// Indices are `DebugConstPool.Index`.
30values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index),33values: std.ArrayList(struct { Unit.Index, Entry.Index }),
31navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index),34navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index),
32decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index),35decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index),
3336
...@@ -1034,15 +1037,14 @@ const Entry = struct {...@@ -1034,15 +1037,14 @@ const Entry = struct {
1034 });1037 });
1035 const zcu = dwarf.bin_file.comp.zcu.?;1038 const zcu = dwarf.bin_file.comp.zcu.?;
1036 const ip = &zcu.intern_pool;1039 const ip = &zcu.intern_pool;
1037 for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| {1040 for (0.., dwarf.values.items) |raw_index, unit_and_entry| {
1038 const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index|1041 const index: DebugConstPool.Index = @enumFromInt(raw_index);
1039 dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?) catch unreachable1042 const val = index.val(&dwarf.const_pool);
1040 else1043 const val_unit, const val_entry = unit_and_entry;
1041 .main;1044 if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry)
1042 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)1045 log.err("missing Value({f}({d}))", .{
1043 log.err("missing Type({f}({d}))", .{1046 Value.fromInterned(val).fmtValue(.{ .tid = .main, .zcu = zcu }),
1044 Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }),1047 @intFromEnum(val),
1045 @intFromEnum(ty),
1046 });1048 });
1047 }1049 }
1048 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {1050 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {
...@@ -1520,7 +1522,6 @@ pub const WipNav = struct {...@@ -1520,7 +1522,6 @@ pub const WipNav = struct {
1520 debug_info: Writer.Allocating,1522 debug_info: Writer.Allocating,
1521 debug_line: Writer.Allocating,1523 debug_line: Writer.Allocating,
1522 debug_loclists: Writer.Allocating,1524 debug_loclists: Writer.Allocating,
1523 pending_lazy: PendingLazy,
15241525
1525 pub fn deinit(wip_nav: *WipNav) void {1526 pub fn deinit(wip_nav: *WipNav) void {
1526 const gpa = wip_nav.dwarf.gpa;1527 const gpa = wip_nav.dwarf.gpa;
...@@ -1529,8 +1530,6 @@ pub const WipNav = struct {...@@ -1529,8 +1530,6 @@ pub const WipNav = struct {
1529 wip_nav.debug_info.deinit();1530 wip_nav.debug_info.deinit();
1530 wip_nav.debug_line.deinit();1531 wip_nav.debug_line.deinit();
1531 wip_nav.debug_loclists.deinit();1532 wip_nav.debug_loclists.deinit();
1532 wip_nav.pending_lazy.types.deinit(gpa);
1533 wip_nav.pending_lazy.values.deinit(gpa);
1534 }1533 }
15351534
1536 pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void {1535 pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void {
...@@ -1945,6 +1944,12 @@ pub const WipNav = struct {...@@ -1945,6 +1944,12 @@ pub const WipNav = struct {
1945 try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0);1944 try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0);
1946 }1945 }
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
1948 const ExprLocCounter = struct {1953 const ExprLocCounter = struct {
1949 dw: Writer.Discarding,1954 dw: Writer.Discarding,
1950 section_offset_bytes: u32,1955 section_offset_bytes: u32,
...@@ -2054,74 +2059,16 @@ pub const WipNav = struct {...@@ -2054,74 +2059,16 @@ pub const WipNav = struct {
2054 try dfw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size));2059 try dfw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size));
2055 }2060 }
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
2072 fn refNav(2062 fn refNav(
2073 wip_nav: *WipNav,2063 wip_nav: *WipNav,
2074 nav_index: InternPool.Nav.Index,2064 nav_index: InternPool.Nav.Index,
2075 ) (UpdateError || Writer.Error)!void {2065 ) (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);
2077 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);2067 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
2078 }2068 }
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
2102 fn refType(wip_nav: *WipNav, ty: Type) (UpdateError || Writer.Error)!void {2070 fn refType(wip_nav: *WipNav, ty: Type) (UpdateError || Writer.Error)!void {
2103 const unit, const entry = try wip_nav.getTypeEntry(ty);2071 return wip_nav.refValue(ty.toValue());
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 };
2125 }2072 }
21262073
2127 fn refValue(wip_nav: *WipNav, value: Value) (UpdateError || Writer.Error)!void {2074 fn refValue(wip_nav: *WipNav, value: Value) (UpdateError || Writer.Error)!void {
...@@ -2129,6 +2076,15 @@ pub const WipNav = struct {...@@ -2129,6 +2076,15 @@ pub const WipNav = struct {
2129 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);2076 try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
2130 }2077 }
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
2132 fn refForward(wip_nav: *WipNav) (Allocator.Error || Writer.Error)!u32 {2088 fn refForward(wip_nav: *WipNav) (Allocator.Error || Writer.Error)!u32 {
2133 const dwarf = wip_nav.dwarf;2089 const dwarf = wip_nav.dwarf;
2134 const diw = &wip_nav.debug_info.writer;2090 const diw = &wip_nav.debug_info.writer;
...@@ -2156,7 +2112,7 @@ pub const WipNav = struct {...@@ -2156,7 +2112,7 @@ pub const WipNav = struct {
2156 ) (UpdateError || Writer.Error)!void {2112 ) (UpdateError || Writer.Error)!void {
2157 const ty = val.typeOf(wip_nav.pt.zcu);2113 const ty = val.typeOf(wip_nav.pt.zcu);
2158 const diw = &wip_nav.debug_info.writer;2114 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);
2160 try diw.writeUleb128(size);2116 try diw.writeUleb128(size);
2161 if (size == 0) return;2117 if (size == 0) return;
2162 const old_end = wip_nav.debug_info.writer.end;2118 const old_end = wip_nav.debug_info.writer.end;
...@@ -2331,22 +2287,6 @@ pub const WipNav = struct {...@@ -2331,22 +2287,6 @@ pub const WipNav = struct {
2331 try wip_nav.refType(parent_type.?);2287 try wip_nav.refType(parent_type.?);
2332 try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0);2288 try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0);
2333 }2289 }
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 }
2350};2290};
23512291
2352/// When allocating, the ideal_capacity is calculated by2292/// When allocating, the ideal_capacity is calculated by
...@@ -2372,8 +2312,9 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {...@@ -2372,8 +2312,9 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf {
2372 },2312 },
2373 .endian = target.cpu.arch.endian(),2313 .endian = target.cpu.arch.endian(),
23742314
2315 .const_pool = .empty,
2316
2375 .mods = .empty,2317 .mods = .empty,
2376 .types = .empty,
2377 .values = .empty,2318 .values = .empty,
2378 .navs = .empty,2319 .navs = .empty,
2379 .decls = .empty,2320 .decls = .empty,
...@@ -2544,9 +2485,9 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void {...@@ -2544,9 +2485,9 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void {
25442485
2545pub fn deinit(dwarf: *Dwarf) void {2486pub fn deinit(dwarf: *Dwarf) void {
2546 const gpa = dwarf.gpa;2487 const gpa = dwarf.gpa;
2488 dwarf.const_pool.deinit(gpa);
2547 for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa);2489 for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa);
2548 dwarf.mods.deinit(gpa);2490 dwarf.mods.deinit(gpa);
2549 dwarf.types.deinit(gpa);
2550 dwarf.values.deinit(gpa);2491 dwarf.values.deinit(gpa);
2551 dwarf.navs.deinit(gpa);2492 dwarf.navs.deinit(gpa);
2552 dwarf.decls.deinit(gpa);2493 dwarf.decls.deinit(gpa);
...@@ -2562,6 +2503,21 @@ pub fn deinit(dwarf: *Dwarf) void {...@@ -2562,6 +2503,21 @@ pub fn deinit(dwarf: *Dwarf) void {
2562 dwarf.* = undefined;2503 dwarf.* = undefined;
2563}2504}
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
2565fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {2521fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {
2566 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);2522 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);
2567 const unit: Unit.Index = @enumFromInt(mod_gop.index);2523 const unit: Unit.Index = @enumFromInt(mod_gop.index);
...@@ -2622,6 +2578,10 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo {...@@ -2622,6 +2578,10 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo {
2622 return &dwarf.mods.values()[@intFromEnum(unit)];2578 return &dwarf.mods.values()[@intFromEnum(unit)];
2623}2579}
26242580
2581fn getUnitModule(dwarf: *Dwarf, unit: Unit.Index) *Module {
2582 return dwarf.mods.keys()[@intFromEnum(unit)];
2583}
2584
2625pub fn initWipNav(2585pub fn initWipNav(
2626 dwarf: *Dwarf,2586 dwarf: *Dwarf,
2627 pt: Zcu.PerThread,2587 pt: Zcu.PerThread,
...@@ -2683,7 +2643,6 @@ fn initWipNavInner(...@@ -2683,7 +2643,6 @@ fn initWipNavInner(
2683 .debug_info = .init(dwarf.gpa),2643 .debug_info = .init(dwarf.gpa),
2684 .debug_line = .init(dwarf.gpa),2644 .debug_line = .init(dwarf.gpa),
2685 .debug_loclists = .init(dwarf.gpa),2645 .debug_loclists = .init(dwarf.gpa),
2686 .pending_lazy = .empty,
2687 };2646 };
2688 errdefer wip_nav.deinit();2647 errdefer wip_nav.deinit();
26892648
...@@ -3050,7 +3009,7 @@ fn finishWipNavWriterError(...@@ -3050,7 +3009,7 @@ fn finishWipNavWriterError(
3050 }3009 }
3051 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written());3010 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 });
3054}3013}
30553014
3056pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {3015pub 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...@@ -3087,34 +3046,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3087 return;3046 return;
3088 }3047 }
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
3112 const tag: union(enum) {3049 const tag: union(enum) {
3113 done,3050 alias,
3114 decl_alias,3051 @"var",
3115 decl_var,3052 @"const",
3116 decl_const,3053 func: Type,
3117 decl_func_alias: InternPool.Nav.Index,3054 func_alias: InternPool.Nav.Index,
3118 } = switch (ip.indexToKey(nav_val.toIntern())) {3055 } = switch (ip.indexToKey(nav_val.toIntern())) {
3119 .int_type,3056 .int_type,
3120 .ptr_type,3057 .ptr_type,
...@@ -3128,242 +3065,49 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3128,242 +3065,49 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3128 .func_type,3065 .func_type,
3129 .error_set_type,3066 .error_set_type,
3130 .inferred_error_set_type,3067 .inferred_error_set_type,
3131 => .decl_alias,3068 => .alias,
3069
3132 .struct_type => tag: {3070 .struct_type => tag: {
3133 const loaded_struct = ip.loadStructType(nav_val.toIntern());3071 const loaded_struct = ip.loadStructType(nav_val.toIntern());
3134 if (loaded_struct.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;3072 if (nav_index.toOptional() == loaded_struct.name_nav) {
31353073 // This Nav's entry is populated by the type, not the actual Nav.
3136 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());3074 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3137 if (type_gop.found_existing) {3075 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3138 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;3076 return;
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 },
3227 }3077 }
3228 break :tag .done;3078 break :tag .alias;
3229 },3079 },
3230 .enum_type => tag: {3080 .enum_type => tag: {
3231 const loaded_enum = ip.loadEnumType(nav_val.toIntern());3081 const loaded_enum = ip.loadEnumType(nav_val.toIntern());
3232 const type_zir_index = loaded_enum.zir_index.unwrap() orelse break :tag .decl_alias;3082 if (nav_index.toOptional() == loaded_enum.name_nav) {
3233 if (type_zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;3083 // This Nav's entry is populated by the type, not the actual Nav.
32343084 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3235 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());3085 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3236 if (type_gop.found_existing) {3086 return;
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));
3266 }3087 }
3267 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));3088 break :tag .alias;
3268 break :tag .done;
3269 },3089 },
3270 .union_type => tag: {3090 .union_type => tag: {
3271 const loaded_union = ip.loadUnionType(nav_val.toIntern());3091 const loaded_union = ip.loadUnionType(nav_val.toIntern());
3272 if (loaded_union.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;3092 if (nav_index.toOptional() == loaded_union.name_nav) {
32733093 // This Nav's entry is populated by the type, not the actual Nav.
3274 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());3094 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3275 if (type_gop.found_existing) {3095 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3276 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;3096 return;
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().?);
3337 }3097 }
3338 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));3098 break :tag .alias;
3339 break :tag .done;
3340 },3099 },
3341 .opaque_type => tag: {3100 .opaque_type => tag: {
3342 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());3101 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());
3343 if (loaded_opaque.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias;3102 if (nav_index.toOptional() == loaded_opaque.name_nav) {
33443103 // This Nav's entry is populated by the type, not the actual Nav.
3345 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());3104 _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern());
3346 if (type_gop.found_existing) {3105 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3347 if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias;3106 return;
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.*;
3356 }3107 }
3357 wip_nav.entry = nav_gop.value_ptr.*;3108 break :tag .alias;
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;
3366 },3109 },
3110
3367 .undef,3111 .undef,
3368 .simple_value,3112 .simple_value,
3369 .int,3113 .int,
...@@ -3378,72 +3122,77 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3378,72 +3122,77 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3378 .aggregate,3122 .aggregate,
3379 .un,3123 .un,
3380 .bitpack,3124 .bitpack,
3381 => .decl_const,3125 => .@"const",
3382 .variable => .decl_var,3126
3127 .variable => .@"var",
3128
3383 .@"extern" => unreachable,3129 .@"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;3131 .func => |func| tag: {
3399 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {3132 if (func.owner_nav != nav_index) break :tag .{ .func_alias = func.owner_nav };
3400 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;3133 break :tag .{ .func = .fromInterned(func.ty) };
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;
3424 },3134 },
3135
3425 // memoization, not types3136 // memoization, not types
3426 .memoized_call => unreachable,3137 .memoized_call => unreachable,
3427 };3138 };
3428 if (tag != .done) {3139
3429 if (nav_gop.found_existing)3140 const unit = try dwarf.getUnit(file.mod.?);
3430 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()3141
3431 else3142 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
3432 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);3143 errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();
3433 wip_nav.entry = nav_gop.value_ptr.*;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);
3434 }3165 }
3435 switch (tag) {3166
3436 .done => {},3167 var wip_nav: WipNav = .{
3437 .decl_alias => {3168 .dwarf = dwarf,
3438 try wip_nav.declCommon(.{3169 .pt = pt,
3439 .decl = .decl_alias,3170 .unit = unit,
3440 .generic_decl = .generic_decl_const,3171 .entry = nav_gop.value_ptr.*,
3441 .decl_instance = .decl_instance_alias,3172 .any_children = false,
3442 }, &nav, inst_info.file, &decl);3173 .func = .none,
3443 try wip_nav.refType(nav_val.toType());3174 .func_sym_index = undefined,
3444 },3175 .func_high_pc = undefined,
3445 .decl_var => {3176 .blocks = undefined,
3446 const diw = &wip_nav.debug_info.writer;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" => {
3447 try wip_nav.declCommon(.{3196 try wip_nav.declCommon(.{
3448 .decl = .decl_var,3197 .decl = .decl_var,
3449 .generic_decl = .generic_decl_var,3198 .generic_decl = .generic_decl_var,
...@@ -3460,8 +3209,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3460,8 +3209,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3460 nav_ty.abiAlignment(zcu).toByteUnits().?);3209 nav_ty.abiAlignment(zcu).toByteUnits().?);
3461 try diw.writeByte(@intFromBool(decl.linkage != .normal));3210 try diw.writeByte(@intFromBool(decl.linkage != .normal));
3462 },3211 },
3463 .decl_const => {3212 .@"const" => {
3464 const diw = &wip_nav.debug_info.writer;
3465 const nav_ty = nav_val.typeOf(zcu);3213 const nav_ty = nav_val.typeOf(zcu);
3466 const has_runtime_bits = nav_ty.hasRuntimeBits(zcu);3214 const has_runtime_bits = nav_ty.hasRuntimeBits(zcu);
3467 const has_comptime_state = nav_ty.comptimeOnly(zcu);3215 const has_comptime_state = nav_ty.comptimeOnly(zcu);
...@@ -3496,7 +3244,33 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3496,7 +3244,33 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3496 try wip_nav.abbrevCode(.is_const);3244 try wip_nav.abbrevCode(.is_const);
3497 try wip_nav.refType(nav_ty);3245 try wip_nav.refType(nav_ty);
3498 },3246 },
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| {
3500 try wip_nav.declCommon(.{3274 try wip_nav.declCommon(.{
3501 .decl = .decl_alias,3275 .decl = .decl_alias,
3502 .generic_decl = .generic_decl_const,3276 .generic_decl = .generic_decl_const,
...@@ -3505,31 +3279,81 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3505,31 +3279,81 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3505 try wip_nav.refNav(owner_nav);3279 try wip_nav.refNav(owner_nav);
3506 },3280 },
3507 }3281 }
3508 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());3282 try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
3509 try wip_nav.updateLazy(nav_src_loc);3283 try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf });
3510}3284}
35113285
3512fn updateLazyType(3286pub fn updateContainerType(
3513 dwarf: *Dwarf,3287 dwarf: *Dwarf,
3514 pt: Zcu.PerThread,3288 pt: Zcu.PerThread,
3515 src_loc: Zcu.LazySrcLoc,3289 ty: InternPool.Index,
3516 type_index: InternPool.Index,3290 success: bool,
3517 pending_lazy: *WipNav.PendingLazy,3291) !void {
3518) (UpdateError || Writer.Error)!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 {
3519 const zcu = pt.zcu;3296 const zcu = pt.zcu;
3520 const ip = &zcu.intern_pool;3297 const ip = &zcu.intern_pool;
3521 assert(ip.typeOf(type_index) == .type_type);3298
3522 const ty: Type = .fromInterned(type_index);3299 const unit: Unit.Index, const entry: Entry.Index = switch (ip.indexToKey(val)) {
3523 switch (type_index) {3300 else => .{ .main, try dwarf.addCommonEntry(.main) },
3524 .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}),3301 .func => |func| try dwarf.getNavEntry(func.owner_nav),
3525 else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}),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 }),
3526 }3339 }
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
3528 var wip_nav: WipNav = .{3352 var wip_nav: WipNav = .{
3529 .dwarf = dwarf,3353 .dwarf = dwarf,
3530 .pt = pt,3354 .pt = pt,
3531 .unit = .main,3355 .unit = unit,
3532 .entry = dwarf.types.get(type_index).?,3356 .entry = entry,
3533 .any_children = false,3357 .any_children = false,
3534 .func = .none,3358 .func = .none,
3535 .func_sym_index = undefined,3359 .func_sym_index = undefined,
...@@ -3540,43 +3364,119 @@ fn updateLazyType(...@@ -3540,43 +3364,119 @@ fn updateLazyType(
3540 .debug_info = .init(dwarf.gpa),3364 .debug_info = .init(dwarf.gpa),
3541 .debug_line = .init(dwarf.gpa),3365 .debug_line = .init(dwarf.gpa),
3542 .debug_loclists = .init(dwarf.gpa),3366 .debug_loclists = .init(dwarf.gpa),
3543 .pending_lazy = pending_lazy.*,
3544 };3367 };
3545 defer {3368 defer wip_nav.deinit();
3546 pending_lazy.* = wip_nav.pending_lazy;3369 switch (val.typeOf(zcu).toIntern()) {
3547 wip_nav.pending_lazy = .empty;3370 .type_type => {
3548 wip_nav.deinit();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 },
3549 }3379 }
3550 const diw = &wip_nav.debug_info.writer;3380 try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());
3551 const name = switch (type_index) {3381 try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());
3552 .generic_poison_type => "",3382}
3553 else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}),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),
3554 };3438 };
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 },
3562 .int_type => |int_type| {3460 .int_type => |int_type| {
3563 try wip_nav.abbrevCode(.numeric_type);3461 try wip_nav.abbrevCode(.numeric_type);
3564 try wip_nav.strp(name);3462 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3565 try diw.writeByte(switch (int_type.signedness) {3463 try diw.writeByte(switch (int_type.signedness) {
3566 inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),3464 inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),
3567 });3465 });
3568 try diw.writeUleb128(int_type.bits);3466 try diw.writeUleb128(int_type.bits);
3569 try diw.writeUleb128(ty.abiSize(zcu));3467 try diw.writeUleb128(val.toType().abiSize(zcu));
3570 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);3468 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3571 },3469 },
3572 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {3470 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
3573 .one, .many, .c => {3471 .one, .many, .c => {
3574 const ptr_child_type: Type = .fromInterned(ptr_type.child);3472 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);3473 try wip_nav.abbrevCode(switch (ptr_type.flags.alignment) {
3576 try wip_nav.strp(name);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)});
3577 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));3478 if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel));
3578 try diw.writeUleb128(ptr_type.flags.alignment.toByteUnits() orelse3479 if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);
3579 ptr_child_type.abiAlignment(zcu).toByteUnits().?);
3580 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));3480 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));
3581 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(3481 if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset(
3582 .debug_info,3482 .debug_info,
...@@ -3600,12 +3500,12 @@ fn updateLazyType(...@@ -3600,12 +3500,12 @@ fn updateLazyType(
3600 },3500 },
3601 .slice => {3501 .slice => {
3602 try wip_nav.abbrevCode(.generated_struct_type);3502 try wip_nav.abbrevCode(.generated_struct_type);
3603 try wip_nav.strp(name);3503 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3604 try diw.writeUleb128(ty.abiSize(zcu));3504 try diw.writeUleb128(val.toType().abiSize(zcu));
3605 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);3505 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3606 try wip_nav.abbrevCode(.generated_field);3506 try wip_nav.abbrevCode(.generated_field);
3607 try wip_nav.strp("ptr");3507 try wip_nav.strp("ptr");
3608 const ptr_field_type = ty.slicePtrFieldType(zcu);3508 const ptr_field_type = val.toType().slicePtrFieldType(zcu);
3609 try wip_nav.refType(ptr_field_type);3509 try wip_nav.refType(ptr_field_type);
3610 try diw.writeUleb128(0);3510 try diw.writeUleb128(0);
3611 try wip_nav.abbrevCode(.generated_field);3511 try wip_nav.abbrevCode(.generated_field);
...@@ -3619,7 +3519,7 @@ fn updateLazyType(...@@ -3619,7 +3519,7 @@ fn updateLazyType(
3619 .array_type => |array_type| {3519 .array_type => |array_type| {
3620 const array_child_type: Type = .fromInterned(array_type.child);3520 const array_child_type: Type = .fromInterned(array_type.child);
3621 try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);3521 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)});
3623 if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));3523 if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));
3624 try wip_nav.refType(array_child_type);3524 try wip_nav.refType(array_child_type);
3625 try wip_nav.abbrevCode(.array_len);3525 try wip_nav.abbrevCode(.array_len);
...@@ -3629,7 +3529,7 @@ fn updateLazyType(...@@ -3629,7 +3529,7 @@ fn updateLazyType(
3629 },3529 },
3630 .vector_type => |vector_type| {3530 .vector_type => |vector_type| {
3631 try wip_nav.abbrevCode(.vector_type);3531 try wip_nav.abbrevCode(.vector_type);
3632 try wip_nav.strp(name);3532 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3633 try wip_nav.refType(.fromInterned(vector_type.child));3533 try wip_nav.refType(.fromInterned(vector_type.child));
3634 try wip_nav.abbrevCode(.array_len);3534 try wip_nav.abbrevCode(.array_len);
3635 try wip_nav.refType(.usize);3535 try wip_nav.refType(.usize);
...@@ -3640,9 +3540,9 @@ fn updateLazyType(...@@ -3640,9 +3540,9 @@ fn updateLazyType(
3640 const opt_child_type: Type = .fromInterned(opt_child_type_index);3540 const opt_child_type: Type = .fromInterned(opt_child_type_index);
3641 const opt_repr = optRepr(opt_child_type, zcu);3541 const opt_repr = optRepr(opt_child_type, zcu);
3642 try wip_nav.abbrevCode(.generated_union_type);3542 try wip_nav.abbrevCode(.generated_union_type);
3643 try wip_nav.strp(name);3543 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3644 try diw.writeUleb128(ty.abiSize(zcu));3544 try diw.writeUleb128(val.toType().abiSize(zcu));
3645 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);3545 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3646 switch (opt_repr) {3546 switch (opt_repr) {
3647 .opv_null => {3547 .opv_null => {
3648 try wip_nav.abbrevCode(.generated_field);3548 try wip_nav.abbrevCode(.generated_field);
...@@ -3720,12 +3620,12 @@ fn updateLazyType(...@@ -3720,12 +3620,12 @@ fn updateLazyType(
3720 };3620 };
37213621
3722 try wip_nav.abbrevCode(.generated_union_type);3622 try wip_nav.abbrevCode(.generated_union_type);
3723 try wip_nav.strp(name);3623 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3724 if (error_union_type.error_set_type != .generic_poison_type and3624 if (error_union_type.error_set_type != .generic_poison_type and
3725 error_union_type.payload_type != .generic_poison_type)3625 error_union_type.payload_type != .generic_poison_type)
3726 {3626 {
3727 try diw.writeUleb128(ty.abiSize(zcu));3627 try diw.writeUleb128(val.toType().abiSize(zcu));
3728 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);3628 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3729 } else {3629 } else {
3730 try diw.writeUleb128(0);3630 try diw.writeUleb128(0);
3731 try diw.writeUleb128(1);3631 try diw.writeUleb128(1);
...@@ -3791,20 +3691,24 @@ fn updateLazyType(...@@ -3791,20 +3691,24 @@ fn updateLazyType(
3791 .bool,3691 .bool,
3792 => {3692 => {
3793 try wip_nav.abbrevCode(.numeric_type);3693 try wip_nav.abbrevCode(.numeric_type);
3794 try wip_nav.strp(name);3694 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3795 try diw.writeByte(if (type_index == .bool_type)3695 try diw.writeByte(if (value_index == .bool_type)
3796 DW.ATE.boolean3696 DW.ATE.boolean
3797 else if (ty.isRuntimeFloat())3697 else if (val.toType().isRuntimeFloat())
3798 DW.ATE.float3698 DW.ATE.float
3799 else if (ty.isSignedInt(zcu))3699 else if (val.toType().isSignedInt(zcu))
3800 DW.ATE.signed3700 DW.ATE.signed
3801 else if (ty.isUnsignedInt(zcu))3701 else if (val.toType().isUnsignedInt(zcu))
3802 DW.ATE.unsigned3702 DW.ATE.unsigned
3803 else3703 else
3804 unreachable);3704 unreachable);
3805 try diw.writeUleb128(ty.bitSize(zcu));3705 try diw.writeUleb128(val.toType().bitSize(zcu));
3806 try diw.writeUleb128(ty.abiSize(zcu));3706 try diw.writeUleb128(val.toType().abiSize(zcu));
3807 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);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");
3808 },3712 },
3809 .anyopaque,3713 .anyopaque,
3810 .void,3714 .void,
...@@ -3815,37 +3719,29 @@ fn updateLazyType(...@@ -3815,37 +3719,29 @@ fn updateLazyType(
3815 .null,3719 .null,
3816 .undefined,3720 .undefined,
3817 .enum_literal,3721 .enum_literal,
3818 .generic_poison,
3819 => {3722 => {
3820 try wip_nav.abbrevCode(.void_type);3723 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)});
3822 },3725 },
3823 .anyerror => return, // delay until flush3726 .anyerror => return, // delay until flush
3824 .adhoc_inferred_error_set => unreachable,3727 .adhoc_inferred_error_set => unreachable,
3825 },3728 },
3826 .struct_type,
3827 .union_type,
3828 .opaque_type,
3829 => unreachable,
3830 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {3729 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
3831 try wip_nav.abbrevCode(.generated_empty_struct_type);3730 try wip_nav.abbrevCode(.generated_empty_struct_type);
3832 try wip_nav.strp(name);3731 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3833 try diw.writeByte(@intFromBool(false));3732 try diw.writeByte(@intFromBool(false));
3834 } else {3733 } else {
3835 try wip_nav.abbrevCode(.generated_struct_type);3734 try wip_nav.abbrevCode(.generated_struct_type);
3836 try wip_nav.strp(name);3735 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3837 try diw.writeUleb128(ty.abiSize(zcu));3736 try diw.writeUleb128(val.toType().abiSize(zcu));
3838 try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?);3737 try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
3839 var field_byte_offset: u64 = 0;3738 var field_byte_offset: u64 = 0;
3840 for (0..tuple_type.types.len) |field_index| {3739 for (0..tuple_type.types.len) |field_index| {
3841 const comptime_value = tuple_type.values.get(ip)[field_index];3740 const comptime_value = tuple_type.values.get(ip)[field_index];
3842 const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]);3741 const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]);
3843 const has_runtime_bits, const has_comptime_state = switch (comptime_value) {3742 const has_runtime_bits, const has_comptime_state = switch (comptime_value) {
3844 .none => .{ false, false },3743 .none => .{ false, false },
3845 else => .{3744 else => .{ field_type.hasRuntimeBits(zcu), field_type.comptimeOnly(zcu) },
3846 field_type.hasRuntimeBits(zcu),
3847 field_type.comptimeOnly(zcu),
3848 },
3849 };3745 };
3850 try wip_nav.abbrevCode(if (has_comptime_state)3746 try wip_nav.abbrevCode(if (has_comptime_state)
3851 .struct_field_comptime_comptime_state3747 .struct_field_comptime_comptime_state
...@@ -3875,25 +3771,259 @@ fn updateLazyType(...@@ -3875,25 +3771,259 @@ fn updateLazyType(
3875 }3771 }
3876 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));3772 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
3877 },3773 },
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 },
3878 .enum_type => {3953 .enum_type => {
3879 const loaded_enum = ip.loadEnumType(type_index);3954 const loaded_enum = ip.loadEnumType(value_index);
3880 try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type);3955 if (loaded_enum.zir_index.unwrap()) |zir_index| {
3881 try wip_nav.strp(name);3956 assert(loaded_enum.owner_union == .none);
3882 try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type));3957 const file = zir_index.resolveFile(ip);
3883 for (0..loaded_enum.field_names.len) |field_index| {3958 if (loaded_enum.name_nav.unwrap()) |nav_index| {
3884 try wip_nav.enumConstValue(loaded_enum, .{3959 const nav = ip.getNav(nav_index);
3885 .sdata = .signed_enum_field,3960 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3886 .udata = .unsigned_enum_field,3961 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3887 .block = .big_enum_field,3962 try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{
3888 }, field_index);3963 .decl = .decl_enum,
3889 try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip));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));
3890 }4020 }
3891 if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));4021 try diw.writeByte(@intFromBool(true));
3892 },4022 },
3893 .func_type => |func_type| {4023 .func_type => |func_type| {
3894 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;4024 const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
3895 try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);4025 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)});
3897 const cc: DW.CC = cc: {4027 const cc: DW.CC = cc: {
3898 if (zcu.getTarget().cCallingConvention()) |cc| {4028 if (zcu.getTarget().cCallingConvention()) |cc| {
3899 if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) {4029 if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) {
...@@ -3975,7 +4105,7 @@ fn updateLazyType(...@@ -3975,7 +4105,7 @@ fn updateLazyType(
3975 },4105 },
3976 .error_set_type => |error_set_type| {4106 .error_set_type => |error_set_type| {
3977 try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);4107 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)});
3979 try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{4109 try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
3980 .signedness = .unsigned,4110 .signedness = .unsigned,
3981 .bits = zcu.errorSetBits(),4111 .bits = zcu.errorSetBits(),
...@@ -3990,100 +4120,28 @@ fn updateLazyType(...@@ -3990,100 +4120,28 @@ fn updateLazyType(
3990 },4120 },
3991 .inferred_error_set_type => |func| {4121 .inferred_error_set_type => |func| {
3992 try wip_nav.abbrevCode(.inferred_error_set_type);4122 try wip_nav.abbrevCode(.inferred_error_set_type);
3993 try wip_nav.strp(name);4123 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3994 try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) {4124 try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) {
3995 .none => .anyerror_type,4125 .none => .anyerror_type,
3996 else => |ies| ies,4126 else => |ies| ies,
3997 }));4127 }));
3998 },4128 },
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
4080 .undef => |ty| {4130 .undef => |ty| {
4081 try wip_nav.abbrevCode(.undefined_comptime_value);4131 try wip_nav.abbrevCode(.undefined_comptime_value);
4082 try wip_nav.refType(.fromInterned(ty));4132 try wip_nav.refType(.fromInterned(ty));
4083 },4133 },
4084 .simple_value => unreachable, // opv state4134 .simple_value => |simple_value| switch (simple_value) {
4085 .variable, .@"extern" => unreachable, // not a value4135 .void => unreachable, // opv state
4086 .func => unreachable, // already handled4136 .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
4087 .int => |int| {4145 .int => |int| {
4088 try wip_nav.bigIntConstValue(.{4146 try wip_nav.bigIntConstValue(.{
4089 .sdata = .sdata_comptime_value,4147 .sdata = .sdata_comptime_value,
...@@ -4202,7 +4260,7 @@ fn updateLazyValue(...@@ -4202,7 +4260,7 @@ fn updateLazyValue(
4202 var byte_offset = ptr.byte_offset;4260 var byte_offset = ptr.byte_offset;
4203 const base_unit, const base_entry = while (true) {4261 const base_unit, const base_entry = while (true) {
4204 const base_ptr, const access: Access = base_ptr_access: switch (base_addr) {4262 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),
4206 .comptime_alloc, .comptime_field => unreachable,4264 .comptime_alloc, .comptime_field => unreachable,
4207 .uav => |uav| {4265 .uav => |uav| {
4208 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));4266 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
...@@ -4319,17 +4377,7 @@ fn updateLazyValue(...@@ -4319,17 +4377,7 @@ fn updateLazyValue(
4319 switch (optRepr(opt_child_type, zcu)) {4377 switch (optRepr(opt_child_type, zcu)) {
4320 .opv_null => try diw.writeUleb128(0),4378 .opv_null => try diw.writeUleb128(0),
4321 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),4379 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
4322 .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),4380 .error_set, .pointer => 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)),
4333 }4381 }
4334 }4382 }
4335 if (opt.val != .none) child_field: {4383 if (opt.val != .none) child_field: {
...@@ -4457,7 +4505,8 @@ fn updateLazyValue(...@@ -4457,7 +4505,8 @@ fn updateLazyValue(
4457 },4505 },
4458 .memoized_call => unreachable, // not a value4506 .memoized_call => unreachable, // not a value
4459 }4507 }
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());
4461}4510}
44624511
4463fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } {4512fn 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...@@ -4472,312 +4521,6 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err
4472 };4521 };
4473}4522}
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
4781pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void {4524pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void {
4782 const comp = dwarf.bin_file.comp;4525 const comp = dwarf.bin_file.comp;
4783 const io = comp.io;4526 const io = comp.io;
...@@ -4840,14 +4583,15 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro...@@ -4840,14 +4583,15 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
4840 const comp = dwarf.bin_file.comp;4583 const comp = dwarf.bin_file.comp;
4841 const io = comp.io;4584 const io = comp.io;
48424585
4586 // Update `anyerror` based on the finished global error set.
4843 {4587 {
4844 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type);4588 const index = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, .anyerror_type);
4845 if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main);4589 const unit, const entry = dwarf.values.items[@intFromEnum(index)];
4846 var wip_nav: WipNav = .{4590 var wip_nav: WipNav = .{
4847 .dwarf = dwarf,4591 .dwarf = dwarf,
4848 .pt = pt,4592 .pt = pt,
4849 .unit = .main,4593 .unit = unit,
4850 .entry = type_gop.value_ptr.*,4594 .entry = entry,
4851 .any_children = false,4595 .any_children = false,
4852 .func = .none,4596 .func = .none,
4853 .func_sym_index = undefined,4597 .func_sym_index = undefined,
...@@ -4858,7 +4602,6 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro...@@ -4858,7 +4602,6 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
4858 .debug_info = .init(dwarf.gpa),4602 .debug_info = .init(dwarf.gpa),
4859 .debug_line = .init(dwarf.gpa),4603 .debug_line = .init(dwarf.gpa),
4860 .debug_loclists = .init(dwarf.gpa),4604 .debug_loclists = .init(dwarf.gpa),
4861 .pending_lazy = .empty,
4862 };4605 };
4863 defer wip_nav.deinit();4606 defer wip_nav.deinit();
4864 const diw = &wip_nav.debug_info.writer;4607 const diw = &wip_nav.debug_info.writer;
...@@ -4876,7 +4619,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro...@@ -4876,7 +4619,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro
4876 }4619 }
4877 if (global_error_set_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));4620 if (global_error_set_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4878 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());4621 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 });
4880 }4623 }
48814624
4882 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {4625 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {
...@@ -5324,6 +5067,8 @@ const AbbrevCode = enum {...@@ -5324,6 +5067,8 @@ const AbbrevCode = enum {
5324 inferred_error_set_type,5067 inferred_error_set_type,
5325 ptr_type,5068 ptr_type,
5326 ptr_sentinel_type,5069 ptr_sentinel_type,
5070 ptr_aligned_type,
5071 ptr_aligned_sentinel_type,
5327 is_const,5072 is_const,
5328 is_volatile,5073 is_volatile,
5329 array_type,5074 array_type,
...@@ -5960,12 +5705,29 @@ const AbbrevCode = enum {...@@ -5960,12 +5705,29 @@ const AbbrevCode = enum {
5960 .tag = .pointer_type,5705 .tag = .pointer_type,
5961 .attrs = &.{5706 .attrs = &.{
5962 .{ .name, .strp },5707 .{ .name, .strp },
5963 .{ .alignment, .udata },
5964 .{ .address_class, .data1 },5708 .{ .address_class, .data1 },
5965 .{ .type, .ref_addr },5709 .{ .type, .ref_addr },
5966 },5710 },
5967 },5711 },
5968 .ptr_sentinel_type = .{5712 .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 = .{
5969 .tag = .pointer_type,5731 .tag = .pointer_type,
5970 .attrs = &.{5732 .attrs = &.{
5971 .{ .name, .strp },5733 .{ .name, .strp },
src/link/Elf.zig+2-1
...@@ -1711,13 +1711,14 @@ pub fn updateContainerType(...@@ -1711,13 +1711,14 @@ pub fn updateContainerType(
1711 self: *Elf,1711 self: *Elf,
1712 pt: Zcu.PerThread,1712 pt: Zcu.PerThread,
1713 ty: InternPool.Index,1713 ty: InternPool.Index,
1714 success: bool,
1714) link.File.UpdateContainerTypeError!void {1715) link.File.UpdateContainerTypeError!void {
1715 if (build_options.skip_non_native and builtin.object_format != .elf) {1716 if (build_options.skip_non_native and builtin.object_format != .elf) {
1716 @panic("Attempted to compile for object format that was disabled by build configuration");1717 @panic("Attempted to compile for object format that was disabled by build configuration");
1717 }1718 }
1718 const zcu = pt.zcu;1719 const zcu = pt.zcu;
1719 const gpa = zcu.gpa;1720 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) {
1721 error.OutOfMemory => return error.OutOfMemory,1722 error.OutOfMemory => return error.OutOfMemory,
1722 else => |e| {1723 else => |e| {
1723 try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create(1724 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(...@@ -1719,11 +1719,12 @@ pub fn updateContainerType(
1719 self: *ZigObject,1719 self: *ZigObject,
1720 pt: Zcu.PerThread,1720 pt: Zcu.PerThread,
1721 ty: InternPool.Index,1721 ty: InternPool.Index,
1722 success: bool,
1722) !void {1723) !void {
1723 const tracy = trace(@src());1724 const tracy = trace(@src());
1724 defer tracy.end();1725 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);
1727}1728}
17281729
1729fn updateLazySymbol(1730fn updateLazySymbol(