authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-19 23:13:40+01:00
committergravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-21 16:24:59+01:00
logc11c7a28a3689b0b8fe35600a4f8ac5d13421529
tree832e54435be58d62c8e5b4e379a778c7f9edfcb4
parentc16818d6239a34ff211186a2e165777e17a847da

codegen/llvm: Remove use of DIBuilder and output bin by parsing bitcode


1 files changed, 978 insertions(+), 1071 deletions(-)

src/codegen/llvm.zig+978-1071
......@@ -770,37 +770,19 @@ pub const Object = struct {
770770 builder: Builder,
771771
772772 module: *Module,
773 di_builder: ?if (build_options.have_llvm) *llvm.DIBuilder else noreturn,
774 /// One of these mappings:
775 /// - *Module.File => *DIFile
776 /// - *Module.Decl (Fn) => *DISubprogram
777 /// - *Module.Decl (Non-Fn) => *DIGlobalVariable
778 di_map: if (build_options.have_llvm) std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DINode) else struct {
779 const K = *const anyopaque;
780 const V = noreturn;
781773
782 const Self = @This();
774 debug_compile_unit: Builder.Metadata,
783775
784 metadata: ?noreturn = null,
785 size: Size = 0,
786 available: Size = 0,
776 debug_enums_fwd_ref: Builder.Metadata,
777 debug_globals_fwd_ref: Builder.Metadata,
787778
788 pub const Size = u0;
779 debug_enums: std.ArrayListUnmanaged(Builder.Metadata),
780 debug_globals: std.ArrayListUnmanaged(Builder.Metadata),
789781
790 pub fn deinit(self: *Self, allocator: Allocator) void {
791 _ = allocator;
792 self.* = undefined;
793 }
782 debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata),
783
784 debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata),
794785
795 pub fn get(self: Self, key: K) ?V {
796 _ = self;
797 _ = key;
798 return null;
799 }
800 },
801 di_compile_unit: ?if (build_options.have_llvm) *llvm.DICompileUnit else noreturn,
802 target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void,
803 target_data: if (build_options.have_llvm) *llvm.TargetData else void,
804786 target: std.Target,
805787 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
806788 /// but that has some downsides:
......@@ -820,7 +802,6 @@ pub const Object = struct {
820802 /// TODO when InternPool garbage collection is implemented, this map needs
821803 /// to be garbage collected as well.
822804 type_map: TypeMap,
823 di_type_map: DITypeMap,
824805 /// The LLVM global table which holds the names corresponding to Zig errors.
825806 /// Note that the values are not added until `emit`, when all errors in
826807 /// the compilation are known.
......@@ -850,146 +831,87 @@ pub const Object = struct {
850831
851832 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
852833
853 /// This is an ArrayHashMap as opposed to a HashMap because in `emit` we
854 /// want to iterate over it while adding entries to it.
855 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
856
857834 pub fn create(arena: Allocator, comp: *Compilation) !*Object {
858835 if (build_options.only_c) unreachable;
859836 const gpa = comp.gpa;
860837 const target = comp.root_mod.resolved_target.result;
861838 const llvm_target_triple = try targetTriple(arena, target);
862839 const strip = comp.root_mod.strip;
863 const optimize_mode = comp.root_mod.optimize_mode;
864 const pic = comp.root_mod.pic;
865840
866841 var builder = try Builder.init(.{
867842 .allocator = gpa,
868 .use_lib_llvm = comp.config.use_lib_llvm,
869 .strip = strip or !comp.config.use_lib_llvm, // TODO
843 .use_lib_llvm = false,
844 .strip = strip,
870845 .name = comp.root_name,
871846 .target = target,
872847 .triple = llvm_target_triple,
873848 });
874849 errdefer builder.deinit();
875850
876 var target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void = undefined;
877 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;
878 if (builder.useLibLlvm()) {
879 debug_info: {
880 switch (comp.config.debug_format) {
881 .strip => break :debug_info,
882 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),
883 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),
884 }
885 builder.llvm.di_builder = builder.llvm.module.?.createDIBuilder(true);
886
887 // Don't use the version string here; LLVM misparses it when it
888 // includes the git revision.
889 const producer = try builder.fmt("zig {d}.{d}.{d}", .{
890 build_options.semver.major,
891 build_options.semver.minor,
892 build_options.semver.patch,
893 });
894
895 // We fully resolve all paths at this point to avoid lack of
896 // source line info in stack traces or lack of debugging
897 // information which, if relative paths were used, would be
898 // very location dependent.
899 // TODO: the only concern I have with this is WASI as either host or target, should
900 // we leave the paths as relative then?
901 // TODO: This is totally wrong. In dwarf, paths are encoded as relative to
902 // a particular directory, and then the directory path is specified elsewhere.
903 // In the compiler frontend we have it stored correctly in this
904 // way already, but here we throw all that sweet information
905 // into the garbage can by converting into absolute paths. What
906 // a terrible tragedy.
907 const compile_unit_dir_z = blk: {
908 if (comp.module) |zcu| m: {
909 const d = try zcu.root_mod.root.joinStringZ(arena, "");
910 if (d.len == 0) break :m;
911 if (std.fs.path.isAbsolute(d)) break :blk d;
912 const realpath = std.fs.realpathAlloc(arena, d) catch break :blk d;
913 break :blk try arena.dupeZ(u8, realpath);
914 }
915 const cwd = try std.process.getCwdAlloc(arena);
916 break :blk try arena.dupeZ(u8, cwd);
917 };
918
919 builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit(
920 DW.LANG.C99,
921 builder.llvm.di_builder.?.createFile(comp.root_name, compile_unit_dir_z),
922 producer.slice(&builder).?,
923 optimize_mode != .Debug,
924 "", // flags
925 0, // runtime version
926 "", // split name
927 0, // dwo id
928 true, // emit debug info
929 );
851 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
852
853 // We fully resolve all paths at this point to avoid lack of
854 // source line info in stack traces or lack of debugging
855 // information which, if relative paths were used, would be
856 // very location dependent.
857 // TODO: the only concern I have with this is WASI as either host or target, should
858 // we leave the paths as relative then?
859 // TODO: This is totally wrong. In dwarf, paths are encoded as relative to
860 // a particular directory, and then the directory path is specified elsewhere.
861 // In the compiler frontend we have it stored correctly in this
862 // way already, but here we throw all that sweet information
863 // into the garbage can by converting into absolute paths. What
864 // a terrible tragedy.
865 const compile_unit_dir = blk: {
866 if (comp.module) |zcu| m: {
867 const d = try zcu.root_mod.root.joinString(arena, "");
868 if (d.len == 0) break :m;
869 if (std.fs.path.isAbsolute(d)) break :blk d;
870 break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
930871 }
872 break :blk try std.process.getCwdAlloc(arena);
873 };
931874
932 const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug)
933 .None
934 else
935 .Aggressive;
875 const debug_file = try builder.debugFile(
876 try builder.string(compile_unit_dir),
877 try builder.string(comp.root_name),
878 );
936879
937 const reloc_mode: llvm.RelocMode = if (pic)
938 .PIC
939 else if (comp.config.link_mode == .Dynamic)
940 llvm.RelocMode.DynamicNoPIC
941 else
942 .Static;
943
944 const code_model: llvm.CodeModel = switch (comp.root_mod.code_model) {
945 .default => .Default,
946 .tiny => .Tiny,
947 .small => .Small,
948 .kernel => .Kernel,
949 .medium => .Medium,
950 .large => .Large,
951 };
880 const debug_enums_fwd_ref = try builder.debugForwardReference();
881 const debug_globals_fwd_ref = try builder.debugForwardReference();
882
883 const debug_compile_unit = try builder.debugCompileUnit(
884 debug_file,
885 // Don't use the version string here; LLVM misparses it when it
886 // includes the git revision.
887 try builder.fmt("zig {d}.{d}.{d}", .{
888 build_options.semver.major,
889 build_options.semver.minor,
890 build_options.semver.patch,
891 }),
892 debug_enums_fwd_ref,
893 debug_globals_fwd_ref,
894 .{ .optimized = comp.root_mod.optimize_mode != .Debug },
895 );
952896
953 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
954 const float_abi: llvm.ABIType = .Default;
955
956 target_machine = llvm.TargetMachine.create(
957 builder.llvm.target.?,
958 builder.target_triple.slice(&builder).?,
959 if (target.cpu.model.llvm_name) |s| s.ptr else null,
960 comp.root_mod.resolved_target.llvm_cpu_features.?,
961 opt_level,
962 reloc_mode,
963 code_model,
964 comp.function_sections,
965 comp.data_sections,
966 float_abi,
967 if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
897 if (!builder.strip) {
898 const debug_info_version = try builder.debugModuleFlag(
899 try builder.debugConstant(try builder.intConst(.i32, 2)),
900 try builder.string("Debug Info Version"),
901 try builder.debugConstant(try builder.intConst(.i32, 3)),
902 );
903 const dwarf_version = try builder.debugModuleFlag(
904 try builder.debugConstant(try builder.intConst(.i32, 2)),
905 try builder.string("Dwarf Version"),
906 try builder.debugConstant(try builder.intConst(.i32, 4)),
968907 );
969 errdefer target_machine.dispose();
970
971 target_data = target_machine.createTargetDataLayout();
972 errdefer target_data.dispose();
973
974 builder.llvm.module.?.setModuleDataLayout(target_data);
975
976 if (pic) builder.llvm.module.?.setModulePICLevel();
977 if (comp.config.pie) builder.llvm.module.?.setModulePIELevel();
978 if (code_model != .Default) builder.llvm.module.?.setModuleCodeModel(code_model);
979908
980 if (comp.llvm_opt_bisect_limit >= 0) {
981 builder.llvm.context.setOptBisectLimit(comp.llvm_opt_bisect_limit);
982 }
909 try builder.debugNamed(try builder.string("llvm.module.flags"), &.{
910 debug_info_version,
911 dwarf_version,
912 });
983913
984 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
985 if (std.debug.runtime_safety) {
986 const rep = target_data.stringRep();
987 defer llvm.disposeMessage(rep);
988 std.testing.expectEqualStrings(
989 std.mem.span(rep),
990 builder.data_layout.slice(&builder).?,
991 ) catch unreachable;
992 }
914 try builder.debugNamed(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit});
993915 }
994916
995917 const obj = try arena.create(Object);
......@@ -997,17 +919,18 @@ pub const Object = struct {
997919 .gpa = gpa,
998920 .builder = builder,
999921 .module = comp.module.?,
1000 .di_map = .{},
1001 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO
1002 .di_compile_unit = if (builder.useLibLlvm()) builder.llvm.di_compile_unit else null,
1003 .target_machine = target_machine,
1004 .target_data = target_data,
922 .debug_compile_unit = debug_compile_unit,
923 .debug_enums_fwd_ref = debug_enums_fwd_ref,
924 .debug_globals_fwd_ref = debug_globals_fwd_ref,
925 .debug_enums = .{},
926 .debug_globals = .{},
927 .debug_type_map = .{},
928 .debug_unresolved_namespace_scopes = .{},
1005929 .target = target,
1006930 .decl_map = .{},
1007931 .anon_decl_map = .{},
1008932 .named_enum_map = .{},
1009933 .type_map = .{},
1010 .di_type_map = .{},
1011934 .error_name_table = .none,
1012935 .extern_collisions = .{},
1013936 .null_opt_usize = .no_init,
......@@ -1018,12 +941,10 @@ pub const Object = struct {
1018941
1019942 pub fn deinit(self: *Object) void {
1020943 const gpa = self.gpa;
1021 self.di_map.deinit(gpa);
1022 self.di_type_map.deinit(gpa);
1023 if (self.builder.useLibLlvm()) {
1024 self.target_data.dispose();
1025 self.target_machine.dispose();
1026 }
944 self.debug_globals.deinit(gpa);
945 self.debug_enums.deinit(gpa);
946 self.debug_type_map.deinit(gpa);
947 self.debug_unresolved_namespace_scopes.deinit(gpa);
1027948 self.decl_map.deinit(gpa);
1028949 self.anon_decl_map.deinit(gpa);
1029950 self.named_enum_map.deinit(gpa);
......@@ -1193,26 +1114,29 @@ pub const Object = struct {
11931114 try self.genCmpLtErrorsLenFunction();
11941115 try self.genModuleLevelAssembly();
11951116
1196 if (self.di_builder) |dib| {
1197 // When lowering debug info for pointers, we emitted the element types as
1198 // forward decls. Now we must go flesh those out.
1199 // Here we iterate over a hash map while modifying it but it is OK because
1200 // we never add or remove entries during this loop.
1117 {
12011118 var i: usize = 0;
1202 while (i < self.di_type_map.count()) : (i += 1) {
1203 const value_ptr = &self.di_type_map.values()[i];
1204 const annotated = value_ptr.*;
1205 if (!annotated.isFwdOnly()) continue;
1206 const entry: Object.DITypeMap.Entry = .{
1207 .key_ptr = &self.di_type_map.keys()[i],
1208 .value_ptr = value_ptr,
1209 };
1210 _ = try self.lowerDebugTypeImpl(entry, .full, annotated.toDIType());
1211 }
1119 while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) {
1120 const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i];
1121 const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
1122 const namespace = self.module.namespacePtr(namespace_index);
1123
1124 const debug_type = try self.lowerDebugType(namespace.ty);
12121125
1213 dib.finalize();
1126 self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
1127 }
12141128 }
12151129
1130 self.builder.debugForwardReferenceSetType(
1131 self.debug_enums_fwd_ref,
1132 try self.builder.debugTuple(self.debug_enums.items),
1133 );
1134
1135 self.builder.debugForwardReferenceSetType(
1136 self.debug_globals_fwd_ref,
1137 try self.builder.debugTuple(self.debug_globals.items),
1138 );
1139
12161140 if (options.pre_ir_path) |path| {
12171141 if (std.mem.eql(u8, path, "-")) {
12181142 self.builder.dump();
......@@ -1238,35 +1162,126 @@ pub const Object = struct {
12381162 if (options.asm_path == null and options.bin_path == null and
12391163 options.post_ir_path == null and options.post_bc_path == null) return;
12401164
1241 if (options.post_bc_path) |path| {
1242 if (!self.builder.useLibLlvm()) {
1243 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
1244 defer arena_allocator.deinit();
1245 const arena = arena_allocator.allocator();
1165 var bitcode_arena_allocator = std.heap.ArenaAllocator.init(
1166 std.heap.page_allocator,
1167 );
1168 errdefer bitcode_arena_allocator.deinit();
12461169
1247 var file = try std.fs.cwd().createFileZ(path, .{});
1248 defer file.close();
1249 const bitcode = try self.builder.toBitcode(arena);
1170 const bitcode = try self.builder.toBitcode(
1171 bitcode_arena_allocator.allocator(),
1172 );
12501173
1251 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
1252 try file.writeAll(ptr[0..(bitcode.len * 4)]);
1253 return;
1254 }
1174 if (options.post_bc_path) |path| {
1175 var file = try std.fs.cwd().createFileZ(path, .{});
1176 defer file.close();
1177
1178 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
1179 try file.writeAll(ptr[0..(bitcode.len * 4)]);
12551180 }
12561181
1257 if (!self.builder.useLibLlvm()) {
1182 if (!self.module.comp.config.use_lib_llvm) {
12581183 log.err("emitting without libllvm not implemented", .{});
12591184 return error.FailedToEmit;
12601185 }
12611186
1187 Builder.initializeLLVMTarget(self.module.comp.root_mod.resolved_target.result.cpu.arch);
1188
1189 const context: *llvm.Context = llvm.Context.create();
1190 defer context.dispose();
1191
1192 const module = blk: {
1193 const bitcode_memory_buffer = llvm.MemoryBuffer.createMemoryBufferWithMemoryRange(
1194 @ptrCast(bitcode.ptr),
1195 bitcode.len * 4,
1196 "BitcodeBuffer",
1197 llvm.Bool.False,
1198 );
1199 defer bitcode_memory_buffer.dispose();
1200
1201 var module: *llvm.Module = undefined;
1202 if (context.parseBitcodeInContext2(bitcode_memory_buffer, &module).toBool()) {
1203 std.debug.print("Failed to parse bitcode\n", .{});
1204 return error.FailedToEmit;
1205 }
1206
1207 break :blk module;
1208 };
1209 bitcode_arena_allocator.deinit();
1210
1211 var error_message: [*:0]const u8 = undefined;
1212 var target: *llvm.Target = undefined;
1213 if (llvm.Target.getFromTriple(
1214 self.builder.target_triple.slice(&self.builder).?,
1215 &target,
1216 &error_message,
1217 ).toBool()) {
1218 defer llvm.disposeMessage(error_message);
1219
1220 log.err("LLVM failed to parse '{s}': {s}", .{
1221 self.builder.target_triple.slice(&self.builder).?,
1222 error_message,
1223 });
1224 @panic("Invalid LLVM triple");
1225 }
1226
1227 const optimize_mode = self.module.comp.root_mod.optimize_mode;
1228 const pic = self.module.comp.root_mod.pic;
1229
1230 const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug)
1231 .None
1232 else
1233 .Aggressive;
1234
1235 const reloc_mode: llvm.RelocMode = if (pic)
1236 .PIC
1237 else if (self.module.comp.config.link_mode == .Dynamic)
1238 llvm.RelocMode.DynamicNoPIC
1239 else
1240 .Static;
1241
1242 const code_model: llvm.CodeModel = switch (self.module.comp.root_mod.code_model) {
1243 .default => .Default,
1244 .tiny => .Tiny,
1245 .small => .Small,
1246 .kernel => .Kernel,
1247 .medium => .Medium,
1248 .large => .Large,
1249 };
1250
1251 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
1252 const float_abi: llvm.ABIType = .Default;
1253
1254 var target_machine = llvm.TargetMachine.create(
1255 target,
1256 self.builder.target_triple.slice(&self.builder).?,
1257 if (self.module.comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null,
1258 self.module.comp.root_mod.resolved_target.llvm_cpu_features.?,
1259 opt_level,
1260 reloc_mode,
1261 code_model,
1262 self.module.comp.function_sections,
1263 self.module.comp.data_sections,
1264 float_abi,
1265 if (target_util.llvmMachineAbi(self.module.comp.root_mod.resolved_target.result)) |s| s.ptr else null,
1266 );
1267 errdefer target_machine.dispose();
1268
1269 if (pic) module.setModulePICLevel();
1270 if (self.module.comp.config.pie) module.setModulePIELevel();
1271 if (code_model != .Default) module.setModuleCodeModel(code_model);
1272
1273 if (self.module.comp.llvm_opt_bisect_limit >= 0) {
1274 context.setOptBisectLimit(self.module.comp.llvm_opt_bisect_limit);
1275 }
1276
12621277 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
12631278 // So we call the entire pipeline multiple times if this is requested.
1264 var error_message: [*:0]const u8 = undefined;
1279 // var error_message: [*:0]const u8 = undefined;
12651280 var emit_bin_path = options.bin_path;
12661281 var post_ir_path = options.post_ir_path;
12671282 if (options.asm_path != null and options.bin_path != null) {
1268 if (self.target_machine.emitToFile(
1269 self.builder.llvm.module.?,
1283 if (target_machine.emitToFile(
1284 module,
12701285 &error_message,
12711286 options.is_debug,
12721287 options.is_small,
......@@ -1289,8 +1304,8 @@ pub const Object = struct {
12891304 post_ir_path = null;
12901305 }
12911306
1292 if (self.target_machine.emitToFile(
1293 self.builder.llvm.module.?,
1307 if (target_machine.emitToFile(
1308 module,
12941309 &error_message,
12951310 options.is_debug,
12961311 options.is_small,
......@@ -1300,7 +1315,7 @@ pub const Object = struct {
13001315 options.asm_path,
13011316 emit_bin_path,
13021317 post_ir_path,
1303 options.post_bc_path,
1318 null,
13041319 )) {
13051320 defer llvm.disposeMessage(error_message);
13061321
......@@ -1440,7 +1455,7 @@ pub const Object = struct {
14401455 if (isByRef(param_ty, zcu)) {
14411456 const alignment = param_ty.abiAlignment(zcu).toLlvm();
14421457 const param_llvm_ty = param.typeOfWip(&wip);
1443 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
1458 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
14441459 _ = try wip.store(.normal, param, arg_ptr, alignment);
14451460 args.appendAssumeCapacity(arg_ptr);
14461461 } else {
......@@ -1488,7 +1503,7 @@ pub const Object = struct {
14881503
14891504 const param_llvm_ty = try o.lowerType(param_ty);
14901505 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1491 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
1506 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
14921507 _ = try wip.store(.normal, param, arg_ptr, alignment);
14931508
14941509 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
......@@ -1533,7 +1548,7 @@ pub const Object = struct {
15331548 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
15341549 const param_llvm_ty = try o.lowerType(param_ty);
15351550 const param_alignment = param_ty.abiAlignment(zcu).toLlvm();
1536 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target);
1551 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, param_alignment, target);
15371552 const llvm_ty = try o.builder.structType(.normal, field_types);
15381553 for (0..field_types.len) |field_i| {
15391554 const param = wip.arg(llvm_arg_i);
......@@ -1563,7 +1578,7 @@ pub const Object = struct {
15631578 llvm_arg_i += 1;
15641579
15651580 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1566 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
1581 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
15671582 _ = try wip.store(.normal, param, arg_ptr, alignment);
15681583
15691584 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
......@@ -1578,7 +1593,7 @@ pub const Object = struct {
15781593 llvm_arg_i += 1;
15791594
15801595 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1581 const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target);
1596 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);
15821597 _ = try wip.store(.normal, param, arg_ptr, alignment);
15831598
15841599 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
......@@ -1592,40 +1607,34 @@ pub const Object = struct {
15921607
15931608 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
15941609
1595 var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null;
1596 var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null;
1597
1598 if (o.di_builder) |dib| {
1599 di_file = try o.getDIFile(gpa, namespace.file_scope);
1610 const file = try o.getDebugFile(namespace.file_scope);
16001611
1612 const subprogram = blk: {
16011613 const line_number = decl.src_line + 1;
16021614 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
16031615 !zcu.decl_exports.contains(decl_index);
1604 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
1616 const noret_bit: u29 = if (fn_info.return_type == .noreturn_type)
16051617 llvm.DIFlags.NoReturn
16061618 else
16071619 0;
1608 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
1609 const subprogram = dib.createFunction(
1610 di_file.?.toScope(),
1611 ip.stringToSlice(decl.name),
1612 function_index.name(&o.builder).slice(&o.builder).?,
1613 di_file.?,
1620 const debug_decl_type = try o.lowerDebugType(decl.ty);
1621
1622 break :blk try o.builder.debugSubprogram(
1623 file,
1624 try o.builder.string(ip.stringToSlice(decl.name)),
1625 function_index.name(&o.builder),
16141626 line_number,
1615 decl_di_ty,
1616 is_internal_linkage,
1617 true, // is definition
1618 line_number + func.lbrace_line, // scope line
1619 llvm.DIFlags.StaticMember | noret_bit,
1620 owner_mod.optimize_mode != .Debug,
1621 null, // decl_subprogram
1627 line_number + func.lbrace_line,
1628 debug_decl_type,
1629 .{
1630 .optimized = owner_mod.optimize_mode != .Debug,
1631 .definition = true,
1632 .local = is_internal_linkage,
1633 .debug_info_flags = llvm.DIFlags.StaticMember | noret_bit,
1634 },
1635 o.debug_compile_unit,
16221636 );
1623 try o.di_map.put(gpa, decl, subprogram.toNode());
1624
1625 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
1626
1627 di_scope = subprogram.toScope();
1628 }
1637 };
16291638
16301639 var fg: FuncGen = .{
16311640 .gpa = gpa,
......@@ -1639,8 +1648,9 @@ pub const Object = struct {
16391648 .func_inst_table = .{},
16401649 .blocks = .{},
16411650 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
1642 .di_scope = di_scope,
1643 .di_file = di_file,
1651 .file = file,
1652 .subprogram = subprogram,
1653 .current_scope = subprogram,
16441654 .base_line = dg.decl.src_line,
16451655 .prev_dbg_line = 0,
16461656 .prev_dbg_column = 0,
......@@ -1726,26 +1736,7 @@ pub const Object = struct {
17261736 global_index.setUnnamedAddr(.default, &self.builder);
17271737 if (comp.config.dll_export_fns)
17281738 global_index.setDllStorageClass(.default, &self.builder);
1729 if (self.di_map.get(decl)) |di_node| {
1730 const decl_name_slice = decl_name.slice(&self.builder).?;
1731 if (try decl.isFunction(mod)) {
1732 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1733 const linkage_name = llvm.MDString.get(
1734 self.builder.llvm.context,
1735 decl_name_slice.ptr,
1736 decl_name_slice.len,
1737 );
1738 di_func.replaceLinkageName(linkage_name);
1739 } else {
1740 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1741 const linkage_name = llvm.MDString.get(
1742 self.builder.llvm.context,
1743 decl_name_slice.ptr,
1744 decl_name_slice.len,
1745 );
1746 di_global.replaceLinkageName(linkage_name);
1747 }
1748 }
1739
17491740 if (decl.val.getVariable(mod)) |decl_var| {
17501741 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
17511742 if (decl_var.is_threadlocal) .generaldynamic else .default,
......@@ -1759,27 +1750,6 @@ pub const Object = struct {
17591750 );
17601751 try global_index.rename(main_exp_name, &self.builder);
17611752
1762 if (self.di_map.get(decl)) |di_node| {
1763 const main_exp_name_slice = main_exp_name.slice(&self.builder).?;
1764 if (try decl.isFunction(mod)) {
1765 const di_func: *llvm.DISubprogram = @ptrCast(di_node);
1766 const linkage_name = llvm.MDString.get(
1767 self.builder.llvm.context,
1768 main_exp_name_slice.ptr,
1769 main_exp_name_slice.len,
1770 );
1771 di_func.replaceLinkageName(linkage_name);
1772 } else {
1773 const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node);
1774 const linkage_name = llvm.MDString.get(
1775 self.builder.llvm.context,
1776 main_exp_name_slice.ptr,
1777 main_exp_name_slice.len,
1778 );
1779 di_global.replaceLinkageName(linkage_name);
1780 }
1781 }
1782
17831753 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
17841754 global_index.ptrConst(&self.builder).kind
17851755 .variable.setThreadLocal(.generaldynamic, &self.builder);
......@@ -1909,119 +1879,64 @@ pub const Object = struct {
19091879 global.delete(&self.builder);
19101880 }
19111881
1912 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
1913 const gop = try o.di_map.getOrPut(gpa, file);
1914 errdefer assert(o.di_map.remove(file));
1915 if (gop.found_existing) {
1916 return @ptrCast(gop.value_ptr.*);
1917 }
1918 const dir_path_z = d: {
1919 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1920 const sub_path = std.fs.path.dirname(file.sub_file_path) orelse "";
1921 const dir_path = try file.mod.root.joinStringZ(gpa, sub_path);
1922 if (std.fs.path.isAbsolute(dir_path)) break :d dir_path;
1923 const abs = std.fs.realpath(dir_path, &buffer) catch break :d dir_path;
1924 gpa.free(dir_path);
1925 break :d try gpa.dupeZ(u8, abs);
1926 };
1927 defer gpa.free(dir_path_z);
1928 const sub_file_path_z = try gpa.dupeZ(u8, std.fs.path.basename(file.sub_file_path));
1929 defer gpa.free(sub_file_path_z);
1930 const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);
1931 gop.value_ptr.* = di_file.toNode();
1932 return di_file;
1882 fn getDebugFile(o: *Object, file: *const Module.File) Allocator.Error!Builder.Metadata {
1883 return try o.builder.debugFile(
1884 if (std.fs.path.dirname(file.sub_file_path)) |dirname| try o.builder.string(dirname) else .empty,
1885 try o.builder.string(std.fs.path.basename(file.sub_file_path)),
1886 );
19331887 }
19341888
1935 const DebugResolveStatus = enum { fwd, full };
1936
1937 /// In the implementation of this function, it is required to store a forward decl
1938 /// into `gop` before making any recursive calls (even directly).
1939 fn lowerDebugType(
1889 pub fn lowerDebugType(
19401890 o: *Object,
19411891 ty: Type,
1942 resolve: DebugResolveStatus,
1943 ) Allocator.Error!*llvm.DIType {
1944 const gpa = o.gpa;
1945 // Be careful not to reference this `gop` variable after any recursive calls
1946 // to `lowerDebugType`.
1947 const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern());
1948 if (gop.found_existing) {
1949 const annotated = gop.value_ptr.*;
1950 switch (annotated) {
1951 // This type is currently attempting to be resolved fully, so make
1952 // sure a second recursion through the types uses forward resolution.
1953 .null => assert(resolve == .fwd),
1954 // This type already has at least forward resolution, only resolve
1955 // fully during full resolution.
1956 _ => {
1957 const di_type = annotated.toDIType();
1958 if (!annotated.isFwdOnly() or resolve == .fwd) {
1959 return di_type;
1960 }
1961 const entry: Object.DITypeMap.Entry = .{
1962 .key_ptr = gop.key_ptr,
1963 .value_ptr = gop.value_ptr,
1964 };
1965 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1966 },
1967 }
1968 } else gop.value_ptr.* = .null;
1969 errdefer if (!gop.found_existing) assert(o.di_type_map.orderedRemove(ty.toIntern()));
1970 const entry: Object.DITypeMap.Entry = .{
1971 .key_ptr = gop.key_ptr,
1972 .value_ptr = gop.value_ptr,
1973 };
1974 return o.lowerDebugTypeImpl(entry, resolve, null);
1975 }
1976
1977 /// This is a helper function used by `lowerDebugType`.
1978 fn lowerDebugTypeImpl(
1979 o: *Object,
1980 gop: Object.DITypeMap.Entry,
1981 resolve: DebugResolveStatus,
1982 opt_fwd_decl: ?*llvm.DIType,
1983 ) Allocator.Error!*llvm.DIType {
1984 const ty = Type.fromInterned(gop.key_ptr.*);
1892 ) Allocator.Error!Builder.Metadata {
1893 if (o.builder.strip) return Builder.Metadata.none;
19851894 const gpa = o.gpa;
19861895 const target = o.target;
1987 const dib = o.di_builder.?;
19881896 const mod = o.module;
19891897 const ip = &mod.intern_pool;
1898
1899 if (o.debug_type_map.get(ty)) |debug_type| return debug_type;
1900
19901901 switch (ty.zigTypeTag(mod)) {
1991 .Void, .NoReturn => {
1992 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
1993 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
1994 return di_type;
1902 .Void,
1903 .NoReturn,
1904 => {
1905 const debug_void_type = try o.builder.debugSignedType(
1906 try o.builder.string("void"),
1907 0,
1908 );
1909 try o.debug_type_map.put(gpa, ty, debug_void_type);
1910 return debug_void_type;
19951911 },
19961912 .Int => {
19971913 const info = ty.intInfo(mod);
19981914 assert(info.bits != 0);
19991915 const name = try o.allocTypeName(ty);
20001916 defer gpa.free(name);
2001 const dwarf_encoding: c_uint = switch (info.signedness) {
2002 .signed => DW.ATE.signed,
2003 .unsigned => DW.ATE.unsigned,
1917 const builder_name = try o.builder.string(name);
1918 const debug_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
1919 const debug_int_type = switch (info.signedness) {
1920 .signed => try o.builder.debugSignedType(builder_name, debug_bits),
1921 .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits),
20041922 };
2005 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
2006 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);
2007 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
2008 return di_type;
1923 try o.debug_type_map.put(gpa, ty, debug_int_type);
1924 return debug_int_type;
20091925 },
20101926 .Enum => {
20111927 const owner_decl_index = ty.getOwnerDecl(mod);
20121928 const owner_decl = o.module.declPtr(owner_decl_index);
20131929
20141930 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2015 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2016 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2017 // means we can't use `gop` anymore.
2018 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
2019 return enum_di_ty;
1931 const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
1932 try o.debug_type_map.put(gpa, ty, debug_enum_type);
1933 try o.debug_enums.append(gpa, debug_enum_type);
1934 return debug_enum_type;
20201935 }
20211936
20221937 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
20231938
2024 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
1939 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
20251940 defer gpa.free(enumerators);
20261941
20271942 const int_ty = Type.fromInterned(enum_type.tag_ty);
......@@ -2029,66 +1944,59 @@ pub const Object = struct {
20291944 assert(int_info.bits != 0);
20301945
20311946 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
2032 const field_name_z = ip.stringToSlice(field_name_ip);
2033
20341947 var bigint_space: Value.BigIntSpace = undefined;
20351948 const bigint = if (enum_type.values.len != 0)
20361949 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod)
20371950 else
20381951 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
20391952
2040 if (bigint.limbs.len == 1) {
2041 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
2042 continue;
2043 }
2044 if (@sizeOf(usize) == @sizeOf(u64)) {
2045 enumerators[i] = dib.createEnumerator2(
2046 field_name_z,
2047 @intCast(bigint.limbs.len),
2048 bigint.limbs.ptr,
2049 int_info.bits,
2050 int_info.signedness == .unsigned,
2051 );
2052 continue;
2053 }
2054 @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");
1953 enumerators[i] = try o.builder.debugEnumerator(
1954 try o.builder.string(ip.stringToSlice(field_name_ip)),
1955 int_ty.isUnsignedInt(mod),
1956 int_info.bits,
1957 bigint,
1958 );
20551959 }
20561960
2057 const di_file = try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope);
2058 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
1961 const file = try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope);
1962 const scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
20591963
20601964 const name = try o.allocTypeName(ty);
20611965 defer gpa.free(name);
20621966
2063 const enum_di_ty = dib.createEnumerationType(
2064 di_scope,
2065 name,
2066 di_file,
2067 owner_decl.src_node + 1,
1967 const debug_enum_type = try o.builder.debugEnumerationType(
1968 try o.builder.string(name),
1969 file,
1970 scope,
1971 owner_decl.src_node + 1, // Line
1972 try o.lowerDebugType(int_ty),
20681973 ty.abiSize(mod) * 8,
20691974 ty.abiAlignment(mod).toByteUnits(0) * 8,
2070 enumerators.ptr,
2071 @intCast(enumerators.len),
2072 try o.lowerDebugType(int_ty, resolve),
2073 "",
1975 try o.builder.debugTuple(enumerators),
20741976 );
2075 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2076 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
2077 return enum_di_ty;
1977
1978 try o.debug_type_map.put(gpa, ty, debug_enum_type);
1979 try o.debug_enums.append(gpa, debug_enum_type);
1980 return debug_enum_type;
20781981 },
20791982 .Float => {
20801983 const bits = ty.floatBits(target);
20811984 const name = try o.allocTypeName(ty);
20821985 defer gpa.free(name);
2083 const di_type = dib.createBasicType(name, bits, DW.ATE.float);
2084 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
2085 return di_type;
1986 const debug_float_type = try o.builder.debugFloatType(
1987 try o.builder.string(name),
1988 bits,
1989 );
1990 try o.debug_type_map.put(gpa, ty, debug_float_type);
1991 return debug_float_type;
20861992 },
20871993 .Bool => {
2088 const di_bits = 8; // lldb cannot handle non-byte sized types
2089 const di_type = dib.createBasicType("bool", di_bits, DW.ATE.boolean);
2090 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
2091 return di_type;
1994 const debug_bool_type = try o.builder.debugBoolType(
1995 try o.builder.string("bool"),
1996 8, // lldb cannot handle non-byte sized types
1997 );
1998 try o.debug_type_map.put(gpa, ty, debug_bool_type);
1999 return debug_bool_type;
20922000 },
20932001 .Pointer => {
20942002 // Normalize everything that the debug info does not represent.
......@@ -2118,136 +2026,145 @@ pub const Object = struct {
21182026 },
21192027 },
21202028 });
2121 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
2122 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2123 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
2124 return ptr_di_ty;
2029 const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty);
2030 try o.debug_type_map.put(gpa, ty, debug_ptr_type);
2031 return debug_ptr_type;
21252032 }
21262033
2034 const debug_fwd_ref = try o.builder.debugForwardReference();
2035
2036 // Set as forward reference while the type is lowered in case it references itself
2037 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2038
21272039 if (ty.isSlice(mod)) {
21282040 const ptr_ty = ty.slicePtrFieldType(mod);
21292041 const len_ty = Type.usize;
21302042
21312043 const name = try o.allocTypeName(ty);
21322044 defer gpa.free(name);
2133 const di_file: ?*llvm.DIFile = null;
21342045 const line = 0;
2135 const compile_unit_scope = o.di_compile_unit.?.toScope();
2136
2137 const fwd_decl = opt_fwd_decl orelse blk: {
2138 const fwd_decl = dib.createReplaceableCompositeType(
2139 DW.TAG.structure_type,
2140 name.ptr,
2141 compile_unit_scope,
2142 di_file,
2143 line,
2144 );
2145 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2146 if (resolve == .fwd) return fwd_decl;
2147 break :blk fwd_decl;
2148 };
21492046
21502047 const ptr_size = ptr_ty.abiSize(mod);
21512048 const ptr_align = ptr_ty.abiAlignment(mod);
21522049 const len_size = len_ty.abiSize(mod);
21532050 const len_align = len_ty.abiAlignment(mod);
21542051
2155 var offset: u64 = 0;
2156 offset += ptr_size;
2157 offset = len_align.forward(offset);
2158 const len_offset = offset;
2159
2160 const fields: [2]*llvm.DIType = .{
2161 dib.createMemberType(
2162 fwd_decl.toScope(),
2163 "ptr",
2164 di_file,
2165 line,
2166 ptr_size * 8, // size in bits
2167 ptr_align.toByteUnits(0) * 8, // align in bits
2168 0, // offset in bits
2169 0, // flags
2170 try o.lowerDebugType(ptr_ty, resolve),
2171 ),
2172 dib.createMemberType(
2173 fwd_decl.toScope(),
2174 "len",
2175 di_file,
2176 line,
2177 len_size * 8, // size in bits
2178 len_align.toByteUnits(0) * 8, // align in bits
2179 len_offset * 8, // offset in bits
2180 0, // flags
2181 try o.lowerDebugType(len_ty, resolve),
2182 ),
2183 };
2052 const len_offset = len_align.forward(ptr_size);
2053
2054 const debug_ptr_type = try o.builder.debugMemberType(
2055 try o.builder.string("ptr"),
2056 Builder.Metadata.none, // File
2057 debug_fwd_ref,
2058 0, // Line
2059 try o.lowerDebugType(ptr_ty),
2060 ptr_size * 8,
2061 ptr_align.toByteUnits(0) * 8,
2062 0, // Offset
2063 );
2064
2065 const debug_len_type = try o.builder.debugMemberType(
2066 try o.builder.string("len"),
2067 Builder.Metadata.none, // File
2068 debug_fwd_ref,
2069 0, // Line
2070 try o.lowerDebugType(len_ty),
2071 len_size * 8,
2072 len_align.toByteUnits(0) * 8,
2073 len_offset * 8,
2074 );
21842075
2185 const full_di_ty = dib.createStructType(
2186 compile_unit_scope,
2187 name.ptr,
2188 di_file,
2076 const debug_slice_type = try o.builder.debugStructType(
2077 try o.builder.string(name),
2078 Builder.Metadata.none, // File
2079 o.debug_compile_unit, // Scope
21892080 line,
2190 ty.abiSize(mod) * 8, // size in bits
2191 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2192 0, // flags
2193 null, // derived from
2194 &fields,
2195 fields.len,
2196 0, // run time lang
2197 null, // vtable holder
2198 "", // unique id
2081 Builder.Metadata.none, // Underlying type
2082 ty.abiSize(mod) * 8,
2083 ty.abiAlignment(mod).toByteUnits(0) * 8,
2084 try o.builder.debugTuple(&.{
2085 debug_ptr_type,
2086 debug_len_type,
2087 }),
21992088 );
2200 dib.replaceTemporary(fwd_decl, full_di_ty);
2201 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2202 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2203 return full_di_ty;
2089
2090 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type);
2091
2092 // Set to real type now that it has been lowered fully
2093 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2094 map_ptr.* = debug_slice_type;
2095
2096 return debug_slice_type;
22042097 }
22052098
2206 const elem_di_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child), .fwd);
2099 const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child));
2100
22072101 const name = try o.allocTypeName(ty);
22082102 defer gpa.free(name);
2209 const ptr_di_ty = dib.createPointerType(
2210 elem_di_ty,
2103
2104 const debug_ptr_type = try o.builder.debugPointerType(
2105 try o.builder.string(name),
2106 Builder.Metadata.none, // File
2107 Builder.Metadata.none, // Scope
2108 0, // Line
2109 debug_elem_ty,
22112110 target.ptrBitWidth(),
22122111 ty.ptrAlignment(mod).toByteUnits(0) * 8,
2213 name,
2112 0, // Offset
22142113 );
2215 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2216 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));
2217 return ptr_di_ty;
2114
2115 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_ptr_type);
2116
2117 // Set to real type now that it has been lowered fully
2118 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2119 map_ptr.* = debug_ptr_type;
2120
2121 return debug_ptr_type;
22182122 },
22192123 .Opaque => {
22202124 if (ty.toIntern() == .anyopaque_type) {
2221 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
2222 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2223 return di_ty;
2125 const debug_opaque_type = try o.builder.debugSignedType(
2126 try o.builder.string("anyopaque"),
2127 0,
2128 );
2129 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2130 return debug_opaque_type;
22242131 }
2132
22252133 const name = try o.allocTypeName(ty);
22262134 defer gpa.free(name);
22272135 const owner_decl_index = ty.getOwnerDecl(mod);
22282136 const owner_decl = o.module.declPtr(owner_decl_index);
2229 const opaque_di_ty = dib.createForwardDeclType(
2230 DW.TAG.structure_type,
2231 name,
2137 const debug_opaque_type = try o.builder.debugStructType(
2138 try o.builder.string(name),
2139 try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope),
22322140 try o.namespaceToDebugScope(owner_decl.src_namespace),
2233 try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope),
2234 owner_decl.src_node + 1,
2141 owner_decl.src_node + 1, // Line
2142 Builder.Metadata.none, // Underlying type
2143 0, // Size
2144 0, // Align
2145 Builder.Metadata.none, // Fields
22352146 );
2236 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
2237 // means we can't use `gop` anymore.
2238 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty));
2239 return opaque_di_ty;
2147 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2148 return debug_opaque_type;
22402149 },
22412150 .Array => {
2242 const array_di_ty = dib.createArrayType(
2151 const debug_array_type = try o.builder.debugArrayType(
2152 Builder.String.empty, // Name
2153 Builder.Metadata.none, // File
2154 Builder.Metadata.none, // Scope
2155 0, // Line
2156 try o.lowerDebugType(ty.childType(mod)),
22432157 ty.abiSize(mod) * 8,
22442158 ty.abiAlignment(mod).toByteUnits(0) * 8,
2245 try o.lowerDebugType(ty.childType(mod), resolve),
2246 @intCast(ty.arrayLen(mod)),
2159 try o.builder.debugTuple(&.{
2160 try o.builder.debugSubrange(
2161 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
2162 try o.builder.debugConstant(try o.builder.intConst(.i64, ty.arrayLen(mod))),
2163 ),
2164 }),
22472165 );
2248 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2249 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));
2250 return array_di_ty;
2166 try o.debug_type_map.put(gpa, ty, debug_array_type);
2167 return debug_array_type;
22512168 },
22522169 .Vector => {
22532170 const elem_ty = ty.elemType2(mod);
......@@ -2255,146 +2172,136 @@ pub const Object = struct {
22552172 // @bitSizOf(elem) * len > @bitSizOf(vec).
22562173 // Neither gdb nor lldb seem to be able to display non-byte sized
22572174 // vectors properly.
2258 const elem_di_type = switch (elem_ty.zigTypeTag(mod)) {
2175 const debug_elem_type = switch (elem_ty.zigTypeTag(mod)) {
22592176 .Int => blk: {
22602177 const info = elem_ty.intInfo(mod);
22612178 assert(info.bits != 0);
22622179 const name = try o.allocTypeName(ty);
22632180 defer gpa.free(name);
2264 const dwarf_encoding: c_uint = switch (info.signedness) {
2265 .signed => DW.ATE.signed,
2266 .unsigned => DW.ATE.unsigned,
2181 const builder_name = try o.builder.string(name);
2182 break :blk switch (info.signedness) {
2183 .signed => try o.builder.debugSignedType(builder_name, info.bits),
2184 .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),
22672185 };
2268 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
22692186 },
2270 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),
2271 else => try o.lowerDebugType(ty.childType(mod), resolve),
2187 .Bool => try o.builder.debugBoolType(
2188 try o.builder.string("bool"),
2189 1,
2190 ),
2191 else => try o.lowerDebugType(ty.childType(mod)),
22722192 };
22732193
2274 const vector_di_ty = dib.createVectorType(
2194 const debug_vector_type = try o.builder.debugArrayType(
2195 Builder.String.empty, // Name
2196 Builder.Metadata.none, // File
2197 Builder.Metadata.none, // Scope
2198 0, // Line
2199 debug_elem_type,
22752200 ty.abiSize(mod) * 8,
2276 @intCast(ty.abiAlignment(mod).toByteUnits(0) * 8),
2277 elem_di_type,
2278 ty.vectorLen(mod),
2201 ty.abiAlignment(mod).toByteUnits(0) * 8,
2202 try o.builder.debugTuple(&.{
2203 try o.builder.debugSubrange(
2204 try o.builder.debugConstant(try o.builder.intConst(.i64, 0)),
2205 try o.builder.debugConstant(try o.builder.intConst(.i64, ty.vectorLen(mod))),
2206 ),
2207 }),
22792208 );
2280 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2281 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty));
2282 return vector_di_ty;
2209
2210 try o.debug_type_map.put(gpa, ty, debug_vector_type);
2211 return debug_vector_type;
22832212 },
22842213 .Optional => {
22852214 const name = try o.allocTypeName(ty);
22862215 defer gpa.free(name);
22872216 const child_ty = ty.optionalChild(mod);
22882217 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2289 const di_bits = 8; // lldb cannot handle non-byte sized types
2290 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);
2291 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2292 return di_ty;
2218 const debug_bool_type = try o.builder.debugBoolType(
2219 try o.builder.string(name),
2220 8,
2221 );
2222 try o.debug_type_map.put(gpa, ty, debug_bool_type);
2223 return debug_bool_type;
22932224 }
2225
2226 const debug_fwd_ref = try o.builder.debugForwardReference();
2227
2228 // Set as forward reference while the type is lowered in case it references itself
2229 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2230
22942231 if (ty.optionalReprIsPayload(mod)) {
2295 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
2296 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2297 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
2298 return ptr_di_ty;
2299 }
2232 const debug_optional_type = try o.lowerDebugType(child_ty);
23002233
2301 const di_file: ?*llvm.DIFile = null;
2302 const line = 0;
2303 const compile_unit_scope = o.di_compile_unit.?.toScope();
2304 const fwd_decl = opt_fwd_decl orelse blk: {
2305 const fwd_decl = dib.createReplaceableCompositeType(
2306 DW.TAG.structure_type,
2307 name.ptr,
2308 compile_unit_scope,
2309 di_file,
2310 line,
2311 );
2312 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2313 if (resolve == .fwd) return fwd_decl;
2314 break :blk fwd_decl;
2315 };
2234 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2235
2236 // Set to real type now that it has been lowered fully
2237 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2238 map_ptr.* = debug_optional_type;
2239
2240 return debug_optional_type;
2241 }
23162242
23172243 const non_null_ty = Type.u8;
23182244 const payload_size = child_ty.abiSize(mod);
23192245 const payload_align = child_ty.abiAlignment(mod);
23202246 const non_null_size = non_null_ty.abiSize(mod);
23212247 const non_null_align = non_null_ty.abiAlignment(mod);
2248 const non_null_offset = non_null_align.forward(payload_size);
2249
2250 const debug_data_type = try o.builder.debugMemberType(
2251 try o.builder.string("data"),
2252 Builder.Metadata.none, // File
2253 debug_fwd_ref,
2254 0, // Line
2255 try o.lowerDebugType(child_ty),
2256 payload_size * 8,
2257 payload_align.toByteUnits(0) * 8,
2258 0, // Offset
2259 );
23222260
2323 var offset: u64 = 0;
2324 offset += payload_size;
2325 offset = non_null_align.forward(offset);
2326 const non_null_offset = offset;
2327
2328 const fields: [2]*llvm.DIType = .{
2329 dib.createMemberType(
2330 fwd_decl.toScope(),
2331 "data",
2332 di_file,
2333 line,
2334 payload_size * 8, // size in bits
2335 payload_align.toByteUnits(0) * 8, // align in bits
2336 0, // offset in bits
2337 0, // flags
2338 try o.lowerDebugType(child_ty, resolve),
2339 ),
2340 dib.createMemberType(
2341 fwd_decl.toScope(),
2342 "some",
2343 di_file,
2344 line,
2345 non_null_size * 8, // size in bits
2346 non_null_align.toByteUnits(0) * 8, // align in bits
2347 non_null_offset * 8, // offset in bits
2348 0, // flags
2349 try o.lowerDebugType(non_null_ty, resolve),
2350 ),
2351 };
2261 const debug_some_type = try o.builder.debugMemberType(
2262 try o.builder.string("some"),
2263 Builder.Metadata.none,
2264 debug_fwd_ref,
2265 0,
2266 try o.lowerDebugType(non_null_ty),
2267 non_null_size * 8,
2268 non_null_align.toByteUnits(0) * 8,
2269 non_null_offset * 8,
2270 );
23522271
2353 const full_di_ty = dib.createStructType(
2354 compile_unit_scope,
2355 name.ptr,
2356 di_file,
2357 line,
2358 ty.abiSize(mod) * 8, // size in bits
2359 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2360 0, // flags
2361 null, // derived from
2362 &fields,
2363 fields.len,
2364 0, // run time lang
2365 null, // vtable holder
2366 "", // unique id
2272 const debug_optional_type = try o.builder.debugStructType(
2273 try o.builder.string(name),
2274 Builder.Metadata.none, // File
2275 o.debug_compile_unit, // Scope
2276 0, // Line
2277 Builder.Metadata.none, // Underlying type
2278 ty.abiSize(mod) * 8,
2279 ty.abiAlignment(mod).toByteUnits(0) * 8,
2280 try o.builder.debugTuple(&.{
2281 debug_data_type,
2282 debug_some_type,
2283 }),
23672284 );
2368 dib.replaceTemporary(fwd_decl, full_di_ty);
2369 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2370 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2371 return full_di_ty;
2285
2286 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2287
2288 // Set to real type now that it has been lowered fully
2289 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2290 map_ptr.* = debug_optional_type;
2291
2292 return debug_optional_type;
23722293 },
23732294 .ErrorUnion => {
23742295 const payload_ty = ty.errorUnionPayload(mod);
23752296 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2376 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, resolve);
2377 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2378 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));
2379 return err_set_di_ty;
2297 // TODO: Maybe remove?
2298 const debug_error_union_type = try o.lowerDebugType(Type.anyerror);
2299 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2300 return debug_error_union_type;
23802301 }
2302
23812303 const name = try o.allocTypeName(ty);
23822304 defer gpa.free(name);
2383 const di_file: ?*llvm.DIFile = null;
2384 const line = 0;
2385 const compile_unit_scope = o.di_compile_unit.?.toScope();
2386 const fwd_decl = opt_fwd_decl orelse blk: {
2387 const fwd_decl = dib.createReplaceableCompositeType(
2388 DW.TAG.structure_type,
2389 name.ptr,
2390 compile_unit_scope,
2391 di_file,
2392 line,
2393 );
2394 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2395 if (resolve == .fwd) return fwd_decl;
2396 break :blk fwd_decl;
2397 };
23982305
23992306 const error_size = Type.anyerror.abiSize(mod);
24002307 const error_align = Type.anyerror.abiAlignment(mod);
......@@ -2417,59 +2324,55 @@ pub const Object = struct {
24172324 error_offset = error_align.forward(payload_size);
24182325 }
24192326
2420 var fields: [2]*llvm.DIType = undefined;
2421 fields[error_index] = dib.createMemberType(
2422 fwd_decl.toScope(),
2423 "tag",
2424 di_file,
2425 line,
2426 error_size * 8, // size in bits
2427 error_align.toByteUnits(0) * 8, // align in bits
2428 error_offset * 8, // offset in bits
2429 0, // flags
2430 try o.lowerDebugType(Type.anyerror, resolve),
2327 const debug_fwd_ref = try o.builder.debugForwardReference();
2328
2329 var fields: [2]Builder.Metadata = undefined;
2330 fields[error_index] = try o.builder.debugMemberType(
2331 try o.builder.string("tag"),
2332 Builder.Metadata.none, // File
2333 debug_fwd_ref,
2334 0, // Line
2335 try o.lowerDebugType(Type.anyerror),
2336 error_size * 8,
2337 error_align.toByteUnits(0) * 8,
2338 error_offset * 8,
24312339 );
2432 fields[payload_index] = dib.createMemberType(
2433 fwd_decl.toScope(),
2434 "value",
2435 di_file,
2436 line,
2437 payload_size * 8, // size in bits
2438 payload_align.toByteUnits(0) * 8, // align in bits
2439 payload_offset * 8, // offset in bits
2440 0, // flags
2441 try o.lowerDebugType(payload_ty, resolve),
2340 fields[payload_index] = try o.builder.debugMemberType(
2341 try o.builder.string("value"),
2342 Builder.Metadata.none, // File
2343 debug_fwd_ref,
2344 0, // Line
2345 try o.lowerDebugType(payload_ty),
2346 payload_size * 8,
2347 payload_align.toByteUnits(0) * 8,
2348 payload_offset * 8,
24422349 );
24432350
2444 const full_di_ty = dib.createStructType(
2445 compile_unit_scope,
2446 name.ptr,
2447 di_file,
2448 line,
2449 ty.abiSize(mod) * 8, // size in bits
2450 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2451 0, // flags
2452 null, // derived from
2453 &fields,
2454 fields.len,
2455 0, // run time lang
2456 null, // vtable holder
2457 "", // unique id
2351 const debug_error_union_type = try o.builder.debugStructType(
2352 try o.builder.string(name),
2353 Builder.Metadata.none, // File
2354 o.debug_compile_unit, // Sope
2355 0, // Line
2356 Builder.Metadata.none, // Underlying type
2357 ty.abiSize(mod) * 8,
2358 ty.abiAlignment(mod).toByteUnits(0) * 8,
2359 try o.builder.debugTuple(&fields),
24582360 );
2459 dib.replaceTemporary(fwd_decl, full_di_ty);
2460 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2461 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2462 return full_di_ty;
2361
2362 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type);
2363
2364 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2365 return debug_error_union_type;
24632366 },
24642367 .ErrorSet => {
2465 // TODO make this a proper enum with all the error codes in it.
2466 // will need to consider how to take incremental compilation into account.
2467 const di_ty = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);
2468 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2469 return di_ty;
2368 const debug_error_set = try o.builder.debugUnsignedType(
2369 try o.builder.string("anyerror"),
2370 16,
2371 );
2372 try o.debug_type_map.put(gpa, ty, debug_error_set);
2373 return debug_error_set;
24702374 },
24712375 .Struct => {
2472 const compile_unit_scope = o.di_compile_unit.?.toScope();
24732376 const name = try o.allocTypeName(ty);
24742377 defer gpa.free(name);
24752378
......@@ -2477,40 +2380,28 @@ pub const Object = struct {
24772380 const backing_int_ty = struct_type.backingIntType(ip).*;
24782381 if (backing_int_ty != .none) {
24792382 const info = Type.fromInterned(backing_int_ty).intInfo(mod);
2480 const dwarf_encoding: c_uint = switch (info.signedness) {
2481 .signed => DW.ATE.signed,
2482 .unsigned => DW.ATE.unsigned,
2383 const builder_name = try o.builder.string(name);
2384 const debug_int_type = switch (info.signedness) {
2385 .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(mod) * 8),
2386 .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(mod) * 8),
24832387 };
2484 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
2485 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);
2486 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2487 return di_ty;
2388 try o.debug_type_map.put(gpa, ty, debug_int_type);
2389 return debug_int_type;
24882390 }
24892391 }
24902392
2491 const fwd_decl = opt_fwd_decl orelse blk: {
2492 const fwd_decl = dib.createReplaceableCompositeType(
2493 DW.TAG.structure_type,
2494 name.ptr,
2495 compile_unit_scope,
2496 null, // file
2497 0, // line
2498 );
2499 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2500 if (resolve == .fwd) return fwd_decl;
2501 break :blk fwd_decl;
2502 };
2503
25042393 switch (ip.indexToKey(ty.toIntern())) {
25052394 .anon_struct_type => |tuple| {
2506 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2507 defer di_fields.deinit(gpa);
2395 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2396 defer fields.deinit(gpa);
25082397
2509 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2398 try fields.ensureUnusedCapacity(gpa, tuple.types.len);
25102399
25112400 comptime assert(struct_layout_version == 2);
25122401 var offset: u64 = 0;
25132402
2403 const debug_fwd_ref = try o.builder.debugForwardReference();
2404
25142405 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
25152406 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
25162407
......@@ -2525,38 +2416,33 @@ pub const Object = struct {
25252416 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
25262417 defer if (tuple.names.len == 0) gpa.free(field_name);
25272418
2528 try di_fields.append(gpa, dib.createMemberType(
2529 fwd_decl.toScope(),
2530 field_name,
2531 null, // file
2532 0, // line
2533 field_size * 8, // size in bits
2534 field_align.toByteUnits(0) * 8, // align in bits
2535 field_offset * 8, // offset in bits
2536 0, // flags
2537 try o.lowerDebugType(Type.fromInterned(field_ty), resolve),
2419 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2420 try o.builder.string(field_name),
2421 Builder.Metadata.none, // File
2422 debug_fwd_ref,
2423 0,
2424 try o.lowerDebugType(Type.fromInterned(field_ty)),
2425 field_size * 8,
2426 field_align.toByteUnits(0) * 8,
2427 field_offset * 8,
25382428 ));
25392429 }
25402430
2541 const full_di_ty = dib.createStructType(
2542 compile_unit_scope,
2543 name.ptr,
2544 null, // file
2545 0, // line
2546 ty.abiSize(mod) * 8, // size in bits
2547 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2548 0, // flags
2549 null, // derived from
2550 di_fields.items.ptr,
2551 @intCast(di_fields.items.len),
2552 0, // run time lang
2553 null, // vtable holder
2554 "", // unique id
2431 const debug_struct_type = try o.builder.debugStructType(
2432 try o.builder.string(name),
2433 Builder.Metadata.none, // File
2434 o.debug_compile_unit, // Scope
2435 0, // Line
2436 Builder.Metadata.none, // Underlying type
2437 ty.abiSize(mod) * 8,
2438 ty.abiAlignment(mod).toByteUnits(0) * 8,
2439 try o.builder.debugTuple(fields.items),
25552440 );
2556 dib.replaceTemporary(fwd_decl, full_di_ty);
2557 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2558 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2559 return full_di_ty;
2441
2442 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2443
2444 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2445 return debug_struct_type;
25602446 },
25612447 .struct_type => |struct_type| {
25622448 if (!struct_type.haveFieldTypes(ip)) {
......@@ -2568,12 +2454,9 @@ pub const Object = struct {
25682454 // rather than changing the frontend to unnecessarily resolve the
25692455 // struct field types.
25702456 const owner_decl_index = ty.getOwnerDecl(mod);
2571 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2572 dib.replaceTemporary(fwd_decl, struct_di_ty);
2573 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2574 // means we can't use `gop` anymore.
2575 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2576 return struct_di_ty;
2457 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2458 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2459 return debug_struct_type;
25772460 }
25782461 },
25792462 else => {},
......@@ -2581,20 +2464,22 @@ pub const Object = struct {
25812464
25822465 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
25832466 const owner_decl_index = ty.getOwnerDecl(mod);
2584 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2585 dib.replaceTemporary(fwd_decl, struct_di_ty);
2586 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2587 // means we can't use `gop` anymore.
2588 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2589 return struct_di_ty;
2467 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2468 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2469 return debug_struct_type;
25902470 }
25912471
25922472 const struct_type = mod.typeToStruct(ty).?;
25932473
2594 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2595 defer di_fields.deinit(gpa);
2474 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2475 defer fields.deinit(gpa);
2476
2477 try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
2478
2479 const debug_fwd_ref = try o.builder.debugForwardReference();
25962480
2597 try di_fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
2481 // Set as forward reference while the type is lowered in case it references itself
2482 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
25982483
25992484 comptime assert(struct_layout_version == 2);
26002485 var it = struct_type.iterateRuntimeOrder(ip);
......@@ -2612,103 +2497,88 @@ pub const Object = struct {
26122497 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
26132498 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});
26142499
2615 const field_di_ty = try o.lowerDebugType(field_ty, resolve);
2616
2617 try di_fields.append(gpa, dib.createMemberType(
2618 fwd_decl.toScope(),
2619 ip.stringToSlice(field_name),
2620 null, // file
2621 0, // line
2622 field_size * 8, // size in bits
2623 field_align.toByteUnits(0) * 8, // align in bits
2624 field_offset * 8, // offset in bits
2625 0, // flags
2626 field_di_ty,
2500 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2501 try o.builder.string(ip.stringToSlice(field_name)),
2502 Builder.Metadata.none, // File
2503 debug_fwd_ref,
2504 0, // Line
2505 try o.lowerDebugType(field_ty),
2506 field_size * 8,
2507 field_align.toByteUnits(0) * 8,
2508 field_offset * 8,
26272509 ));
26282510 }
26292511
2630 const full_di_ty = dib.createStructType(
2631 compile_unit_scope,
2632 name.ptr,
2633 null, // file
2634 0, // line
2635 ty.abiSize(mod) * 8, // size in bits
2636 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2637 0, // flags
2638 null, // derived from
2639 di_fields.items.ptr,
2640 @intCast(di_fields.items.len),
2641 0, // run time lang
2642 null, // vtable holder
2643 "", // unique id
2512 const debug_struct_type = try o.builder.debugStructType(
2513 try o.builder.string(name),
2514 Builder.Metadata.none, // File
2515 o.debug_compile_unit, // Scope
2516 0, // Line
2517 Builder.Metadata.none, // Underlying type
2518 ty.abiSize(mod) * 8,
2519 ty.abiAlignment(mod).toByteUnits(0) * 8,
2520 try o.builder.debugTuple(fields.items),
26442521 );
2645 dib.replaceTemporary(fwd_decl, full_di_ty);
2646 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2647 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2648 return full_di_ty;
2522
2523 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2524
2525 // Set to real type now that it has been lowered fully
2526 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2527 map_ptr.* = debug_struct_type;
2528
2529 return debug_struct_type;
26492530 },
26502531 .Union => {
2651 const compile_unit_scope = o.di_compile_unit.?.toScope();
26522532 const owner_decl_index = ty.getOwnerDecl(mod);
26532533
26542534 const name = try o.allocTypeName(ty);
26552535 defer gpa.free(name);
26562536
2657 const fwd_decl = opt_fwd_decl orelse blk: {
2658 const fwd_decl = dib.createReplaceableCompositeType(
2659 DW.TAG.structure_type,
2660 name.ptr,
2661 o.di_compile_unit.?.toScope(),
2662 null, // file
2663 0, // line
2664 );
2665 gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl);
2666 if (resolve == .fwd) return fwd_decl;
2667 break :blk fwd_decl;
2668 };
2669
26702537 const union_type = ip.indexToKey(ty.toIntern()).union_type;
26712538 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
2672 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2673 dib.replaceTemporary(fwd_decl, union_di_ty);
2674 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2675 // means we can't use `gop` anymore.
2676 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
2677 return union_di_ty;
2539 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2540 try o.debug_type_map.put(gpa, ty, debug_union_type);
2541 return debug_union_type;
26782542 }
26792543
26802544 const union_obj = ip.loadUnionType(union_type);
26812545 const layout = mod.getUnionLayout(union_obj);
26822546
2547 const debug_fwd_ref = try o.builder.debugForwardReference();
2548
2549 // Set as forward reference while the type is lowered in case it references itself
2550 try o.debug_type_map.put(gpa, ty, debug_fwd_ref);
2551
26832552 if (layout.payload_size == 0) {
2684 const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve);
2685 const di_fields = [_]*llvm.DIType{tag_di_ty};
2686 const full_di_ty = dib.createStructType(
2687 compile_unit_scope,
2688 name.ptr,
2689 null, // file
2690 0, // line
2691 ty.abiSize(mod) * 8, // size in bits
2692 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2693 0, // flags
2694 null, // derived from
2695 &di_fields,
2696 di_fields.len,
2697 0, // run time lang
2698 null, // vtable holder
2699 "", // unique id
2553 const debug_union_type = try o.builder.debugStructType(
2554 try o.builder.string(name),
2555 Builder.Metadata.none, // File
2556 o.debug_compile_unit, // Scope
2557 0, // Line
2558 Builder.Metadata.none, // Underlying type
2559 ty.abiSize(mod) * 8,
2560 ty.abiAlignment(mod).toByteUnits(0) * 8,
2561 try o.builder.debugTuple(
2562 &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))},
2563 ),
27002564 );
2701 dib.replaceTemporary(fwd_decl, full_di_ty);
2702 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2703 // means we can't use `gop` anymore.
2704 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2705 return full_di_ty;
2565
2566 // Set to real type now that it has been lowered fully
2567 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2568 map_ptr.* = debug_union_type;
2569
2570 return debug_union_type;
27062571 }
27072572
2708 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2709 defer di_fields.deinit(gpa);
2573 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2574 defer fields.deinit(gpa);
27102575
2711 try di_fields.ensureUnusedCapacity(gpa, union_obj.field_names.len);
2576 try fields.ensureUnusedCapacity(gpa, union_obj.field_names.len);
2577
2578 const debug_union_fwd_ref = if (layout.tag_size == 0)
2579 debug_fwd_ref
2580 else
2581 try o.builder.debugForwardReference();
27122582
27132583 for (0..union_obj.field_names.len) |field_index| {
27142584 const field_ty = union_obj.field_types.get(ip)[field_index];
......@@ -2717,18 +2587,16 @@ pub const Object = struct {
27172587 const field_size = Type.fromInterned(field_ty).abiSize(mod);
27182588 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));
27192589
2720 const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), resolve);
27212590 const field_name = union_obj.field_names.get(ip)[field_index];
2722 di_fields.appendAssumeCapacity(dib.createMemberType(
2723 fwd_decl.toScope(),
2724 ip.stringToSlice(field_name),
2725 null, // file
2726 0, // line
2727 field_size * 8, // size in bits
2728 field_align.toByteUnits(0) * 8, // align in bits
2729 0, // offset in bits
2730 0, // flags
2731 field_di_ty,
2591 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2592 try o.builder.string(ip.stringToSlice(field_name)),
2593 Builder.Metadata.none, // File
2594 debug_union_fwd_ref,
2595 0, // Line
2596 try o.lowerDebugType(Type.fromInterned(field_ty)),
2597 field_size * 8,
2598 field_align.toByteUnits(0) * 8,
2599 0, // Offset
27322600 ));
27332601 }
27342602
......@@ -2739,25 +2607,25 @@ pub const Object = struct {
27392607 break :name union_name_buf.?;
27402608 };
27412609
2742 const union_di_ty = dib.createUnionType(
2743 compile_unit_scope,
2744 union_name.ptr,
2745 null, // file
2746 0, // line
2747 ty.abiSize(mod) * 8, // size in bits
2748 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2749 0, // flags
2750 di_fields.items.ptr,
2751 @intCast(di_fields.items.len),
2752 0, // run time lang
2753 "", // unique id
2610 const debug_union_type = try o.builder.debugUnionType(
2611 try o.builder.string(union_name),
2612 Builder.Metadata.none, // File
2613 o.debug_compile_unit, // Scope
2614 0, // Line
2615 Builder.Metadata.none, // Underlying type
2616 ty.abiSize(mod) * 8,
2617 ty.abiAlignment(mod).toByteUnits(0) * 8,
2618 try o.builder.debugTuple(fields.items),
27542619 );
27552620
2621 o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type);
2622
27562623 if (layout.tag_size == 0) {
2757 dib.replaceTemporary(fwd_decl, union_di_ty);
2758 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2759 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
2760 return union_di_ty;
2624 // Set to real type now that it has been lowered fully
2625 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2626 map_ptr.* = debug_union_type;
2627
2628 return debug_union_type;
27612629 }
27622630
27632631 var tag_offset: u64 = undefined;
......@@ -2770,81 +2638,80 @@ pub const Object = struct {
27702638 tag_offset = layout.tag_align.forward(layout.payload_size);
27712639 }
27722640
2773 const tag_di = dib.createMemberType(
2774 fwd_decl.toScope(),
2775 "tag",
2776 null, // file
2777 0, // line
2641 const debug_tag_type = try o.builder.debugMemberType(
2642 try o.builder.string("tag"),
2643 Builder.Metadata.none, // File
2644 debug_fwd_ref,
2645 0, // Line
2646 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)),
27782647 layout.tag_size * 8,
27792648 layout.tag_align.toByteUnits(0) * 8,
2780 tag_offset * 8, // offset in bits
2781 0, // flags
2782 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve),
2649 tag_offset * 8,
27832650 );
27842651
2785 const payload_di = dib.createMemberType(
2786 fwd_decl.toScope(),
2787 "payload",
2788 null, // file
2789 0, // line
2790 layout.payload_size * 8, // size in bits
2652 const debug_payload_type = try o.builder.debugMemberType(
2653 try o.builder.string("payload"),
2654 Builder.Metadata.none, // File
2655 debug_fwd_ref,
2656 0, // Line
2657 debug_union_type,
2658 layout.payload_size * 8,
27912659 layout.payload_align.toByteUnits(0) * 8,
2792 payload_offset * 8, // offset in bits
2793 0, // flags
2794 union_di_ty,
2660 payload_offset * 8,
27952661 );
27962662
2797 const full_di_fields: [2]*llvm.DIType =
2663 const full_fields: [2]Builder.Metadata =
27982664 if (layout.tag_align.compare(.gte, layout.payload_align))
2799 .{ tag_di, payload_di }
2665 .{ debug_tag_type, debug_payload_type }
28002666 else
2801 .{ payload_di, tag_di };
2802
2803 const full_di_ty = dib.createStructType(
2804 compile_unit_scope,
2805 name.ptr,
2806 null, // file
2807 0, // line
2808 ty.abiSize(mod) * 8, // size in bits
2809 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits
2810 0, // flags
2811 null, // derived from
2812 &full_di_fields,
2813 full_di_fields.len,
2814 0, // run time lang
2815 null, // vtable holder
2816 "", // unique id
2667 .{ debug_payload_type, debug_tag_type };
2668
2669 const debug_tagged_union_type = try o.builder.debugStructType(
2670 try o.builder.string(name),
2671 Builder.Metadata.none, // File
2672 o.debug_compile_unit, // Scope
2673 0, // Line
2674 Builder.Metadata.none, // Underlying type
2675 ty.abiSize(mod) * 8,
2676 ty.abiAlignment(mod).toByteUnits(0) * 8,
2677 try o.builder.debugTuple(&full_fields),
28172678 );
2818 dib.replaceTemporary(fwd_decl, full_di_ty);
2819 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2820 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2821 return full_di_ty;
2679
2680 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type);
2681
2682 // Set to real type now that it has been lowered fully
2683 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2684 map_ptr.* = debug_tagged_union_type;
2685
2686 return debug_tagged_union_type;
28222687 },
28232688 .Fn => {
28242689 const fn_info = mod.typeToFunc(ty).?;
28252690
2826 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
2827 defer param_di_types.deinit();
2691 var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa);
2692 defer debug_param_types.deinit();
2693
2694 try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);
28282695
28292696 // Return type goes first.
28302697 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {
28312698 const sret = firstParamSRet(fn_info, mod);
2832 const di_ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
2833 try param_di_types.append(try o.lowerDebugType(di_ret_ty, resolve));
2699 const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
2700 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty));
28342701
28352702 if (sret) {
28362703 const ptr_ty = try mod.singleMutPtrType(Type.fromInterned(fn_info.return_type));
2837 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
2704 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
28382705 }
28392706 } else {
2840 try param_di_types.append(try o.lowerDebugType(Type.void, resolve));
2707 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
28412708 }
28422709
28432710 if (Type.fromInterned(fn_info.return_type).isError(mod) and
28442711 o.module.comp.config.any_error_tracing)
28452712 {
28462713 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
2847 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
2714 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
28482715 }
28492716
28502717 for (0..fn_info.param_types.len) |i| {
......@@ -2853,20 +2720,18 @@ pub const Object = struct {
28532720
28542721 if (isByRef(param_ty, mod)) {
28552722 const ptr_ty = try mod.singleMutPtrType(param_ty);
2856 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
2723 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
28572724 } else {
2858 try param_di_types.append(try o.lowerDebugType(param_ty, resolve));
2725 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty));
28592726 }
28602727 }
28612728
2862 const fn_di_ty = dib.createSubroutineType(
2863 param_di_types.items.ptr,
2864 @intCast(param_di_types.items.len),
2865 0,
2729 const debug_function_type = try o.builder.debugSubroutineType(
2730 try o.builder.debugTuple(debug_param_types.items),
28662731 );
2867 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2868 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty));
2869 return fn_di_ty;
2732
2733 try o.debug_type_map.put(gpa, ty, debug_function_type);
2734 return debug_function_type;
28702735 },
28712736 .ComptimeInt => unreachable,
28722737 .ComptimeFloat => unreachable,
......@@ -2880,39 +2745,30 @@ pub const Object = struct {
28802745 }
28812746 }
28822747
2883 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !*llvm.DIScope {
2748 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
28842749 const mod = o.module;
28852750 const namespace = mod.namespacePtr(namespace_index);
2886 if (namespace.parent == .none) {
2887 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);
2888 return di_file.toScope();
2889 }
2890 const di_type = try o.lowerDebugType(namespace.ty, .fwd);
2891 return di_type.toScope();
2751 if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope);
2752
2753 const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);
2754
2755 if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();
2756
2757 return gop.value_ptr.*;
28922758 }
28932759
2894 /// This is to be used instead of void for debug info types, to avoid tripping
2895 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
2896 /// when targeting CodeView (Windows).
2897 fn makeEmptyNamespaceDIType(o: *Object, decl_index: InternPool.DeclIndex) !*llvm.DIType {
2760 fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata {
28982761 const mod = o.module;
28992762 const decl = mod.declPtr(decl_index);
2900 const fields: [0]*llvm.DIType = .{};
2901 const di_scope = try o.namespaceToDebugScope(decl.src_namespace);
2902 return o.di_builder.?.createStructType(
2903 di_scope,
2904 mod.intern_pool.stringToSlice(decl.name), // TODO use fully qualified name
2905 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope),
2763 return o.builder.debugStructType(
2764 try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name
2765 try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope),
2766 try o.namespaceToDebugScope(decl.src_namespace),
29062767 decl.src_line + 1,
2907 0, // size in bits
2908 0, // align in bits
2909 0, // flags
2910 null, // derived from
2911 undefined, // TODO should be able to pass &fields,
2912 fields.len,
2913 0, // run time lang
2914 null, // vtable holder
2915 "", // unique id
2768 Builder.Metadata.none,
2769 0,
2770 0,
2771 .none,
29162772 );
29172773 }
29182774
......@@ -4822,26 +4678,32 @@ pub const DeclGen = struct {
48224678 else => try o.lowerValue(init_val),
48234679 }, &o.builder);
48244680
4825 if (o.di_builder) |dib| {
4826 const di_file =
4827 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
4828
4829 const line_number = decl.src_line + 1;
4830 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
4831 const di_global = dib.createGlobalVariableExpression(
4832 di_file.toScope(),
4833 mod.intern_pool.stringToSlice(decl.name),
4834 variable_index.name(&o.builder).slice(&o.builder).?,
4835 di_file,
4836 line_number,
4837 try o.lowerDebugType(decl.ty, .full),
4838 is_internal_linkage,
4839 );
4681 const line_number = decl.src_line + 1;
4682 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
48404683
4841 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());
4842 if (!is_internal_linkage or decl.isExtern(mod))
4843 variable_index.toLlvm(&o.builder).attachMetaData(di_global);
4844 }
4684 if (dg.object.builder.strip) return;
4685
4686 const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
4687
4688 const debug_global_var = try o.builder.debugGlobalVar(
4689 try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // Name
4690 variable_index.name(&o.builder), // Linkage name
4691 debug_file, // File
4692 debug_file, // Scope
4693 line_number,
4694 try o.lowerDebugType(decl.ty),
4695 variable_index,
4696 .{ .local = is_internal_linkage },
4697 );
4698
4699 const debug_expression = try o.builder.debugExpression(&.{});
4700
4701 const debug_global_var_expression = try o.builder.debugGlobalVarExpression(
4702 debug_global_var,
4703 debug_expression,
4704 );
4705
4706 try o.debug_globals.append(o.gpa, debug_global_var_expression);
48454707 }
48464708 }
48474709};
......@@ -4852,19 +4714,23 @@ pub const FuncGen = struct {
48524714 air: Air,
48534715 liveness: Liveness,
48544716 wip: Builder.WipFunction,
4855 di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn,
4856 di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn,
4717
4718 file: Builder.Metadata,
4719 subprogram: Builder.Metadata,
4720 current_scope: Builder.Metadata,
4721
4722 inlined: std.ArrayListUnmanaged(struct {
4723 base_line: u32,
4724 location: Builder.Metadata,
4725 scope: Builder.Metadata,
4726 }) = .{},
4727
4728 scope_stack: std.ArrayListUnmanaged(Builder.Metadata) = .{},
4729
48574730 base_line: u32,
48584731 prev_dbg_line: c_uint,
48594732 prev_dbg_column: c_uint,
48604733
4861 /// Stack of locations where a call was inlined.
4862 dbg_inlined: std.ArrayListUnmanaged(if (build_options.have_llvm) DbgState else void) = .{},
4863
4864 /// Stack of `DILexicalBlock`s. dbg_block instructions cannot happend accross
4865 /// dbg_inline instructions so no special handling there is required.
4866 dbg_block_stack: std.ArrayListUnmanaged(if (build_options.have_llvm) *llvm.DIScope else void) = .{},
4867
48684734 /// This stores the LLVM values used in a function, such that they can be referred to
48694735 /// in other instructions. This table is cleared before every function is generated.
48704736 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value),
......@@ -4905,8 +4771,8 @@ pub const FuncGen = struct {
49054771
49064772 fn deinit(self: *FuncGen) void {
49074773 self.wip.deinit();
4908 self.dbg_inlined.deinit(self.gpa);
4909 self.dbg_block_stack.deinit(self.gpa);
4774 self.scope_stack.deinit(self.gpa);
4775 self.inlined.deinit(self.gpa);
49104776 self.func_inst_table.deinit(self.gpa);
49114777 self.blocks.deinit(self.gpa);
49124778 }
......@@ -5515,9 +5381,6 @@ pub const FuncGen = struct {
55155381 // a different LLVM type than the usual one. We solve this here at the callsite
55165382 // by using our canonical type, then loading it if necessary.
55175383 const alignment = return_type.abiAlignment(mod).toLlvm();
5518 if (o.builder.useLibLlvm())
5519 assert(o.target_data.abiSizeOfType(abi_ret_ty.toLlvm(&o.builder)) >=
5520 o.target_data.abiSizeOfType(llvm_ret_ty.toLlvm(&o.builder)));
55215384 const rp = try self.buildAlloca(abi_ret_ty, alignment);
55225385 _ = try self.wip.store(.normal, call, rp, alignment);
55235386 return if (isByRef(return_type, mod))
......@@ -6675,42 +6538,48 @@ pub const FuncGen = struct {
66756538 }
66766539
66776540 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6678 const di_scope = self.di_scope orelse return .none;
6541 if (self.wip.builder.strip) return .none;
66796542 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
66806543 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
66816544 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
6682 const inlined_at = if (self.dbg_inlined.items.len > 0)
6683 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6545 const inlined_at = if (self.inlined.items.len > 0)
6546 self.inlined.items[self.inlined.items.len - 1].location
66846547 else
6685 null;
6686 self.wip.llvm.builder.setCurrentDebugLocation(
6687 self.prev_dbg_line,
6688 self.prev_dbg_column,
6689 di_scope,
6690 inlined_at,
6691 );
6548 Builder.Metadata.none;
6549
6550 self.wip.current_debug_location = .{
6551 .line = self.prev_dbg_line,
6552 .column = self.prev_dbg_column,
6553 .scope = self.current_scope,
6554 .inlined_at = inlined_at,
6555 };
6556
66926557 return .none;
66936558 }
66946559
66956560 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6561 if (self.wip.builder.strip or true) return .none;
66966562 const o = self.dg.object;
6697 const dib = o.di_builder orelse return .none;
6698 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
6699
67006563 const zcu = o.module;
6564
6565 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
67016566 const func = zcu.funcInfo(ty_fn.func);
67026567 const decl_index = func.owner_decl;
67036568 const decl = zcu.declPtr(decl_index);
67046569 const namespace = zcu.namespacePtr(decl.src_namespace);
67056570 const owner_mod = namespace.file_scope.mod;
6706 const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope);
6707 self.di_file = di_file;
6708 const line_number = decl.src_line + 1;
6709 const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2();
67106571
6711 try self.dbg_inlined.append(self.gpa, .{
6712 .loc = @ptrCast(cur_debug_location),
6713 .scope = self.di_scope.?,
6572 self.file = try o.getDebugFile(namespace.file_scope);
6573
6574 const line_number = decl.src_line + 1;
6575 try self.inlined.append(self.gpa, .{
6576 .location = if (self.wip.current_debug_location) |location| try self.wip.builder.debugLocation(
6577 location.scope,
6578 location.line,
6579 location.column,
6580 location.inlined_at,
6581 ) else .none,
6582 .scope = self.current_scope,
67146583 .base_line = self.base_line,
67156584 });
67166585
......@@ -6721,91 +6590,108 @@ pub const FuncGen = struct {
67216590 .param_types = &.{},
67226591 .return_type = .void_type,
67236592 });
6724 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);
6725 const subprogram = dib.createFunction(
6726 di_file.toScope(),
6727 zcu.intern_pool.stringToSlice(decl.name),
6728 zcu.intern_pool.stringToSlice(fqn),
6729 di_file,
6593
6594 const subprogram = try o.builder.debugSubprogram(
6595 self.file,
6596 try o.builder.string(zcu.intern_pool.stringToSlice(decl.name)),
6597 try o.builder.string(zcu.intern_pool.stringToSlice(fqn)),
67306598 line_number,
6731 fn_di_ty,
6732 is_internal_linkage,
6733 true, // is definition
6734 line_number + func.lbrace_line, // scope line
6735 llvm.DIFlags.StaticMember,
6736 owner_mod.optimize_mode != .Debug,
6737 null, // decl_subprogram
6599 line_number + func.lbrace_line,
6600 try o.lowerDebugType(fn_ty),
6601 .{
6602 .optimized = owner_mod.optimize_mode != .Debug,
6603 .local = is_internal_linkage,
6604 .definition = true,
6605 .debug_info_flags = llvm.DIFlags.StaticMember,
6606 },
6607 o.debug_compile_unit,
67386608 );
67396609
6740 const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1);
6741 self.di_scope = lexical_block.toScope();
6610 const lexical_block = try o.builder.debugLexicalBlock(
6611 subprogram,
6612 self.file,
6613 line_number,
6614 1,
6615 );
6616 self.current_scope = lexical_block;
67426617 self.base_line = decl.src_line;
67436618 return .none;
67446619 }
67456620
6746 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6621 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
6622 if (self.wip.builder.strip or true) return .none;
67476623 const o = self.dg.object;
6748 if (o.di_builder == null) return .none;
6624
67496625 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
67506626
67516627 const mod = o.module;
67526628 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
6753 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6754 self.di_file = di_file;
6755 const old = self.dbg_inlined.pop();
6756 self.di_scope = old.scope;
6629 self.file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
6630
6631 const old = self.inlined.pop();
6632 self.current_scope = old.scope;
67576633 self.base_line = old.base_line;
67586634 return .none;
67596635 }
67606636
6761 fn airDbgBlockBegin(self: *FuncGen) !Builder.Value {
6637 fn airDbgBlockBegin(self: *FuncGen) Allocator.Error!Builder.Value {
6638 if (self.wip.builder.strip) return .none;
67626639 const o = self.dg.object;
6763 const dib = o.di_builder orelse return .none;
6764 const old_scope = self.di_scope.?;
6765 try self.dbg_block_stack.append(self.gpa, old_scope);
6766 const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column);
6767 self.di_scope = lexical_block.toScope();
6640
6641 try self.scope_stack.append(self.gpa, self.current_scope);
6642
6643 const old = self.current_scope;
6644 self.current_scope = try o.builder.debugLexicalBlock(
6645 self.file,
6646 old,
6647 self.prev_dbg_line,
6648 self.prev_dbg_column,
6649 );
67686650 return .none;
67696651 }
67706652
67716653 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6772 const o = self.dg.object;
6773 if (o.di_builder == null) return .none;
6774 self.di_scope = self.dbg_block_stack.pop();
6654 if (self.wip.builder.strip) return .none;
6655 self.current_scope = self.scope_stack.pop();
67756656 return .none;
67766657 }
67776658
67786659 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6660 if (self.wip.builder.strip) return .none;
67796661 const o = self.dg.object;
67806662 const mod = o.module;
6781 const dib = o.di_builder orelse return .none;
67826663 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
67836664 const operand = try self.resolveInst(pl_op.operand);
67846665 const name = self.air.nullTerminatedString(pl_op.payload);
67856666 const ptr_ty = self.typeOf(pl_op.operand);
67866667
6787 const di_local_var = dib.createAutoVariable(
6788 self.di_scope.?,
6789 name.ptr,
6790 self.di_file.?,
6668 const debug_local_var = try o.builder.debugLocalVar(
6669 try o.builder.string(name),
6670 self.file,
6671 self.current_scope,
67916672 self.prev_dbg_line,
6792 try o.lowerDebugType(ptr_ty.childType(mod), .full),
6793 true, // always preserve
6794 0, // flags
6673 try o.lowerDebugType(ptr_ty.childType(mod)),
67956674 );
6796 const inlined_at = if (self.dbg_inlined.items.len > 0)
6797 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6798 else
6799 null;
6800 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
6801 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
6802 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
6675
6676 _ = try self.wip.callIntrinsic(
6677 .normal,
6678 .none,
6679 .@"dbg.declare",
6680 &.{},
6681 &.{
6682 (try self.wip.debugValue(operand)).toValue(),
6683 debug_local_var.toValue(),
6684 (try o.builder.debugExpression(&.{})).toValue(),
6685 },
6686 "",
6687 );
6688
68036689 return .none;
68046690 }
68056691
68066692 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6693 if (self.wip.builder.strip) return .none;
68076694 const o = self.dg.object;
6808 const dib = o.di_builder orelse return .none;
68096695 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
68106696 const operand = try self.resolveInst(pl_op.operand);
68116697 const operand_ty = self.typeOf(pl_op.operand);
......@@ -6813,32 +6699,58 @@ pub const FuncGen = struct {
68136699
68146700 if (needDbgVarWorkaround(o)) return .none;
68156701
6816 const di_local_var = dib.createAutoVariable(
6817 self.di_scope.?,
6818 name.ptr,
6819 self.di_file.?,
6702 const debug_local_var = try o.builder.debugLocalVar(
6703 try o.builder.string(name),
6704 self.file,
6705 self.current_scope,
68206706 self.prev_dbg_line,
6821 try o.lowerDebugType(operand_ty, .full),
6822 true, // always preserve
6823 0, // flags
6707 try o.lowerDebugType(operand_ty),
68246708 );
6825 const inlined_at = if (self.dbg_inlined.items.len > 0)
6826 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc
6827 else
6828 null;
6829 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
6830 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
6709
68316710 const zcu = o.module;
68326711 const owner_mod = self.dg.ownerModule();
68336712 if (isByRef(operand_ty, zcu)) {
6834 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
6713 _ = try self.wip.callIntrinsic(
6714 .normal,
6715 .none,
6716 .@"dbg.declare",
6717 &.{},
6718 &.{
6719 (try self.wip.debugValue(operand)).toValue(),
6720 debug_local_var.toValue(),
6721 (try o.builder.debugExpression(&.{})).toValue(),
6722 },
6723 "",
6724 );
68356725 } else if (owner_mod.optimize_mode == .Debug) {
68366726 const alignment = operand_ty.abiAlignment(zcu).toLlvm();
68376727 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
68386728 _ = try self.wip.store(.normal, operand, alloca, alignment);
6839 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
6729 _ = try self.wip.callIntrinsic(
6730 .normal,
6731 .none,
6732 .@"dbg.declare",
6733 &.{},
6734 &.{
6735 (try self.wip.debugValue(alloca)).toValue(),
6736 debug_local_var.toValue(),
6737 (try o.builder.debugExpression(&.{})).toValue(),
6738 },
6739 "",
6740 );
68406741 } else {
6841 _ = dib.insertDbgValueIntrinsicAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
6742 _ = try self.wip.callIntrinsic(
6743 .normal,
6744 .none,
6745 .@"dbg.value",
6746 &.{},
6747 &.{
6748 (try self.wip.debugValue(operand)).toValue(),
6749 debug_local_var.toValue(),
6750 (try o.builder.debugExpression(&.{})).toValue(),
6751 },
6752 "",
6753 );
68426754 }
68436755 return .none;
68446756 }
......@@ -8860,41 +8772,80 @@ pub const FuncGen = struct {
88608772 const arg_val = self.args[self.arg_index];
88618773 self.arg_index += 1;
88628774
8775 if (self.wip.builder.strip) return arg_val;
8776
88638777 const inst_ty = self.typeOfIndex(inst);
8864 if (o.di_builder) |dib| {
8865 if (needDbgVarWorkaround(o)) return arg_val;
8866
8867 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
8868 const func_index = self.dg.decl.getOwnedFunctionIndex();
8869 const func = mod.funcInfo(func_index);
8870 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8871 const lbrace_col = func.lbrace_column + 1;
8872 const di_local_var = dib.createParameterVariable(
8873 self.di_scope.?,
8874 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
8875 self.di_file.?,
8876 lbrace_line,
8877 try o.lowerDebugType(inst_ty, .full),
8878 true, // always preserve
8879 0, // flags
8880 @intCast(self.arg_index), // includes +1 because 0 is return type
8881 );
8778 if (needDbgVarWorkaround(o)) return arg_val;
8779
8780 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
8781 const func_index = self.dg.decl.getOwnedFunctionIndex();
8782 const func = mod.funcInfo(func_index);
8783 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8784 const lbrace_col = func.lbrace_column + 1;
8785
8786 const debug_parameter = try o.builder.debugParameter(
8787 try o.builder.string(mod.getParamName(func_index, src_index)),
8788 self.file,
8789 self.current_scope,
8790 lbrace_line,
8791 try o.lowerDebugType(inst_ty),
8792 @intCast(self.arg_index),
8793 );
88828794
8883 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);
8884 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);
8885 const owner_mod = self.dg.ownerModule();
8886 if (isByRef(inst_ty, mod)) {
8887 _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
8888 } else if (owner_mod.optimize_mode == .Debug) {
8889 const alignment = inst_ty.abiAlignment(mod).toLlvm();
8890 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
8891 _ = try self.wip.store(.normal, arg_val, alloca, alignment);
8892 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
8893 } else {
8894 _ = dib.insertDbgValueIntrinsicAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);
8895 }
8795 const old_location = self.wip.current_debug_location;
8796 self.wip.current_debug_location = .{
8797 .line = lbrace_line,
8798 .column = lbrace_col,
8799 .scope = self.current_scope,
8800 .inlined_at = Builder.Metadata.none,
8801 };
8802
8803 const owner_mod = self.dg.ownerModule();
8804 if (isByRef(inst_ty, mod)) {
8805 _ = try self.wip.callIntrinsic(
8806 .normal,
8807 .none,
8808 .@"dbg.declare",
8809 &.{},
8810 &.{
8811 (try self.wip.debugValue(arg_val)).toValue(),
8812 debug_parameter.toValue(),
8813 (try o.builder.debugExpression(&.{})).toValue(),
8814 },
8815 "",
8816 );
8817 } else if (owner_mod.optimize_mode == .Debug) {
8818 const alignment = inst_ty.abiAlignment(mod).toLlvm();
8819 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);
8820 _ = try self.wip.store(.normal, arg_val, alloca, alignment);
8821 _ = try self.wip.callIntrinsic(
8822 .normal,
8823 .none,
8824 .@"dbg.declare",
8825 &.{},
8826 &.{
8827 (try self.wip.debugValue(alloca)).toValue(),
8828 debug_parameter.toValue(),
8829 (try o.builder.debugExpression(&.{})).toValue(),
8830 },
8831 "",
8832 );
8833 } else {
8834 _ = try self.wip.callIntrinsic(
8835 .normal,
8836 .none,
8837 .@"dbg.value",
8838 &.{},
8839 &.{
8840 (try self.wip.debugValue(arg_val)).toValue(),
8841 debug_parameter.toValue(),
8842 (try o.builder.debugExpression(&.{})).toValue(),
8843 },
8844 "",
8845 );
88968846 }
88978847
8848 self.wip.current_debug_location = old_location;
88988849 return arg_val;
88998850 }
89008851
......@@ -8932,7 +8883,7 @@ pub const FuncGen = struct {
89328883 alignment: Builder.Alignment,
89338884 ) Allocator.Error!Builder.Value {
89348885 const target = self.dg.object.module.getTarget();
8935 return buildAllocaInner(&self.wip, self.di_scope != null, llvm_ty, alignment, target);
8886 return buildAllocaInner(&self.wip, llvm_ty, alignment, target);
89368887 }
89378888
89388889 // Workaround for https://github.com/ziglang/zig/issues/16392
......@@ -11716,45 +11667,6 @@ const struct_layout_version = 2;
1171611667// https://github.com/llvm/llvm-project/issues/56585/ is fixed
1171711668const optional_layout_version = 3;
1171811669
11719/// We use the least significant bit of the pointer address to tell us
11720/// whether the type is fully resolved. Types that are only fwd declared
11721/// have the LSB flipped to a 1.
11722const AnnotatedDITypePtr = enum(usize) {
11723 null,
11724 _,
11725
11726 fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr {
11727 const addr = @intFromPtr(di_type);
11728 assert(@as(u1, @truncate(addr)) == 0);
11729 return @enumFromInt(addr | 1);
11730 }
11731
11732 fn initFull(di_type: *llvm.DIType) AnnotatedDITypePtr {
11733 const addr = @intFromPtr(di_type);
11734 return @enumFromInt(addr);
11735 }
11736
11737 fn init(di_type: *llvm.DIType, resolve: Object.DebugResolveStatus) AnnotatedDITypePtr {
11738 const addr = @intFromPtr(di_type);
11739 const bit = @intFromBool(resolve == .fwd);
11740 return @enumFromInt(addr | bit);
11741 }
11742
11743 fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType {
11744 switch (self) {
11745 .null => unreachable,
11746 _ => return @ptrFromInt(@intFromEnum(self) & ~@as(usize, 1)),
11747 }
11748 }
11749
11750 fn isFwdOnly(self: AnnotatedDITypePtr) bool {
11751 switch (self) {
11752 .null => unreachable,
11753 _ => return @as(u1, @truncate(@intFromEnum(self))) != 0,
11754 }
11755 }
11756};
11757
1175811670const lt_errors_fn_name = "__zig_lt_errors_len";
1175911671
1176011672/// Without this workaround, LLVM crashes with "unknown codeview register H1"
......@@ -11778,7 +11690,6 @@ fn compilerRtIntBits(bits: u16) u16 {
1177811690
1177911691fn buildAllocaInner(
1178011692 wip: *Builder.WipFunction,
11781 di_scope_non_null: bool,
1178211693 llvm_ty: Builder.Type,
1178311694 alignment: Builder.Alignment,
1178411695 target: std.Target,
......@@ -11787,19 +11698,15 @@ fn buildAllocaInner(
1178711698
1178811699 const alloca = blk: {
1178911700 const prev_cursor = wip.cursor;
11790 const prev_debug_location = if (wip.builder.useLibLlvm())
11791 wip.llvm.builder.getCurrentDebugLocation2()
11792 else
11793 undefined;
11701 const prev_debug_location = wip.current_debug_location;
1179411702 defer {
1179511703 wip.cursor = prev_cursor;
1179611704 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
11797 if (wip.builder.useLibLlvm() and di_scope_non_null)
11798 wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
11705 wip.current_debug_location = prev_debug_location;
1179911706 }
1180011707
1180111708 wip.cursor = .{ .block = .entry };
11802 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();
11709 wip.current_debug_location = null;
1180311710 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
1180411711 };
1180511712