| ... | ... | @@ -770,37 +770,19 @@ pub const Object = struct { |
| 770 | 770 | builder: Builder, |
| 771 | 771 | |
| 772 | 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; |
| 781 | 773 | |
| 782 | | const Self = @This(); |
| 774 | debug_compile_unit: Builder.Metadata, |
| 783 | 775 | |
| 784 | | metadata: ?noreturn = null, |
| 785 | | size: Size = 0, |
| 786 | | available: Size = 0, |
| 776 | debug_enums_fwd_ref: Builder.Metadata, |
| 777 | debug_globals_fwd_ref: Builder.Metadata, |
| 787 | 778 | |
| 788 | | pub const Size = u0; |
| 779 | debug_enums: std.ArrayListUnmanaged(Builder.Metadata), |
| 780 | debug_globals: std.ArrayListUnmanaged(Builder.Metadata), |
| 789 | 781 | |
| 790 | | pub fn deinit(self: *Self, allocator: Allocator) void { |
| 791 | | _ = allocator; |
| 792 | | self.* = undefined; |
| 793 | | } |
| 782 | debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata), |
| 783 | |
| 784 | debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata), |
| 794 | 785 | |
| 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 | 786 | target: std.Target, |
| 805 | 787 | /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function, |
| 806 | 788 | /// but that has some downsides: |
| ... | ... | @@ -820,7 +802,6 @@ pub const Object = struct { |
| 820 | 802 | /// TODO when InternPool garbage collection is implemented, this map needs |
| 821 | 803 | /// to be garbage collected as well. |
| 822 | 804 | type_map: TypeMap, |
| 823 | | di_type_map: DITypeMap, |
| 824 | 805 | /// The LLVM global table which holds the names corresponding to Zig errors. |
| 825 | 806 | /// Note that the values are not added until `emit`, when all errors in |
| 826 | 807 | /// the compilation are known. |
| ... | ... | @@ -850,146 +831,87 @@ pub const Object = struct { |
| 850 | 831 | |
| 851 | 832 | pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); |
| 852 | 833 | |
| 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 | 834 | pub fn create(arena: Allocator, comp: *Compilation) !*Object { |
| 858 | 835 | if (build_options.only_c) unreachable; |
| 859 | 836 | const gpa = comp.gpa; |
| 860 | 837 | const target = comp.root_mod.resolved_target.result; |
| 861 | 838 | const llvm_target_triple = try targetTriple(arena, target); |
| 862 | 839 | const strip = comp.root_mod.strip; |
| 863 | | const optimize_mode = comp.root_mod.optimize_mode; |
| 864 | | const pic = comp.root_mod.pic; |
| 865 | 840 | |
| 866 | 841 | var builder = try Builder.init(.{ |
| 867 | 842 | .allocator = gpa, |
| 868 | | .use_lib_llvm = comp.config.use_lib_llvm, |
| 869 | | .strip = strip or !comp.config.use_lib_llvm, // TODO |
| 843 | .use_lib_llvm = false, |
| 844 | .strip = strip, |
| 870 | 845 | .name = comp.root_name, |
| 871 | 846 | .target = target, |
| 872 | 847 | .triple = llvm_target_triple, |
| 873 | 848 | }); |
| 874 | 849 | errdefer builder.deinit(); |
| 875 | 850 | |
| 876 | | var target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void = undefined; |
| 877 | | var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined; |
| 878 | | if (builder.useLibLlvm()) { |
| 879 | | debug_info: { |
| 880 | | switch (comp.config.debug_format) { |
| 881 | | .strip => break :debug_info, |
| 882 | | .code_view => builder.llvm.module.?.addModuleCodeViewFlag(), |
| 883 | | .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"), |
| 884 | | } |
| 885 | | builder.llvm.di_builder = builder.llvm.module.?.createDIBuilder(true); |
| 886 | | |
| 887 | | // Don't use the version string here; LLVM misparses it when it |
| 888 | | // includes the git revision. |
| 889 | | const producer = try builder.fmt("zig {d}.{d}.{d}", .{ |
| 890 | | build_options.semver.major, |
| 891 | | build_options.semver.minor, |
| 892 | | build_options.semver.patch, |
| 893 | | }); |
| 894 | | |
| 895 | | // We fully resolve all paths at this point to avoid lack of |
| 896 | | // source line info in stack traces or lack of debugging |
| 897 | | // information which, if relative paths were used, would be |
| 898 | | // very location dependent. |
| 899 | | // TODO: the only concern I have with this is WASI as either host or target, should |
| 900 | | // we leave the paths as relative then? |
| 901 | | // TODO: This is totally wrong. In dwarf, paths are encoded as relative to |
| 902 | | // a particular directory, and then the directory path is specified elsewhere. |
| 903 | | // In the compiler frontend we have it stored correctly in this |
| 904 | | // way already, but here we throw all that sweet information |
| 905 | | // into the garbage can by converting into absolute paths. What |
| 906 | | // a terrible tragedy. |
| 907 | | const compile_unit_dir_z = blk: { |
| 908 | | if (comp.module) |zcu| m: { |
| 909 | | const d = try zcu.root_mod.root.joinStringZ(arena, ""); |
| 910 | | if (d.len == 0) break :m; |
| 911 | | if (std.fs.path.isAbsolute(d)) break :blk d; |
| 912 | | const realpath = std.fs.realpathAlloc(arena, d) catch break :blk d; |
| 913 | | break :blk try arena.dupeZ(u8, realpath); |
| 914 | | } |
| 915 | | const cwd = try std.process.getCwdAlloc(arena); |
| 916 | | break :blk try arena.dupeZ(u8, cwd); |
| 917 | | }; |
| 918 | | |
| 919 | | builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( |
| 920 | | DW.LANG.C99, |
| 921 | | builder.llvm.di_builder.?.createFile(comp.root_name, compile_unit_dir_z), |
| 922 | | producer.slice(&builder).?, |
| 923 | | optimize_mode != .Debug, |
| 924 | | "", // flags |
| 925 | | 0, // runtime version |
| 926 | | "", // split name |
| 927 | | 0, // dwo id |
| 928 | | true, // emit debug info |
| 929 | | ); |
| 851 | builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }}); |
| 852 | |
| 853 | // We fully resolve all paths at this point to avoid lack of |
| 854 | // source line info in stack traces or lack of debugging |
| 855 | // information which, if relative paths were used, would be |
| 856 | // very location dependent. |
| 857 | // TODO: the only concern I have with this is WASI as either host or target, should |
| 858 | // we leave the paths as relative then? |
| 859 | // TODO: This is totally wrong. In dwarf, paths are encoded as relative to |
| 860 | // a particular directory, and then the directory path is specified elsewhere. |
| 861 | // In the compiler frontend we have it stored correctly in this |
| 862 | // way already, but here we throw all that sweet information |
| 863 | // into the garbage can by converting into absolute paths. What |
| 864 | // a terrible tragedy. |
| 865 | const compile_unit_dir = blk: { |
| 866 | if (comp.module) |zcu| m: { |
| 867 | const d = try zcu.root_mod.root.joinString(arena, ""); |
| 868 | if (d.len == 0) break :m; |
| 869 | if (std.fs.path.isAbsolute(d)) break :blk d; |
| 870 | break :blk std.fs.realpathAlloc(arena, d) catch break :blk d; |
| 930 | 871 | } |
| 872 | break :blk try std.process.getCwdAlloc(arena); |
| 873 | }; |
| 931 | 874 | |
| 932 | | const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug) |
| 933 | | .None |
| 934 | | else |
| 935 | | .Aggressive; |
| 875 | const debug_file = try builder.debugFile( |
| 876 | try builder.string(compile_unit_dir), |
| 877 | try builder.string(comp.root_name), |
| 878 | ); |
| 936 | 879 | |
| 937 | | const reloc_mode: llvm.RelocMode = if (pic) |
| 938 | | .PIC |
| 939 | | else if (comp.config.link_mode == .Dynamic) |
| 940 | | llvm.RelocMode.DynamicNoPIC |
| 941 | | else |
| 942 | | .Static; |
| 943 | | |
| 944 | | const code_model: llvm.CodeModel = switch (comp.root_mod.code_model) { |
| 945 | | .default => .Default, |
| 946 | | .tiny => .Tiny, |
| 947 | | .small => .Small, |
| 948 | | .kernel => .Kernel, |
| 949 | | .medium => .Medium, |
| 950 | | .large => .Large, |
| 951 | | }; |
| 880 | const debug_enums_fwd_ref = try builder.debugForwardReference(); |
| 881 | const debug_globals_fwd_ref = try builder.debugForwardReference(); |
| 882 | |
| 883 | const debug_compile_unit = try builder.debugCompileUnit( |
| 884 | debug_file, |
| 885 | // Don't use the version string here; LLVM misparses it when it |
| 886 | // includes the git revision. |
| 887 | try builder.fmt("zig {d}.{d}.{d}", .{ |
| 888 | build_options.semver.major, |
| 889 | build_options.semver.minor, |
| 890 | build_options.semver.patch, |
| 891 | }), |
| 892 | debug_enums_fwd_ref, |
| 893 | debug_globals_fwd_ref, |
| 894 | .{ .optimized = comp.root_mod.optimize_mode != .Debug }, |
| 895 | ); |
| 952 | 896 | |
| 953 | | // TODO handle float ABI better- it should depend on the ABI portion of std.Target |
| 954 | | const float_abi: llvm.ABIType = .Default; |
| 955 | | |
| 956 | | target_machine = llvm.TargetMachine.create( |
| 957 | | builder.llvm.target.?, |
| 958 | | builder.target_triple.slice(&builder).?, |
| 959 | | if (target.cpu.model.llvm_name) |s| s.ptr else null, |
| 960 | | comp.root_mod.resolved_target.llvm_cpu_features.?, |
| 961 | | opt_level, |
| 962 | | reloc_mode, |
| 963 | | code_model, |
| 964 | | comp.function_sections, |
| 965 | | comp.data_sections, |
| 966 | | float_abi, |
| 967 | | if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, |
| 897 | if (!builder.strip) { |
| 898 | const debug_info_version = try builder.debugModuleFlag( |
| 899 | try builder.debugConstant(try builder.intConst(.i32, 2)), |
| 900 | try builder.string("Debug Info Version"), |
| 901 | try builder.debugConstant(try builder.intConst(.i32, 3)), |
| 902 | ); |
| 903 | const dwarf_version = try builder.debugModuleFlag( |
| 904 | try builder.debugConstant(try builder.intConst(.i32, 2)), |
| 905 | try builder.string("Dwarf Version"), |
| 906 | try builder.debugConstant(try builder.intConst(.i32, 4)), |
| 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); |
| 979 | 908 | |
| 980 | | if (comp.llvm_opt_bisect_limit >= 0) { |
| 981 | | builder.llvm.context.setOptBisectLimit(comp.llvm_opt_bisect_limit); |
| 982 | | } |
| 909 | try builder.debugNamed(try builder.string("llvm.module.flags"), &.{ |
| 910 | debug_info_version, |
| 911 | dwarf_version, |
| 912 | }); |
| 983 | 913 | |
| 984 | | builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }}); |
| 985 | | if (std.debug.runtime_safety) { |
| 986 | | const rep = target_data.stringRep(); |
| 987 | | defer llvm.disposeMessage(rep); |
| 988 | | std.testing.expectEqualStrings( |
| 989 | | std.mem.span(rep), |
| 990 | | builder.data_layout.slice(&builder).?, |
| 991 | | ) catch unreachable; |
| 992 | | } |
| 914 | try builder.debugNamed(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit}); |
| 993 | 915 | } |
| 994 | 916 | |
| 995 | 917 | const obj = try arena.create(Object); |
| ... | ... | @@ -997,17 +919,18 @@ pub const Object = struct { |
| 997 | 919 | .gpa = gpa, |
| 998 | 920 | .builder = builder, |
| 999 | 921 | .module = comp.module.?, |
| 1000 | | .di_map = .{}, |
| 1001 | | .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO |
| 1002 | | .di_compile_unit = if (builder.useLibLlvm()) builder.llvm.di_compile_unit else null, |
| 1003 | | .target_machine = target_machine, |
| 1004 | | .target_data = target_data, |
| 922 | .debug_compile_unit = debug_compile_unit, |
| 923 | .debug_enums_fwd_ref = debug_enums_fwd_ref, |
| 924 | .debug_globals_fwd_ref = debug_globals_fwd_ref, |
| 925 | .debug_enums = .{}, |
| 926 | .debug_globals = .{}, |
| 927 | .debug_type_map = .{}, |
| 928 | .debug_unresolved_namespace_scopes = .{}, |
| 1005 | 929 | .target = target, |
| 1006 | 930 | .decl_map = .{}, |
| 1007 | 931 | .anon_decl_map = .{}, |
| 1008 | 932 | .named_enum_map = .{}, |
| 1009 | 933 | .type_map = .{}, |
| 1010 | | .di_type_map = .{}, |
| 1011 | 934 | .error_name_table = .none, |
| 1012 | 935 | .extern_collisions = .{}, |
| 1013 | 936 | .null_opt_usize = .no_init, |
| ... | ... | @@ -1018,12 +941,10 @@ pub const Object = struct { |
| 1018 | 941 | |
| 1019 | 942 | pub fn deinit(self: *Object) void { |
| 1020 | 943 | const gpa = self.gpa; |
| 1021 | | self.di_map.deinit(gpa); |
| 1022 | | self.di_type_map.deinit(gpa); |
| 1023 | | if (self.builder.useLibLlvm()) { |
| 1024 | | self.target_data.dispose(); |
| 1025 | | self.target_machine.dispose(); |
| 1026 | | } |
| 944 | self.debug_globals.deinit(gpa); |
| 945 | self.debug_enums.deinit(gpa); |
| 946 | self.debug_type_map.deinit(gpa); |
| 947 | self.debug_unresolved_namespace_scopes.deinit(gpa); |
| 1027 | 948 | self.decl_map.deinit(gpa); |
| 1028 | 949 | self.anon_decl_map.deinit(gpa); |
| 1029 | 950 | self.named_enum_map.deinit(gpa); |
| ... | ... | @@ -1193,26 +1114,29 @@ pub const Object = struct { |
| 1193 | 1114 | try self.genCmpLtErrorsLenFunction(); |
| 1194 | 1115 | try self.genModuleLevelAssembly(); |
| 1195 | 1116 | |
| 1196 | | if (self.di_builder) |dib| { |
| 1197 | | // When lowering debug info for pointers, we emitted the element types as |
| 1198 | | // forward decls. Now we must go flesh those out. |
| 1199 | | // Here we iterate over a hash map while modifying it but it is OK because |
| 1200 | | // we never add or remove entries during this loop. |
| 1117 | { |
| 1201 | 1118 | var i: usize = 0; |
| 1202 | | while (i < self.di_type_map.count()) : (i += 1) { |
| 1203 | | const value_ptr = &self.di_type_map.values()[i]; |
| 1204 | | const annotated = value_ptr.*; |
| 1205 | | if (!annotated.isFwdOnly()) continue; |
| 1206 | | const entry: Object.DITypeMap.Entry = .{ |
| 1207 | | .key_ptr = &self.di_type_map.keys()[i], |
| 1208 | | .value_ptr = value_ptr, |
| 1209 | | }; |
| 1210 | | _ = try self.lowerDebugTypeImpl(entry, .full, annotated.toDIType()); |
| 1211 | | } |
| 1119 | while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) { |
| 1120 | const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i]; |
| 1121 | const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i]; |
| 1122 | const namespace = self.module.namespacePtr(namespace_index); |
| 1123 | |
| 1124 | const debug_type = try self.lowerDebugType(namespace.ty); |
| 1212 | 1125 | |
| 1213 | | dib.finalize(); |
| 1126 | self.builder.debugForwardReferenceSetType(fwd_ref, debug_type); |
| 1127 | } |
| 1214 | 1128 | } |
| 1215 | 1129 | |
| 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 | 1140 | if (options.pre_ir_path) |path| { |
| 1217 | 1141 | if (std.mem.eql(u8, path, "-")) { |
| 1218 | 1142 | self.builder.dump(); |
| ... | ... | @@ -1238,35 +1162,126 @@ pub const Object = struct { |
| 1238 | 1162 | if (options.asm_path == null and options.bin_path == null and |
| 1239 | 1163 | options.post_ir_path == null and options.post_bc_path == null) return; |
| 1240 | 1164 | |
| 1241 | | if (options.post_bc_path) |path| { |
| 1242 | | if (!self.builder.useLibLlvm()) { |
| 1243 | | var arena_allocator = std.heap.ArenaAllocator.init(self.gpa); |
| 1244 | | defer arena_allocator.deinit(); |
| 1245 | | const arena = arena_allocator.allocator(); |
| 1165 | var bitcode_arena_allocator = std.heap.ArenaAllocator.init( |
| 1166 | std.heap.page_allocator, |
| 1167 | ); |
| 1168 | errdefer bitcode_arena_allocator.deinit(); |
| 1246 | 1169 | |
| 1247 | | var file = try std.fs.cwd().createFileZ(path, .{}); |
| 1248 | | defer file.close(); |
| 1249 | | const bitcode = try self.builder.toBitcode(arena); |
| 1170 | const bitcode = try self.builder.toBitcode( |
| 1171 | bitcode_arena_allocator.allocator(), |
| 1172 | ); |
| 1250 | 1173 | |
| 1251 | | const ptr: [*]const u8 = @ptrCast(bitcode.ptr); |
| 1252 | | try file.writeAll(ptr[0..(bitcode.len * 4)]); |
| 1253 | | return; |
| 1254 | | } |
| 1174 | if (options.post_bc_path) |path| { |
| 1175 | var file = try std.fs.cwd().createFileZ(path, .{}); |
| 1176 | defer file.close(); |
| 1177 | |
| 1178 | const ptr: [*]const u8 = @ptrCast(bitcode.ptr); |
| 1179 | try file.writeAll(ptr[0..(bitcode.len * 4)]); |
| 1255 | 1180 | } |
| 1256 | 1181 | |
| 1257 | | if (!self.builder.useLibLlvm()) { |
| 1182 | if (!self.module.comp.config.use_lib_llvm) { |
| 1258 | 1183 | log.err("emitting without libllvm not implemented", .{}); |
| 1259 | 1184 | return error.FailedToEmit; |
| 1260 | 1185 | } |
| 1261 | 1186 | |
| 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 | 1277 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 1263 | 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 | 1280 | var emit_bin_path = options.bin_path; |
| 1266 | 1281 | var post_ir_path = options.post_ir_path; |
| 1267 | 1282 | if (options.asm_path != null and options.bin_path != null) { |
| 1268 | | if (self.target_machine.emitToFile( |
| 1269 | | self.builder.llvm.module.?, |
| 1283 | if (target_machine.emitToFile( |
| 1284 | module, |
| 1270 | 1285 | &error_message, |
| 1271 | 1286 | options.is_debug, |
| 1272 | 1287 | options.is_small, |
| ... | ... | @@ -1289,8 +1304,8 @@ pub const Object = struct { |
| 1289 | 1304 | post_ir_path = null; |
| 1290 | 1305 | } |
| 1291 | 1306 | |
| 1292 | | if (self.target_machine.emitToFile( |
| 1293 | | self.builder.llvm.module.?, |
| 1307 | if (target_machine.emitToFile( |
| 1308 | module, |
| 1294 | 1309 | &error_message, |
| 1295 | 1310 | options.is_debug, |
| 1296 | 1311 | options.is_small, |
| ... | ... | @@ -1300,7 +1315,7 @@ pub const Object = struct { |
| 1300 | 1315 | options.asm_path, |
| 1301 | 1316 | emit_bin_path, |
| 1302 | 1317 | post_ir_path, |
| 1303 | | options.post_bc_path, |
| 1318 | null, |
| 1304 | 1319 | )) { |
| 1305 | 1320 | defer llvm.disposeMessage(error_message); |
| 1306 | 1321 | |
| ... | ... | @@ -1440,7 +1455,7 @@ pub const Object = struct { |
| 1440 | 1455 | if (isByRef(param_ty, zcu)) { |
| 1441 | 1456 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); |
| 1442 | 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 | 1459 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1445 | 1460 | args.appendAssumeCapacity(arg_ptr); |
| 1446 | 1461 | } else { |
| ... | ... | @@ -1488,7 +1503,7 @@ pub const Object = struct { |
| 1488 | 1503 | |
| 1489 | 1504 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1490 | 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 | 1507 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1493 | 1508 | |
| 1494 | 1509 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| ... | ... | @@ -1533,7 +1548,7 @@ pub const Object = struct { |
| 1533 | 1548 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); |
| 1534 | 1549 | const param_llvm_ty = try o.lowerType(param_ty); |
| 1535 | 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 | 1552 | const llvm_ty = try o.builder.structType(.normal, field_types); |
| 1538 | 1553 | for (0..field_types.len) |field_i| { |
| 1539 | 1554 | const param = wip.arg(llvm_arg_i); |
| ... | ... | @@ -1563,7 +1578,7 @@ pub const Object = struct { |
| 1563 | 1578 | llvm_arg_i += 1; |
| 1564 | 1579 | |
| 1565 | 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 | 1582 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1568 | 1583 | |
| 1569 | 1584 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| ... | ... | @@ -1578,7 +1593,7 @@ pub const Object = struct { |
| 1578 | 1593 | llvm_arg_i += 1; |
| 1579 | 1594 | |
| 1580 | 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 | 1597 | _ = try wip.store(.normal, param, arg_ptr, alignment); |
| 1583 | 1598 | |
| 1584 | 1599 | args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) |
| ... | ... | @@ -1592,40 +1607,34 @@ pub const Object = struct { |
| 1592 | 1607 | |
| 1593 | 1608 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); |
| 1594 | 1609 | |
| 1595 | | var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; |
| 1596 | | var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; |
| 1597 | | |
| 1598 | | if (o.di_builder) |dib| { |
| 1599 | | di_file = try o.getDIFile(gpa, namespace.file_scope); |
| 1610 | const file = try o.getDebugFile(namespace.file_scope); |
| 1600 | 1611 | |
| 1612 | const subprogram = blk: { |
| 1601 | 1613 | const line_number = decl.src_line + 1; |
| 1602 | 1614 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null and |
| 1603 | 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 | 1617 | llvm.DIFlags.NoReturn |
| 1606 | 1618 | else |
| 1607 | 1619 | 0; |
| 1608 | | const decl_di_ty = try o.lowerDebugType(decl.ty, .full); |
| 1609 | | const subprogram = dib.createFunction( |
| 1610 | | di_file.?.toScope(), |
| 1611 | | ip.stringToSlice(decl.name), |
| 1612 | | function_index.name(&o.builder).slice(&o.builder).?, |
| 1613 | | di_file.?, |
| 1620 | const debug_decl_type = try o.lowerDebugType(decl.ty); |
| 1621 | |
| 1622 | break :blk try o.builder.debugSubprogram( |
| 1623 | file, |
| 1624 | try o.builder.string(ip.stringToSlice(decl.name)), |
| 1625 | function_index.name(&o.builder), |
| 1614 | 1626 | line_number, |
| 1615 | | decl_di_ty, |
| 1616 | | is_internal_linkage, |
| 1617 | | true, // is definition |
| 1618 | | line_number + func.lbrace_line, // scope line |
| 1619 | | llvm.DIFlags.StaticMember | noret_bit, |
| 1620 | | owner_mod.optimize_mode != .Debug, |
| 1621 | | null, // decl_subprogram |
| 1627 | line_number + func.lbrace_line, |
| 1628 | debug_decl_type, |
| 1629 | .{ |
| 1630 | .optimized = owner_mod.optimize_mode != .Debug, |
| 1631 | .definition = true, |
| 1632 | .local = is_internal_linkage, |
| 1633 | .debug_info_flags = llvm.DIFlags.StaticMember | noret_bit, |
| 1634 | }, |
| 1635 | o.debug_compile_unit, |
| 1622 | 1636 | ); |
| 1623 | | try o.di_map.put(gpa, decl, subprogram.toNode()); |
| 1624 | | |
| 1625 | | function_index.toLlvm(&o.builder).fnSetSubprogram(subprogram); |
| 1626 | | |
| 1627 | | di_scope = subprogram.toScope(); |
| 1628 | | } |
| 1637 | }; |
| 1629 | 1638 | |
| 1630 | 1639 | var fg: FuncGen = .{ |
| 1631 | 1640 | .gpa = gpa, |
| ... | ... | @@ -1639,8 +1648,9 @@ pub const Object = struct { |
| 1639 | 1648 | .func_inst_table = .{}, |
| 1640 | 1649 | .blocks = .{}, |
| 1641 | 1650 | .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, |
| 1642 | | .di_scope = di_scope, |
| 1643 | | .di_file = di_file, |
| 1651 | .file = file, |
| 1652 | .subprogram = subprogram, |
| 1653 | .current_scope = subprogram, |
| 1644 | 1654 | .base_line = dg.decl.src_line, |
| 1645 | 1655 | .prev_dbg_line = 0, |
| 1646 | 1656 | .prev_dbg_column = 0, |
| ... | ... | @@ -1726,26 +1736,7 @@ pub const Object = struct { |
| 1726 | 1736 | global_index.setUnnamedAddr(.default, &self.builder); |
| 1727 | 1737 | if (comp.config.dll_export_fns) |
| 1728 | 1738 | global_index.setDllStorageClass(.default, &self.builder); |
| 1729 | | if (self.di_map.get(decl)) |di_node| { |
| 1730 | | const decl_name_slice = decl_name.slice(&self.builder).?; |
| 1731 | | if (try decl.isFunction(mod)) { |
| 1732 | | const di_func: *llvm.DISubprogram = @ptrCast(di_node); |
| 1733 | | const linkage_name = llvm.MDString.get( |
| 1734 | | self.builder.llvm.context, |
| 1735 | | decl_name_slice.ptr, |
| 1736 | | decl_name_slice.len, |
| 1737 | | ); |
| 1738 | | di_func.replaceLinkageName(linkage_name); |
| 1739 | | } else { |
| 1740 | | const di_global: *llvm.DIGlobalVariable = @ptrCast(di_node); |
| 1741 | | const linkage_name = llvm.MDString.get( |
| 1742 | | self.builder.llvm.context, |
| 1743 | | decl_name_slice.ptr, |
| 1744 | | decl_name_slice.len, |
| 1745 | | ); |
| 1746 | | di_global.replaceLinkageName(linkage_name); |
| 1747 | | } |
| 1748 | | } |
| 1739 | |
| 1749 | 1740 | if (decl.val.getVariable(mod)) |decl_var| { |
| 1750 | 1741 | global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( |
| 1751 | 1742 | if (decl_var.is_threadlocal) .generaldynamic else .default, |
| ... | ... | @@ -1759,27 +1750,6 @@ pub const Object = struct { |
| 1759 | 1750 | ); |
| 1760 | 1751 | try global_index.rename(main_exp_name, &self.builder); |
| 1761 | 1752 | |
| 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 | 1753 | if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal) |
| 1784 | 1754 | global_index.ptrConst(&self.builder).kind |
| 1785 | 1755 | .variable.setThreadLocal(.generaldynamic, &self.builder); |
| ... | ... | @@ -1909,119 +1879,64 @@ pub const Object = struct { |
| 1909 | 1879 | global.delete(&self.builder); |
| 1910 | 1880 | } |
| 1911 | 1881 | |
| 1912 | | fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile { |
| 1913 | | const gop = try o.di_map.getOrPut(gpa, file); |
| 1914 | | errdefer assert(o.di_map.remove(file)); |
| 1915 | | if (gop.found_existing) { |
| 1916 | | return @ptrCast(gop.value_ptr.*); |
| 1917 | | } |
| 1918 | | const dir_path_z = d: { |
| 1919 | | var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| 1920 | | const sub_path = std.fs.path.dirname(file.sub_file_path) orelse ""; |
| 1921 | | const dir_path = try file.mod.root.joinStringZ(gpa, sub_path); |
| 1922 | | if (std.fs.path.isAbsolute(dir_path)) break :d dir_path; |
| 1923 | | const abs = std.fs.realpath(dir_path, &buffer) catch break :d dir_path; |
| 1924 | | gpa.free(dir_path); |
| 1925 | | break :d try gpa.dupeZ(u8, abs); |
| 1926 | | }; |
| 1927 | | defer gpa.free(dir_path_z); |
| 1928 | | const sub_file_path_z = try gpa.dupeZ(u8, std.fs.path.basename(file.sub_file_path)); |
| 1929 | | defer gpa.free(sub_file_path_z); |
| 1930 | | const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z); |
| 1931 | | gop.value_ptr.* = di_file.toNode(); |
| 1932 | | return di_file; |
| 1882 | fn getDebugFile(o: *Object, file: *const Module.File) Allocator.Error!Builder.Metadata { |
| 1883 | return try o.builder.debugFile( |
| 1884 | if (std.fs.path.dirname(file.sub_file_path)) |dirname| try o.builder.string(dirname) else .empty, |
| 1885 | try o.builder.string(std.fs.path.basename(file.sub_file_path)), |
| 1886 | ); |
| 1933 | 1887 | } |
| 1934 | 1888 | |
| 1935 | | const DebugResolveStatus = enum { fwd, full }; |
| 1936 | | |
| 1937 | | /// In the implementation of this function, it is required to store a forward decl |
| 1938 | | /// into `gop` before making any recursive calls (even directly). |
| 1939 | | fn lowerDebugType( |
| 1889 | pub fn lowerDebugType( |
| 1940 | 1890 | o: *Object, |
| 1941 | 1891 | ty: Type, |
| 1942 | | resolve: DebugResolveStatus, |
| 1943 | | ) Allocator.Error!*llvm.DIType { |
| 1944 | | const gpa = o.gpa; |
| 1945 | | // Be careful not to reference this `gop` variable after any recursive calls |
| 1946 | | // to `lowerDebugType`. |
| 1947 | | const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern()); |
| 1948 | | if (gop.found_existing) { |
| 1949 | | const annotated = gop.value_ptr.*; |
| 1950 | | switch (annotated) { |
| 1951 | | // This type is currently attempting to be resolved fully, so make |
| 1952 | | // sure a second recursion through the types uses forward resolution. |
| 1953 | | .null => assert(resolve == .fwd), |
| 1954 | | // This type already has at least forward resolution, only resolve |
| 1955 | | // fully during full resolution. |
| 1956 | | _ => { |
| 1957 | | const di_type = annotated.toDIType(); |
| 1958 | | if (!annotated.isFwdOnly() or resolve == .fwd) { |
| 1959 | | return di_type; |
| 1960 | | } |
| 1961 | | const entry: Object.DITypeMap.Entry = .{ |
| 1962 | | .key_ptr = gop.key_ptr, |
| 1963 | | .value_ptr = gop.value_ptr, |
| 1964 | | }; |
| 1965 | | return o.lowerDebugTypeImpl(entry, resolve, di_type); |
| 1966 | | }, |
| 1967 | | } |
| 1968 | | } else gop.value_ptr.* = .null; |
| 1969 | | errdefer if (!gop.found_existing) assert(o.di_type_map.orderedRemove(ty.toIntern())); |
| 1970 | | const entry: Object.DITypeMap.Entry = .{ |
| 1971 | | .key_ptr = gop.key_ptr, |
| 1972 | | .value_ptr = gop.value_ptr, |
| 1973 | | }; |
| 1974 | | return o.lowerDebugTypeImpl(entry, resolve, null); |
| 1975 | | } |
| 1976 | | |
| 1977 | | /// This is a helper function used by `lowerDebugType`. |
| 1978 | | fn lowerDebugTypeImpl( |
| 1979 | | o: *Object, |
| 1980 | | gop: Object.DITypeMap.Entry, |
| 1981 | | resolve: DebugResolveStatus, |
| 1982 | | opt_fwd_decl: ?*llvm.DIType, |
| 1983 | | ) Allocator.Error!*llvm.DIType { |
| 1984 | | const ty = Type.fromInterned(gop.key_ptr.*); |
| 1892 | ) Allocator.Error!Builder.Metadata { |
| 1893 | if (o.builder.strip) return Builder.Metadata.none; |
| 1985 | 1894 | const gpa = o.gpa; |
| 1986 | 1895 | const target = o.target; |
| 1987 | | const dib = o.di_builder.?; |
| 1988 | 1896 | const mod = o.module; |
| 1989 | 1897 | const ip = &mod.intern_pool; |
| 1898 | |
| 1899 | if (o.debug_type_map.get(ty)) |debug_type| return debug_type; |
| 1900 | |
| 1990 | 1901 | switch (ty.zigTypeTag(mod)) { |
| 1991 | | .Void, .NoReturn => { |
| 1992 | | const di_type = dib.createBasicType("void", 0, DW.ATE.signed); |
| 1993 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 1994 | | return di_type; |
| 1902 | .Void, |
| 1903 | .NoReturn, |
| 1904 | => { |
| 1905 | const debug_void_type = try o.builder.debugSignedType( |
| 1906 | try o.builder.string("void"), |
| 1907 | 0, |
| 1908 | ); |
| 1909 | try o.debug_type_map.put(gpa, ty, debug_void_type); |
| 1910 | return debug_void_type; |
| 1995 | 1911 | }, |
| 1996 | 1912 | .Int => { |
| 1997 | 1913 | const info = ty.intInfo(mod); |
| 1998 | 1914 | assert(info.bits != 0); |
| 1999 | 1915 | const name = try o.allocTypeName(ty); |
| 2000 | 1916 | defer gpa.free(name); |
| 2001 | | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 2002 | | .signed => DW.ATE.signed, |
| 2003 | | .unsigned => DW.ATE.unsigned, |
| 1917 | const builder_name = try o.builder.string(name); |
| 1918 | const debug_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types |
| 1919 | const debug_int_type = switch (info.signedness) { |
| 1920 | .signed => try o.builder.debugSignedType(builder_name, debug_bits), |
| 1921 | .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits), |
| 2004 | 1922 | }; |
| 2005 | | const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types |
| 2006 | | const di_type = dib.createBasicType(name, di_bits, dwarf_encoding); |
| 2007 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 2008 | | return di_type; |
| 1923 | try o.debug_type_map.put(gpa, ty, debug_int_type); |
| 1924 | return debug_int_type; |
| 2009 | 1925 | }, |
| 2010 | 1926 | .Enum => { |
| 2011 | 1927 | const owner_decl_index = ty.getOwnerDecl(mod); |
| 2012 | 1928 | const owner_decl = o.module.declPtr(owner_decl_index); |
| 2013 | 1929 | |
| 2014 | 1930 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2015 | | const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2016 | | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 2017 | | // means we can't use `gop` anymore. |
| 2018 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty)); |
| 2019 | | return enum_di_ty; |
| 1931 | const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); |
| 1932 | try o.debug_type_map.put(gpa, ty, debug_enum_type); |
| 1933 | try o.debug_enums.append(gpa, debug_enum_type); |
| 1934 | return debug_enum_type; |
| 2020 | 1935 | } |
| 2021 | 1936 | |
| 2022 | 1937 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; |
| 2023 | 1938 | |
| 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 | 1940 | defer gpa.free(enumerators); |
| 2026 | 1941 | |
| 2027 | 1942 | const int_ty = Type.fromInterned(enum_type.tag_ty); |
| ... | ... | @@ -2029,66 +1944,59 @@ pub const Object = struct { |
| 2029 | 1944 | assert(int_info.bits != 0); |
| 2030 | 1945 | |
| 2031 | 1946 | for (enum_type.names.get(ip), 0..) |field_name_ip, i| { |
| 2032 | | const field_name_z = ip.stringToSlice(field_name_ip); |
| 2033 | | |
| 2034 | 1947 | var bigint_space: Value.BigIntSpace = undefined; |
| 2035 | 1948 | const bigint = if (enum_type.values.len != 0) |
| 2036 | 1949 | Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, mod) |
| 2037 | 1950 | else |
| 2038 | 1951 | std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); |
| 2039 | 1952 | |
| 2040 | | if (bigint.limbs.len == 1) { |
| 2041 | | enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned); |
| 2042 | | continue; |
| 2043 | | } |
| 2044 | | if (@sizeOf(usize) == @sizeOf(u64)) { |
| 2045 | | enumerators[i] = dib.createEnumerator2( |
| 2046 | | field_name_z, |
| 2047 | | @intCast(bigint.limbs.len), |
| 2048 | | bigint.limbs.ptr, |
| 2049 | | int_info.bits, |
| 2050 | | int_info.signedness == .unsigned, |
| 2051 | | ); |
| 2052 | | continue; |
| 2053 | | } |
| 2054 | | @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds"); |
| 1953 | enumerators[i] = try o.builder.debugEnumerator( |
| 1954 | try o.builder.string(ip.stringToSlice(field_name_ip)), |
| 1955 | int_ty.isUnsignedInt(mod), |
| 1956 | int_info.bits, |
| 1957 | bigint, |
| 1958 | ); |
| 2055 | 1959 | } |
| 2056 | 1960 | |
| 2057 | | const di_file = try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope); |
| 2058 | | const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace); |
| 1961 | const file = try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope); |
| 1962 | const scope = try o.namespaceToDebugScope(owner_decl.src_namespace); |
| 2059 | 1963 | |
| 2060 | 1964 | const name = try o.allocTypeName(ty); |
| 2061 | 1965 | defer gpa.free(name); |
| 2062 | 1966 | |
| 2063 | | const enum_di_ty = dib.createEnumerationType( |
| 2064 | | di_scope, |
| 2065 | | name, |
| 2066 | | di_file, |
| 2067 | | owner_decl.src_node + 1, |
| 1967 | const debug_enum_type = try o.builder.debugEnumerationType( |
| 1968 | try o.builder.string(name), |
| 1969 | file, |
| 1970 | scope, |
| 1971 | owner_decl.src_node + 1, // Line |
| 1972 | try o.lowerDebugType(int_ty), |
| 2068 | 1973 | ty.abiSize(mod) * 8, |
| 2069 | 1974 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2070 | | enumerators.ptr, |
| 2071 | | @intCast(enumerators.len), |
| 2072 | | try o.lowerDebugType(int_ty, resolve), |
| 2073 | | "", |
| 1975 | try o.builder.debugTuple(enumerators), |
| 2074 | 1976 | ); |
| 2075 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2076 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty)); |
| 2077 | | return enum_di_ty; |
| 1977 | |
| 1978 | try o.debug_type_map.put(gpa, ty, debug_enum_type); |
| 1979 | try o.debug_enums.append(gpa, debug_enum_type); |
| 1980 | return debug_enum_type; |
| 2078 | 1981 | }, |
| 2079 | 1982 | .Float => { |
| 2080 | 1983 | const bits = ty.floatBits(target); |
| 2081 | 1984 | const name = try o.allocTypeName(ty); |
| 2082 | 1985 | defer gpa.free(name); |
| 2083 | | const di_type = dib.createBasicType(name, bits, DW.ATE.float); |
| 2084 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 2085 | | return di_type; |
| 1986 | const debug_float_type = try o.builder.debugFloatType( |
| 1987 | try o.builder.string(name), |
| 1988 | bits, |
| 1989 | ); |
| 1990 | try o.debug_type_map.put(gpa, ty, debug_float_type); |
| 1991 | return debug_float_type; |
| 2086 | 1992 | }, |
| 2087 | 1993 | .Bool => { |
| 2088 | | const di_bits = 8; // lldb cannot handle non-byte sized types |
| 2089 | | const di_type = dib.createBasicType("bool", di_bits, DW.ATE.boolean); |
| 2090 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| 2091 | | return di_type; |
| 1994 | const debug_bool_type = try o.builder.debugBoolType( |
| 1995 | try o.builder.string("bool"), |
| 1996 | 8, // lldb cannot handle non-byte sized types |
| 1997 | ); |
| 1998 | try o.debug_type_map.put(gpa, ty, debug_bool_type); |
| 1999 | return debug_bool_type; |
| 2092 | 2000 | }, |
| 2093 | 2001 | .Pointer => { |
| 2094 | 2002 | // Normalize everything that the debug info does not represent. |
| ... | ... | @@ -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); |
| 2122 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2123 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve)); |
| 2124 | | return ptr_di_ty; |
| 2029 | const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty); |
| 2030 | try o.debug_type_map.put(gpa, ty, debug_ptr_type); |
| 2031 | return debug_ptr_type; |
| 2125 | 2032 | } |
| 2126 | 2033 | |
| 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 | 2039 | if (ty.isSlice(mod)) { |
| 2128 | 2040 | const ptr_ty = ty.slicePtrFieldType(mod); |
| 2129 | 2041 | const len_ty = Type.usize; |
| 2130 | 2042 | |
| 2131 | 2043 | const name = try o.allocTypeName(ty); |
| 2132 | 2044 | defer gpa.free(name); |
| 2133 | | const di_file: ?*llvm.DIFile = null; |
| 2134 | 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 | | }; |
| 2149 | 2046 | |
| 2150 | 2047 | const ptr_size = ptr_ty.abiSize(mod); |
| 2151 | 2048 | const ptr_align = ptr_ty.abiAlignment(mod); |
| 2152 | 2049 | const len_size = len_ty.abiSize(mod); |
| 2153 | 2050 | const len_align = len_ty.abiAlignment(mod); |
| 2154 | 2051 | |
| 2155 | | var offset: u64 = 0; |
| 2156 | | offset += ptr_size; |
| 2157 | | offset = len_align.forward(offset); |
| 2158 | | const len_offset = offset; |
| 2159 | | |
| 2160 | | const fields: [2]*llvm.DIType = .{ |
| 2161 | | dib.createMemberType( |
| 2162 | | fwd_decl.toScope(), |
| 2163 | | "ptr", |
| 2164 | | di_file, |
| 2165 | | line, |
| 2166 | | ptr_size * 8, // size in bits |
| 2167 | | ptr_align.toByteUnits(0) * 8, // align in bits |
| 2168 | | 0, // offset in bits |
| 2169 | | 0, // flags |
| 2170 | | try o.lowerDebugType(ptr_ty, resolve), |
| 2171 | | ), |
| 2172 | | dib.createMemberType( |
| 2173 | | fwd_decl.toScope(), |
| 2174 | | "len", |
| 2175 | | di_file, |
| 2176 | | line, |
| 2177 | | len_size * 8, // size in bits |
| 2178 | | len_align.toByteUnits(0) * 8, // align in bits |
| 2179 | | len_offset * 8, // offset in bits |
| 2180 | | 0, // flags |
| 2181 | | try o.lowerDebugType(len_ty, resolve), |
| 2182 | | ), |
| 2183 | | }; |
| 2052 | const len_offset = len_align.forward(ptr_size); |
| 2053 | |
| 2054 | const debug_ptr_type = try o.builder.debugMemberType( |
| 2055 | try o.builder.string("ptr"), |
| 2056 | Builder.Metadata.none, // File |
| 2057 | debug_fwd_ref, |
| 2058 | 0, // Line |
| 2059 | try o.lowerDebugType(ptr_ty), |
| 2060 | ptr_size * 8, |
| 2061 | ptr_align.toByteUnits(0) * 8, |
| 2062 | 0, // Offset |
| 2063 | ); |
| 2064 | |
| 2065 | const debug_len_type = try o.builder.debugMemberType( |
| 2066 | try o.builder.string("len"), |
| 2067 | Builder.Metadata.none, // File |
| 2068 | debug_fwd_ref, |
| 2069 | 0, // Line |
| 2070 | try o.lowerDebugType(len_ty), |
| 2071 | len_size * 8, |
| 2072 | len_align.toByteUnits(0) * 8, |
| 2073 | len_offset * 8, |
| 2074 | ); |
| 2184 | 2075 | |
| 2185 | | const full_di_ty = dib.createStructType( |
| 2186 | | compile_unit_scope, |
| 2187 | | name.ptr, |
| 2188 | | di_file, |
| 2076 | const debug_slice_type = try o.builder.debugStructType( |
| 2077 | try o.builder.string(name), |
| 2078 | Builder.Metadata.none, // File |
| 2079 | o.debug_compile_unit, // Scope |
| 2189 | 2080 | line, |
| 2190 | | ty.abiSize(mod) * 8, // size in bits |
| 2191 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2192 | | 0, // flags |
| 2193 | | null, // derived from |
| 2194 | | &fields, |
| 2195 | | fields.len, |
| 2196 | | 0, // run time lang |
| 2197 | | null, // vtable holder |
| 2198 | | "", // unique id |
| 2081 | Builder.Metadata.none, // Underlying type |
| 2082 | ty.abiSize(mod) * 8, |
| 2083 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2084 | try o.builder.debugTuple(&.{ |
| 2085 | debug_ptr_type, |
| 2086 | debug_len_type, |
| 2087 | }), |
| 2199 | 2088 | ); |
| 2200 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2201 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2202 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2203 | | return full_di_ty; |
| 2089 | |
| 2090 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type); |
| 2091 | |
| 2092 | // Set to real type now that it has been lowered fully |
| 2093 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2094 | map_ptr.* = debug_slice_type; |
| 2095 | |
| 2096 | return debug_slice_type; |
| 2204 | 2097 | } |
| 2205 | 2098 | |
| 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 | 2101 | const name = try o.allocTypeName(ty); |
| 2208 | 2102 | defer gpa.free(name); |
| 2209 | | const ptr_di_ty = dib.createPointerType( |
| 2210 | | elem_di_ty, |
| 2103 | |
| 2104 | const debug_ptr_type = try o.builder.debugPointerType( |
| 2105 | try o.builder.string(name), |
| 2106 | Builder.Metadata.none, // File |
| 2107 | Builder.Metadata.none, // Scope |
| 2108 | 0, // Line |
| 2109 | debug_elem_ty, |
| 2211 | 2110 | target.ptrBitWidth(), |
| 2212 | 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. |
| 2216 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty)); |
| 2217 | | return ptr_di_ty; |
| 2114 | |
| 2115 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_ptr_type); |
| 2116 | |
| 2117 | // Set to real type now that it has been lowered fully |
| 2118 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2119 | map_ptr.* = debug_ptr_type; |
| 2120 | |
| 2121 | return debug_ptr_type; |
| 2218 | 2122 | }, |
| 2219 | 2123 | .Opaque => { |
| 2220 | 2124 | if (ty.toIntern() == .anyopaque_type) { |
| 2221 | | const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed); |
| 2222 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 2223 | | return di_ty; |
| 2125 | const debug_opaque_type = try o.builder.debugSignedType( |
| 2126 | try o.builder.string("anyopaque"), |
| 2127 | 0, |
| 2128 | ); |
| 2129 | try o.debug_type_map.put(gpa, ty, debug_opaque_type); |
| 2130 | return debug_opaque_type; |
| 2224 | 2131 | } |
| 2132 | |
| 2225 | 2133 | const name = try o.allocTypeName(ty); |
| 2226 | 2134 | defer gpa.free(name); |
| 2227 | 2135 | const owner_decl_index = ty.getOwnerDecl(mod); |
| 2228 | 2136 | const owner_decl = o.module.declPtr(owner_decl_index); |
| 2229 | | const opaque_di_ty = dib.createForwardDeclType( |
| 2230 | | DW.TAG.structure_type, |
| 2231 | | name, |
| 2137 | const debug_opaque_type = try o.builder.debugStructType( |
| 2138 | try o.builder.string(name), |
| 2139 | try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope), |
| 2232 | 2140 | try o.namespaceToDebugScope(owner_decl.src_namespace), |
| 2233 | | try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope), |
| 2234 | | owner_decl.src_node + 1, |
| 2141 | owner_decl.src_node + 1, // Line |
| 2142 | Builder.Metadata.none, // Underlying type |
| 2143 | 0, // Size |
| 2144 | 0, // Align |
| 2145 | Builder.Metadata.none, // Fields |
| 2235 | 2146 | ); |
| 2236 | | // The recursive call to `lowerDebugType` va `namespaceToDebugScope` |
| 2237 | | // means we can't use `gop` anymore. |
| 2238 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty)); |
| 2239 | | return opaque_di_ty; |
| 2147 | try o.debug_type_map.put(gpa, ty, debug_opaque_type); |
| 2148 | return debug_opaque_type; |
| 2240 | 2149 | }, |
| 2241 | 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 | 2157 | ty.abiSize(mod) * 8, |
| 2244 | 2158 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2245 | | try o.lowerDebugType(ty.childType(mod), resolve), |
| 2246 | | @intCast(ty.arrayLen(mod)), |
| 2159 | try o.builder.debugTuple(&.{ |
| 2160 | try o.builder.debugSubrange( |
| 2161 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| 2162 | try o.builder.debugConstant(try o.builder.intConst(.i64, ty.arrayLen(mod))), |
| 2163 | ), |
| 2164 | }), |
| 2247 | 2165 | ); |
| 2248 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2249 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty)); |
| 2250 | | return array_di_ty; |
| 2166 | try o.debug_type_map.put(gpa, ty, debug_array_type); |
| 2167 | return debug_array_type; |
| 2251 | 2168 | }, |
| 2252 | 2169 | .Vector => { |
| 2253 | 2170 | const elem_ty = ty.elemType2(mod); |
| ... | ... | @@ -2255,146 +2172,136 @@ pub const Object = struct { |
| 2255 | 2172 | // @bitSizOf(elem) * len > @bitSizOf(vec). |
| 2256 | 2173 | // Neither gdb nor lldb seem to be able to display non-byte sized |
| 2257 | 2174 | // vectors properly. |
| 2258 | | const elem_di_type = switch (elem_ty.zigTypeTag(mod)) { |
| 2175 | const debug_elem_type = switch (elem_ty.zigTypeTag(mod)) { |
| 2259 | 2176 | .Int => blk: { |
| 2260 | 2177 | const info = elem_ty.intInfo(mod); |
| 2261 | 2178 | assert(info.bits != 0); |
| 2262 | 2179 | const name = try o.allocTypeName(ty); |
| 2263 | 2180 | defer gpa.free(name); |
| 2264 | | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 2265 | | .signed => DW.ATE.signed, |
| 2266 | | .unsigned => DW.ATE.unsigned, |
| 2181 | const builder_name = try o.builder.string(name); |
| 2182 | break :blk switch (info.signedness) { |
| 2183 | .signed => try o.builder.debugSignedType(builder_name, info.bits), |
| 2184 | .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits), |
| 2267 | 2185 | }; |
| 2268 | | break :blk dib.createBasicType(name, info.bits, dwarf_encoding); |
| 2269 | 2186 | }, |
| 2270 | | .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean), |
| 2271 | | else => try o.lowerDebugType(ty.childType(mod), resolve), |
| 2187 | .Bool => try o.builder.debugBoolType( |
| 2188 | try o.builder.string("bool"), |
| 2189 | 1, |
| 2190 | ), |
| 2191 | else => try o.lowerDebugType(ty.childType(mod)), |
| 2272 | 2192 | }; |
| 2273 | 2193 | |
| 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 | 2200 | ty.abiSize(mod) * 8, |
| 2276 | | @intCast(ty.abiAlignment(mod).toByteUnits(0) * 8), |
| 2277 | | elem_di_type, |
| 2278 | | ty.vectorLen(mod), |
| 2201 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2202 | try o.builder.debugTuple(&.{ |
| 2203 | try o.builder.debugSubrange( |
| 2204 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| 2205 | try o.builder.debugConstant(try o.builder.intConst(.i64, ty.vectorLen(mod))), |
| 2206 | ), |
| 2207 | }), |
| 2279 | 2208 | ); |
| 2280 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2281 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty)); |
| 2282 | | return vector_di_ty; |
| 2209 | |
| 2210 | try o.debug_type_map.put(gpa, ty, debug_vector_type); |
| 2211 | return debug_vector_type; |
| 2283 | 2212 | }, |
| 2284 | 2213 | .Optional => { |
| 2285 | 2214 | const name = try o.allocTypeName(ty); |
| 2286 | 2215 | defer gpa.free(name); |
| 2287 | 2216 | const child_ty = ty.optionalChild(mod); |
| 2288 | 2217 | if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2289 | | const di_bits = 8; // lldb cannot handle non-byte sized types |
| 2290 | | const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean); |
| 2291 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 2292 | | return di_ty; |
| 2218 | const debug_bool_type = try o.builder.debugBoolType( |
| 2219 | try o.builder.string(name), |
| 2220 | 8, |
| 2221 | ); |
| 2222 | try o.debug_type_map.put(gpa, ty, debug_bool_type); |
| 2223 | return debug_bool_type; |
| 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 | 2231 | if (ty.optionalReprIsPayload(mod)) { |
| 2295 | | const ptr_di_ty = try o.lowerDebugType(child_ty, resolve); |
| 2296 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2297 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve)); |
| 2298 | | return ptr_di_ty; |
| 2299 | | } |
| 2232 | const debug_optional_type = try o.lowerDebugType(child_ty); |
| 2300 | 2233 | |
| 2301 | | const di_file: ?*llvm.DIFile = null; |
| 2302 | | const line = 0; |
| 2303 | | const compile_unit_scope = o.di_compile_unit.?.toScope(); |
| 2304 | | const fwd_decl = opt_fwd_decl orelse blk: { |
| 2305 | | const fwd_decl = dib.createReplaceableCompositeType( |
| 2306 | | DW.TAG.structure_type, |
| 2307 | | name.ptr, |
| 2308 | | compile_unit_scope, |
| 2309 | | di_file, |
| 2310 | | line, |
| 2311 | | ); |
| 2312 | | gop.value_ptr.* = AnnotatedDITypePtr.initFwd(fwd_decl); |
| 2313 | | if (resolve == .fwd) return fwd_decl; |
| 2314 | | break :blk fwd_decl; |
| 2315 | | }; |
| 2234 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type); |
| 2235 | |
| 2236 | // Set to real type now that it has been lowered fully |
| 2237 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2238 | map_ptr.* = debug_optional_type; |
| 2239 | |
| 2240 | return debug_optional_type; |
| 2241 | } |
| 2316 | 2242 | |
| 2317 | 2243 | const non_null_ty = Type.u8; |
| 2318 | 2244 | const payload_size = child_ty.abiSize(mod); |
| 2319 | 2245 | const payload_align = child_ty.abiAlignment(mod); |
| 2320 | 2246 | const non_null_size = non_null_ty.abiSize(mod); |
| 2321 | 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 | ); |
| 2322 | 2260 | |
| 2323 | | var offset: u64 = 0; |
| 2324 | | offset += payload_size; |
| 2325 | | offset = non_null_align.forward(offset); |
| 2326 | | const non_null_offset = offset; |
| 2327 | | |
| 2328 | | const fields: [2]*llvm.DIType = .{ |
| 2329 | | dib.createMemberType( |
| 2330 | | fwd_decl.toScope(), |
| 2331 | | "data", |
| 2332 | | di_file, |
| 2333 | | line, |
| 2334 | | payload_size * 8, // size in bits |
| 2335 | | payload_align.toByteUnits(0) * 8, // align in bits |
| 2336 | | 0, // offset in bits |
| 2337 | | 0, // flags |
| 2338 | | try o.lowerDebugType(child_ty, resolve), |
| 2339 | | ), |
| 2340 | | dib.createMemberType( |
| 2341 | | fwd_decl.toScope(), |
| 2342 | | "some", |
| 2343 | | di_file, |
| 2344 | | line, |
| 2345 | | non_null_size * 8, // size in bits |
| 2346 | | non_null_align.toByteUnits(0) * 8, // align in bits |
| 2347 | | non_null_offset * 8, // offset in bits |
| 2348 | | 0, // flags |
| 2349 | | try o.lowerDebugType(non_null_ty, resolve), |
| 2350 | | ), |
| 2351 | | }; |
| 2261 | const debug_some_type = try o.builder.debugMemberType( |
| 2262 | try o.builder.string("some"), |
| 2263 | Builder.Metadata.none, |
| 2264 | debug_fwd_ref, |
| 2265 | 0, |
| 2266 | try o.lowerDebugType(non_null_ty), |
| 2267 | non_null_size * 8, |
| 2268 | non_null_align.toByteUnits(0) * 8, |
| 2269 | non_null_offset * 8, |
| 2270 | ); |
| 2352 | 2271 | |
| 2353 | | const full_di_ty = dib.createStructType( |
| 2354 | | compile_unit_scope, |
| 2355 | | name.ptr, |
| 2356 | | di_file, |
| 2357 | | line, |
| 2358 | | ty.abiSize(mod) * 8, // size in bits |
| 2359 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2360 | | 0, // flags |
| 2361 | | null, // derived from |
| 2362 | | &fields, |
| 2363 | | fields.len, |
| 2364 | | 0, // run time lang |
| 2365 | | null, // vtable holder |
| 2366 | | "", // unique id |
| 2272 | const debug_optional_type = try o.builder.debugStructType( |
| 2273 | try o.builder.string(name), |
| 2274 | Builder.Metadata.none, // File |
| 2275 | o.debug_compile_unit, // Scope |
| 2276 | 0, // Line |
| 2277 | Builder.Metadata.none, // Underlying type |
| 2278 | ty.abiSize(mod) * 8, |
| 2279 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2280 | try o.builder.debugTuple(&.{ |
| 2281 | debug_data_type, |
| 2282 | debug_some_type, |
| 2283 | }), |
| 2367 | 2284 | ); |
| 2368 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2369 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2370 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2371 | | return full_di_ty; |
| 2285 | |
| 2286 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type); |
| 2287 | |
| 2288 | // Set to real type now that it has been lowered fully |
| 2289 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2290 | map_ptr.* = debug_optional_type; |
| 2291 | |
| 2292 | return debug_optional_type; |
| 2372 | 2293 | }, |
| 2373 | 2294 | .ErrorUnion => { |
| 2374 | 2295 | const payload_ty = ty.errorUnionPayload(mod); |
| 2375 | 2296 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2376 | | const err_set_di_ty = try o.lowerDebugType(Type.anyerror, resolve); |
| 2377 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2378 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty)); |
| 2379 | | return err_set_di_ty; |
| 2297 | // TODO: Maybe remove? |
| 2298 | const debug_error_union_type = try o.lowerDebugType(Type.anyerror); |
| 2299 | try o.debug_type_map.put(gpa, ty, debug_error_union_type); |
| 2300 | return debug_error_union_type; |
| 2380 | 2301 | } |
| 2302 | |
| 2381 | 2303 | const name = try o.allocTypeName(ty); |
| 2382 | 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 | | }; |
| 2398 | 2305 | |
| 2399 | 2306 | const error_size = Type.anyerror.abiSize(mod); |
| 2400 | 2307 | const error_align = Type.anyerror.abiAlignment(mod); |
| ... | ... | @@ -2417,59 +2324,55 @@ pub const Object = struct { |
| 2417 | 2324 | error_offset = error_align.forward(payload_size); |
| 2418 | 2325 | } |
| 2419 | 2326 | |
| 2420 | | var fields: [2]*llvm.DIType = undefined; |
| 2421 | | fields[error_index] = dib.createMemberType( |
| 2422 | | fwd_decl.toScope(), |
| 2423 | | "tag", |
| 2424 | | di_file, |
| 2425 | | line, |
| 2426 | | error_size * 8, // size in bits |
| 2427 | | error_align.toByteUnits(0) * 8, // align in bits |
| 2428 | | error_offset * 8, // offset in bits |
| 2429 | | 0, // flags |
| 2430 | | try o.lowerDebugType(Type.anyerror, resolve), |
| 2327 | const debug_fwd_ref = try o.builder.debugForwardReference(); |
| 2328 | |
| 2329 | var fields: [2]Builder.Metadata = undefined; |
| 2330 | fields[error_index] = try o.builder.debugMemberType( |
| 2331 | try o.builder.string("tag"), |
| 2332 | Builder.Metadata.none, // File |
| 2333 | debug_fwd_ref, |
| 2334 | 0, // Line |
| 2335 | try o.lowerDebugType(Type.anyerror), |
| 2336 | error_size * 8, |
| 2337 | error_align.toByteUnits(0) * 8, |
| 2338 | error_offset * 8, |
| 2431 | 2339 | ); |
| 2432 | | fields[payload_index] = dib.createMemberType( |
| 2433 | | fwd_decl.toScope(), |
| 2434 | | "value", |
| 2435 | | di_file, |
| 2436 | | line, |
| 2437 | | payload_size * 8, // size in bits |
| 2438 | | payload_align.toByteUnits(0) * 8, // align in bits |
| 2439 | | payload_offset * 8, // offset in bits |
| 2440 | | 0, // flags |
| 2441 | | try o.lowerDebugType(payload_ty, resolve), |
| 2340 | fields[payload_index] = try o.builder.debugMemberType( |
| 2341 | try o.builder.string("value"), |
| 2342 | Builder.Metadata.none, // File |
| 2343 | debug_fwd_ref, |
| 2344 | 0, // Line |
| 2345 | try o.lowerDebugType(payload_ty), |
| 2346 | payload_size * 8, |
| 2347 | payload_align.toByteUnits(0) * 8, |
| 2348 | payload_offset * 8, |
| 2442 | 2349 | ); |
| 2443 | 2350 | |
| 2444 | | const full_di_ty = dib.createStructType( |
| 2445 | | compile_unit_scope, |
| 2446 | | name.ptr, |
| 2447 | | di_file, |
| 2448 | | line, |
| 2449 | | ty.abiSize(mod) * 8, // size in bits |
| 2450 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2451 | | 0, // flags |
| 2452 | | null, // derived from |
| 2453 | | &fields, |
| 2454 | | fields.len, |
| 2455 | | 0, // run time lang |
| 2456 | | null, // vtable holder |
| 2457 | | "", // unique id |
| 2351 | const debug_error_union_type = try o.builder.debugStructType( |
| 2352 | try o.builder.string(name), |
| 2353 | Builder.Metadata.none, // File |
| 2354 | o.debug_compile_unit, // Sope |
| 2355 | 0, // Line |
| 2356 | Builder.Metadata.none, // Underlying type |
| 2357 | ty.abiSize(mod) * 8, |
| 2358 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2359 | try o.builder.debugTuple(&fields), |
| 2458 | 2360 | ); |
| 2459 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2460 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2461 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2462 | | return full_di_ty; |
| 2361 | |
| 2362 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type); |
| 2363 | |
| 2364 | try o.debug_type_map.put(gpa, ty, debug_error_union_type); |
| 2365 | return debug_error_union_type; |
| 2463 | 2366 | }, |
| 2464 | 2367 | .ErrorSet => { |
| 2465 | | // TODO make this a proper enum with all the error codes in it. |
| 2466 | | // will need to consider how to take incremental compilation into account. |
| 2467 | | const di_ty = dib.createBasicType("anyerror", 16, DW.ATE.unsigned); |
| 2468 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 2469 | | return di_ty; |
| 2368 | const debug_error_set = try o.builder.debugUnsignedType( |
| 2369 | try o.builder.string("anyerror"), |
| 2370 | 16, |
| 2371 | ); |
| 2372 | try o.debug_type_map.put(gpa, ty, debug_error_set); |
| 2373 | return debug_error_set; |
| 2470 | 2374 | }, |
| 2471 | 2375 | .Struct => { |
| 2472 | | const compile_unit_scope = o.di_compile_unit.?.toScope(); |
| 2473 | 2376 | const name = try o.allocTypeName(ty); |
| 2474 | 2377 | defer gpa.free(name); |
| 2475 | 2378 | |
| ... | ... | @@ -2477,40 +2380,28 @@ pub const Object = struct { |
| 2477 | 2380 | const backing_int_ty = struct_type.backingIntType(ip).*; |
| 2478 | 2381 | if (backing_int_ty != .none) { |
| 2479 | 2382 | const info = Type.fromInterned(backing_int_ty).intInfo(mod); |
| 2480 | | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 2481 | | .signed => DW.ATE.signed, |
| 2482 | | .unsigned => DW.ATE.unsigned, |
| 2383 | const builder_name = try o.builder.string(name); |
| 2384 | const debug_int_type = switch (info.signedness) { |
| 2385 | .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(mod) * 8), |
| 2386 | .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(mod) * 8), |
| 2483 | 2387 | }; |
| 2484 | | const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types |
| 2485 | | const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding); |
| 2486 | | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 2487 | | return di_ty; |
| 2388 | try o.debug_type_map.put(gpa, ty, debug_int_type); |
| 2389 | return debug_int_type; |
| 2488 | 2390 | } |
| 2489 | 2391 | } |
| 2490 | 2392 | |
| 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 | 2393 | switch (ip.indexToKey(ty.toIntern())) { |
| 2505 | 2394 | .anon_struct_type => |tuple| { |
| 2506 | | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| 2507 | | defer di_fields.deinit(gpa); |
| 2395 | var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; |
| 2396 | defer fields.deinit(gpa); |
| 2508 | 2397 | |
| 2509 | | try di_fields.ensureUnusedCapacity(gpa, tuple.types.len); |
| 2398 | try fields.ensureUnusedCapacity(gpa, tuple.types.len); |
| 2510 | 2399 | |
| 2511 | 2400 | comptime assert(struct_layout_version == 2); |
| 2512 | 2401 | var offset: u64 = 0; |
| 2513 | 2402 | |
| 2403 | const debug_fwd_ref = try o.builder.debugForwardReference(); |
| 2404 | |
| 2514 | 2405 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { |
| 2515 | 2406 | if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; |
| 2516 | 2407 | |
| ... | ... | @@ -2525,38 +2416,33 @@ pub const Object = struct { |
| 2525 | 2416 | try std.fmt.allocPrintZ(gpa, "{d}", .{i}); |
| 2526 | 2417 | defer if (tuple.names.len == 0) gpa.free(field_name); |
| 2527 | 2418 | |
| 2528 | | try di_fields.append(gpa, dib.createMemberType( |
| 2529 | | fwd_decl.toScope(), |
| 2530 | | field_name, |
| 2531 | | null, // file |
| 2532 | | 0, // line |
| 2533 | | field_size * 8, // size in bits |
| 2534 | | field_align.toByteUnits(0) * 8, // align in bits |
| 2535 | | field_offset * 8, // offset in bits |
| 2536 | | 0, // flags |
| 2537 | | try o.lowerDebugType(Type.fromInterned(field_ty), resolve), |
| 2419 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| 2420 | try o.builder.string(field_name), |
| 2421 | Builder.Metadata.none, // File |
| 2422 | debug_fwd_ref, |
| 2423 | 0, |
| 2424 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2425 | field_size * 8, |
| 2426 | field_align.toByteUnits(0) * 8, |
| 2427 | field_offset * 8, |
| 2538 | 2428 | )); |
| 2539 | 2429 | } |
| 2540 | 2430 | |
| 2541 | | const full_di_ty = dib.createStructType( |
| 2542 | | compile_unit_scope, |
| 2543 | | name.ptr, |
| 2544 | | null, // file |
| 2545 | | 0, // line |
| 2546 | | ty.abiSize(mod) * 8, // size in bits |
| 2547 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2548 | | 0, // flags |
| 2549 | | null, // derived from |
| 2550 | | di_fields.items.ptr, |
| 2551 | | @intCast(di_fields.items.len), |
| 2552 | | 0, // run time lang |
| 2553 | | null, // vtable holder |
| 2554 | | "", // unique id |
| 2431 | const debug_struct_type = try o.builder.debugStructType( |
| 2432 | try o.builder.string(name), |
| 2433 | Builder.Metadata.none, // File |
| 2434 | o.debug_compile_unit, // Scope |
| 2435 | 0, // Line |
| 2436 | Builder.Metadata.none, // Underlying type |
| 2437 | ty.abiSize(mod) * 8, |
| 2438 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2439 | try o.builder.debugTuple(fields.items), |
| 2555 | 2440 | ); |
| 2556 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2557 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2558 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2559 | | return full_di_ty; |
| 2441 | |
| 2442 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type); |
| 2443 | |
| 2444 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2445 | return debug_struct_type; |
| 2560 | 2446 | }, |
| 2561 | 2447 | .struct_type => |struct_type| { |
| 2562 | 2448 | if (!struct_type.haveFieldTypes(ip)) { |
| ... | ... | @@ -2568,12 +2454,9 @@ pub const Object = struct { |
| 2568 | 2454 | // rather than changing the frontend to unnecessarily resolve the |
| 2569 | 2455 | // struct field types. |
| 2570 | 2456 | const owner_decl_index = ty.getOwnerDecl(mod); |
| 2571 | | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2572 | | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| 2573 | | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 2574 | | // means we can't use `gop` anymore. |
| 2575 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty)); |
| 2576 | | return struct_di_ty; |
| 2457 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); |
| 2458 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2459 | return debug_struct_type; |
| 2577 | 2460 | } |
| 2578 | 2461 | }, |
| 2579 | 2462 | else => {}, |
| ... | ... | @@ -2581,20 +2464,22 @@ pub const Object = struct { |
| 2581 | 2464 | |
| 2582 | 2465 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2583 | 2466 | const owner_decl_index = ty.getOwnerDecl(mod); |
| 2584 | | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2585 | | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| 2586 | | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 2587 | | // means we can't use `gop` anymore. |
| 2588 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty)); |
| 2589 | | return struct_di_ty; |
| 2467 | const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); |
| 2468 | try o.debug_type_map.put(gpa, ty, debug_struct_type); |
| 2469 | return debug_struct_type; |
| 2590 | 2470 | } |
| 2591 | 2471 | |
| 2592 | 2472 | const struct_type = mod.typeToStruct(ty).?; |
| 2593 | 2473 | |
| 2594 | | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| 2595 | | defer di_fields.deinit(gpa); |
| 2474 | var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; |
| 2475 | defer fields.deinit(gpa); |
| 2476 | |
| 2477 | try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); |
| 2478 | |
| 2479 | const debug_fwd_ref = try o.builder.debugForwardReference(); |
| 2596 | 2480 | |
| 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); |
| 2598 | 2483 | |
| 2599 | 2484 | comptime assert(struct_layout_version == 2); |
| 2600 | 2485 | var it = struct_type.iterateRuntimeOrder(ip); |
| ... | ... | @@ -2612,103 +2497,88 @@ pub const Object = struct { |
| 2612 | 2497 | const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse |
| 2613 | 2498 | try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}); |
| 2614 | 2499 | |
| 2615 | | const field_di_ty = try o.lowerDebugType(field_ty, resolve); |
| 2616 | | |
| 2617 | | try di_fields.append(gpa, dib.createMemberType( |
| 2618 | | fwd_decl.toScope(), |
| 2619 | | ip.stringToSlice(field_name), |
| 2620 | | null, // file |
| 2621 | | 0, // line |
| 2622 | | field_size * 8, // size in bits |
| 2623 | | field_align.toByteUnits(0) * 8, // align in bits |
| 2624 | | field_offset * 8, // offset in bits |
| 2625 | | 0, // flags |
| 2626 | | field_di_ty, |
| 2500 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| 2501 | try o.builder.string(ip.stringToSlice(field_name)), |
| 2502 | Builder.Metadata.none, // File |
| 2503 | debug_fwd_ref, |
| 2504 | 0, // Line |
| 2505 | try o.lowerDebugType(field_ty), |
| 2506 | field_size * 8, |
| 2507 | field_align.toByteUnits(0) * 8, |
| 2508 | field_offset * 8, |
| 2627 | 2509 | )); |
| 2628 | 2510 | } |
| 2629 | 2511 | |
| 2630 | | const full_di_ty = dib.createStructType( |
| 2631 | | compile_unit_scope, |
| 2632 | | name.ptr, |
| 2633 | | null, // file |
| 2634 | | 0, // line |
| 2635 | | ty.abiSize(mod) * 8, // size in bits |
| 2636 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2637 | | 0, // flags |
| 2638 | | null, // derived from |
| 2639 | | di_fields.items.ptr, |
| 2640 | | @intCast(di_fields.items.len), |
| 2641 | | 0, // run time lang |
| 2642 | | null, // vtable holder |
| 2643 | | "", // unique id |
| 2512 | const debug_struct_type = try o.builder.debugStructType( |
| 2513 | try o.builder.string(name), |
| 2514 | Builder.Metadata.none, // File |
| 2515 | o.debug_compile_unit, // Scope |
| 2516 | 0, // Line |
| 2517 | Builder.Metadata.none, // Underlying type |
| 2518 | ty.abiSize(mod) * 8, |
| 2519 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2520 | try o.builder.debugTuple(fields.items), |
| 2644 | 2521 | ); |
| 2645 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2646 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2647 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2648 | | return full_di_ty; |
| 2522 | |
| 2523 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type); |
| 2524 | |
| 2525 | // Set to real type now that it has been lowered fully |
| 2526 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2527 | map_ptr.* = debug_struct_type; |
| 2528 | |
| 2529 | return debug_struct_type; |
| 2649 | 2530 | }, |
| 2650 | 2531 | .Union => { |
| 2651 | | const compile_unit_scope = o.di_compile_unit.?.toScope(); |
| 2652 | 2532 | const owner_decl_index = ty.getOwnerDecl(mod); |
| 2653 | 2533 | |
| 2654 | 2534 | const name = try o.allocTypeName(ty); |
| 2655 | 2535 | defer gpa.free(name); |
| 2656 | 2536 | |
| 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 | 2537 | const union_type = ip.indexToKey(ty.toIntern()).union_type; |
| 2671 | 2538 | if (!union_type.haveFieldTypes(ip) or !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2672 | | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2673 | | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 2674 | | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 2675 | | // means we can't use `gop` anymore. |
| 2676 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty)); |
| 2677 | | return union_di_ty; |
| 2539 | const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index); |
| 2540 | try o.debug_type_map.put(gpa, ty, debug_union_type); |
| 2541 | return debug_union_type; |
| 2678 | 2542 | } |
| 2679 | 2543 | |
| 2680 | 2544 | const union_obj = ip.loadUnionType(union_type); |
| 2681 | 2545 | const layout = mod.getUnionLayout(union_obj); |
| 2682 | 2546 | |
| 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 | 2552 | if (layout.payload_size == 0) { |
| 2684 | | const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve); |
| 2685 | | const di_fields = [_]*llvm.DIType{tag_di_ty}; |
| 2686 | | const full_di_ty = dib.createStructType( |
| 2687 | | compile_unit_scope, |
| 2688 | | name.ptr, |
| 2689 | | null, // file |
| 2690 | | 0, // line |
| 2691 | | ty.abiSize(mod) * 8, // size in bits |
| 2692 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2693 | | 0, // flags |
| 2694 | | null, // derived from |
| 2695 | | &di_fields, |
| 2696 | | di_fields.len, |
| 2697 | | 0, // run time lang |
| 2698 | | null, // vtable holder |
| 2699 | | "", // unique id |
| 2553 | const debug_union_type = try o.builder.debugStructType( |
| 2554 | try o.builder.string(name), |
| 2555 | Builder.Metadata.none, // File |
| 2556 | o.debug_compile_unit, // Scope |
| 2557 | 0, // Line |
| 2558 | Builder.Metadata.none, // Underlying type |
| 2559 | ty.abiSize(mod) * 8, |
| 2560 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2561 | try o.builder.debugTuple( |
| 2562 | &.{try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty))}, |
| 2563 | ), |
| 2700 | 2564 | ); |
| 2701 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2702 | | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 2703 | | // means we can't use `gop` anymore. |
| 2704 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2705 | | return full_di_ty; |
| 2565 | |
| 2566 | // Set to real type now that it has been lowered fully |
| 2567 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2568 | map_ptr.* = debug_union_type; |
| 2569 | |
| 2570 | return debug_union_type; |
| 2706 | 2571 | } |
| 2707 | 2572 | |
| 2708 | | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| 2709 | | defer di_fields.deinit(gpa); |
| 2573 | var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; |
| 2574 | defer fields.deinit(gpa); |
| 2710 | 2575 | |
| 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(); |
| 2712 | 2582 | |
| 2713 | 2583 | for (0..union_obj.field_names.len) |field_index| { |
| 2714 | 2584 | const field_ty = union_obj.field_types.get(ip)[field_index]; |
| ... | ... | @@ -2717,18 +2587,16 @@ pub const Object = struct { |
| 2717 | 2587 | const field_size = Type.fromInterned(field_ty).abiSize(mod); |
| 2718 | 2588 | const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index)); |
| 2719 | 2589 | |
| 2720 | | const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), resolve); |
| 2721 | 2590 | const field_name = union_obj.field_names.get(ip)[field_index]; |
| 2722 | | di_fields.appendAssumeCapacity(dib.createMemberType( |
| 2723 | | fwd_decl.toScope(), |
| 2724 | | ip.stringToSlice(field_name), |
| 2725 | | null, // file |
| 2726 | | 0, // line |
| 2727 | | field_size * 8, // size in bits |
| 2728 | | field_align.toByteUnits(0) * 8, // align in bits |
| 2729 | | 0, // offset in bits |
| 2730 | | 0, // flags |
| 2731 | | field_di_ty, |
| 2591 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| 2592 | try o.builder.string(ip.stringToSlice(field_name)), |
| 2593 | Builder.Metadata.none, // File |
| 2594 | debug_union_fwd_ref, |
| 2595 | 0, // Line |
| 2596 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2597 | field_size * 8, |
| 2598 | field_align.toByteUnits(0) * 8, |
| 2599 | 0, // Offset |
| 2732 | 2600 | )); |
| 2733 | 2601 | } |
| 2734 | 2602 | |
| ... | ... | @@ -2739,25 +2607,25 @@ pub const Object = struct { |
| 2739 | 2607 | break :name union_name_buf.?; |
| 2740 | 2608 | }; |
| 2741 | 2609 | |
| 2742 | | const union_di_ty = dib.createUnionType( |
| 2743 | | compile_unit_scope, |
| 2744 | | union_name.ptr, |
| 2745 | | null, // file |
| 2746 | | 0, // line |
| 2747 | | ty.abiSize(mod) * 8, // size in bits |
| 2748 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2749 | | 0, // flags |
| 2750 | | di_fields.items.ptr, |
| 2751 | | @intCast(di_fields.items.len), |
| 2752 | | 0, // run time lang |
| 2753 | | "", // unique id |
| 2610 | const debug_union_type = try o.builder.debugUnionType( |
| 2611 | try o.builder.string(union_name), |
| 2612 | Builder.Metadata.none, // File |
| 2613 | o.debug_compile_unit, // Scope |
| 2614 | 0, // Line |
| 2615 | Builder.Metadata.none, // Underlying type |
| 2616 | ty.abiSize(mod) * 8, |
| 2617 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2618 | try o.builder.debugTuple(fields.items), |
| 2754 | 2619 | ); |
| 2755 | 2620 | |
| 2621 | o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type); |
| 2622 | |
| 2756 | 2623 | if (layout.tag_size == 0) { |
| 2757 | | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 2758 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2759 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty)); |
| 2760 | | return union_di_ty; |
| 2624 | // Set to real type now that it has been lowered fully |
| 2625 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2626 | map_ptr.* = debug_union_type; |
| 2627 | |
| 2628 | return debug_union_type; |
| 2761 | 2629 | } |
| 2762 | 2630 | |
| 2763 | 2631 | var tag_offset: u64 = undefined; |
| ... | ... | @@ -2770,81 +2638,80 @@ pub const Object = struct { |
| 2770 | 2638 | tag_offset = layout.tag_align.forward(layout.payload_size); |
| 2771 | 2639 | } |
| 2772 | 2640 | |
| 2773 | | const tag_di = dib.createMemberType( |
| 2774 | | fwd_decl.toScope(), |
| 2775 | | "tag", |
| 2776 | | null, // file |
| 2777 | | 0, // line |
| 2641 | const debug_tag_type = try o.builder.debugMemberType( |
| 2642 | try o.builder.string("tag"), |
| 2643 | Builder.Metadata.none, // File |
| 2644 | debug_fwd_ref, |
| 2645 | 0, // Line |
| 2646 | try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty)), |
| 2778 | 2647 | layout.tag_size * 8, |
| 2779 | 2648 | layout.tag_align.toByteUnits(0) * 8, |
| 2780 | | tag_offset * 8, // offset in bits |
| 2781 | | 0, // flags |
| 2782 | | try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve), |
| 2649 | tag_offset * 8, |
| 2783 | 2650 | ); |
| 2784 | 2651 | |
| 2785 | | const payload_di = dib.createMemberType( |
| 2786 | | fwd_decl.toScope(), |
| 2787 | | "payload", |
| 2788 | | null, // file |
| 2789 | | 0, // line |
| 2790 | | layout.payload_size * 8, // size in bits |
| 2652 | const debug_payload_type = try o.builder.debugMemberType( |
| 2653 | try o.builder.string("payload"), |
| 2654 | Builder.Metadata.none, // File |
| 2655 | debug_fwd_ref, |
| 2656 | 0, // Line |
| 2657 | debug_union_type, |
| 2658 | layout.payload_size * 8, |
| 2791 | 2659 | layout.payload_align.toByteUnits(0) * 8, |
| 2792 | | payload_offset * 8, // offset in bits |
| 2793 | | 0, // flags |
| 2794 | | union_di_ty, |
| 2660 | payload_offset * 8, |
| 2795 | 2661 | ); |
| 2796 | 2662 | |
| 2797 | | const full_di_fields: [2]*llvm.DIType = |
| 2663 | const full_fields: [2]Builder.Metadata = |
| 2798 | 2664 | if (layout.tag_align.compare(.gte, layout.payload_align)) |
| 2799 | | .{ tag_di, payload_di } |
| 2665 | .{ debug_tag_type, debug_payload_type } |
| 2800 | 2666 | else |
| 2801 | | .{ payload_di, tag_di }; |
| 2802 | | |
| 2803 | | const full_di_ty = dib.createStructType( |
| 2804 | | compile_unit_scope, |
| 2805 | | name.ptr, |
| 2806 | | null, // file |
| 2807 | | 0, // line |
| 2808 | | ty.abiSize(mod) * 8, // size in bits |
| 2809 | | ty.abiAlignment(mod).toByteUnits(0) * 8, // align in bits |
| 2810 | | 0, // flags |
| 2811 | | null, // derived from |
| 2812 | | &full_di_fields, |
| 2813 | | full_di_fields.len, |
| 2814 | | 0, // run time lang |
| 2815 | | null, // vtable holder |
| 2816 | | "", // unique id |
| 2667 | .{ debug_payload_type, debug_tag_type }; |
| 2668 | |
| 2669 | const debug_tagged_union_type = try o.builder.debugStructType( |
| 2670 | try o.builder.string(name), |
| 2671 | Builder.Metadata.none, // File |
| 2672 | o.debug_compile_unit, // Scope |
| 2673 | 0, // Line |
| 2674 | Builder.Metadata.none, // Underlying type |
| 2675 | ty.abiSize(mod) * 8, |
| 2676 | ty.abiAlignment(mod).toByteUnits(0) * 8, |
| 2677 | try o.builder.debugTuple(&full_fields), |
| 2817 | 2678 | ); |
| 2818 | | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 2819 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2820 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty)); |
| 2821 | | return full_di_ty; |
| 2679 | |
| 2680 | o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type); |
| 2681 | |
| 2682 | // Set to real type now that it has been lowered fully |
| 2683 | const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; |
| 2684 | map_ptr.* = debug_tagged_union_type; |
| 2685 | |
| 2686 | return debug_tagged_union_type; |
| 2822 | 2687 | }, |
| 2823 | 2688 | .Fn => { |
| 2824 | 2689 | const fn_info = mod.typeToFunc(ty).?; |
| 2825 | 2690 | |
| 2826 | | var param_di_types = std.ArrayList(*llvm.DIType).init(gpa); |
| 2827 | | defer param_di_types.deinit(); |
| 2691 | var debug_param_types = std.ArrayList(Builder.Metadata).init(gpa); |
| 2692 | defer debug_param_types.deinit(); |
| 2693 | |
| 2694 | try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len); |
| 2828 | 2695 | |
| 2829 | 2696 | // Return type goes first. |
| 2830 | 2697 | if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) { |
| 2831 | 2698 | const sret = firstParamSRet(fn_info, mod); |
| 2832 | | const di_ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type); |
| 2833 | | try param_di_types.append(try o.lowerDebugType(di_ret_ty, resolve)); |
| 2699 | const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type); |
| 2700 | debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty)); |
| 2834 | 2701 | |
| 2835 | 2702 | if (sret) { |
| 2836 | 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 | 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 | } |
| 2842 | 2709 | |
| 2843 | 2710 | if (Type.fromInterned(fn_info.return_type).isError(mod) and |
| 2844 | 2711 | o.module.comp.config.any_error_tracing) |
| 2845 | 2712 | { |
| 2846 | 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 | } |
| 2849 | 2716 | |
| 2850 | 2717 | for (0..fn_info.param_types.len) |i| { |
| ... | ... | @@ -2853,20 +2720,18 @@ pub const Object = struct { |
| 2853 | 2720 | |
| 2854 | 2721 | if (isByRef(param_ty, mod)) { |
| 2855 | 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 | 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 | } |
| 2861 | 2728 | |
| 2862 | | const fn_di_ty = dib.createSubroutineType( |
| 2863 | | param_di_types.items.ptr, |
| 2864 | | @intCast(param_di_types.items.len), |
| 2865 | | 0, |
| 2729 | const debug_function_type = try o.builder.debugSubroutineType( |
| 2730 | try o.builder.debugTuple(debug_param_types.items), |
| 2866 | 2731 | ); |
| 2867 | | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2868 | | try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty)); |
| 2869 | | return fn_di_ty; |
| 2732 | |
| 2733 | try o.debug_type_map.put(gpa, ty, debug_function_type); |
| 2734 | return debug_function_type; |
| 2870 | 2735 | }, |
| 2871 | 2736 | .ComptimeInt => unreachable, |
| 2872 | 2737 | .ComptimeFloat => unreachable, |
| ... | ... | @@ -2880,39 +2745,30 @@ pub const Object = struct { |
| 2880 | 2745 | } |
| 2881 | 2746 | } |
| 2882 | 2747 | |
| 2883 | | fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !*llvm.DIScope { |
| 2748 | fn namespaceToDebugScope(o: *Object, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { |
| 2884 | 2749 | const mod = o.module; |
| 2885 | 2750 | const namespace = mod.namespacePtr(namespace_index); |
| 2886 | | if (namespace.parent == .none) { |
| 2887 | | const di_file = try o.getDIFile(o.gpa, namespace.file_scope); |
| 2888 | | return di_file.toScope(); |
| 2889 | | } |
| 2890 | | const di_type = try o.lowerDebugType(namespace.ty, .fwd); |
| 2891 | | return di_type.toScope(); |
| 2751 | if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); |
| 2752 | |
| 2753 | const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index); |
| 2754 | |
| 2755 | if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference(); |
| 2756 | |
| 2757 | return gop.value_ptr.*; |
| 2892 | 2758 | } |
| 2893 | 2759 | |
| 2894 | | /// This is to be used instead of void for debug info types, to avoid tripping |
| 2895 | | /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"' |
| 2896 | | /// when targeting CodeView (Windows). |
| 2897 | | fn makeEmptyNamespaceDIType(o: *Object, decl_index: InternPool.DeclIndex) !*llvm.DIType { |
| 2760 | fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata { |
| 2898 | 2761 | const mod = o.module; |
| 2899 | 2762 | const decl = mod.declPtr(decl_index); |
| 2900 | | const fields: [0]*llvm.DIType = .{}; |
| 2901 | | const di_scope = try o.namespaceToDebugScope(decl.src_namespace); |
| 2902 | | return o.di_builder.?.createStructType( |
| 2903 | | di_scope, |
| 2904 | | mod.intern_pool.stringToSlice(decl.name), // TODO use fully qualified name |
| 2905 | | try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope), |
| 2763 | return o.builder.debugStructType( |
| 2764 | try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name |
| 2765 | try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope), |
| 2766 | try o.namespaceToDebugScope(decl.src_namespace), |
| 2906 | 2767 | decl.src_line + 1, |
| 2907 | | 0, // size in bits |
| 2908 | | 0, // align in bits |
| 2909 | | 0, // flags |
| 2910 | | null, // derived from |
| 2911 | | undefined, // TODO should be able to pass &fields, |
| 2912 | | fields.len, |
| 2913 | | 0, // run time lang |
| 2914 | | null, // vtable holder |
| 2915 | | "", // unique id |
| 2768 | Builder.Metadata.none, |
| 2769 | 0, |
| 2770 | 0, |
| 2771 | .none, |
| 2916 | 2772 | ); |
| 2917 | 2773 | } |
| 2918 | 2774 | |
| ... | ... | @@ -4822,26 +4678,32 @@ pub const DeclGen = struct { |
| 4822 | 4678 | else => try o.lowerValue(init_val), |
| 4823 | 4679 | }, &o.builder); |
| 4824 | 4680 | |
| 4825 | | if (o.di_builder) |dib| { |
| 4826 | | const di_file = |
| 4827 | | try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| 4828 | | |
| 4829 | | const line_number = decl.src_line + 1; |
| 4830 | | const is_internal_linkage = !o.module.decl_exports.contains(decl_index); |
| 4831 | | const di_global = dib.createGlobalVariableExpression( |
| 4832 | | di_file.toScope(), |
| 4833 | | mod.intern_pool.stringToSlice(decl.name), |
| 4834 | | variable_index.name(&o.builder).slice(&o.builder).?, |
| 4835 | | di_file, |
| 4836 | | line_number, |
| 4837 | | try o.lowerDebugType(decl.ty, .full), |
| 4838 | | is_internal_linkage, |
| 4839 | | ); |
| 4681 | const line_number = decl.src_line + 1; |
| 4682 | const is_internal_linkage = !o.module.decl_exports.contains(decl_index); |
| 4840 | 4683 | |
| 4841 | | try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode()); |
| 4842 | | if (!is_internal_linkage or decl.isExtern(mod)) |
| 4843 | | variable_index.toLlvm(&o.builder).attachMetaData(di_global); |
| 4844 | | } |
| 4684 | if (dg.object.builder.strip) return; |
| 4685 | |
| 4686 | const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope); |
| 4687 | |
| 4688 | const debug_global_var = try o.builder.debugGlobalVar( |
| 4689 | try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // Name |
| 4690 | variable_index.name(&o.builder), // Linkage name |
| 4691 | debug_file, // File |
| 4692 | debug_file, // Scope |
| 4693 | line_number, |
| 4694 | try o.lowerDebugType(decl.ty), |
| 4695 | variable_index, |
| 4696 | .{ .local = is_internal_linkage }, |
| 4697 | ); |
| 4698 | |
| 4699 | const debug_expression = try o.builder.debugExpression(&.{}); |
| 4700 | |
| 4701 | const debug_global_var_expression = try o.builder.debugGlobalVarExpression( |
| 4702 | debug_global_var, |
| 4703 | debug_expression, |
| 4704 | ); |
| 4705 | |
| 4706 | try o.debug_globals.append(o.gpa, debug_global_var_expression); |
| 4845 | 4707 | } |
| 4846 | 4708 | } |
| 4847 | 4709 | }; |
| ... | ... | @@ -4852,19 +4714,23 @@ pub const FuncGen = struct { |
| 4852 | 4714 | air: Air, |
| 4853 | 4715 | liveness: Liveness, |
| 4854 | 4716 | wip: Builder.WipFunction, |
| 4855 | | di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn, |
| 4856 | | di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn, |
| 4717 | |
| 4718 | file: Builder.Metadata, |
| 4719 | subprogram: Builder.Metadata, |
| 4720 | current_scope: Builder.Metadata, |
| 4721 | |
| 4722 | inlined: std.ArrayListUnmanaged(struct { |
| 4723 | base_line: u32, |
| 4724 | location: Builder.Metadata, |
| 4725 | scope: Builder.Metadata, |
| 4726 | }) = .{}, |
| 4727 | |
| 4728 | scope_stack: std.ArrayListUnmanaged(Builder.Metadata) = .{}, |
| 4729 | |
| 4857 | 4730 | base_line: u32, |
| 4858 | 4731 | prev_dbg_line: c_uint, |
| 4859 | 4732 | prev_dbg_column: c_uint, |
| 4860 | 4733 | |
| 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 | 4734 | /// This stores the LLVM values used in a function, such that they can be referred to |
| 4869 | 4735 | /// in other instructions. This table is cleared before every function is generated. |
| 4870 | 4736 | func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, Builder.Value), |
| ... | ... | @@ -4905,8 +4771,8 @@ pub const FuncGen = struct { |
| 4905 | 4771 | |
| 4906 | 4772 | fn deinit(self: *FuncGen) void { |
| 4907 | 4773 | self.wip.deinit(); |
| 4908 | | self.dbg_inlined.deinit(self.gpa); |
| 4909 | | self.dbg_block_stack.deinit(self.gpa); |
| 4774 | self.scope_stack.deinit(self.gpa); |
| 4775 | self.inlined.deinit(self.gpa); |
| 4910 | 4776 | self.func_inst_table.deinit(self.gpa); |
| 4911 | 4777 | self.blocks.deinit(self.gpa); |
| 4912 | 4778 | } |
| ... | ... | @@ -5515,9 +5381,6 @@ pub const FuncGen = struct { |
| 5515 | 5381 | // a different LLVM type than the usual one. We solve this here at the callsite |
| 5516 | 5382 | // by using our canonical type, then loading it if necessary. |
| 5517 | 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 | 5384 | const rp = try self.buildAlloca(abi_ret_ty, alignment); |
| 5522 | 5385 | _ = try self.wip.store(.normal, call, rp, alignment); |
| 5523 | 5386 | return if (isByRef(return_type, mod)) |
| ... | ... | @@ -6675,42 +6538,48 @@ pub const FuncGen = struct { |
| 6675 | 6538 | } |
| 6676 | 6539 | |
| 6677 | 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 | 6542 | const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 6680 | 6543 | self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1); |
| 6681 | 6544 | self.prev_dbg_column = @intCast(dbg_stmt.column + 1); |
| 6682 | | const inlined_at = if (self.dbg_inlined.items.len > 0) |
| 6683 | | self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc |
| 6545 | const inlined_at = if (self.inlined.items.len > 0) |
| 6546 | self.inlined.items[self.inlined.items.len - 1].location |
| 6684 | 6547 | else |
| 6685 | | null; |
| 6686 | | self.wip.llvm.builder.setCurrentDebugLocation( |
| 6687 | | self.prev_dbg_line, |
| 6688 | | self.prev_dbg_column, |
| 6689 | | di_scope, |
| 6690 | | inlined_at, |
| 6691 | | ); |
| 6548 | Builder.Metadata.none; |
| 6549 | |
| 6550 | self.wip.current_debug_location = .{ |
| 6551 | .line = self.prev_dbg_line, |
| 6552 | .column = self.prev_dbg_column, |
| 6553 | .scope = self.current_scope, |
| 6554 | .inlined_at = inlined_at, |
| 6555 | }; |
| 6556 | |
| 6692 | 6557 | return .none; |
| 6693 | 6558 | } |
| 6694 | 6559 | |
| 6695 | 6560 | fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6561 | if (self.wip.builder.strip or true) return .none; |
| 6696 | 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 | 6563 | const zcu = o.module; |
| 6564 | |
| 6565 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; |
| 6701 | 6566 | const func = zcu.funcInfo(ty_fn.func); |
| 6702 | 6567 | const decl_index = func.owner_decl; |
| 6703 | 6568 | const decl = zcu.declPtr(decl_index); |
| 6704 | 6569 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 6705 | 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(); |
| 6710 | 6571 | |
| 6711 | | try self.dbg_inlined.append(self.gpa, .{ |
| 6712 | | .loc = @ptrCast(cur_debug_location), |
| 6713 | | .scope = self.di_scope.?, |
| 6572 | self.file = try o.getDebugFile(namespace.file_scope); |
| 6573 | |
| 6574 | const line_number = decl.src_line + 1; |
| 6575 | try self.inlined.append(self.gpa, .{ |
| 6576 | .location = if (self.wip.current_debug_location) |location| try self.wip.builder.debugLocation( |
| 6577 | location.scope, |
| 6578 | location.line, |
| 6579 | location.column, |
| 6580 | location.inlined_at, |
| 6581 | ) else .none, |
| 6582 | .scope = self.current_scope, |
| 6714 | 6583 | .base_line = self.base_line, |
| 6715 | 6584 | }); |
| 6716 | 6585 | |
| ... | ... | @@ -6721,91 +6590,108 @@ pub const FuncGen = struct { |
| 6721 | 6590 | .param_types = &.{}, |
| 6722 | 6591 | .return_type = .void_type, |
| 6723 | 6592 | }); |
| 6724 | | const fn_di_ty = try o.lowerDebugType(fn_ty, .full); |
| 6725 | | const subprogram = dib.createFunction( |
| 6726 | | di_file.toScope(), |
| 6727 | | zcu.intern_pool.stringToSlice(decl.name), |
| 6728 | | zcu.intern_pool.stringToSlice(fqn), |
| 6729 | | di_file, |
| 6593 | |
| 6594 | const subprogram = try o.builder.debugSubprogram( |
| 6595 | self.file, |
| 6596 | try o.builder.string(zcu.intern_pool.stringToSlice(decl.name)), |
| 6597 | try o.builder.string(zcu.intern_pool.stringToSlice(fqn)), |
| 6730 | 6598 | line_number, |
| 6731 | | fn_di_ty, |
| 6732 | | is_internal_linkage, |
| 6733 | | true, // is definition |
| 6734 | | line_number + func.lbrace_line, // scope line |
| 6735 | | llvm.DIFlags.StaticMember, |
| 6736 | | owner_mod.optimize_mode != .Debug, |
| 6737 | | null, // decl_subprogram |
| 6599 | line_number + func.lbrace_line, |
| 6600 | try o.lowerDebugType(fn_ty), |
| 6601 | .{ |
| 6602 | .optimized = owner_mod.optimize_mode != .Debug, |
| 6603 | .local = is_internal_linkage, |
| 6604 | .definition = true, |
| 6605 | .debug_info_flags = llvm.DIFlags.StaticMember, |
| 6606 | }, |
| 6607 | o.debug_compile_unit, |
| 6738 | 6608 | ); |
| 6739 | 6609 | |
| 6740 | | const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1); |
| 6741 | | self.di_scope = lexical_block.toScope(); |
| 6610 | const lexical_block = try o.builder.debugLexicalBlock( |
| 6611 | subprogram, |
| 6612 | self.file, |
| 6613 | line_number, |
| 6614 | 1, |
| 6615 | ); |
| 6616 | self.current_scope = lexical_block; |
| 6742 | 6617 | self.base_line = decl.src_line; |
| 6743 | 6618 | return .none; |
| 6744 | 6619 | } |
| 6745 | 6620 | |
| 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 | 6623 | const o = self.dg.object; |
| 6748 | | if (o.di_builder == null) return .none; |
| 6624 | |
| 6749 | 6625 | const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; |
| 6750 | 6626 | |
| 6751 | 6627 | const mod = o.module; |
| 6752 | 6628 | const decl = mod.funcOwnerDeclPtr(ty_fn.func); |
| 6753 | | const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); |
| 6754 | | self.di_file = di_file; |
| 6755 | | const old = self.dbg_inlined.pop(); |
| 6756 | | self.di_scope = old.scope; |
| 6629 | self.file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope); |
| 6630 | |
| 6631 | const old = self.inlined.pop(); |
| 6632 | self.current_scope = old.scope; |
| 6757 | 6633 | self.base_line = old.base_line; |
| 6758 | 6634 | return .none; |
| 6759 | 6635 | } |
| 6760 | 6636 | |
| 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 | 6639 | const o = self.dg.object; |
| 6763 | | const dib = o.di_builder orelse return .none; |
| 6764 | | const old_scope = self.di_scope.?; |
| 6765 | | try self.dbg_block_stack.append(self.gpa, old_scope); |
| 6766 | | const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column); |
| 6767 | | self.di_scope = lexical_block.toScope(); |
| 6640 | |
| 6641 | try self.scope_stack.append(self.gpa, self.current_scope); |
| 6642 | |
| 6643 | const old = self.current_scope; |
| 6644 | self.current_scope = try o.builder.debugLexicalBlock( |
| 6645 | self.file, |
| 6646 | old, |
| 6647 | self.prev_dbg_line, |
| 6648 | self.prev_dbg_column, |
| 6649 | ); |
| 6768 | 6650 | return .none; |
| 6769 | 6651 | } |
| 6770 | 6652 | |
| 6771 | 6653 | fn airDbgBlockEnd(self: *FuncGen) !Builder.Value { |
| 6772 | | const o = self.dg.object; |
| 6773 | | if (o.di_builder == null) return .none; |
| 6774 | | self.di_scope = self.dbg_block_stack.pop(); |
| 6654 | if (self.wip.builder.strip) return .none; |
| 6655 | self.current_scope = self.scope_stack.pop(); |
| 6775 | 6656 | return .none; |
| 6776 | 6657 | } |
| 6777 | 6658 | |
| 6778 | 6659 | fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6660 | if (self.wip.builder.strip) return .none; |
| 6779 | 6661 | const o = self.dg.object; |
| 6780 | 6662 | const mod = o.module; |
| 6781 | | const dib = o.di_builder orelse return .none; |
| 6782 | 6663 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6783 | 6664 | const operand = try self.resolveInst(pl_op.operand); |
| 6784 | 6665 | const name = self.air.nullTerminatedString(pl_op.payload); |
| 6785 | 6666 | const ptr_ty = self.typeOf(pl_op.operand); |
| 6786 | 6667 | |
| 6787 | | const di_local_var = dib.createAutoVariable( |
| 6788 | | self.di_scope.?, |
| 6789 | | name.ptr, |
| 6790 | | self.di_file.?, |
| 6668 | const debug_local_var = try o.builder.debugLocalVar( |
| 6669 | try o.builder.string(name), |
| 6670 | self.file, |
| 6671 | self.current_scope, |
| 6791 | 6672 | self.prev_dbg_line, |
| 6792 | | try o.lowerDebugType(ptr_ty.childType(mod), .full), |
| 6793 | | true, // always preserve |
| 6794 | | 0, // flags |
| 6673 | try o.lowerDebugType(ptr_ty.childType(mod)), |
| 6795 | 6674 | ); |
| 6796 | | const inlined_at = if (self.dbg_inlined.items.len > 0) |
| 6797 | | self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc |
| 6798 | | else |
| 6799 | | null; |
| 6800 | | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); |
| 6801 | | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 6802 | | _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 6675 | |
| 6676 | _ = try self.wip.callIntrinsic( |
| 6677 | .normal, |
| 6678 | .none, |
| 6679 | .@"dbg.declare", |
| 6680 | &.{}, |
| 6681 | &.{ |
| 6682 | (try self.wip.debugValue(operand)).toValue(), |
| 6683 | debug_local_var.toValue(), |
| 6684 | (try o.builder.debugExpression(&.{})).toValue(), |
| 6685 | }, |
| 6686 | "", |
| 6687 | ); |
| 6688 | |
| 6803 | 6689 | return .none; |
| 6804 | 6690 | } |
| 6805 | 6691 | |
| 6806 | 6692 | fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 6693 | if (self.wip.builder.strip) return .none; |
| 6807 | 6694 | const o = self.dg.object; |
| 6808 | | const dib = o.di_builder orelse return .none; |
| 6809 | 6695 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 6810 | 6696 | const operand = try self.resolveInst(pl_op.operand); |
| 6811 | 6697 | const operand_ty = self.typeOf(pl_op.operand); |
| ... | ... | @@ -6813,32 +6699,58 @@ pub const FuncGen = struct { |
| 6813 | 6699 | |
| 6814 | 6700 | if (needDbgVarWorkaround(o)) return .none; |
| 6815 | 6701 | |
| 6816 | | const di_local_var = dib.createAutoVariable( |
| 6817 | | self.di_scope.?, |
| 6818 | | name.ptr, |
| 6819 | | self.di_file.?, |
| 6702 | const debug_local_var = try o.builder.debugLocalVar( |
| 6703 | try o.builder.string(name), |
| 6704 | self.file, |
| 6705 | self.current_scope, |
| 6820 | 6706 | self.prev_dbg_line, |
| 6821 | | try o.lowerDebugType(operand_ty, .full), |
| 6822 | | true, // always preserve |
| 6823 | | 0, // flags |
| 6707 | try o.lowerDebugType(operand_ty), |
| 6824 | 6708 | ); |
| 6825 | | const inlined_at = if (self.dbg_inlined.items.len > 0) |
| 6826 | | self.dbg_inlined.items[self.dbg_inlined.items.len - 1].loc |
| 6827 | | else |
| 6828 | | null; |
| 6829 | | const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); |
| 6830 | | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 6709 | |
| 6831 | 6710 | const zcu = o.module; |
| 6832 | 6711 | const owner_mod = self.dg.ownerModule(); |
| 6833 | 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 | 6725 | } else if (owner_mod.optimize_mode == .Debug) { |
| 6836 | 6726 | const alignment = operand_ty.abiAlignment(zcu).toLlvm(); |
| 6837 | 6727 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); |
| 6838 | 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 | 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 | 6755 | return .none; |
| 6844 | 6756 | } |
| ... | ... | @@ -8860,41 +8772,80 @@ pub const FuncGen = struct { |
| 8860 | 8772 | const arg_val = self.args[self.arg_index]; |
| 8861 | 8773 | self.arg_index += 1; |
| 8862 | 8774 | |
| 8775 | if (self.wip.builder.strip) return arg_val; |
| 8776 | |
| 8863 | 8777 | const inst_ty = self.typeOfIndex(inst); |
| 8864 | | if (o.di_builder) |dib| { |
| 8865 | | if (needDbgVarWorkaround(o)) return arg_val; |
| 8866 | | |
| 8867 | | const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index; |
| 8868 | | const func_index = self.dg.decl.getOwnedFunctionIndex(); |
| 8869 | | const func = mod.funcInfo(func_index); |
| 8870 | | const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; |
| 8871 | | const lbrace_col = func.lbrace_column + 1; |
| 8872 | | const di_local_var = dib.createParameterVariable( |
| 8873 | | self.di_scope.?, |
| 8874 | | mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args |
| 8875 | | self.di_file.?, |
| 8876 | | lbrace_line, |
| 8877 | | try o.lowerDebugType(inst_ty, .full), |
| 8878 | | true, // always preserve |
| 8879 | | 0, // flags |
| 8880 | | @intCast(self.arg_index), // includes +1 because 0 is return type |
| 8881 | | ); |
| 8778 | if (needDbgVarWorkaround(o)) return arg_val; |
| 8779 | |
| 8780 | const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index; |
| 8781 | const func_index = self.dg.decl.getOwnedFunctionIndex(); |
| 8782 | const func = mod.funcInfo(func_index); |
| 8783 | const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; |
| 8784 | const lbrace_col = func.lbrace_column + 1; |
| 8785 | |
| 8786 | const debug_parameter = try o.builder.debugParameter( |
| 8787 | try o.builder.string(mod.getParamName(func_index, src_index)), |
| 8788 | self.file, |
| 8789 | self.current_scope, |
| 8790 | lbrace_line, |
| 8791 | try o.lowerDebugType(inst_ty), |
| 8792 | @intCast(self.arg_index), |
| 8793 | ); |
| 8882 | 8794 | |
| 8883 | | const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); |
| 8884 | | const insert_block = self.wip.cursor.block.toLlvm(&self.wip); |
| 8885 | | const owner_mod = self.dg.ownerModule(); |
| 8886 | | if (isByRef(inst_ty, mod)) { |
| 8887 | | _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 8888 | | } else if (owner_mod.optimize_mode == .Debug) { |
| 8889 | | const alignment = inst_ty.abiAlignment(mod).toLlvm(); |
| 8890 | | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); |
| 8891 | | _ = try self.wip.store(.normal, arg_val, alloca, alignment); |
| 8892 | | _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 8893 | | } else { |
| 8894 | | _ = dib.insertDbgValueIntrinsicAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); |
| 8895 | | } |
| 8795 | const old_location = self.wip.current_debug_location; |
| 8796 | self.wip.current_debug_location = .{ |
| 8797 | .line = lbrace_line, |
| 8798 | .column = lbrace_col, |
| 8799 | .scope = self.current_scope, |
| 8800 | .inlined_at = Builder.Metadata.none, |
| 8801 | }; |
| 8802 | |
| 8803 | const owner_mod = self.dg.ownerModule(); |
| 8804 | if (isByRef(inst_ty, mod)) { |
| 8805 | _ = try self.wip.callIntrinsic( |
| 8806 | .normal, |
| 8807 | .none, |
| 8808 | .@"dbg.declare", |
| 8809 | &.{}, |
| 8810 | &.{ |
| 8811 | (try self.wip.debugValue(arg_val)).toValue(), |
| 8812 | debug_parameter.toValue(), |
| 8813 | (try o.builder.debugExpression(&.{})).toValue(), |
| 8814 | }, |
| 8815 | "", |
| 8816 | ); |
| 8817 | } else if (owner_mod.optimize_mode == .Debug) { |
| 8818 | const alignment = inst_ty.abiAlignment(mod).toLlvm(); |
| 8819 | const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); |
| 8820 | _ = try self.wip.store(.normal, arg_val, alloca, alignment); |
| 8821 | _ = try self.wip.callIntrinsic( |
| 8822 | .normal, |
| 8823 | .none, |
| 8824 | .@"dbg.declare", |
| 8825 | &.{}, |
| 8826 | &.{ |
| 8827 | (try self.wip.debugValue(alloca)).toValue(), |
| 8828 | debug_parameter.toValue(), |
| 8829 | (try o.builder.debugExpression(&.{})).toValue(), |
| 8830 | }, |
| 8831 | "", |
| 8832 | ); |
| 8833 | } else { |
| 8834 | _ = try self.wip.callIntrinsic( |
| 8835 | .normal, |
| 8836 | .none, |
| 8837 | .@"dbg.value", |
| 8838 | &.{}, |
| 8839 | &.{ |
| 8840 | (try self.wip.debugValue(arg_val)).toValue(), |
| 8841 | debug_parameter.toValue(), |
| 8842 | (try o.builder.debugExpression(&.{})).toValue(), |
| 8843 | }, |
| 8844 | "", |
| 8845 | ); |
| 8896 | 8846 | } |
| 8897 | 8847 | |
| 8848 | self.wip.current_debug_location = old_location; |
| 8898 | 8849 | return arg_val; |
| 8899 | 8850 | } |
| 8900 | 8851 | |
| ... | ... | @@ -8932,7 +8883,7 @@ pub const FuncGen = struct { |
| 8932 | 8883 | alignment: Builder.Alignment, |
| 8933 | 8884 | ) Allocator.Error!Builder.Value { |
| 8934 | 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 | } |
| 8937 | 8888 | |
| 8938 | 8889 | // Workaround for https://github.com/ziglang/zig/issues/16392 |
| ... | ... | @@ -11716,45 +11667,6 @@ const struct_layout_version = 2; |
| 11716 | 11667 | // https://github.com/llvm/llvm-project/issues/56585/ is fixed |
| 11717 | 11668 | const optional_layout_version = 3; |
| 11718 | 11669 | |
| 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. |
| 11722 | | const 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 | | |
| 11758 | 11670 | const lt_errors_fn_name = "__zig_lt_errors_len"; |
| 11759 | 11671 | |
| 11760 | 11672 | /// Without this workaround, LLVM crashes with "unknown codeview register H1" |
| ... | ... | @@ -11778,7 +11690,6 @@ fn compilerRtIntBits(bits: u16) u16 { |
| 11778 | 11690 | |
| 11779 | 11691 | fn buildAllocaInner( |
| 11780 | 11692 | wip: *Builder.WipFunction, |
| 11781 | | di_scope_non_null: bool, |
| 11782 | 11693 | llvm_ty: Builder.Type, |
| 11783 | 11694 | alignment: Builder.Alignment, |
| 11784 | 11695 | target: std.Target, |
| ... | ... | @@ -11787,19 +11698,15 @@ fn buildAllocaInner( |
| 11787 | 11698 | |
| 11788 | 11699 | const alloca = blk: { |
| 11789 | 11700 | const prev_cursor = wip.cursor; |
| 11790 | | const prev_debug_location = if (wip.builder.useLibLlvm()) |
| 11791 | | wip.llvm.builder.getCurrentDebugLocation2() |
| 11792 | | else |
| 11793 | | undefined; |
| 11701 | const prev_debug_location = wip.current_debug_location; |
| 11794 | 11702 | defer { |
| 11795 | 11703 | wip.cursor = prev_cursor; |
| 11796 | 11704 | if (wip.cursor.block == .entry) wip.cursor.instruction += 1; |
| 11797 | | if (wip.builder.useLibLlvm() and di_scope_non_null) |
| 11798 | | wip.llvm.builder.setCurrentDebugLocation2(prev_debug_location); |
| 11705 | wip.current_debug_location = prev_debug_location; |
| 11799 | 11706 | } |
| 11800 | 11707 | |
| 11801 | 11708 | wip.cursor = .{ .block = .entry }; |
| 11802 | | if (wip.builder.useLibLlvm()) wip.llvm.builder.clearCurrentDebugLocation(); |
| 11709 | wip.current_debug_location = null; |
| 11803 | 11710 | break :blk try wip.alloca(.normal, llvm_ty, .none, alignment, address_space, ""); |
| 11804 | 11711 | }; |
| 11805 | 11712 | |