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 {...@@ -770,37 +770,19 @@ pub const Object = struct {
770 builder: Builder,770 builder: Builder,
771771
772 module: *Module,772 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,776 debug_enums_fwd_ref: Builder.Metadata,
785 size: Size = 0,777 debug_globals_fwd_ref: Builder.Metadata,
786 available: Size = 0,
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 {782 debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata),
791 _ = allocator;783
792 self.* = undefined;784 debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata),
793 }
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,
804 target: std.Target,786 target: std.Target,
805 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,787 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
806 /// but that has some downsides:788 /// but that has some downsides:
...@@ -820,7 +802,6 @@ pub const Object = struct {...@@ -820,7 +802,6 @@ pub const Object = struct {
820 /// TODO when InternPool garbage collection is implemented, this map needs802 /// TODO when InternPool garbage collection is implemented, this map needs
821 /// to be garbage collected as well.803 /// to be garbage collected as well.
822 type_map: TypeMap,804 type_map: TypeMap,
823 di_type_map: DITypeMap,
824 /// The LLVM global table which holds the names corresponding to Zig errors.805 /// The LLVM global table which holds the names corresponding to Zig errors.
825 /// Note that the values are not added until `emit`, when all errors in806 /// Note that the values are not added until `emit`, when all errors in
826 /// the compilation are known.807 /// the compilation are known.
...@@ -850,146 +831,87 @@ pub const Object = struct {...@@ -850,146 +831,87 @@ pub const Object = struct {
850831
851 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);832 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
857 pub fn create(arena: Allocator, comp: *Compilation) !*Object {834 pub fn create(arena: Allocator, comp: *Compilation) !*Object {
858 if (build_options.only_c) unreachable;835 if (build_options.only_c) unreachable;
859 const gpa = comp.gpa;836 const gpa = comp.gpa;
860 const target = comp.root_mod.resolved_target.result;837 const target = comp.root_mod.resolved_target.result;
861 const llvm_target_triple = try targetTriple(arena, target);838 const llvm_target_triple = try targetTriple(arena, target);
862 const strip = comp.root_mod.strip;839 const strip = comp.root_mod.strip;
863 const optimize_mode = comp.root_mod.optimize_mode;
864 const pic = comp.root_mod.pic;
865840
866 var builder = try Builder.init(.{841 var builder = try Builder.init(.{
867 .allocator = gpa,842 .allocator = gpa,
868 .use_lib_llvm = comp.config.use_lib_llvm,843 .use_lib_llvm = false,
869 .strip = strip or !comp.config.use_lib_llvm, // TODO844 .strip = strip,
870 .name = comp.root_name,845 .name = comp.root_name,
871 .target = target,846 .target = target,
872 .triple = llvm_target_triple,847 .triple = llvm_target_triple,
873 });848 });
874 errdefer builder.deinit();849 errdefer builder.deinit();
875850
876 var target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void = undefined;851 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
877 var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;852
878 if (builder.useLibLlvm()) {853 // We fully resolve all paths at this point to avoid lack of
879 debug_info: {854 // source line info in stack traces or lack of debugging
880 switch (comp.config.debug_format) {855 // information which, if relative paths were used, would be
881 .strip => break :debug_info,856 // very location dependent.
882 .code_view => builder.llvm.module.?.addModuleCodeViewFlag(),857 // TODO: the only concern I have with this is WASI as either host or target, should
883 .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),858 // we leave the paths as relative then?
884 }859 // TODO: This is totally wrong. In dwarf, paths are encoded as relative to
885 builder.llvm.di_builder = builder.llvm.module.?.createDIBuilder(true);860 // a particular directory, and then the directory path is specified elsewhere.
886861 // In the compiler frontend we have it stored correctly in this
887 // Don't use the version string here; LLVM misparses it when it862 // way already, but here we throw all that sweet information
888 // includes the git revision.863 // into the garbage can by converting into absolute paths. What
889 const producer = try builder.fmt("zig {d}.{d}.{d}", .{864 // a terrible tragedy.
890 build_options.semver.major,865 const compile_unit_dir = blk: {
891 build_options.semver.minor,866 if (comp.module) |zcu| m: {
892 build_options.semver.patch,867 const d = try zcu.root_mod.root.joinString(arena, "");
893 });868 if (d.len == 0) break :m;
894869 if (std.fs.path.isAbsolute(d)) break :blk d;
895 // We fully resolve all paths at this point to avoid lack of870 break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
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 );
930 }871 }
872 break :blk try std.process.getCwdAlloc(arena);
873 };
931874
932 const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug)875 const debug_file = try builder.debugFile(
933 .None876 try builder.string(compile_unit_dir),
934 else877 try builder.string(comp.root_name),
935 .Aggressive;878 );
936879
937 const reloc_mode: llvm.RelocMode = if (pic)880 const debug_enums_fwd_ref = try builder.debugForwardReference();
938 .PIC881 const debug_globals_fwd_ref = try builder.debugForwardReference();
939 else if (comp.config.link_mode == .Dynamic)882
940 llvm.RelocMode.DynamicNoPIC883 const debug_compile_unit = try builder.debugCompileUnit(
941 else884 debug_file,
942 .Static;885 // Don't use the version string here; LLVM misparses it when it
943886 // includes the git revision.
944 const code_model: llvm.CodeModel = switch (comp.root_mod.code_model) {887 try builder.fmt("zig {d}.{d}.{d}", .{
945 .default => .Default,888 build_options.semver.major,
946 .tiny => .Tiny,889 build_options.semver.minor,
947 .small => .Small,890 build_options.semver.patch,
948 .kernel => .Kernel,891 }),
949 .medium => .Medium,892 debug_enums_fwd_ref,
950 .large => .Large,893 debug_globals_fwd_ref,
951 };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.Target897 if (!builder.strip) {
954 const float_abi: llvm.ABIType = .Default;898 const debug_info_version = try builder.debugModuleFlag(
955899 try builder.debugConstant(try builder.intConst(.i32, 2)),
956 target_machine = llvm.TargetMachine.create(900 try builder.string("Debug Info Version"),
957 builder.llvm.target.?,901 try builder.debugConstant(try builder.intConst(.i32, 3)),
958 builder.target_triple.slice(&builder).?,902 );
959 if (target.cpu.model.llvm_name) |s| s.ptr else null,903 const dwarf_version = try builder.debugModuleFlag(
960 comp.root_mod.resolved_target.llvm_cpu_features.?,904 try builder.debugConstant(try builder.intConst(.i32, 2)),
961 opt_level,905 try builder.string("Dwarf Version"),
962 reloc_mode,906 try builder.debugConstant(try builder.intConst(.i32, 4)),
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,
968 );907 );
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) {909 try builder.debugNamed(try builder.string("llvm.module.flags"), &.{
981 builder.llvm.context.setOptBisectLimit(comp.llvm_opt_bisect_limit);910 debug_info_version,
982 }911 dwarf_version,
912 });
983913
984 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});914 try builder.debugNamed(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit});
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 }
993 }915 }
994916
995 const obj = try arena.create(Object);917 const obj = try arena.create(Object);
...@@ -997,17 +919,18 @@ pub const Object = struct {...@@ -997,17 +919,18 @@ pub const Object = struct {
997 .gpa = gpa,919 .gpa = gpa,
998 .builder = builder,920 .builder = builder,
999 .module = comp.module.?,921 .module = comp.module.?,
1000 .di_map = .{},922 .debug_compile_unit = debug_compile_unit,
1001 .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO923 .debug_enums_fwd_ref = debug_enums_fwd_ref,
1002 .di_compile_unit = if (builder.useLibLlvm()) builder.llvm.di_compile_unit else null,924 .debug_globals_fwd_ref = debug_globals_fwd_ref,
1003 .target_machine = target_machine,925 .debug_enums = .{},
1004 .target_data = target_data,926 .debug_globals = .{},
927 .debug_type_map = .{},
928 .debug_unresolved_namespace_scopes = .{},
1005 .target = target,929 .target = target,
1006 .decl_map = .{},930 .decl_map = .{},
1007 .anon_decl_map = .{},931 .anon_decl_map = .{},
1008 .named_enum_map = .{},932 .named_enum_map = .{},
1009 .type_map = .{},933 .type_map = .{},
1010 .di_type_map = .{},
1011 .error_name_table = .none,934 .error_name_table = .none,
1012 .extern_collisions = .{},935 .extern_collisions = .{},
1013 .null_opt_usize = .no_init,936 .null_opt_usize = .no_init,
...@@ -1018,12 +941,10 @@ pub const Object = struct {...@@ -1018,12 +941,10 @@ pub const Object = struct {
1018941
1019 pub fn deinit(self: *Object) void {942 pub fn deinit(self: *Object) void {
1020 const gpa = self.gpa;943 const gpa = self.gpa;
1021 self.di_map.deinit(gpa);944 self.debug_globals.deinit(gpa);
1022 self.di_type_map.deinit(gpa);945 self.debug_enums.deinit(gpa);
1023 if (self.builder.useLibLlvm()) {946 self.debug_type_map.deinit(gpa);
1024 self.target_data.dispose();947 self.debug_unresolved_namespace_scopes.deinit(gpa);
1025 self.target_machine.dispose();
1026 }
1027 self.decl_map.deinit(gpa);948 self.decl_map.deinit(gpa);
1028 self.anon_decl_map.deinit(gpa);949 self.anon_decl_map.deinit(gpa);
1029 self.named_enum_map.deinit(gpa);950 self.named_enum_map.deinit(gpa);
...@@ -1193,26 +1114,29 @@ pub const Object = struct {...@@ -1193,26 +1114,29 @@ pub const Object = struct {
1193 try self.genCmpLtErrorsLenFunction();1114 try self.genCmpLtErrorsLenFunction();
1194 try self.genModuleLevelAssembly();1115 try self.genModuleLevelAssembly();
11951116
1196 if (self.di_builder) |dib| {1117 {
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.
1201 var i: usize = 0;1118 var i: usize = 0;
1202 while (i < self.di_type_map.count()) : (i += 1) {1119 while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) {
1203 const value_ptr = &self.di_type_map.values()[i];1120 const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i];
1204 const annotated = value_ptr.*;1121 const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
1205 if (!annotated.isFwdOnly()) continue;1122 const namespace = self.module.namespacePtr(namespace_index);
1206 const entry: Object.DITypeMap.Entry = .{1123
1207 .key_ptr = &self.di_type_map.keys()[i],1124 const debug_type = try self.lowerDebugType(namespace.ty);
1208 .value_ptr = value_ptr,
1209 };
1210 _ = try self.lowerDebugTypeImpl(entry, .full, annotated.toDIType());
1211 }
12121125
1213 dib.finalize();1126 self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
1127 }
1214 }1128 }
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
1216 if (options.pre_ir_path) |path| {1140 if (options.pre_ir_path) |path| {
1217 if (std.mem.eql(u8, path, "-")) {1141 if (std.mem.eql(u8, path, "-")) {
1218 self.builder.dump();1142 self.builder.dump();
...@@ -1238,35 +1162,126 @@ pub const Object = struct {...@@ -1238,35 +1162,126 @@ pub const Object = struct {
1238 if (options.asm_path == null and options.bin_path == null and1162 if (options.asm_path == null and options.bin_path == null and
1239 options.post_ir_path == null and options.post_bc_path == null) return;1163 options.post_ir_path == null and options.post_bc_path == null) return;
12401164
1241 if (options.post_bc_path) |path| {1165 var bitcode_arena_allocator = std.heap.ArenaAllocator.init(
1242 if (!self.builder.useLibLlvm()) {1166 std.heap.page_allocator,
1243 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);1167 );
1244 defer arena_allocator.deinit();1168 errdefer bitcode_arena_allocator.deinit();
1245 const arena = arena_allocator.allocator();
12461169
1247 var file = try std.fs.cwd().createFileZ(path, .{});1170 const bitcode = try self.builder.toBitcode(
1248 defer file.close();1171 bitcode_arena_allocator.allocator(),
1249 const bitcode = try self.builder.toBitcode(arena);1172 );
12501173
1251 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);1174 if (options.post_bc_path) |path| {
1252 try file.writeAll(ptr[0..(bitcode.len * 4)]);1175 var file = try std.fs.cwd().createFileZ(path, .{});
1253 return;1176 defer file.close();
1254 }1177
1178 const ptr: [*]const u8 = @ptrCast(bitcode.ptr);
1179 try file.writeAll(ptr[0..(bitcode.len * 4)]);
1255 }1180 }
12561181
1257 if (!self.builder.useLibLlvm()) {1182 if (!self.module.comp.config.use_lib_llvm) {
1258 log.err("emitting without libllvm not implemented", .{});1183 log.err("emitting without libllvm not implemented", .{});
1259 return error.FailedToEmit;1184 return error.FailedToEmit;
1260 }1185 }
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
1262 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.1277 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
1263 // So we call the entire pipeline multiple times if this is requested.1278 // 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;
1265 var emit_bin_path = options.bin_path;1280 var emit_bin_path = options.bin_path;
1266 var post_ir_path = options.post_ir_path;1281 var post_ir_path = options.post_ir_path;
1267 if (options.asm_path != null and options.bin_path != null) {1282 if (options.asm_path != null and options.bin_path != null) {
1268 if (self.target_machine.emitToFile(1283 if (target_machine.emitToFile(
1269 self.builder.llvm.module.?,1284 module,
1270 &error_message,1285 &error_message,
1271 options.is_debug,1286 options.is_debug,
1272 options.is_small,1287 options.is_small,
...@@ -1289,8 +1304,8 @@ pub const Object = struct {...@@ -1289,8 +1304,8 @@ pub const Object = struct {
1289 post_ir_path = null;1304 post_ir_path = null;
1290 }1305 }
12911306
1292 if (self.target_machine.emitToFile(1307 if (target_machine.emitToFile(
1293 self.builder.llvm.module.?,1308 module,
1294 &error_message,1309 &error_message,
1295 options.is_debug,1310 options.is_debug,
1296 options.is_small,1311 options.is_small,
...@@ -1300,7 +1315,7 @@ pub const Object = struct {...@@ -1300,7 +1315,7 @@ pub const Object = struct {
1300 options.asm_path,1315 options.asm_path,
1301 emit_bin_path,1316 emit_bin_path,
1302 post_ir_path,1317 post_ir_path,
1303 options.post_bc_path,1318 null,
1304 )) {1319 )) {
1305 defer llvm.disposeMessage(error_message);1320 defer llvm.disposeMessage(error_message);
13061321
...@@ -1440,7 +1455,7 @@ pub const Object = struct {...@@ -1440,7 +1455,7 @@ pub const Object = struct {
1440 if (isByRef(param_ty, zcu)) {1455 if (isByRef(param_ty, zcu)) {
1441 const alignment = param_ty.abiAlignment(zcu).toLlvm();1456 const alignment = param_ty.abiAlignment(zcu).toLlvm();
1442 const param_llvm_ty = param.typeOfWip(&wip);1457 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);
1444 _ = try wip.store(.normal, param, arg_ptr, alignment);1459 _ = try wip.store(.normal, param, arg_ptr, alignment);
1445 args.appendAssumeCapacity(arg_ptr);1460 args.appendAssumeCapacity(arg_ptr);
1446 } else {1461 } else {
...@@ -1488,7 +1503,7 @@ pub const Object = struct {...@@ -1488,7 +1503,7 @@ pub const Object = struct {
14881503
1489 const param_llvm_ty = try o.lowerType(param_ty);1504 const param_llvm_ty = try o.lowerType(param_ty);
1490 const alignment = param_ty.abiAlignment(zcu).toLlvm();1505 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);
1492 _ = try wip.store(.normal, param, arg_ptr, alignment);1507 _ = try wip.store(.normal, param, arg_ptr, alignment);
14931508
1494 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1509 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1533,7 +1548,7 @@ pub const Object = struct {...@@ -1533,7 +1548,7 @@ pub const Object = struct {
1533 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);1548 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
1534 const param_llvm_ty = try o.lowerType(param_ty);1549 const param_llvm_ty = try o.lowerType(param_ty);
1535 const param_alignment = param_ty.abiAlignment(zcu).toLlvm();1550 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);
1537 const llvm_ty = try o.builder.structType(.normal, field_types);1552 const llvm_ty = try o.builder.structType(.normal, field_types);
1538 for (0..field_types.len) |field_i| {1553 for (0..field_types.len) |field_i| {
1539 const param = wip.arg(llvm_arg_i);1554 const param = wip.arg(llvm_arg_i);
...@@ -1563,7 +1578,7 @@ pub const Object = struct {...@@ -1563,7 +1578,7 @@ pub const Object = struct {
1563 llvm_arg_i += 1;1578 llvm_arg_i += 1;
15641579
1565 const alignment = param_ty.abiAlignment(zcu).toLlvm();1580 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);
1567 _ = try wip.store(.normal, param, arg_ptr, alignment);1582 _ = try wip.store(.normal, param, arg_ptr, alignment);
15681583
1569 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1584 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1578,7 +1593,7 @@ pub const Object = struct {...@@ -1578,7 +1593,7 @@ pub const Object = struct {
1578 llvm_arg_i += 1;1593 llvm_arg_i += 1;
15791594
1580 const alignment = param_ty.abiAlignment(zcu).toLlvm();1595 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);
1582 _ = try wip.store(.normal, param, arg_ptr, alignment);1597 _ = try wip.store(.normal, param, arg_ptr, alignment);
15831598
1584 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))1599 args.appendAssumeCapacity(if (isByRef(param_ty, zcu))
...@@ -1592,40 +1607,34 @@ pub const Object = struct {...@@ -1592,40 +1607,34 @@ pub const Object = struct {
15921607
1593 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);1608 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;1610 const file = try o.getDebugFile(namespace.file_scope);
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);
16001611
1612 const subprogram = blk: {
1601 const line_number = decl.src_line + 1;1613 const line_number = decl.src_line + 1;
1602 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and1614 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
1603 !zcu.decl_exports.contains(decl_index);1615 !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)
1605 llvm.DIFlags.NoReturn1617 llvm.DIFlags.NoReturn
1606 else1618 else
1607 0;1619 0;
1608 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);1620 const debug_decl_type = try o.lowerDebugType(decl.ty);
1609 const subprogram = dib.createFunction(1621
1610 di_file.?.toScope(),1622 break :blk try o.builder.debugSubprogram(
1611 ip.stringToSlice(decl.name),1623 file,
1612 function_index.name(&o.builder).slice(&o.builder).?,1624 try o.builder.string(ip.stringToSlice(decl.name)),
1613 di_file.?,1625 function_index.name(&o.builder),
1614 line_number,1626 line_number,
1615 decl_di_ty,1627 line_number + func.lbrace_line,
1616 is_internal_linkage,1628 debug_decl_type,
1617 true, // is definition1629 .{
1618 line_number + func.lbrace_line, // scope line1630 .optimized = owner_mod.optimize_mode != .Debug,
1619 llvm.DIFlags.StaticMember | noret_bit,1631 .definition = true,
1620 owner_mod.optimize_mode != .Debug,1632 .local = is_internal_linkage,
1621 null, // decl_subprogram1633 .debug_info_flags = llvm.DIFlags.StaticMember | noret_bit,
1634 },
1635 o.debug_compile_unit,
1622 );1636 );
1623 try o.di_map.put(gpa, decl, subprogram.toNode());1637 };
1624
1625 function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram);
1626
1627 di_scope = subprogram.toScope();
1628 }
16291638
1630 var fg: FuncGen = .{1639 var fg: FuncGen = .{
1631 .gpa = gpa,1640 .gpa = gpa,
...@@ -1639,8 +1648,9 @@ pub const Object = struct {...@@ -1639,8 +1648,9 @@ pub const Object = struct {
1639 .func_inst_table = .{},1648 .func_inst_table = .{},
1640 .blocks = .{},1649 .blocks = .{},
1641 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,1650 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
1642 .di_scope = di_scope,1651 .file = file,
1643 .di_file = di_file,1652 .subprogram = subprogram,
1653 .current_scope = subprogram,
1644 .base_line = dg.decl.src_line,1654 .base_line = dg.decl.src_line,
1645 .prev_dbg_line = 0,1655 .prev_dbg_line = 0,
1646 .prev_dbg_column = 0,1656 .prev_dbg_column = 0,
...@@ -1726,26 +1736,7 @@ pub const Object = struct {...@@ -1726,26 +1736,7 @@ pub const Object = struct {
1726 global_index.setUnnamedAddr(.default, &self.builder);1736 global_index.setUnnamedAddr(.default, &self.builder);
1727 if (comp.config.dll_export_fns)1737 if (comp.config.dll_export_fns)
1728 global_index.setDllStorageClass(.default, &self.builder);1738 global_index.setDllStorageClass(.default, &self.builder);
1729 if (self.di_map.get(decl)) |di_node| {1739
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 }
1749 if (decl.val.getVariable(mod)) |decl_var| {1740 if (decl.val.getVariable(mod)) |decl_var| {
1750 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(1741 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1751 if (decl_var.is_threadlocal) .generaldynamic else .default,1742 if (decl_var.is_threadlocal) .generaldynamic else .default,
...@@ -1759,27 +1750,6 @@ pub const Object = struct {...@@ -1759,27 +1750,6 @@ pub const Object = struct {
1759 );1750 );
1760 try global_index.rename(main_exp_name, &self.builder);1751 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
1783 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)1753 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1784 global_index.ptrConst(&self.builder).kind1754 global_index.ptrConst(&self.builder).kind
1785 .variable.setThreadLocal(.generaldynamic, &self.builder);1755 .variable.setThreadLocal(.generaldynamic, &self.builder);
...@@ -1909,119 +1879,64 @@ pub const Object = struct {...@@ -1909,119 +1879,64 @@ pub const Object = struct {
1909 global.delete(&self.builder);1879 global.delete(&self.builder);
1910 }1880 }
19111881
1912 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {1882 fn getDebugFile(o: *Object, file: *const Module.File) Allocator.Error!Builder.Metadata {
1913 const gop = try o.di_map.getOrPut(gpa, file);1883 return try o.builder.debugFile(
1914 errdefer assert(o.di_map.remove(file));1884 if (std.fs.path.dirname(file.sub_file_path)) |dirname| try o.builder.string(dirname) else .empty,
1915 if (gop.found_existing) {1885 try o.builder.string(std.fs.path.basename(file.sub_file_path)),
1916 return @ptrCast(gop.value_ptr.*);1886 );
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;
1933 }1887 }
19341888
1935 const DebugResolveStatus = enum { fwd, full };1889 pub fn lowerDebugType(
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(
1940 o: *Object,1890 o: *Object,
1941 ty: Type,1891 ty: Type,
1942 resolve: DebugResolveStatus,1892 ) Allocator.Error!Builder.Metadata {
1943 ) Allocator.Error!*llvm.DIType {1893 if (o.builder.strip) return Builder.Metadata.none;
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.*);
1985 const gpa = o.gpa;1894 const gpa = o.gpa;
1986 const target = o.target;1895 const target = o.target;
1987 const dib = o.di_builder.?;
1988 const mod = o.module;1896 const mod = o.module;
1989 const ip = &mod.intern_pool;1897 const ip = &mod.intern_pool;
1898
1899 if (o.debug_type_map.get(ty)) |debug_type| return debug_type;
1900
1990 switch (ty.zigTypeTag(mod)) {1901 switch (ty.zigTypeTag(mod)) {
1991 .Void, .NoReturn => {1902 .Void,
1992 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);1903 .NoReturn,
1993 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1904 => {
1994 return di_type;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;
1995 },1911 },
1996 .Int => {1912 .Int => {
1997 const info = ty.intInfo(mod);1913 const info = ty.intInfo(mod);
1998 assert(info.bits != 0);1914 assert(info.bits != 0);
1999 const name = try o.allocTypeName(ty);1915 const name = try o.allocTypeName(ty);
2000 defer gpa.free(name);1916 defer gpa.free(name);
2001 const dwarf_encoding: c_uint = switch (info.signedness) {1917 const builder_name = try o.builder.string(name);
2002 .signed => DW.ATE.signed,1918 const debug_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
2003 .unsigned => DW.ATE.unsigned,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),
2004 };1922 };
2005 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types1923 try o.debug_type_map.put(gpa, ty, debug_int_type);
2006 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);1924 return debug_int_type;
2007 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
2008 return di_type;
2009 },1925 },
2010 .Enum => {1926 .Enum => {
2011 const owner_decl_index = ty.getOwnerDecl(mod);1927 const owner_decl_index = ty.getOwnerDecl(mod);
2012 const owner_decl = o.module.declPtr(owner_decl_index);1928 const owner_decl = o.module.declPtr(owner_decl_index);
20131929
2014 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {1930 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2015 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);1931 const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2016 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`1932 try o.debug_type_map.put(gpa, ty, debug_enum_type);
2017 // means we can't use `gop` anymore.1933 try o.debug_enums.append(gpa, debug_enum_type);
2018 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));1934 return debug_enum_type;
2019 return enum_di_ty;
2020 }1935 }
20211936
2022 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;1937 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);
2025 defer gpa.free(enumerators);1940 defer gpa.free(enumerators);
20261941
2027 const int_ty = Type.fromInterned(enum_type.tag_ty);1942 const int_ty = Type.fromInterned(enum_type.tag_ty);
...@@ -2029,66 +1944,59 @@ pub const Object = struct {...@@ -2029,66 +1944,59 @@ pub const Object = struct {
2029 assert(int_info.bits != 0);1944 assert(int_info.bits != 0);
20301945
2031 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {1946 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
2032 const field_name_z = ip.stringToSlice(field_name_ip);
2033
2034 var bigint_space: Value.BigIntSpace = undefined;1947 var bigint_space: Value.BigIntSpace = undefined;
2035 const bigint = if (enum_type.values.len != 0)1948 const bigint = if (enum_type.values.len != 0)
2036 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod)1949 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod)
2037 else1950 else
2038 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();1951 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
20391952
2040 if (bigint.limbs.len == 1) {1953 enumerators[i] = try o.builder.debugEnumerator(
2041 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);1954 try o.builder.string(ip.stringToSlice(field_name_ip)),
2042 continue;1955 int_ty.isUnsignedInt(mod),
2043 }1956 int_info.bits,
2044 if (@sizeOf(usize) == @sizeOf(u64)) {1957 bigint,
2045 enumerators[i] = dib.createEnumerator2(1958 );
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");
2055 }1959 }
20561960
2057 const di_file = try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope);1961 const file = try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope);
2058 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);1962 const scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
20591963
2060 const name = try o.allocTypeName(ty);1964 const name = try o.allocTypeName(ty);
2061 defer gpa.free(name);1965 defer gpa.free(name);
20621966
2063 const enum_di_ty = dib.createEnumerationType(1967 const debug_enum_type = try o.builder.debugEnumerationType(
2064 di_scope,1968 try o.builder.string(name),
2065 name,1969 file,
2066 di_file,1970 scope,
2067 owner_decl.src_node + 1,1971 owner_decl.src_node + 1, // Line
1972 try o.lowerDebugType(int_ty),
2068 ty.abiSize(mod) * 8,1973 ty.abiSize(mod) * 8,
2069 ty.abiAlignment(mod).toByteUnits(0) * 8,1974 ty.abiAlignment(mod).toByteUnits(0) * 8,
2070 enumerators.ptr,1975 try o.builder.debugTuple(enumerators),
2071 @intCast(enumerators.len),
2072 try o.lowerDebugType(int_ty, resolve),
2073 "",
2074 );1976 );
2075 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.1977
2076 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));1978 try o.debug_type_map.put(gpa, ty, debug_enum_type);
2077 return enum_di_ty;1979 try o.debug_enums.append(gpa, debug_enum_type);
1980 return debug_enum_type;
2078 },1981 },
2079 .Float => {1982 .Float => {
2080 const bits = ty.floatBits(target);1983 const bits = ty.floatBits(target);
2081 const name = try o.allocTypeName(ty);1984 const name = try o.allocTypeName(ty);
2082 defer gpa.free(name);1985 defer gpa.free(name);
2083 const di_type = dib.createBasicType(name, bits, DW.ATE.float);1986 const debug_float_type = try o.builder.debugFloatType(
2084 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1987 try o.builder.string(name),
2085 return di_type;1988 bits,
1989 );
1990 try o.debug_type_map.put(gpa, ty, debug_float_type);
1991 return debug_float_type;
2086 },1992 },
2087 .Bool => {1993 .Bool => {
2088 const di_bits = 8; // lldb cannot handle non-byte sized types1994 const debug_bool_type = try o.builder.debugBoolType(
2089 const di_type = dib.createBasicType("bool", di_bits, DW.ATE.boolean);1995 try o.builder.string("bool"),
2090 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);1996 8, // lldb cannot handle non-byte sized types
2091 return di_type;1997 );
1998 try o.debug_type_map.put(gpa, ty, debug_bool_type);
1999 return debug_bool_type;
2092 },2000 },
2093 .Pointer => {2001 .Pointer => {
2094 // Normalize everything that the debug info does not represent.2002 // Normalize everything that the debug info does not represent.
...@@ -2118,136 +2026,145 @@ pub const Object = struct {...@@ -2118,136 +2026,145 @@ pub const Object = struct {
2118 },2026 },
2119 },2027 },
2120 });2028 });
2121 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);2029 const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty);
2122 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2030 try o.debug_type_map.put(gpa, ty, debug_ptr_type);
2123 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));2031 return debug_ptr_type;
2124 return ptr_di_ty;
2125 }2032 }
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
2127 if (ty.isSlice(mod)) {2039 if (ty.isSlice(mod)) {
2128 const ptr_ty = ty.slicePtrFieldType(mod);2040 const ptr_ty = ty.slicePtrFieldType(mod);
2129 const len_ty = Type.usize;2041 const len_ty = Type.usize;
21302042
2131 const name = try o.allocTypeName(ty);2043 const name = try o.allocTypeName(ty);
2132 defer gpa.free(name);2044 defer gpa.free(name);
2133 const di_file: ?*llvm.DIFile = null;
2134 const line = 0;2045 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
2150 const ptr_size = ptr_ty.abiSize(mod);2047 const ptr_size = ptr_ty.abiSize(mod);
2151 const ptr_align = ptr_ty.abiAlignment(mod);2048 const ptr_align = ptr_ty.abiAlignment(mod);
2152 const len_size = len_ty.abiSize(mod);2049 const len_size = len_ty.abiSize(mod);
2153 const len_align = len_ty.abiAlignment(mod);2050 const len_align = len_ty.abiAlignment(mod);
21542051
2155 var offset: u64 = 0;2052 const len_offset = len_align.forward(ptr_size);
2156 offset += ptr_size;2053
2157 offset = len_align.forward(offset);2054 const debug_ptr_type = try o.builder.debugMemberType(
2158 const len_offset = offset;2055 try o.builder.string("ptr"),
21592056 Builder.Metadata.none, // File
2160 const fields: [2]*llvm.DIType = .{2057 debug_fwd_ref,
2161 dib.createMemberType(2058 0, // Line
2162 fwd_decl.toScope(),2059 try o.lowerDebugType(ptr_ty),
2163 "ptr",2060 ptr_size * 8,
2164 di_file,2061 ptr_align.toByteUnits(0) * 8,
2165 line,2062 0, // Offset
2166 ptr_size * 8, // size in bits2063 );
2167 ptr_align.toByteUnits(0) * 8, // align in bits2064
2168 0, // offset in bits2065 const debug_len_type = try o.builder.debugMemberType(
2169 0, // flags2066 try o.builder.string("len"),
2170 try o.lowerDebugType(ptr_ty, resolve),2067 Builder.Metadata.none, // File
2171 ),2068 debug_fwd_ref,
2172 dib.createMemberType(2069 0, // Line
2173 fwd_decl.toScope(),2070 try o.lowerDebugType(len_ty),
2174 "len",2071 len_size * 8,
2175 di_file,2072 len_align.toByteUnits(0) * 8,
2176 line,2073 len_offset * 8,
2177 len_size * 8, // size in bits2074 );
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 };
21842075
2185 const full_di_ty = dib.createStructType(2076 const debug_slice_type = try o.builder.debugStructType(
2186 compile_unit_scope,2077 try o.builder.string(name),
2187 name.ptr,2078 Builder.Metadata.none, // File
2188 di_file,2079 o.debug_compile_unit, // Scope
2189 line,2080 line,
2190 ty.abiSize(mod) * 8, // size in bits2081 Builder.Metadata.none, // Underlying type
2191 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2082 ty.abiSize(mod) * 8,
2192 0, // flags2083 ty.abiAlignment(mod).toByteUnits(0) * 8,
2193 null, // derived from2084 try o.builder.debugTuple(&.{
2194 &fields,2085 debug_ptr_type,
2195 fields.len,2086 debug_len_type,
2196 0, // run time lang2087 }),
2197 null, // vtable holder
2198 "", // unique id
2199 );2088 );
2200 dib.replaceTemporary(fwd_decl, full_di_ty);2089
2201 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2090 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type);
2202 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2091
2203 return full_di_ty;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;
2204 }2097 }
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
2207 const name = try o.allocTypeName(ty);2101 const name = try o.allocTypeName(ty);
2208 defer gpa.free(name);2102 defer gpa.free(name);
2209 const ptr_di_ty = dib.createPointerType(2103
2210 elem_di_ty,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,
2211 target.ptrBitWidth(),2110 target.ptrBitWidth(),
2212 ty.ptrAlignment(mod).toByteUnits(0) * 8,2111 ty.ptrAlignment(mod).toByteUnits(0) * 8,
2213 name,2112 0, // Offset
2214 );2113 );
2215 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2114
2216 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));2115 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_ptr_type);
2217 return ptr_di_ty;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;
2218 },2122 },
2219 .Opaque => {2123 .Opaque => {
2220 if (ty.toIntern() == .anyopaque_type) {2124 if (ty.toIntern() == .anyopaque_type) {
2221 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);2125 const debug_opaque_type = try o.builder.debugSignedType(
2222 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2126 try o.builder.string("anyopaque"),
2223 return di_ty;2127 0,
2128 );
2129 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2130 return debug_opaque_type;
2224 }2131 }
2132
2225 const name = try o.allocTypeName(ty);2133 const name = try o.allocTypeName(ty);
2226 defer gpa.free(name);2134 defer gpa.free(name);
2227 const owner_decl_index = ty.getOwnerDecl(mod);2135 const owner_decl_index = ty.getOwnerDecl(mod);
2228 const owner_decl = o.module.declPtr(owner_decl_index);2136 const owner_decl = o.module.declPtr(owner_decl_index);
2229 const opaque_di_ty = dib.createForwardDeclType(2137 const debug_opaque_type = try o.builder.debugStructType(
2230 DW.TAG.structure_type,2138 try o.builder.string(name),
2231 name,2139 try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope),
2232 try o.namespaceToDebugScope(owner_decl.src_namespace),2140 try o.namespaceToDebugScope(owner_decl.src_namespace),
2233 try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope),2141 owner_decl.src_node + 1, // Line
2234 owner_decl.src_node + 1,2142 Builder.Metadata.none, // Underlying type
2143 0, // Size
2144 0, // Align
2145 Builder.Metadata.none, // Fields
2235 );2146 );
2236 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`2147 try o.debug_type_map.put(gpa, ty, debug_opaque_type);
2237 // means we can't use `gop` anymore.2148 return debug_opaque_type;
2238 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty));
2239 return opaque_di_ty;
2240 },2149 },
2241 .Array => {2150 .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)),
2243 ty.abiSize(mod) * 8,2157 ty.abiSize(mod) * 8,
2244 ty.abiAlignment(mod).toByteUnits(0) * 8,2158 ty.abiAlignment(mod).toByteUnits(0) * 8,
2245 try o.lowerDebugType(ty.childType(mod), resolve),2159 try o.builder.debugTuple(&.{
2246 @intCast(ty.arrayLen(mod)),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 }),
2247 );2165 );
2248 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2166 try o.debug_type_map.put(gpa, ty, debug_array_type);
2249 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));2167 return debug_array_type;
2250 return array_di_ty;
2251 },2168 },
2252 .Vector => {2169 .Vector => {
2253 const elem_ty = ty.elemType2(mod);2170 const elem_ty = ty.elemType2(mod);
...@@ -2255,146 +2172,136 @@ pub const Object = struct {...@@ -2255,146 +2172,136 @@ pub const Object = struct {
2255 // @bitSizOf(elem) * len > @bitSizOf(vec).2172 // @bitSizOf(elem) * len > @bitSizOf(vec).
2256 // Neither gdb nor lldb seem to be able to display non-byte sized2173 // Neither gdb nor lldb seem to be able to display non-byte sized
2257 // vectors properly.2174 // vectors properly.
2258 const elem_di_type = switch (elem_ty.zigTypeTag(mod)) {2175 const debug_elem_type = switch (elem_ty.zigTypeTag(mod)) {
2259 .Int => blk: {2176 .Int => blk: {
2260 const info = elem_ty.intInfo(mod);2177 const info = elem_ty.intInfo(mod);
2261 assert(info.bits != 0);2178 assert(info.bits != 0);
2262 const name = try o.allocTypeName(ty);2179 const name = try o.allocTypeName(ty);
2263 defer gpa.free(name);2180 defer gpa.free(name);
2264 const dwarf_encoding: c_uint = switch (info.signedness) {2181 const builder_name = try o.builder.string(name);
2265 .signed => DW.ATE.signed,2182 break :blk switch (info.signedness) {
2266 .unsigned => DW.ATE.unsigned,2183 .signed => try o.builder.debugSignedType(builder_name, info.bits),
2184 .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),
2267 };2185 };
2268 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
2269 },2186 },
2270 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),2187 .Bool => try o.builder.debugBoolType(
2271 else => try o.lowerDebugType(ty.childType(mod), resolve),2188 try o.builder.string("bool"),
2189 1,
2190 ),
2191 else => try o.lowerDebugType(ty.childType(mod)),
2272 };2192 };
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,
2275 ty.abiSize(mod) * 8,2200 ty.abiSize(mod) * 8,
2276 @intCast(ty.abiAlignment(mod).toByteUnits(0) * 8),2201 ty.abiAlignment(mod).toByteUnits(0) * 8,
2277 elem_di_type,2202 try o.builder.debugTuple(&.{
2278 ty.vectorLen(mod),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 }),
2279 );2208 );
2280 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2209
2281 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty));2210 try o.debug_type_map.put(gpa, ty, debug_vector_type);
2282 return vector_di_ty;2211 return debug_vector_type;
2283 },2212 },
2284 .Optional => {2213 .Optional => {
2285 const name = try o.allocTypeName(ty);2214 const name = try o.allocTypeName(ty);
2286 defer gpa.free(name);2215 defer gpa.free(name);
2287 const child_ty = ty.optionalChild(mod);2216 const child_ty = ty.optionalChild(mod);
2288 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {2217 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2289 const di_bits = 8; // lldb cannot handle non-byte sized types2218 const debug_bool_type = try o.builder.debugBoolType(
2290 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);2219 try o.builder.string(name),
2291 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2220 8,
2292 return di_ty;2221 );
2222 try o.debug_type_map.put(gpa, ty, debug_bool_type);
2223 return debug_bool_type;
2293 }2224 }
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
2294 if (ty.optionalReprIsPayload(mod)) {2231 if (ty.optionalReprIsPayload(mod)) {
2295 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);2232 const debug_optional_type = try o.lowerDebugType(child_ty);
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 }
23002233
2301 const di_file: ?*llvm.DIFile = null;2234 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2302 const line = 0;2235
2303 const compile_unit_scope = o.di_compile_unit.?.toScope();2236 // Set to real type now that it has been lowered fully
2304 const fwd_decl = opt_fwd_decl orelse blk: {2237 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2305 const fwd_decl = dib.createReplaceableCompositeType(2238 map_ptr.* = debug_optional_type;
2306 DW.TAG.structure_type,2239
2307 name.ptr,2240 return debug_optional_type;
2308 compile_unit_scope,2241 }
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 };
23162242
2317 const non_null_ty = Type.u8;2243 const non_null_ty = Type.u8;
2318 const payload_size = child_ty.abiSize(mod);2244 const payload_size = child_ty.abiSize(mod);
2319 const payload_align = child_ty.abiAlignment(mod);2245 const payload_align = child_ty.abiAlignment(mod);
2320 const non_null_size = non_null_ty.abiSize(mod);2246 const non_null_size = non_null_ty.abiSize(mod);
2321 const non_null_align = non_null_ty.abiAlignment(mod);2247 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;2261 const debug_some_type = try o.builder.debugMemberType(
2324 offset += payload_size;2262 try o.builder.string("some"),
2325 offset = non_null_align.forward(offset);2263 Builder.Metadata.none,
2326 const non_null_offset = offset;2264 debug_fwd_ref,
23272265 0,
2328 const fields: [2]*llvm.DIType = .{2266 try o.lowerDebugType(non_null_ty),
2329 dib.createMemberType(2267 non_null_size * 8,
2330 fwd_decl.toScope(),2268 non_null_align.toByteUnits(0) * 8,
2331 "data",2269 non_null_offset * 8,
2332 di_file,2270 );
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 };
23522271
2353 const full_di_ty = dib.createStructType(2272 const debug_optional_type = try o.builder.debugStructType(
2354 compile_unit_scope,2273 try o.builder.string(name),
2355 name.ptr,2274 Builder.Metadata.none, // File
2356 di_file,2275 o.debug_compile_unit, // Scope
2357 line,2276 0, // Line
2358 ty.abiSize(mod) * 8, // size in bits2277 Builder.Metadata.none, // Underlying type
2359 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2278 ty.abiSize(mod) * 8,
2360 0, // flags2279 ty.abiAlignment(mod).toByteUnits(0) * 8,
2361 null, // derived from2280 try o.builder.debugTuple(&.{
2362 &fields,2281 debug_data_type,
2363 fields.len,2282 debug_some_type,
2364 0, // run time lang2283 }),
2365 null, // vtable holder
2366 "", // unique id
2367 );2284 );
2368 dib.replaceTemporary(fwd_decl, full_di_ty);2285
2369 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2286 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
2370 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2287
2371 return full_di_ty;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;
2372 },2293 },
2373 .ErrorUnion => {2294 .ErrorUnion => {
2374 const payload_ty = ty.errorUnionPayload(mod);2295 const payload_ty = ty.errorUnionPayload(mod);
2375 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {2296 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2376 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, resolve);2297 // TODO: Maybe remove?
2377 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2298 const debug_error_union_type = try o.lowerDebugType(Type.anyerror);
2378 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));2299 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2379 return err_set_di_ty;2300 return debug_error_union_type;
2380 }2301 }
2302
2381 const name = try o.allocTypeName(ty);2303 const name = try o.allocTypeName(ty);
2382 defer gpa.free(name);2304 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
2399 const error_size = Type.anyerror.abiSize(mod);2306 const error_size = Type.anyerror.abiSize(mod);
2400 const error_align = Type.anyerror.abiAlignment(mod);2307 const error_align = Type.anyerror.abiAlignment(mod);
...@@ -2417,59 +2324,55 @@ pub const Object = struct {...@@ -2417,59 +2324,55 @@ pub const Object = struct {
2417 error_offset = error_align.forward(payload_size);2324 error_offset = error_align.forward(payload_size);
2418 }2325 }
24192326
2420 var fields: [2]*llvm.DIType = undefined;2327 const debug_fwd_ref = try o.builder.debugForwardReference();
2421 fields[error_index] = dib.createMemberType(2328
2422 fwd_decl.toScope(),2329 var fields: [2]Builder.Metadata = undefined;
2423 "tag",2330 fields[error_index] = try o.builder.debugMemberType(
2424 di_file,2331 try o.builder.string("tag"),
2425 line,2332 Builder.Metadata.none, // File
2426 error_size * 8, // size in bits2333 debug_fwd_ref,
2427 error_align.toByteUnits(0) * 8, // align in bits2334 0, // Line
2428 error_offset * 8, // offset in bits2335 try o.lowerDebugType(Type.anyerror),
2429 0, // flags2336 error_size * 8,
2430 try o.lowerDebugType(Type.anyerror, resolve),2337 error_align.toByteUnits(0) * 8,
2338 error_offset * 8,
2431 );2339 );
2432 fields[payload_index] = dib.createMemberType(2340 fields[payload_index] = try o.builder.debugMemberType(
2433 fwd_decl.toScope(),2341 try o.builder.string("value"),
2434 "value",2342 Builder.Metadata.none, // File
2435 di_file,2343 debug_fwd_ref,
2436 line,2344 0, // Line
2437 payload_size * 8, // size in bits2345 try o.lowerDebugType(payload_ty),
2438 payload_align.toByteUnits(0) * 8, // align in bits2346 payload_size * 8,
2439 payload_offset * 8, // offset in bits2347 payload_align.toByteUnits(0) * 8,
2440 0, // flags2348 payload_offset * 8,
2441 try o.lowerDebugType(payload_ty, resolve),
2442 );2349 );
24432350
2444 const full_di_ty = dib.createStructType(2351 const debug_error_union_type = try o.builder.debugStructType(
2445 compile_unit_scope,2352 try o.builder.string(name),
2446 name.ptr,2353 Builder.Metadata.none, // File
2447 di_file,2354 o.debug_compile_unit, // Sope
2448 line,2355 0, // Line
2449 ty.abiSize(mod) * 8, // size in bits2356 Builder.Metadata.none, // Underlying type
2450 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2357 ty.abiSize(mod) * 8,
2451 0, // flags2358 ty.abiAlignment(mod).toByteUnits(0) * 8,
2452 null, // derived from2359 try o.builder.debugTuple(&fields),
2453 &fields,
2454 fields.len,
2455 0, // run time lang
2456 null, // vtable holder
2457 "", // unique id
2458 );2360 );
2459 dib.replaceTemporary(fwd_decl, full_di_ty);2361
2460 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2362 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type);
2461 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2363
2462 return full_di_ty;2364 try o.debug_type_map.put(gpa, ty, debug_error_union_type);
2365 return debug_error_union_type;
2463 },2366 },
2464 .ErrorSet => {2367 .ErrorSet => {
2465 // TODO make this a proper enum with all the error codes in it.2368 const debug_error_set = try o.builder.debugUnsignedType(
2466 // will need to consider how to take incremental compilation into account.2369 try o.builder.string("anyerror"),
2467 const di_ty = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);2370 16,
2468 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);2371 );
2469 return di_ty;2372 try o.debug_type_map.put(gpa, ty, debug_error_set);
2373 return debug_error_set;
2470 },2374 },
2471 .Struct => {2375 .Struct => {
2472 const compile_unit_scope = o.di_compile_unit.?.toScope();
2473 const name = try o.allocTypeName(ty);2376 const name = try o.allocTypeName(ty);
2474 defer gpa.free(name);2377 defer gpa.free(name);
24752378
...@@ -2477,40 +2380,28 @@ pub const Object = struct {...@@ -2477,40 +2380,28 @@ pub const Object = struct {
2477 const backing_int_ty = struct_type.backingIntType(ip).*;2380 const backing_int_ty = struct_type.backingIntType(ip).*;
2478 if (backing_int_ty != .none) {2381 if (backing_int_ty != .none) {
2479 const info = Type.fromInterned(backing_int_ty).intInfo(mod);2382 const info = Type.fromInterned(backing_int_ty).intInfo(mod);
2480 const dwarf_encoding: c_uint = switch (info.signedness) {2383 const builder_name = try o.builder.string(name);
2481 .signed => DW.ATE.signed,2384 const debug_int_type = switch (info.signedness) {
2482 .unsigned => DW.ATE.unsigned,2385 .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(mod) * 8),
2386 .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(mod) * 8),
2483 };2387 };
2484 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types2388 try o.debug_type_map.put(gpa, ty, debug_int_type);
2485 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);2389 return debug_int_type;
2486 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
2487 return di_ty;
2488 }2390 }
2489 }2391 }
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
2504 switch (ip.indexToKey(ty.toIntern())) {2393 switch (ip.indexToKey(ty.toIntern())) {
2505 .anon_struct_type => |tuple| {2394 .anon_struct_type => |tuple| {
2506 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2395 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2507 defer di_fields.deinit(gpa);2396 defer fields.deinit(gpa);
25082397
2509 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);2398 try fields.ensureUnusedCapacity(gpa, tuple.types.len);
25102399
2511 comptime assert(struct_layout_version == 2);2400 comptime assert(struct_layout_version == 2);
2512 var offset: u64 = 0;2401 var offset: u64 = 0;
25132402
2403 const debug_fwd_ref = try o.builder.debugForwardReference();
2404
2514 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {2405 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
2515 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;2406 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
25162407
...@@ -2525,38 +2416,33 @@ pub const Object = struct {...@@ -2525,38 +2416,33 @@ pub const Object = struct {
2525 try std.fmt.allocPrintZ(gpa, "{d}", .{i});2416 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2526 defer if (tuple.names.len == 0) gpa.free(field_name);2417 defer if (tuple.names.len == 0) gpa.free(field_name);
25272418
2528 try di_fields.append(gpa, dib.createMemberType(2419 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2529 fwd_decl.toScope(),2420 try o.builder.string(field_name),
2530 field_name,2421 Builder.Metadata.none, // File
2531 null, // file2422 debug_fwd_ref,
2532 0, // line2423 0,
2533 field_size * 8, // size in bits2424 try o.lowerDebugType(Type.fromInterned(field_ty)),
2534 field_align.toByteUnits(0) * 8, // align in bits2425 field_size * 8,
2535 field_offset * 8, // offset in bits2426 field_align.toByteUnits(0) * 8,
2536 0, // flags2427 field_offset * 8,
2537 try o.lowerDebugType(Type.fromInterned(field_ty), resolve),
2538 ));2428 ));
2539 }2429 }
25402430
2541 const full_di_ty = dib.createStructType(2431 const debug_struct_type = try o.builder.debugStructType(
2542 compile_unit_scope,2432 try o.builder.string(name),
2543 name.ptr,2433 Builder.Metadata.none, // File
2544 null, // file2434 o.debug_compile_unit, // Scope
2545 0, // line2435 0, // Line
2546 ty.abiSize(mod) * 8, // size in bits2436 Builder.Metadata.none, // Underlying type
2547 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2437 ty.abiSize(mod) * 8,
2548 0, // flags2438 ty.abiAlignment(mod).toByteUnits(0) * 8,
2549 null, // derived from2439 try o.builder.debugTuple(fields.items),
2550 di_fields.items.ptr,
2551 @intCast(di_fields.items.len),
2552 0, // run time lang
2553 null, // vtable holder
2554 "", // unique id
2555 );2440 );
2556 dib.replaceTemporary(fwd_decl, full_di_ty);2441
2557 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2442 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2558 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2443
2559 return full_di_ty;2444 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2445 return debug_struct_type;
2560 },2446 },
2561 .struct_type => |struct_type| {2447 .struct_type => |struct_type| {
2562 if (!struct_type.haveFieldTypes(ip)) {2448 if (!struct_type.haveFieldTypes(ip)) {
...@@ -2568,12 +2454,9 @@ pub const Object = struct {...@@ -2568,12 +2454,9 @@ pub const Object = struct {
2568 // rather than changing the frontend to unnecessarily resolve the2454 // rather than changing the frontend to unnecessarily resolve the
2569 // struct field types.2455 // struct field types.
2570 const owner_decl_index = ty.getOwnerDecl(mod);2456 const owner_decl_index = ty.getOwnerDecl(mod);
2571 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2457 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2572 dib.replaceTemporary(fwd_decl, struct_di_ty);2458 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2573 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2459 return debug_struct_type;
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;
2577 }2460 }
2578 },2461 },
2579 else => {},2462 else => {},
...@@ -2581,20 +2464,22 @@ pub const Object = struct {...@@ -2581,20 +2464,22 @@ pub const Object = struct {
25812464
2582 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {2465 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2583 const owner_decl_index = ty.getOwnerDecl(mod);2466 const owner_decl_index = ty.getOwnerDecl(mod);
2584 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2467 const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2585 dib.replaceTemporary(fwd_decl, struct_di_ty);2468 try o.debug_type_map.put(gpa, ty, debug_struct_type);
2586 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2469 return debug_struct_type;
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;
2590 }2470 }
25912471
2592 const struct_type = mod.typeToStruct(ty).?;2472 const struct_type = mod.typeToStruct(ty).?;
25932473
2594 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2474 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2595 defer di_fields.deinit(gpa);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
2599 comptime assert(struct_layout_version == 2);2484 comptime assert(struct_layout_version == 2);
2600 var it = struct_type.iterateRuntimeOrder(ip);2485 var it = struct_type.iterateRuntimeOrder(ip);
...@@ -2612,103 +2497,88 @@ pub const Object = struct {...@@ -2612,103 +2497,88 @@ pub const Object = struct {
2612 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse2497 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
2613 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});2498 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});
26142499
2615 const field_di_ty = try o.lowerDebugType(field_ty, resolve);2500 fields.appendAssumeCapacity(try o.builder.debugMemberType(
26162501 try o.builder.string(ip.stringToSlice(field_name)),
2617 try di_fields.append(gpa, dib.createMemberType(2502 Builder.Metadata.none, // File
2618 fwd_decl.toScope(),2503 debug_fwd_ref,
2619 ip.stringToSlice(field_name),2504 0, // Line
2620 null, // file2505 try o.lowerDebugType(field_ty),
2621 0, // line2506 field_size * 8,
2622 field_size * 8, // size in bits2507 field_align.toByteUnits(0) * 8,
2623 field_align.toByteUnits(0) * 8, // align in bits2508 field_offset * 8,
2624 field_offset * 8, // offset in bits
2625 0, // flags
2626 field_di_ty,
2627 ));2509 ));
2628 }2510 }
26292511
2630 const full_di_ty = dib.createStructType(2512 const debug_struct_type = try o.builder.debugStructType(
2631 compile_unit_scope,2513 try o.builder.string(name),
2632 name.ptr,2514 Builder.Metadata.none, // File
2633 null, // file2515 o.debug_compile_unit, // Scope
2634 0, // line2516 0, // Line
2635 ty.abiSize(mod) * 8, // size in bits2517 Builder.Metadata.none, // Underlying type
2636 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2518 ty.abiSize(mod) * 8,
2637 0, // flags2519 ty.abiAlignment(mod).toByteUnits(0) * 8,
2638 null, // derived from2520 try o.builder.debugTuple(fields.items),
2639 di_fields.items.ptr,
2640 @intCast(di_fields.items.len),
2641 0, // run time lang
2642 null, // vtable holder
2643 "", // unique id
2644 );2521 );
2645 dib.replaceTemporary(fwd_decl, full_di_ty);2522
2646 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2523 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type);
2647 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2524
2648 return full_di_ty;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;
2649 },2530 },
2650 .Union => {2531 .Union => {
2651 const compile_unit_scope = o.di_compile_unit.?.toScope();
2652 const owner_decl_index = ty.getOwnerDecl(mod);2532 const owner_decl_index = ty.getOwnerDecl(mod);
26532533
2654 const name = try o.allocTypeName(ty);2534 const name = try o.allocTypeName(ty);
2655 defer gpa.free(name);2535 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
2670 const union_type = ip.indexToKey(ty.toIntern()).union_type;2537 const union_type = ip.indexToKey(ty.toIntern()).union_type;
2671 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {2538 if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
2672 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);2539 const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index);
2673 dib.replaceTemporary(fwd_decl, union_di_ty);2540 try o.debug_type_map.put(gpa, ty, debug_union_type);
2674 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2541 return debug_union_type;
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;
2678 }2542 }
26792543
2680 const union_obj = ip.loadUnionType(union_type);2544 const union_obj = ip.loadUnionType(union_type);
2681 const layout = mod.getUnionLayout(union_obj);2545 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
2683 if (layout.payload_size == 0) {2552 if (layout.payload_size == 0) {
2684 const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve);2553 const debug_union_type = try o.builder.debugStructType(
2685 const di_fields = [_]*llvm.DIType{tag_di_ty};2554 try o.builder.string(name),
2686 const full_di_ty = dib.createStructType(2555 Builder.Metadata.none, // File
2687 compile_unit_scope,2556 o.debug_compile_unit, // Scope
2688 name.ptr,2557 0, // Line
2689 null, // file2558 Builder.Metadata.none, // Underlying type
2690 0, // line2559 ty.abiSize(mod) * 8,
2691 ty.abiSize(mod) * 8, // size in bits2560 ty.abiAlignment(mod).toByteUnits(0) * 8,
2692 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2561 try o.builder.debugTuple(
2693 0, // flags2562 &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))},
2694 null, // derived from2563 ),
2695 &di_fields,
2696 di_fields.len,
2697 0, // run time lang
2698 null, // vtable holder
2699 "", // unique id
2700 );2564 );
2701 dib.replaceTemporary(fwd_decl, full_di_ty);2565
2702 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`2566 // Set to real type now that it has been lowered fully
2703 // means we can't use `gop` anymore.2567 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2704 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2568 map_ptr.* = debug_union_type;
2705 return full_di_ty;2569
2570 return debug_union_type;
2706 }2571 }
27072572
2708 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};2573 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{};
2709 defer di_fields.deinit(gpa);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
2713 for (0..union_obj.field_names.len) |field_index| {2583 for (0..union_obj.field_names.len) |field_index| {
2714 const field_ty = union_obj.field_types.get(ip)[field_index];2584 const field_ty = union_obj.field_types.get(ip)[field_index];
...@@ -2717,18 +2587,16 @@ pub const Object = struct {...@@ -2717,18 +2587,16 @@ pub const Object = struct {
2717 const field_size = Type.fromInterned(field_ty).abiSize(mod);2587 const field_size = Type.fromInterned(field_ty).abiSize(mod);
2718 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));2588 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));
27192589
2720 const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), resolve);
2721 const field_name = union_obj.field_names.get(ip)[field_index];2590 const field_name = union_obj.field_names.get(ip)[field_index];
2722 di_fields.appendAssumeCapacity(dib.createMemberType(2591 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2723 fwd_decl.toScope(),2592 try o.builder.string(ip.stringToSlice(field_name)),
2724 ip.stringToSlice(field_name),2593 Builder.Metadata.none, // File
2725 null, // file2594 debug_union_fwd_ref,
2726 0, // line2595 0, // Line
2727 field_size * 8, // size in bits2596 try o.lowerDebugType(Type.fromInterned(field_ty)),
2728 field_align.toByteUnits(0) * 8, // align in bits2597 field_size * 8,
2729 0, // offset in bits2598 field_align.toByteUnits(0) * 8,
2730 0, // flags2599 0, // Offset
2731 field_di_ty,
2732 ));2600 ));
2733 }2601 }
27342602
...@@ -2739,25 +2607,25 @@ pub const Object = struct {...@@ -2739,25 +2607,25 @@ pub const Object = struct {
2739 break :name union_name_buf.?;2607 break :name union_name_buf.?;
2740 };2608 };
27412609
2742 const union_di_ty = dib.createUnionType(2610 const debug_union_type = try o.builder.debugUnionType(
2743 compile_unit_scope,2611 try o.builder.string(union_name),
2744 union_name.ptr,2612 Builder.Metadata.none, // File
2745 null, // file2613 o.debug_compile_unit, // Scope
2746 0, // line2614 0, // Line
2747 ty.abiSize(mod) * 8, // size in bits2615 Builder.Metadata.none, // Underlying type
2748 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2616 ty.abiSize(mod) * 8,
2749 0, // flags2617 ty.abiAlignment(mod).toByteUnits(0) * 8,
2750 di_fields.items.ptr,2618 try o.builder.debugTuple(fields.items),
2751 @intCast(di_fields.items.len),
2752 0, // run time lang
2753 "", // unique id
2754 );2619 );
27552620
2621 o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type);
2622
2756 if (layout.tag_size == 0) {2623 if (layout.tag_size == 0) {
2757 dib.replaceTemporary(fwd_decl, union_di_ty);2624 // Set to real type now that it has been lowered fully
2758 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2625 const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable;
2759 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));2626 map_ptr.* = debug_union_type;
2760 return union_di_ty;2627
2628 return debug_union_type;
2761 }2629 }
27622630
2763 var tag_offset: u64 = undefined;2631 var tag_offset: u64 = undefined;
...@@ -2770,81 +2638,80 @@ pub const Object = struct {...@@ -2770,81 +2638,80 @@ pub const Object = struct {
2770 tag_offset = layout.tag_align.forward(layout.payload_size);2638 tag_offset = layout.tag_align.forward(layout.payload_size);
2771 }2639 }
27722640
2773 const tag_di = dib.createMemberType(2641 const debug_tag_type = try o.builder.debugMemberType(
2774 fwd_decl.toScope(),2642 try o.builder.string("tag"),
2775 "tag",2643 Builder.Metadata.none, // File
2776 null, // file2644 debug_fwd_ref,
2777 0, // line2645 0, // Line
2646 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)),
2778 layout.tag_size * 8,2647 layout.tag_size * 8,
2779 layout.tag_align.toByteUnits(0) * 8,2648 layout.tag_align.toByteUnits(0) * 8,
2780 tag_offset * 8, // offset in bits2649 tag_offset * 8,
2781 0, // flags
2782 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve),
2783 );2650 );
27842651
2785 const payload_di = dib.createMemberType(2652 const debug_payload_type = try o.builder.debugMemberType(
2786 fwd_decl.toScope(),2653 try o.builder.string("payload"),
2787 "payload",2654 Builder.Metadata.none, // File
2788 null, // file2655 debug_fwd_ref,
2789 0, // line2656 0, // Line
2790 layout.payload_size * 8, // size in bits2657 debug_union_type,
2658 layout.payload_size * 8,
2791 layout.payload_align.toByteUnits(0) * 8,2659 layout.payload_align.toByteUnits(0) * 8,
2792 payload_offset * 8, // offset in bits2660 payload_offset * 8,
2793 0, // flags
2794 union_di_ty,
2795 );2661 );
27962662
2797 const full_di_fields: [2]*llvm.DIType =2663 const full_fields: [2]Builder.Metadata =
2798 if (layout.tag_align.compare(.gte, layout.payload_align))2664 if (layout.tag_align.compare(.gte, layout.payload_align))
2799 .{ tag_di, payload_di }2665 .{ debug_tag_type, debug_payload_type }
2800 else2666 else
2801 .{ payload_di, tag_di };2667 .{ debug_payload_type, debug_tag_type };
28022668
2803 const full_di_ty = dib.createStructType(2669 const debug_tagged_union_type = try o.builder.debugStructType(
2804 compile_unit_scope,2670 try o.builder.string(name),
2805 name.ptr,2671 Builder.Metadata.none, // File
2806 null, // file2672 o.debug_compile_unit, // Scope
2807 0, // line2673 0, // Line
2808 ty.abiSize(mod) * 8, // size in bits2674 Builder.Metadata.none, // Underlying type
2809 ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits2675 ty.abiSize(mod) * 8,
2810 0, // flags2676 ty.abiAlignment(mod).toByteUnits(0) * 8,
2811 null, // derived from2677 try o.builder.debugTuple(&full_fields),
2812 &full_di_fields,
2813 full_di_fields.len,
2814 0, // run time lang
2815 null, // vtable holder
2816 "", // unique id
2817 );2678 );
2818 dib.replaceTemporary(fwd_decl, full_di_ty);2679
2819 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2680 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type);
2820 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));2681
2821 return full_di_ty;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;
2822 },2687 },
2823 .Fn => {2688 .Fn => {
2824 const fn_info = mod.typeToFunc(ty).?;2689 const fn_info = mod.typeToFunc(ty).?;
28252690
2826 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);2691 var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa);
2827 defer param_di_types.deinit();2692 defer debug_param_types.deinit();
2693
2694 try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);
28282695
2829 // Return type goes first.2696 // Return type goes first.
2830 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {2697 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {
2831 const sret = firstParamSRet(fn_info, mod);2698 const sret = firstParamSRet(fn_info, mod);
2832 const di_ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);2699 const 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));2700 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty));
28342701
2835 if (sret) {2702 if (sret) {
2836 const ptr_ty = try mod.singleMutPtrType(Type.fromInterned(fn_info.return_type));2703 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));
2838 }2705 }
2839 } else {2706 } else {
2840 try param_di_types.append(try o.lowerDebugType(Type.void, resolve));2707 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
2841 }2708 }
28422709
2843 if (Type.fromInterned(fn_info.return_type).isError(mod) and2710 if (Type.fromInterned(fn_info.return_type).isError(mod) and
2844 o.module.comp.config.any_error_tracing)2711 o.module.comp.config.any_error_tracing)
2845 {2712 {
2846 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());2713 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));
2848 }2715 }
28492716
2850 for (0..fn_info.param_types.len) |i| {2717 for (0..fn_info.param_types.len) |i| {
...@@ -2853,20 +2720,18 @@ pub const Object = struct {...@@ -2853,20 +2720,18 @@ pub const Object = struct {
28532720
2854 if (isByRef(param_ty, mod)) {2721 if (isByRef(param_ty, mod)) {
2855 const ptr_ty = try mod.singleMutPtrType(param_ty);2722 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));
2857 } else {2724 } else {
2858 try param_di_types.append(try o.lowerDebugType(param_ty, resolve));2725 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty));
2859 }2726 }
2860 }2727 }
28612728
2862 const fn_di_ty = dib.createSubroutineType(2729 const debug_function_type = try o.builder.debugSubroutineType(
2863 param_di_types.items.ptr,2730 try o.builder.debugTuple(debug_param_types.items),
2864 @intCast(param_di_types.items.len),
2865 0,
2866 );2731 );
2867 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.2732
2868 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty));2733 try o.debug_type_map.put(gpa, ty, debug_function_type);
2869 return fn_di_ty;2734 return debug_function_type;
2870 },2735 },
2871 .ComptimeInt => unreachable,2736 .ComptimeInt => unreachable,
2872 .ComptimeFloat => unreachable,2737 .ComptimeFloat => unreachable,
...@@ -2880,39 +2745,30 @@ pub const Object = struct {...@@ -2880,39 +2745,30 @@ pub const Object = struct {
2880 }2745 }
2881 }2746 }
28822747
2883 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !*llvm.DIScope {2748 fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
2884 const mod = o.module;2749 const mod = o.module;
2885 const namespace = mod.namespacePtr(namespace_index);2750 const namespace = mod.namespacePtr(namespace_index);
2886 if (namespace.parent == .none) {2751 if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope);
2887 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);2752
2888 return di_file.toScope();2753 const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);
2889 }2754
2890 const di_type = try o.lowerDebugType(namespace.ty, .fwd);2755 if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();
2891 return di_type.toScope();2756
2757 return gop.value_ptr.*;
2892 }2758 }
28932759
2894 /// This is to be used instead of void for debug info types, to avoid tripping2760 fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata {
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 {
2898 const mod = o.module;2761 const mod = o.module;
2899 const decl = mod.declPtr(decl_index);2762 const decl = mod.declPtr(decl_index);
2900 const fields: [0]*llvm.DIType = .{};2763 return o.builder.debugStructType(
2901 const di_scope = try o.namespaceToDebugScope(decl.src_namespace);2764 try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name
2902 return o.di_builder.?.createStructType(2765 try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope),
2903 di_scope,2766 try o.namespaceToDebugScope(decl.src_namespace),
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),
2906 decl.src_line + 1,2767 decl.src_line + 1,
2907 0, // size in bits2768 Builder.Metadata.none,
2908 0, // align in bits2769 0,
2909 0, // flags2770 0,
2910 null, // derived from2771 .none,
2911 undefined, // TODO should be able to pass &fields,
2912 fields.len,
2913 0, // run time lang
2914 null, // vtable holder
2915 "", // unique id
2916 );2772 );
2917 }2773 }
29182774
...@@ -4822,26 +4678,32 @@ pub const DeclGen = struct {...@@ -4822,26 +4678,32 @@ pub const DeclGen = struct {
4822 else => try o.lowerValue(init_val),4678 else => try o.lowerValue(init_val),
4823 }, &o.builder);4679 }, &o.builder);
48244680
4825 if (o.di_builder) |dib| {4681 const line_number = decl.src_line + 1;
4826 const di_file =4682 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
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 );
48404683
4841 try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode());4684 if (dg.object.builder.strip) return;
4842 if (!is_internal_linkage or decl.isExtern(mod))4685
4843 variable_index.toLlvm(&o.builder).attachMetaData(di_global);4686 const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
4844 }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);
4845 }4707 }
4846 }4708 }
4847};4709};
...@@ -4852,19 +4714,23 @@ pub const FuncGen = struct {...@@ -4852,19 +4714,23 @@ pub const FuncGen = struct {
4852 air: Air,4714 air: Air,
4853 liveness: Liveness,4715 liveness: Liveness,
4854 wip: Builder.WipFunction,4716 wip: Builder.WipFunction,
4855 di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn,4717
4856 di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn,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
4857 base_line: u32,4730 base_line: u32,
4858 prev_dbg_line: c_uint,4731 prev_dbg_line: c_uint,
4859 prev_dbg_column: c_uint,4732 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
4868 /// This stores the LLVM values used in a function, such that they can be referred to4734 /// This stores the LLVM values used in a function, such that they can be referred to
4869 /// in other instructions. This table is cleared before every function is generated.4735 /// in other instructions. This table is cleared before every function is generated.
4870 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value),4736 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value),
...@@ -4905,8 +4771,8 @@ pub const FuncGen = struct {...@@ -4905,8 +4771,8 @@ pub const FuncGen = struct {
49054771
4906 fn deinit(self: *FuncGen) void {4772 fn deinit(self: *FuncGen) void {
4907 self.wip.deinit();4773 self.wip.deinit();
4908 self.dbg_inlined.deinit(self.gpa);4774 self.scope_stack.deinit(self.gpa);
4909 self.dbg_block_stack.deinit(self.gpa);4775 self.inlined.deinit(self.gpa);
4910 self.func_inst_table.deinit(self.gpa);4776 self.func_inst_table.deinit(self.gpa);
4911 self.blocks.deinit(self.gpa);4777 self.blocks.deinit(self.gpa);
4912 }4778 }
...@@ -5515,9 +5381,6 @@ pub const FuncGen = struct {...@@ -5515,9 +5381,6 @@ pub const FuncGen = struct {
5515 // a different LLVM type than the usual one. We solve this here at the callsite5381 // a different LLVM type than the usual one. We solve this here at the callsite
5516 // by using our canonical type, then loading it if necessary.5382 // by using our canonical type, then loading it if necessary.
5517 const alignment = return_type.abiAlignment(mod).toLlvm();5383 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)));
5521 const rp = try self.buildAlloca(abi_ret_ty, alignment);5384 const rp = try self.buildAlloca(abi_ret_ty, alignment);
5522 _ = try self.wip.store(.normal, call, rp, alignment);5385 _ = try self.wip.store(.normal, call, rp, alignment);
5523 return if (isByRef(return_type, mod))5386 return if (isByRef(return_type, mod))
...@@ -6675,42 +6538,48 @@ pub const FuncGen = struct {...@@ -6675,42 +6538,48 @@ pub const FuncGen = struct {
6675 }6538 }
66766539
6677 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6540 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;
6679 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;6542 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
6680 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);6543 self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
6681 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);6544 self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
6682 const inlined_at = if (self.dbg_inlined.items.len > 0)6545 const inlined_at = if (self.inlined.items.len > 0)
6683 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6546 self.inlined.items[self.inlined.items.len - 1].location
6684 else6547 else
6685 null;6548 Builder.Metadata.none;
6686 self.wip.llvm.builder.setCurrentDebugLocation(6549
6687 self.prev_dbg_line,6550 self.wip.current_debug_location = .{
6688 self.prev_dbg_column,6551 .line = self.prev_dbg_line,
6689 di_scope,6552 .column = self.prev_dbg_column,
6690 inlined_at,6553 .scope = self.current_scope,
6691 );6554 .inlined_at = inlined_at,
6555 };
6556
6692 return .none;6557 return .none;
6693 }6558 }
66946559
6695 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6560 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6561 if (self.wip.builder.strip or true) return .none;
6696 const o = self.dg.object;6562 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
6700 const zcu = o.module;6563 const zcu = o.module;
6564
6565 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
6701 const func = zcu.funcInfo(ty_fn.func);6566 const func = zcu.funcInfo(ty_fn.func);
6702 const decl_index = func.owner_decl;6567 const decl_index = func.owner_decl;
6703 const decl = zcu.declPtr(decl_index);6568 const decl = zcu.declPtr(decl_index);
6704 const namespace = zcu.namespacePtr(decl.src_namespace);6569 const namespace = zcu.namespacePtr(decl.src_namespace);
6705 const owner_mod = namespace.file_scope.mod;6570 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, .{6572 self.file = try o.getDebugFile(namespace.file_scope);
6712 .loc = @ptrCast(cur_debug_location),6573
6713 .scope = self.di_scope.?,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,
6714 .base_line = self.base_line,6583 .base_line = self.base_line,
6715 });6584 });
67166585
...@@ -6721,91 +6590,108 @@ pub const FuncGen = struct {...@@ -6721,91 +6590,108 @@ pub const FuncGen = struct {
6721 .param_types = &.{},6590 .param_types = &.{},
6722 .return_type = .void_type,6591 .return_type = .void_type,
6723 });6592 });
6724 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);6593
6725 const subprogram = dib.createFunction(6594 const subprogram = try o.builder.debugSubprogram(
6726 di_file.toScope(),6595 self.file,
6727 zcu.intern_pool.stringToSlice(decl.name),6596 try o.builder.string(zcu.intern_pool.stringToSlice(decl.name)),
6728 zcu.intern_pool.stringToSlice(fqn),6597 try o.builder.string(zcu.intern_pool.stringToSlice(fqn)),
6729 di_file,
6730 line_number,6598 line_number,
6731 fn_di_ty,6599 line_number + func.lbrace_line,
6732 is_internal_linkage,6600 try o.lowerDebugType(fn_ty),
6733 true, // is definition6601 .{
6734 line_number + func.lbrace_line, // scope line6602 .optimized = owner_mod.optimize_mode != .Debug,
6735 llvm.DIFlags.StaticMember,6603 .local = is_internal_linkage,
6736 owner_mod.optimize_mode != .Debug,6604 .definition = true,
6737 null, // decl_subprogram6605 .debug_info_flags = llvm.DIFlags.StaticMember,
6606 },
6607 o.debug_compile_unit,
6738 );6608 );
67396609
6740 const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1);6610 const lexical_block = try o.builder.debugLexicalBlock(
6741 self.di_scope = lexical_block.toScope();6611 subprogram,
6612 self.file,
6613 line_number,
6614 1,
6615 );
6616 self.current_scope = lexical_block;
6742 self.base_line = decl.src_line;6617 self.base_line = decl.src_line;
6743 return .none;6618 return .none;
6744 }6619 }
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;
6747 const o = self.dg.object;6623 const o = self.dg.object;
6748 if (o.di_builder == null) return .none;6624
6749 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;6625 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
67506626
6751 const mod = o.module;6627 const mod = o.module;
6752 const decl = mod.funcOwnerDeclPtr(ty_fn.func);6628 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
6753 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6629 self.file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
6754 self.di_file = di_file;6630
6755 const old = self.dbg_inlined.pop();6631 const old = self.inlined.pop();
6756 self.di_scope = old.scope;6632 self.current_scope = old.scope;
6757 self.base_line = old.base_line;6633 self.base_line = old.base_line;
6758 return .none;6634 return .none;
6759 }6635 }
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;
6762 const o = self.dg.object;6639 const o = self.dg.object;
6763 const dib = o.di_builder orelse return .none;6640
6764 const old_scope = self.di_scope.?;6641 try self.scope_stack.append(self.gpa, self.current_scope);
6765 try self.dbg_block_stack.append(self.gpa, old_scope);6642
6766 const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column);6643 const old = self.current_scope;
6767 self.di_scope = lexical_block.toScope();6644 self.current_scope = try o.builder.debugLexicalBlock(
6645 self.file,
6646 old,
6647 self.prev_dbg_line,
6648 self.prev_dbg_column,
6649 );
6768 return .none;6650 return .none;
6769 }6651 }
67706652
6771 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {6653 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6772 const o = self.dg.object;6654 if (self.wip.builder.strip) return .none;
6773 if (o.di_builder == null) return .none;6655 self.current_scope = self.scope_stack.pop();
6774 self.di_scope = self.dbg_block_stack.pop();
6775 return .none;6656 return .none;
6776 }6657 }
67776658
6778 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6659 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6660 if (self.wip.builder.strip) return .none;
6779 const o = self.dg.object;6661 const o = self.dg.object;
6780 const mod = o.module;6662 const mod = o.module;
6781 const dib = o.di_builder orelse return .none;
6782 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6663 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6783 const operand = try self.resolveInst(pl_op.operand);6664 const operand = try self.resolveInst(pl_op.operand);
6784 const name = self.air.nullTerminatedString(pl_op.payload);6665 const name = self.air.nullTerminatedString(pl_op.payload);
6785 const ptr_ty = self.typeOf(pl_op.operand);6666 const ptr_ty = self.typeOf(pl_op.operand);
67866667
6787 const di_local_var = dib.createAutoVariable(6668 const debug_local_var = try o.builder.debugLocalVar(
6788 self.di_scope.?,6669 try o.builder.string(name),
6789 name.ptr,6670 self.file,
6790 self.di_file.?,6671 self.current_scope,
6791 self.prev_dbg_line,6672 self.prev_dbg_line,
6792 try o.lowerDebugType(ptr_ty.childType(mod), .full),6673 try o.lowerDebugType(ptr_ty.childType(mod)),
6793 true, // always preserve
6794 0, // flags
6795 );6674 );
6796 const inlined_at = if (self.dbg_inlined.items.len > 0)6675
6797 self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc6676 _ = try self.wip.callIntrinsic(
6798 else6677 .normal,
6799 null;6678 .none,
6800 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);6679 .@"dbg.declare",
6801 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);6680 &.{},
6802 _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);6681 &.{
6682 (try self.wip.debugValue(operand)).toValue(),
6683 debug_local_var.toValue(),
6684 (try o.builder.debugExpression(&.{})).toValue(),
6685 },
6686 "",
6687 );
6688
6803 return .none;6689 return .none;
6804 }6690 }
68056691
6806 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6692 fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6693 if (self.wip.builder.strip) return .none;
6807 const o = self.dg.object;6694 const o = self.dg.object;
6808 const dib = o.di_builder orelse return .none;
6809 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;6695 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
6810 const operand = try self.resolveInst(pl_op.operand);6696 const operand = try self.resolveInst(pl_op.operand);
6811 const operand_ty = self.typeOf(pl_op.operand);6697 const operand_ty = self.typeOf(pl_op.operand);
...@@ -6813,32 +6699,58 @@ pub const FuncGen = struct {...@@ -6813,32 +6699,58 @@ pub const FuncGen = struct {
68136699
6814 if (needDbgVarWorkaround(o)) return .none;6700 if (needDbgVarWorkaround(o)) return .none;
68156701
6816 const di_local_var = dib.createAutoVariable(6702 const debug_local_var = try o.builder.debugLocalVar(
6817 self.di_scope.?,6703 try o.builder.string(name),
6818 name.ptr,6704 self.file,
6819 self.di_file.?,6705 self.current_scope,
6820 self.prev_dbg_line,6706 self.prev_dbg_line,
6821 try o.lowerDebugType(operand_ty, .full),6707 try o.lowerDebugType(operand_ty),
6822 true, // always preserve
6823 0, // flags
6824 );6708 );
6825 const inlined_at = if (self.dbg_inlined.items.len > 0)6709
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);
6831 const zcu = o.module;6710 const zcu = o.module;
6832 const owner_mod = self.dg.ownerModule();6711 const owner_mod = self.dg.ownerModule();
6833 if (isByRef(operand_ty, zcu)) {6712 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 );
6835 } else if (owner_mod.optimize_mode == .Debug) {6725 } else if (owner_mod.optimize_mode == .Debug) {
6836 const alignment = operand_ty.abiAlignment(zcu).toLlvm();6726 const alignment = operand_ty.abiAlignment(zcu).toLlvm();
6837 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);6727 const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
6838 _ = try self.wip.store(.normal, operand, alloca, alignment);6728 _ = 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 );
6840 } else {6741 } 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 );
6842 }6754 }
6843 return .none;6755 return .none;
6844 }6756 }
...@@ -8860,41 +8772,80 @@ pub const FuncGen = struct {...@@ -8860,41 +8772,80 @@ pub const FuncGen = struct {
8860 const arg_val = self.args[self.arg_index];8772 const arg_val = self.args[self.arg_index];
8861 self.arg_index += 1;8773 self.arg_index += 1;
88628774
8775 if (self.wip.builder.strip) return arg_val;
8776
8863 const inst_ty = self.typeOfIndex(inst);8777 const inst_ty = self.typeOfIndex(inst);
8864 if (o.di_builder) |dib| {8778 if (needDbgVarWorkaround(o)) return arg_val;
8865 if (needDbgVarWorkaround(o)) return arg_val;8779
88668780 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
8867 const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;8781 const func_index = self.dg.decl.getOwnedFunctionIndex();
8868 const func_index = self.dg.decl.getOwnedFunctionIndex();8782 const func = mod.funcInfo(func_index);
8869 const func = mod.funcInfo(func_index);8783 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8870 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;8784 const lbrace_col = func.lbrace_column + 1;
8871 const lbrace_col = func.lbrace_column + 1;8785
8872 const di_local_var = dib.createParameterVariable(8786 const debug_parameter = try o.builder.debugParameter(
8873 self.di_scope.?,8787 try o.builder.string(mod.getParamName(func_index, src_index)),
8874 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args8788 self.file,
8875 self.di_file.?,8789 self.current_scope,
8876 lbrace_line,8790 lbrace_line,
8877 try o.lowerDebugType(inst_ty, .full),8791 try o.lowerDebugType(inst_ty),
8878 true, // always preserve8792 @intCast(self.arg_index),
8879 0, // flags8793 );
8880 @intCast(self.arg_index), // includes +1 because 0 is return type
8881 );
88828794
8883 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);8795 const old_location = self.wip.current_debug_location;
8884 const insert_block = self.wip.cursor.block.toLlvm(&self.wip);8796 self.wip.current_debug_location = .{
8885 const owner_mod = self.dg.ownerModule();8797 .line = lbrace_line,
8886 if (isByRef(inst_ty, mod)) {8798 .column = lbrace_col,
8887 _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8799 .scope = self.current_scope,
8888 } else if (owner_mod.optimize_mode == .Debug) {8800 .inlined_at = Builder.Metadata.none,
8889 const alignment = inst_ty.abiAlignment(mod).toLlvm();8801 };
8890 const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment);8802
8891 _ = try self.wip.store(.normal, arg_val, alloca, alignment);8803 const owner_mod = self.dg.ownerModule();
8892 _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8804 if (isByRef(inst_ty, mod)) {
8893 } else {8805 _ = try self.wip.callIntrinsic(
8894 _ = dib.insertDbgValueIntrinsicAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block);8806 .normal,
8895 }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 );
8896 }8846 }
88978847
8848 self.wip.current_debug_location = old_location;
8898 return arg_val;8849 return arg_val;
8899 }8850 }
89008851
...@@ -8932,7 +8883,7 @@ pub const FuncGen = struct {...@@ -8932,7 +8883,7 @@ pub const FuncGen = struct {
8932 alignment: Builder.Alignment,8883 alignment: Builder.Alignment,
8933 ) Allocator.Error!Builder.Value {8884 ) Allocator.Error!Builder.Value {
8934 const target = self.dg.object.module.getTarget();8885 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);
8936 }8887 }
89378888
8938 // Workaround for https://github.com/ziglang/zig/issues/163928889 // Workaround for https://github.com/ziglang/zig/issues/16392
...@@ -11716,45 +11667,6 @@ const struct_layout_version = 2;...@@ -11716,45 +11667,6 @@ const struct_layout_version = 2;
11716// https://github.com/llvm/llvm-project/issues/56585/ is fixed11667// https://github.com/llvm/llvm-project/issues/56585/ is fixed
11717const optional_layout_version = 3;11668const 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
11758const lt_errors_fn_name = "__zig_lt_errors_len";11670const lt_errors_fn_name = "__zig_lt_errors_len";
1175911671
11760/// Without this workaround, LLVM crashes with "unknown codeview register H1"11672/// Without this workaround, LLVM crashes with "unknown codeview register H1"
...@@ -11778,7 +11690,6 @@ fn compilerRtIntBits(bits: u16) u16 {...@@ -11778,7 +11690,6 @@ fn compilerRtIntBits(bits: u16) u16 {
1177811690
11779fn buildAllocaInner(11691fn buildAllocaInner(
11780 wip: *Builder.WipFunction,11692 wip: *Builder.WipFunction,
11781 di_scope_non_null: bool,
11782 llvm_ty: Builder.Type,11693 llvm_ty: Builder.Type,
11783 alignment: Builder.Alignment,11694 alignment: Builder.Alignment,
11784 target: std.Target,11695 target: std.Target,
...@@ -11787,19 +11698,15 @@ fn buildAllocaInner(...@@ -11787,19 +11698,15 @@ fn buildAllocaInner(
1178711698
11788 const alloca = blk: {11699 const alloca = blk: {
11789 const prev_cursor = wip.cursor;11700 const prev_cursor = wip.cursor;
11790 const prev_debug_location = if (wip.builder.useLibLlvm())11701 const prev_debug_location = wip.current_debug_location;
11791 wip.llvm.builder.getCurrentDebugLocation2()
11792 else
11793 undefined;
11794 defer {11702 defer {
11795 wip.cursor = prev_cursor;11703 wip.cursor = prev_cursor;
11796 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;11704 if (wip.cursor.block == .entry) wip.cursor.instruction += 1;
11797 if (wip.builder.useLibLlvm() and di_scope_non_null)11705 wip.current_debug_location = prev_debug_location;
11798 wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location);
11799 }11706 }
1180011707
11801 wip.cursor = .{ .block = .entry };11708 wip.cursor = .{ .block = .entry };
11802 if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation();11709 wip.current_debug_location = null;
11803 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");11710 break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, "");
11804 };11711 };
1180511712