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