authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-08 21:09:20-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-08 21:09:20-05:00
loga91753219df5d0b51f55dcad3e2ef96044efdd62
tree11c840f3f7405eba160c7876e64b696e08e6fd3e
parent935d208ffb955e74864e12f0f7e265f64642a02f
parentfb4ad37e0bd07513a0a56afb45e95c68036b1eea
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11085 from ziglang/llvm-debug-info

stage2 LLVM debug info

12 files changed, 1417 insertions(+), 81 deletions(-)

doc/langref.html.in+1-1
......@@ -1317,7 +1317,7 @@ const @"identifier with spaces in it" = 0xff;
13171317const @"1SmallStep4Man" = 112358;
13181318
13191319const c = @import("std").c;
1320pub extern "c" fn @"error"() anyopaque;
1320pub extern "c" fn @"error"() void;
13211321pub extern "c" fn @"fstat$INODE64"(fd: c.fd_t, buf: *c.Stat) c_int;
13221322
13231323const Color = enum {
lib/std/dwarf.zig+15
......@@ -226,6 +226,21 @@ pub const LNCT = struct {
226226 pub const hi_user = 0x3fff;
227227};
228228
229pub const CC = enum(u8) {
230 normal = 0x1,
231 program = 0x2,
232 nocall = 0x3,
233
234 pass_by_reference = 0x4,
235 pass_by_value = 0x5,
236
237 lo_user = 0x40,
238 hi_user = 0xff,
239
240 GNU_renesas_sh = 0x40,
241 GNU_borland_fastcall_i386 = 0x41,
242};
243
229244const PcRange = struct {
230245 start: u64,
231246 end: u64,
src/Compilation.zig+1-1
......@@ -898,7 +898,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
898898 // We put the `Compilation` itself in the arena. Freeing the arena will free the module.
899899 // It's initialized later after we prepare the initialization options.
900900 const comp = try arena.create(Compilation);
901 const root_name = try arena.dupe(u8, options.root_name);
901 const root_name = try arena.dupeZ(u8, options.root_name);
902902
903903 const ofmt = options.object_format orelse options.target.getObjectFormat();
904904
src/Sema.zig+1-1
......@@ -12399,7 +12399,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1239912399 var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded);
1240012400 defer anon_decl.deinit();
1240112401
12402 const bytes = try ty.nameAlloc(anon_decl.arena());
12402 const bytes = try ty.nameAllocArena(anon_decl.arena());
1240312403
1240412404 const new_decl = try anon_decl.finish(
1240512405 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
src/codegen/llvm.zig+956-26
......@@ -5,12 +5,14 @@ const Allocator = std.mem.Allocator;
55const log = std.log.scoped(.codegen);
66const math = std.math;
77const native_endian = builtin.cpu.arch.endian();
8const DW = std.dwarf;
89
910const llvm = @import("llvm/bindings.zig");
1011const link = @import("../link.zig");
1112const Compilation = @import("../Compilation.zig");
1213const build_options = @import("build_options");
1314const Module = @import("../Module.zig");
15const Package = @import("../Package.zig");
1416const TypedValue = @import("../TypedValue.zig");
1517const Air = @import("../Air.zig");
1618const Liveness = @import("../Liveness.zig");
......@@ -159,6 +161,12 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
159161
160162pub const Object = struct {
161163 llvm_module: *const llvm.Module,
164 di_builder: ?*llvm.DIBuilder,
165 /// One of these mappings:
166 /// - *Module.File => *DIFile
167 /// - *Module.Decl => *DISubprogram
168 di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DIScope),
169 di_compile_unit: ?*llvm.DICompileUnit,
162170 context: *const llvm.Context,
163171 target_machine: *const llvm.TargetMachine,
164172 target_data: *const llvm.TargetData,
......@@ -180,8 +188,10 @@ pub const Object = struct {
180188 /// The backing memory for `type_map`. Periodically garbage collected after flush().
181189 /// The code for doing the periodical GC is not yet implemented.
182190 type_map_arena: std.heap.ArenaAllocator,
183 /// The LLVM global table which holds the names corresponding to Zig errors. Note that the values
184 /// are not added until flushModule, when all errors in the compilation are known.
191 di_type_map: DITypeMap,
192 /// The LLVM global table which holds the names corresponding to Zig errors.
193 /// Note that the values are not added until flushModule, when all errors in
194 /// the compilation are known.
185195 error_name_table: ?*const llvm.Value,
186196
187197 pub const TypeMap = std.HashMapUnmanaged(
......@@ -191,6 +201,13 @@ pub const Object = struct {
191201 std.hash_map.default_max_load_percentage,
192202 );
193203
204 pub const DITypeMap = std.HashMapUnmanaged(
205 Type,
206 *llvm.DIType,
207 Type.HashContext64,
208 std.hash_map.default_max_load_percentage,
209 );
210
194211 pub fn create(gpa: Allocator, options: link.Options) !*Object {
195212 const obj = try gpa.create(Object);
196213 errdefer gpa.destroy(obj);
......@@ -204,9 +221,7 @@ pub const Object = struct {
204221
205222 initializeLLVMTarget(options.target.cpu.arch);
206223
207 const root_nameZ = try gpa.dupeZ(u8, options.root_name);
208 defer gpa.free(root_nameZ);
209 const llvm_module = llvm.Module.createWithName(root_nameZ.ptr, context);
224 const llvm_module = llvm.Module.createWithName(options.root_name.ptr, context);
210225 errdefer llvm_module.dispose();
211226
212227 const llvm_target_triple = try targetTriple(gpa, options.target);
......@@ -221,6 +236,60 @@ pub const Object = struct {
221236 return error.InvalidLlvmTriple;
222237 }
223238
239 llvm_module.setTarget(llvm_target_triple.ptr);
240 var opt_di_builder: ?*llvm.DIBuilder = null;
241 errdefer if (opt_di_builder) |di_builder| di_builder.dispose();
242
243 var di_compile_unit: ?*llvm.DICompileUnit = null;
244
245 if (!options.strip) {
246 switch (options.object_format) {
247 .coff => llvm_module.addModuleCodeViewFlag(),
248 else => llvm_module.addModuleDebugInfoFlag(),
249 }
250 const di_builder = llvm_module.createDIBuilder(true);
251 opt_di_builder = di_builder;
252
253 // Don't use the version string here; LLVM misparses it when it
254 // includes the git revision.
255 const producer = try std.fmt.allocPrintZ(gpa, "zig {d}.{d}.{d}", .{
256 build_options.semver.major,
257 build_options.semver.minor,
258 build_options.semver.patch,
259 });
260 defer gpa.free(producer);
261
262 // For macOS stack traces, we want to avoid having to parse the compilation unit debug
263 // info. As long as each debug info file has a path independent of the compilation unit
264 // directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug
265 // info. If we provide an absolute path to LLVM here for the compilation unit debug
266 // info, LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we
267 // pass "." for the compilation unit directory. This forces each debug file to have a
268 // directory rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug
269 // files will no longer reference DW_AT_comp_dir, for the purpose of being able to
270 // support the common practice of stripping all but the line number sections from an
271 // executable.
272 const compile_unit_dir = d: {
273 if (options.target.isDarwin()) break :d ".";
274 const mod = options.module orelse break :d ".";
275 break :d mod.root_pkg.root_src_directory.path orelse ".";
276 };
277 const compile_unit_dir_z = try gpa.dupeZ(u8, compile_unit_dir);
278 defer gpa.free(compile_unit_dir_z);
279
280 di_compile_unit = di_builder.createCompileUnit(
281 DW.LANG.C99,
282 di_builder.createFile(options.root_name, compile_unit_dir_z),
283 producer,
284 options.optimize_mode != .Debug,
285 "", // flags
286 0, // runtime version
287 "", // split name
288 0, // dwo id
289 true, // emit debug info
290 );
291 }
292
224293 const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug)
225294 .None
226295 else
......@@ -266,17 +335,26 @@ pub const Object = struct {
266335
267336 return Object{
268337 .llvm_module = llvm_module,
338 .di_map = .{},
339 .di_builder = opt_di_builder,
340 .di_compile_unit = di_compile_unit,
269341 .context = context,
270342 .target_machine = target_machine,
271343 .target_data = target_data,
272344 .decl_map = .{},
273345 .type_map = .{},
274346 .type_map_arena = std.heap.ArenaAllocator.init(gpa),
347 .di_type_map = .{},
275348 .error_name_table = null,
276349 };
277350 }
278351
279352 pub fn deinit(self: *Object, gpa: Allocator) void {
353 if (self.di_builder) |dib| {
354 dib.dispose();
355 self.di_map.deinit(gpa);
356 self.di_type_map.deinit(gpa);
357 }
280358 self.target_data.dispose();
281359 self.target_machine.dispose();
282360 self.llvm_module.dispose();
......@@ -357,6 +435,9 @@ pub const Object = struct {
357435
358436 pub fn flushModule(self: *Object, comp: *Compilation) !void {
359437 try self.genErrorNameTable(comp);
438
439 if (self.di_builder) |dib| dib.finalize();
440
360441 if (comp.verbose_llvm_ir) {
361442 self.llvm_module.dump();
362443 }
......@@ -470,8 +551,9 @@ pub const Object = struct {
470551 const target = dg.module.getTarget();
471552 const sret = firstParamSRet(fn_info, target);
472553 const ret_ptr = if (sret) llvm_func.getParam(0) else null;
554 const gpa = dg.gpa;
473555
474 var args = std.ArrayList(*const llvm.Value).init(dg.gpa);
556 var args = std.ArrayList(*const llvm.Value).init(gpa);
475557 defer args.deinit();
476558
477559 const param_offset: c_uint = @boolToInt(ret_ptr != null);
......@@ -482,8 +564,41 @@ pub const Object = struct {
482564 try args.append(llvm_func.getParam(llvm_arg_i));
483565 }
484566
567 var di_file: ?*llvm.DIFile = null;
568 var di_scope: ?*llvm.DIScope = null;
569
570 if (dg.object.di_builder) |dib| {
571 di_file = try dg.object.getDIFile(gpa, decl.src_namespace.file_scope);
572
573 const line_number = decl.src_line + 1;
574 const is_internal_linkage = decl.val.tag() != .extern_fn and
575 !dg.module.decl_exports.contains(decl);
576 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
577 llvm.DIFlags.NoReturn
578 else
579 0;
580 const subprogram = dib.createFunction(
581 di_file.?.toScope(),
582 decl.name,
583 llvm_func.getValueName(),
584 di_file.?,
585 line_number,
586 try dg.lowerDebugType(decl.ty),
587 is_internal_linkage,
588 true, // is definition
589 line_number + func.lbrace_line, // scope line
590 llvm.DIFlags.StaticMember | noret_bit,
591 dg.module.comp.bin_file.options.optimize_mode != .Debug,
592 null, // decl_subprogram
593 );
594
595 llvm_func.fnSetSubprogram(subprogram);
596
597 di_scope = subprogram.toScope();
598 }
599
485600 var fg: FuncGen = .{
486 .gpa = dg.gpa,
601 .gpa = gpa,
487602 .air = air,
488603 .liveness = liveness,
489604 .context = dg.context,
......@@ -496,6 +611,8 @@ pub const Object = struct {
496611 .llvm_func = llvm_func,
497612 .blocks = .{},
498613 .single_threaded = module.comp.bin_file.options.single_threaded,
614 .di_scope = di_scope,
615 .di_file = di_file,
499616 };
500617 defer fg.deinit();
501618
......@@ -599,6 +716,22 @@ pub const Object = struct {
599716 const llvm_value = self.decl_map.get(decl) orelse return;
600717 llvm_value.deleteGlobal();
601718 }
719
720 fn getDIFile(o: *Object, gpa: Allocator, file: *const Module.File) !*llvm.DIFile {
721 const gop = try o.di_map.getOrPut(gpa, file);
722 errdefer assert(o.di_map.remove(file));
723 if (gop.found_existing) {
724 return @ptrCast(*llvm.DIFile, gop.value_ptr.*);
725 }
726 const dir_path = file.pkg.root_src_directory.path orelse ".";
727 const sub_file_path_z = try gpa.dupeZ(u8, file.sub_file_path);
728 defer gpa.free(sub_file_path_z);
729 const dir_path_z = try gpa.dupeZ(u8, dir_path);
730 defer gpa.free(dir_path_z);
731 const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);
732 gop.value_ptr.* = di_file.toScope();
733 return di_file;
734 }
602735};
603736
604737pub const DeclGen = struct {
......@@ -942,15 +1075,13 @@ pub const DeclGen = struct {
9421075 },
9431076 .Optional => {
9441077 var buf: Type.Payload.ElemType = undefined;
945 const child_type = t.optionalChild(&buf);
946 if (!child_type.hasRuntimeBits()) {
1078 const child_ty = t.optionalChild(&buf);
1079 if (!child_ty.hasRuntimeBits()) {
9471080 return dg.context.intType(1);
9481081 }
949 const payload_llvm_ty = try dg.llvmType(child_type);
1082 const payload_llvm_ty = try dg.llvmType(child_ty);
9501083 if (t.isPtrLikeOptional()) {
9511084 return payload_llvm_ty;
952 } else if (!child_type.hasRuntimeBits()) {
953 return dg.context.intType(1);
9541085 }
9551086
9561087 const fields: [2]*const llvm.Type = .{
......@@ -1771,6 +1902,768 @@ pub const DeclGen = struct {
17711902 }
17721903 }
17731904
1905 fn lowerDebugType(dg: *DeclGen, ty: Type) Allocator.Error!*llvm.DIType {
1906 const gpa = dg.gpa;
1907 // Be careful not to reference this `gop` variable after any recursive calls
1908 // to `lowerDebugType`.
1909 const gop = try dg.object.di_type_map.getOrPut(gpa, ty);
1910 if (gop.found_existing) return gop.value_ptr.*;
1911 errdefer assert(dg.object.di_type_map.remove(ty));
1912 // The Type memory is ephemeral; since we want to store a longer-lived
1913 // reference, we need to copy it here.
1914 gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator());
1915 const target = dg.module.getTarget();
1916 const dib = dg.object.di_builder.?;
1917 switch (ty.zigTypeTag()) {
1918 .Void, .NoReturn => {
1919 gop.value_ptr.* = dib.createBasicType("void", 0, DW.ATE.signed);
1920 return gop.value_ptr.*;
1921 },
1922 .Int => {
1923 const info = ty.intInfo(target);
1924 assert(info.bits != 0);
1925 const name = try ty.nameAlloc(gpa);
1926 defer gpa.free(name);
1927 const dwarf_encoding: c_uint = switch (info.signedness) {
1928 .signed => DW.ATE.signed,
1929 .unsigned => DW.ATE.unsigned,
1930 };
1931 gop.value_ptr.* = dib.createBasicType(name, info.bits, dwarf_encoding);
1932 return gop.value_ptr.*;
1933 },
1934 .Enum => {
1935 const owner_decl = ty.getOwnerDecl();
1936
1937 if (!ty.hasRuntimeBits()) {
1938 const enum_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);
1939 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1940 // means we can't use `gop` anymore.
1941 try dg.object.di_type_map.put(gpa, ty, enum_di_ty);
1942 return enum_di_ty;
1943 }
1944
1945 const field_names = ty.enumFields().keys();
1946
1947 const enumerators = try gpa.alloc(*llvm.DIEnumerator, field_names.len);
1948 defer gpa.free(enumerators);
1949
1950 var buf_field_index: Value.Payload.U32 = .{
1951 .base = .{ .tag = .enum_field_index },
1952 .data = undefined,
1953 };
1954 const field_index_val = Value.initPayload(&buf_field_index.base);
1955
1956 for (field_names) |field_name, i| {
1957 const field_name_z = try gpa.dupeZ(u8, field_name);
1958 defer gpa.free(field_name_z);
1959
1960 buf_field_index.data = @intCast(u32, i);
1961 var buf_u64: Value.Payload.U64 = undefined;
1962 const field_int_val = field_index_val.enumToInt(ty, &buf_u64);
1963 // See https://github.com/ziglang/zig/issues/645
1964 const field_int = field_int_val.toSignedInt();
1965 enumerators[i] = dib.createEnumerator(field_name_z, field_int);
1966 }
1967
1968 const di_file = try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope);
1969 const di_scope = try dg.namespaceToDebugScope(owner_decl.src_namespace);
1970
1971 const name = try ty.nameAlloc(gpa);
1972 defer gpa.free(name);
1973 var buffer: Type.Payload.Bits = undefined;
1974 const int_ty = ty.intTagType(&buffer);
1975
1976 const enum_di_ty = dib.createEnumerationType(
1977 di_scope,
1978 name,
1979 di_file,
1980 owner_decl.src_node + 1,
1981 ty.abiSize(target) * 8,
1982 ty.abiAlignment(target) * 8,
1983 enumerators.ptr,
1984 @intCast(c_int, enumerators.len),
1985 try lowerDebugType(dg, int_ty),
1986 "",
1987 );
1988 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1989 try dg.object.di_type_map.put(gpa, ty, enum_di_ty);
1990 return enum_di_ty;
1991 },
1992 .Float => {
1993 const bits = ty.floatBits(target);
1994 const name = try ty.nameAlloc(gpa);
1995 defer gpa.free(name);
1996 gop.value_ptr.* = dib.createBasicType(name, bits, DW.ATE.float);
1997 return gop.value_ptr.*;
1998 },
1999 .Bool => {
2000 gop.value_ptr.* = dib.createBasicType("bool", 1, DW.ATE.boolean);
2001 return gop.value_ptr.*;
2002 },
2003 .Pointer => {
2004 // Normalize everything that the debug info does not represent.
2005 const ptr_info = ty.ptrInfo().data;
2006
2007 if (ptr_info.sentinel != null or
2008 ptr_info.@"addrspace" != .generic or
2009 ptr_info.bit_offset != 0 or
2010 ptr_info.host_size != 0 or
2011 ptr_info.@"allowzero" or
2012 !ptr_info.mutable or
2013 ptr_info.@"volatile" or
2014 ptr_info.size == .Many or ptr_info.size == .C)
2015 {
2016 var payload: Type.Payload.Pointer = .{
2017 .data = .{
2018 .pointee_type = ptr_info.pointee_type,
2019 .sentinel = null,
2020 .@"align" = ptr_info.@"align",
2021 .@"addrspace" = .generic,
2022 .bit_offset = 0,
2023 .host_size = 0,
2024 .@"allowzero" = false,
2025 .mutable = true,
2026 .@"volatile" = false,
2027 .size = switch (ptr_info.size) {
2028 .Many, .C, .One => .One,
2029 .Slice => .Slice,
2030 },
2031 },
2032 };
2033 const bland_ptr_ty = Type.initPayload(&payload.base);
2034 const ptr_di_ty = try dg.lowerDebugType(bland_ptr_ty);
2035 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2036 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);
2037 return ptr_di_ty;
2038 }
2039
2040 if (ty.isSlice()) {
2041 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2042 const ptr_ty = ty.slicePtrFieldType(&buf);
2043 const len_ty = Type.usize;
2044
2045 const name = try ty.nameAlloc(gpa);
2046 defer gpa.free(name);
2047 const di_file: ?*llvm.DIFile = null;
2048 const line = 0;
2049 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2050 const fwd_decl = dib.createReplaceableCompositeType(
2051 DW.TAG.structure_type,
2052 name.ptr,
2053 compile_unit_scope,
2054 di_file,
2055 line,
2056 );
2057 gop.value_ptr.* = fwd_decl;
2058
2059 const ptr_size = ptr_ty.abiSize(target);
2060 const ptr_align = ptr_ty.abiAlignment(target);
2061 const len_size = len_ty.abiSize(target);
2062 const len_align = len_ty.abiAlignment(target);
2063
2064 var offset: u64 = 0;
2065 offset += ptr_size;
2066 offset = std.mem.alignForwardGeneric(u64, offset, len_align);
2067 const len_offset = offset;
2068
2069 const fields: [2]*llvm.DIType = .{
2070 dib.createMemberType(
2071 fwd_decl.toScope(),
2072 "ptr",
2073 di_file,
2074 line,
2075 ptr_size * 8, // size in bits
2076 ptr_align * 8, // align in bits
2077 0, // offset in bits
2078 0, // flags
2079 try dg.lowerDebugType(ptr_ty),
2080 ),
2081 dib.createMemberType(
2082 fwd_decl.toScope(),
2083 "len",
2084 di_file,
2085 line,
2086 len_size * 8, // size in bits
2087 len_align * 8, // align in bits
2088 len_offset * 8, // offset in bits
2089 0, // flags
2090 try dg.lowerDebugType(len_ty),
2091 ),
2092 };
2093
2094 const replacement_di_ty = dib.createStructType(
2095 compile_unit_scope,
2096 name.ptr,
2097 di_file,
2098 line,
2099 ty.abiSize(target) * 8, // size in bits
2100 ty.abiAlignment(target) * 8, // align in bits
2101 0, // flags
2102 null, // derived from
2103 &fields,
2104 fields.len,
2105 0, // run time lang
2106 null, // vtable holder
2107 "", // unique id
2108 );
2109 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2110 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2111 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2112 return replacement_di_ty;
2113 }
2114
2115 const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type);
2116 const name = try ty.nameAlloc(gpa);
2117 defer gpa.free(name);
2118 const ptr_di_ty = dib.createPointerType(
2119 elem_di_ty,
2120 target.cpu.arch.ptrBitWidth(),
2121 ty.ptrAlignment(target) * 8,
2122 name,
2123 );
2124 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2125 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);
2126 return ptr_di_ty;
2127 },
2128 .Opaque => {
2129 if (ty.tag() == .anyopaque) {
2130 gop.value_ptr.* = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
2131 return gop.value_ptr.*;
2132 }
2133 const name = try ty.nameAlloc(gpa);
2134 defer gpa.free(name);
2135 const owner_decl = ty.getOwnerDecl();
2136 const opaque_di_ty = dib.createForwardDeclType(
2137 DW.TAG.structure_type,
2138 name,
2139 try dg.namespaceToDebugScope(owner_decl.src_namespace),
2140 try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope),
2141 owner_decl.src_node + 1,
2142 );
2143 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
2144 // means we can't use `gop` anymore.
2145 try dg.object.di_type_map.put(gpa, ty, opaque_di_ty);
2146 return opaque_di_ty;
2147 },
2148 .Array => {
2149 const array_di_ty = dib.createArrayType(
2150 ty.abiSize(target) * 8,
2151 ty.abiAlignment(target) * 8,
2152 try lowerDebugType(dg, ty.childType()),
2153 @intCast(c_int, ty.arrayLen()),
2154 );
2155 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2156 try dg.object.di_type_map.put(gpa, ty, array_di_ty);
2157 return array_di_ty;
2158 },
2159 .Vector => {
2160 const vector_di_ty = dib.createVectorType(
2161 ty.abiSize(target) * 8,
2162 ty.abiAlignment(target) * 8,
2163 try lowerDebugType(dg, ty.childType()),
2164 ty.vectorLen(),
2165 );
2166 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2167 try dg.object.di_type_map.put(gpa, ty, vector_di_ty);
2168 return vector_di_ty;
2169 },
2170 .Optional => {
2171 const name = try ty.nameAlloc(gpa);
2172 defer gpa.free(name);
2173 var buf: Type.Payload.ElemType = undefined;
2174 const child_ty = ty.optionalChild(&buf);
2175 if (!child_ty.hasRuntimeBits()) {
2176 gop.value_ptr.* = dib.createBasicType(name, 1, DW.ATE.boolean);
2177 return gop.value_ptr.*;
2178 }
2179 if (ty.isPtrLikeOptional()) {
2180 const ptr_di_ty = try dg.lowerDebugType(child_ty);
2181 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2182 try dg.object.di_type_map.put(gpa, ty, ptr_di_ty);
2183 return ptr_di_ty;
2184 }
2185
2186 const di_file: ?*llvm.DIFile = null;
2187 const line = 0;
2188 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2189 const fwd_decl = dib.createReplaceableCompositeType(
2190 DW.TAG.structure_type,
2191 name.ptr,
2192 compile_unit_scope,
2193 di_file,
2194 line,
2195 );
2196 gop.value_ptr.* = fwd_decl;
2197
2198 const non_null_ty = Type.bool;
2199 const payload_size = child_ty.abiSize(target);
2200 const payload_align = child_ty.abiAlignment(target);
2201 const non_null_size = non_null_ty.abiSize(target);
2202 const non_null_align = non_null_ty.abiAlignment(target);
2203
2204 var offset: u64 = 0;
2205 offset += payload_size;
2206 offset = std.mem.alignForwardGeneric(u64, offset, non_null_align);
2207 const non_null_offset = offset;
2208
2209 const fields: [2]*llvm.DIType = .{
2210 dib.createMemberType(
2211 fwd_decl.toScope(),
2212 "data",
2213 di_file,
2214 line,
2215 payload_size * 8, // size in bits
2216 payload_align * 8, // align in bits
2217 0, // offset in bits
2218 0, // flags
2219 try dg.lowerDebugType(child_ty),
2220 ),
2221 dib.createMemberType(
2222 fwd_decl.toScope(),
2223 "some",
2224 di_file,
2225 line,
2226 non_null_size * 8, // size in bits
2227 non_null_align * 8, // align in bits
2228 non_null_offset * 8, // offset in bits
2229 0, // flags
2230 try dg.lowerDebugType(non_null_ty),
2231 ),
2232 };
2233
2234 const replacement_di_ty = dib.createStructType(
2235 compile_unit_scope,
2236 name.ptr,
2237 di_file,
2238 line,
2239 ty.abiSize(target) * 8, // size in bits
2240 ty.abiAlignment(target) * 8, // align in bits
2241 0, // flags
2242 null, // derived from
2243 &fields,
2244 fields.len,
2245 0, // run time lang
2246 null, // vtable holder
2247 "", // unique id
2248 );
2249 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2250 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2251 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2252 return replacement_di_ty;
2253 },
2254 .ErrorUnion => {
2255 const err_set_ty = ty.errorUnionSet();
2256 const payload_ty = ty.errorUnionPayload();
2257 if (!payload_ty.hasRuntimeBits()) {
2258 const err_set_di_ty = try dg.lowerDebugType(err_set_ty);
2259 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2260 try dg.object.di_type_map.put(gpa, ty, err_set_di_ty);
2261 return err_set_di_ty;
2262 }
2263 const name = try ty.nameAlloc(gpa);
2264 defer gpa.free(name);
2265 const di_file: ?*llvm.DIFile = null;
2266 const line = 0;
2267 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2268 const fwd_decl = dib.createReplaceableCompositeType(
2269 DW.TAG.structure_type,
2270 name.ptr,
2271 compile_unit_scope,
2272 di_file,
2273 line,
2274 );
2275 gop.value_ptr.* = fwd_decl;
2276
2277 const err_set_size = err_set_ty.abiSize(target);
2278 const err_set_align = err_set_ty.abiAlignment(target);
2279 const payload_size = payload_ty.abiSize(target);
2280 const payload_align = payload_ty.abiAlignment(target);
2281
2282 var offset: u64 = 0;
2283 offset += err_set_size;
2284 offset = std.mem.alignForwardGeneric(u64, offset, payload_align);
2285 const payload_offset = offset;
2286
2287 const fields: [2]*llvm.DIType = .{
2288 dib.createMemberType(
2289 fwd_decl.toScope(),
2290 "tag",
2291 di_file,
2292 line,
2293 err_set_size * 8, // size in bits
2294 err_set_align * 8, // align in bits
2295 0, // offset in bits
2296 0, // flags
2297 try dg.lowerDebugType(err_set_ty),
2298 ),
2299 dib.createMemberType(
2300 fwd_decl.toScope(),
2301 "value",
2302 di_file,
2303 line,
2304 payload_size * 8, // size in bits
2305 payload_align * 8, // align in bits
2306 payload_offset * 8, // offset in bits
2307 0, // flags
2308 try dg.lowerDebugType(payload_ty),
2309 ),
2310 };
2311
2312 const replacement_di_ty = dib.createStructType(
2313 compile_unit_scope,
2314 name.ptr,
2315 di_file,
2316 line,
2317 ty.abiSize(target) * 8, // size in bits
2318 ty.abiAlignment(target) * 8, // align in bits
2319 0, // flags
2320 null, // derived from
2321 &fields,
2322 fields.len,
2323 0, // run time lang
2324 null, // vtable holder
2325 "", // unique id
2326 );
2327 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2328 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2329 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2330 return replacement_di_ty;
2331 },
2332 .ErrorSet => {
2333 // TODO make this a proper enum with all the error codes in it.
2334 // will need to consider how to take incremental compilation into account.
2335 gop.value_ptr.* = dib.createBasicType("anyerror", 16, DW.ATE.unsigned);
2336 return gop.value_ptr.*;
2337 },
2338 .Struct => {
2339 const compile_unit_scope = dg.object.di_compile_unit.?.toScope();
2340 const name = try ty.nameAlloc(gpa);
2341 defer gpa.free(name);
2342 const fwd_decl = dib.createReplaceableCompositeType(
2343 DW.TAG.structure_type,
2344 name.ptr,
2345 compile_unit_scope,
2346 null, // file
2347 0, // line
2348 );
2349 gop.value_ptr.* = fwd_decl;
2350
2351 if (ty.isTupleOrAnonStruct()) {
2352 const tuple = ty.tupleFields();
2353
2354 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2355 defer di_fields.deinit(gpa);
2356
2357 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2358
2359 comptime assert(struct_layout_version == 2);
2360 var offset: u64 = 0;
2361
2362 for (tuple.types) |field_ty, i| {
2363 const field_val = tuple.values[i];
2364 if (field_val.tag() != .unreachable_value) continue;
2365
2366 const field_size = field_ty.abiSize(target);
2367 const field_align = field_ty.abiAlignment(target);
2368 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2369 offset = field_offset + field_size;
2370
2371 const field_name = if (ty.castTag(.anon_struct)) |payload|
2372 try gpa.dupeZ(u8, payload.data.names[i])
2373 else
2374 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2375 defer gpa.free(field_name);
2376
2377 try di_fields.append(gpa, dib.createMemberType(
2378 fwd_decl.toScope(),
2379 field_name,
2380 null, // file
2381 0, // line
2382 field_size * 8, // size in bits
2383 field_align * 8, // align in bits
2384 field_offset * 8, // offset in bits
2385 0, // flags
2386 try dg.lowerDebugType(field_ty),
2387 ));
2388 }
2389
2390 const replacement_di_ty = dib.createStructType(
2391 compile_unit_scope,
2392 name.ptr,
2393 null, // file
2394 0, // line
2395 ty.abiSize(target) * 8, // size in bits
2396 ty.abiAlignment(target) * 8, // align in bits
2397 0, // flags
2398 null, // derived from
2399 di_fields.items.ptr,
2400 @intCast(c_int, di_fields.items.len),
2401 0, // run time lang
2402 null, // vtable holder
2403 "", // unique id
2404 );
2405 dib.replaceTemporary(fwd_decl, replacement_di_ty);
2406 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2407 try dg.object.di_type_map.put(gpa, ty, replacement_di_ty);
2408 return replacement_di_ty;
2409 }
2410
2411 const TODO_implement_this = true; // TODO
2412 if (TODO_implement_this or !ty.hasRuntimeBits()) {
2413 const owner_decl = ty.getOwnerDecl();
2414 const struct_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);
2415 dib.replaceTemporary(fwd_decl, struct_di_ty);
2416 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2417 // means we can't use `gop` anymore.
2418 try dg.object.di_type_map.put(gpa, ty, struct_di_ty);
2419 return struct_di_ty;
2420 }
2421 @panic("TODO debug info type for struct");
2422
2423 //const struct_obj = ty.castTag(.@"struct").?.data;
2424
2425 //if (struct_obj.layout == .Packed) {
2426 // var buf: Type.Payload.Bits = undefined;
2427 // const int_ty = struct_obj.packedIntegerType(target, &buf);
2428 // const int_llvm_ty = try dg.llvmType(int_ty);
2429 // gop.value_ptr.* = int_llvm_ty;
2430 // return int_llvm_ty;
2431 //}
2432
2433 //const name = try struct_obj.getFullyQualifiedName(gpa);
2434 //defer gpa.free(name);
2435
2436 //const llvm_struct_ty = dg.context.structCreateNamed(name);
2437 //gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2438
2439 //assert(struct_obj.haveFieldTypes());
2440
2441 //var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};
2442 //defer llvm_field_types.deinit(gpa);
2443
2444 //try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count());
2445
2446 //comptime assert(struct_layout_version == 2);
2447 //var offset: u64 = 0;
2448 //var big_align: u32 = 0;
2449
2450 //for (struct_obj.fields.values()) |field| {
2451 // if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
2452
2453 // const field_align = field.normalAlignment(target);
2454 // big_align = @maximum(big_align, field_align);
2455 // const prev_offset = offset;
2456 // offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2457
2458 // const padding_len = offset - prev_offset;
2459 // if (padding_len > 0) {
2460 // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2461 // try llvm_field_types.append(gpa, llvm_array_ty);
2462 // }
2463 // const field_llvm_ty = try dg.llvmType(field.ty);
2464 // try llvm_field_types.append(gpa, field_llvm_ty);
2465
2466 // offset += field.ty.abiSize(target);
2467 //}
2468 //{
2469 // const prev_offset = offset;
2470 // offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2471 // const padding_len = offset - prev_offset;
2472 // if (padding_len > 0) {
2473 // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2474 // try llvm_field_types.append(gpa, llvm_array_ty);
2475 // }
2476 //}
2477
2478 //llvm_struct_ty.structSetBody(
2479 // llvm_field_types.items.ptr,
2480 // @intCast(c_uint, llvm_field_types.items.len),
2481 // .False,
2482 //);
2483
2484 //return llvm_struct_ty;
2485 },
2486 .Union => {
2487 const owner_decl = ty.getOwnerDecl();
2488
2489 const name = try ty.nameAlloc(gpa);
2490 defer gpa.free(name);
2491 const fwd_decl = dib.createReplaceableCompositeType(
2492 DW.TAG.structure_type,
2493 name.ptr,
2494 dg.object.di_compile_unit.?.toScope(),
2495 null, // file
2496 0, // line
2497 );
2498 gop.value_ptr.* = fwd_decl;
2499
2500 const TODO_implement_this = true; // TODO
2501 if (TODO_implement_this or !ty.hasRuntimeBits()) {
2502 const union_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl);
2503 dib.replaceTemporary(fwd_decl, union_di_ty);
2504 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2505 // means we can't use `gop` anymore.
2506 try dg.object.di_type_map.put(gpa, ty, union_di_ty);
2507 return union_di_ty;
2508 }
2509
2510 @panic("TODO debug info type for union");
2511 //const gop = try dg.object.type_map.getOrPut(gpa, ty);
2512 //if (gop.found_existing) return gop.value_ptr.*;
2513
2514 //// The Type memory is ephemeral; since we want to store a longer-lived
2515 //// reference, we need to copy it here.
2516 //gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator());
2517
2518 //const layout = ty.unionGetLayout(target);
2519 //const union_obj = ty.cast(Type.Payload.Union).?.data;
2520
2521 //if (layout.payload_size == 0) {
2522 // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
2523 // gop.value_ptr.* = enum_tag_llvm_ty;
2524 // return enum_tag_llvm_ty;
2525 //}
2526
2527 //const name = try union_obj.getFullyQualifiedName(gpa);
2528 //defer gpa.free(name);
2529
2530 //const llvm_union_ty = dg.context.structCreateNamed(name);
2531 //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
2532
2533 //const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
2534 //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);
2535
2536 //const llvm_payload_ty = ty: {
2537 // if (layout.most_aligned_field_size == layout.payload_size) {
2538 // break :ty llvm_aligned_field_ty;
2539 // }
2540 // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
2541 // const fields: [2]*const llvm.Type = .{
2542 // llvm_aligned_field_ty,
2543 // dg.context.intType(8).arrayType(padding_len),
2544 // };
2545 // break :ty dg.context.structType(&fields, fields.len, .True);
2546 //};
2547
2548 //if (layout.tag_size == 0) {
2549 // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};
2550 // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
2551 // return llvm_union_ty;
2552 //}
2553 //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
2554
2555 //// Put the tag before or after the payload depending on which one's
2556 //// alignment is greater.
2557 //var llvm_fields: [3]*const llvm.Type = undefined;
2558 //var llvm_fields_len: c_uint = 2;
2559
2560 //if (layout.tag_align >= layout.payload_align) {
2561 // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
2562 //} else {
2563 // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
2564 //}
2565
2566 //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
2567 //if (layout.padding != 0) {
2568 // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);
2569 // llvm_fields_len = 3;
2570 //}
2571
2572 //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
2573 //return llvm_union_ty;
2574 },
2575 .Fn => {
2576 const fn_info = ty.fnInfo();
2577 const sret = firstParamSRet(fn_info, target);
2578
2579 var param_di_types = std.ArrayList(*llvm.DIType).init(dg.gpa);
2580 defer param_di_types.deinit();
2581
2582 // Return type goes first.
2583 const di_ret_ty = if (sret or !fn_info.return_type.hasRuntimeBits())
2584 Type.void
2585 else
2586 fn_info.return_type;
2587 try param_di_types.append(try dg.lowerDebugType(di_ret_ty));
2588
2589 if (sret) {
2590 var ptr_ty_payload: Type.Payload.ElemType = .{
2591 .base = .{ .tag = .single_mut_pointer },
2592 .data = fn_info.return_type,
2593 };
2594 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2595 try param_di_types.append(try dg.lowerDebugType(ptr_ty));
2596 }
2597
2598 for (fn_info.param_types) |param_ty| {
2599 if (!param_ty.hasRuntimeBits()) continue;
2600
2601 if (isByRef(param_ty)) {
2602 var ptr_ty_payload: Type.Payload.ElemType = .{
2603 .base = .{ .tag = .single_mut_pointer },
2604 .data = param_ty,
2605 };
2606 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2607 try param_di_types.append(try dg.lowerDebugType(ptr_ty));
2608 } else {
2609 try param_di_types.append(try dg.lowerDebugType(param_ty));
2610 }
2611 }
2612
2613 const fn_di_ty = dib.createSubroutineType(
2614 param_di_types.items.ptr,
2615 @intCast(c_int, param_di_types.items.len),
2616 0,
2617 );
2618 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2619 try dg.object.di_type_map.put(gpa, ty, fn_di_ty);
2620 return fn_di_ty;
2621 },
2622 .ComptimeInt => unreachable,
2623 .ComptimeFloat => unreachable,
2624 .Type => unreachable,
2625 .Undefined => unreachable,
2626 .Null => unreachable,
2627 .EnumLiteral => unreachable,
2628
2629 .BoundFn => @panic("TODO remove BoundFn from the language"),
2630
2631 .Frame => @panic("TODO implement lowerDebugType for Frame types"),
2632 .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
2633 }
2634 }
2635
2636 fn namespaceToDebugScope(dg: *DeclGen, namespace: *const Module.Namespace) !*llvm.DIScope {
2637 if (namespace.parent == null) {
2638 const di_file = try dg.object.getDIFile(dg.gpa, namespace.file_scope);
2639 return di_file.toScope();
2640 }
2641 const di_type = try dg.lowerDebugType(namespace.ty);
2642 return di_type.toScope();
2643 }
2644
2645 /// This is to be used instead of void for debug info types, to avoid tripping
2646 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
2647 /// when targeting CodeView (Windows).
2648 fn makeEmptyNamespaceDIType(dg: *DeclGen, decl: *const Module.Decl) !*llvm.DIType {
2649 const fields: [0]*llvm.DIType = .{};
2650 return dg.object.di_builder.?.createStructType(
2651 try dg.namespaceToDebugScope(decl.src_namespace),
2652 decl.name, // TODO use fully qualified name
2653 try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope),
2654 decl.src_line + 1,
2655 0, // size in bits
2656 0, // align in bits
2657 0, // flags
2658 null, // derived from
2659 undefined, // TODO should be able to pass &fields,
2660 fields.len,
2661 0, // run time lang
2662 null, // vtable holder
2663 "", // unique id
2664 );
2665 }
2666
17742667 const ParentPtr = struct {
17752668 ty: Type,
17762669 llvm_ptr: *const llvm.Value,
......@@ -2085,6 +2978,8 @@ pub const FuncGen = struct {
20852978 liveness: Liveness,
20862979 context: *const llvm.Context,
20872980 builder: *const llvm.Builder,
2981 di_scope: ?*llvm.DIScope,
2982 di_file: ?*llvm.DIFile,
20882983
20892984 /// This stores the LLVM values used in a function, such that they can be referred to
20902985 /// in other instructions. This table is cleared before every function is generated.
......@@ -2100,7 +2995,7 @@ pub const FuncGen = struct {
21002995 /// it omits 0-bit types. If the function uses sret as the first parameter,
21012996 /// this slice does not include it.
21022997 args: []const *const llvm.Value,
2103 arg_index: usize,
2998 arg_index: c_uint,
21042999
21053000 llvm_func: *const llvm.Value,
21063001
......@@ -2330,10 +3225,7 @@ pub const FuncGen = struct {
23303225 .constant => unreachable,
23313226 .const_ty => unreachable,
23323227 .unreach => self.airUnreach(inst),
2333 .dbg_stmt => blk: {
2334 // TODO: implement debug info
2335 break :blk null;
2336 },
3228 .dbg_stmt => self.airDbgStmt(inst),
23373229 // zig fmt: on
23383230 };
23393231 if (opt_value) |val| {
......@@ -3043,6 +3935,17 @@ pub const FuncGen = struct {
30433935 return null;
30443936 }
30453937
3938 fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) ?*const llvm.Value {
3939 const di_scope = self.di_scope orelse return null;
3940 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
3941 self.builder.setCurrentDebugLocation(
3942 @intCast(c_int, self.dg.decl.src_line + dbg_stmt.line + 1),
3943 @intCast(c_int, dbg_stmt.column + 1),
3944 di_scope,
3945 );
3946 return null;
3947 }
3948
30463949 fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
30473950 // Eventually, the Zig compiler needs to be reworked to have inline assembly go
30483951 // through the same parsing code regardless of backend, and have LLVM-flavored
......@@ -4243,15 +5146,42 @@ pub const FuncGen = struct {
42435146 self.arg_index += 1;
42445147
42455148 const inst_ty = self.air.typeOfIndex(inst);
4246 if (isByRef(inst_ty)) {
4247 // TODO declare debug variable
4248 return arg_val;
4249 } else {
4250 const ptr_val = self.buildAlloca(try self.dg.llvmType(inst_ty));
4251 _ = self.builder.buildStore(arg_val, ptr_val);
4252 // TODO declare debug variable
4253 return arg_val;
5149 if (self.dg.object.di_builder) |dib| {
5150 const src_index = self.getSrcArgIndex(self.arg_index - 1);
5151 const func = self.dg.decl.getFunction().?;
5152 const lbrace_line = func.owner_decl.src_line + func.lbrace_line + 1;
5153 const lbrace_col = func.lbrace_column + 1;
5154 const di_local_var = dib.createParameterVariable(
5155 self.di_scope.?,
5156 func.getParamName(src_index).ptr, // TODO test 0 bit args
5157 self.di_file.?,
5158 lbrace_line,
5159 try self.dg.lowerDebugType(inst_ty),
5160 true, // always preserve
5161 0, // flags
5162 self.arg_index, // includes +1 because 0 is return type
5163 );
5164
5165 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?);
5166 const insert_block = self.builder.getInsertBlock();
5167 if (isByRef(inst_ty)) {
5168 _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block);
5169 } else {
5170 _ = dib.insertDbgValueIntrinsicAtEnd(arg_val, di_local_var, debug_loc, insert_block);
5171 }
42545172 }
5173
5174 return arg_val;
5175 }
5176
5177 fn getSrcArgIndex(self: *FuncGen, runtime_index: u32) u32 {
5178 const fn_info = self.dg.decl.ty.fnInfo();
5179 var i: u32 = 0;
5180 for (fn_info.param_types) |param_ty, src_index| {
5181 if (!param_ty.hasRuntimeBits()) continue;
5182 if (i == runtime_index) return @intCast(u32, src_index);
5183 i += 1;
5184 } else unreachable;
42555185 }
42565186
42575187 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
......@@ -4774,7 +5704,7 @@ pub const FuncGen = struct {
47745704 const prev_debug_location = self.builder.getCurrentDebugLocation2();
47755705 defer {
47765706 self.builder.positionBuilderAtEnd(prev_block);
4777 if (!self.dg.module.comp.bin_file.options.strip) {
5707 if (self.di_scope != null) {
47785708 self.builder.setCurrentDebugLocation2(prev_debug_location);
47795709 }
47805710 }
src/codegen/llvm/bindings.zig+350-2
......@@ -184,12 +184,18 @@ pub const Value = opaque {
184184 pub const setFunctionCallConv = LLVMSetFunctionCallConv;
185185 extern fn LLVMSetFunctionCallConv(Fn: *const Value, CC: CallConv) void;
186186
187 pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
188 extern fn ZigLLVMFnSetSubprogram(f: *const Value, subprogram: *DISubprogram) void;
189
187190 pub const setValueName = LLVMSetValueName;
188191 extern fn LLVMSetValueName(Val: *const Value, Name: [*:0]const u8) void;
189192
190193 pub const setValueName2 = LLVMSetValueName2;
191194 extern fn LLVMSetValueName2(Val: *const Value, Name: [*]const u8, NameLen: usize) void;
192195
196 pub const getValueName = LLVMGetValueName;
197 extern fn LLVMGetValueName(Val: *const Value) [*:0]const u8;
198
193199 pub const takeName = ZigLLVMTakeName;
194200 extern fn ZigLLVMTakeName(new_owner: *const Value, victim: *const Value) void;
195201
......@@ -354,6 +360,18 @@ pub const Module = opaque {
354360 Name: [*:0]const u8,
355361 NameLen: usize,
356362 ) ?*const Value;
363
364 pub const setTarget = LLVMSetTarget;
365 extern fn LLVMSetTarget(M: *const Module, Triple: [*:0]const u8) void;
366
367 pub const addModuleDebugInfoFlag = ZigLLVMAddModuleDebugInfoFlag;
368 extern fn ZigLLVMAddModuleDebugInfoFlag(module: *const Module) void;
369
370 pub const addModuleCodeViewFlag = ZigLLVMAddModuleCodeViewFlag;
371 extern fn ZigLLVMAddModuleCodeViewFlag(module: *const Module) void;
372
373 pub const createDIBuilder = ZigLLVMCreateDIBuilder;
374 extern fn ZigLLVMCreateDIBuilder(module: *const Module, allow_unresolved: bool) *DIBuilder;
357375};
358376
359377pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
......@@ -821,7 +839,7 @@ pub const Builder = opaque {
821839 pub const buildExactSDiv = LLVMBuildExactSDiv;
822840 extern fn LLVMBuildExactSDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
823841
824 pub const zigSetCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation;
842 pub const setCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation;
825843 extern fn ZigLLVMSetCurrentDebugLocation(builder: *const Builder, line: c_int, column: c_int, scope: *DIScope) void;
826844
827845 pub const clearCurrentDebugLocation = ZigLLVMClearCurrentDebugLocation;
......@@ -1203,7 +1221,7 @@ pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
12031221extern fn ZigLLVMWriteImportLibrary(
12041222 def_path: [*:0]const u8,
12051223 arch: ArchType,
1206 output_lib_path: [*c]const u8,
1224 output_lib_path: [*:0]const u8,
12071225 kill_at: bool,
12081226) bool;
12091227
......@@ -1400,3 +1418,333 @@ pub const address_space = struct {
14001418 pub const constant_buffer_15: c_uint = 23;
14011419 };
14021420};
1421
1422pub const DIEnumerator = opaque {};
1423pub const DILocalVariable = opaque {};
1424pub const DIGlobalVariable = opaque {};
1425pub const DILocation = opaque {};
1426
1427pub const DIType = opaque {
1428 pub const toScope = ZigLLVMTypeToScope;
1429 extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;
1430};
1431pub const DIFile = opaque {
1432 pub const toScope = ZigLLVMFileToScope;
1433 extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;
1434};
1435pub const DILexicalBlock = opaque {
1436 pub const toScope = ZigLLVMLexicalBlockToScope;
1437 extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;
1438};
1439pub const DICompileUnit = opaque {
1440 pub const toScope = ZigLLVMCompileUnitToScope;
1441 extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;
1442};
1443pub const DISubprogram = opaque {
1444 pub const toScope = ZigLLVMSubprogramToScope;
1445 extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;
1446};
1447
1448pub const getDebugLoc = ZigLLVMGetDebugLoc;
1449extern fn ZigLLVMGetDebugLoc(line: c_uint, col: c_uint, scope: *DIScope) *DILocation;
1450
1451pub const DIBuilder = opaque {
1452 pub const dispose = ZigLLVMDisposeDIBuilder;
1453 extern fn ZigLLVMDisposeDIBuilder(dib: *DIBuilder) void;
1454
1455 pub const finalize = ZigLLVMDIBuilderFinalize;
1456 extern fn ZigLLVMDIBuilderFinalize(dib: *DIBuilder) void;
1457
1458 pub const createPointerType = ZigLLVMCreateDebugPointerType;
1459 extern fn ZigLLVMCreateDebugPointerType(
1460 dib: *DIBuilder,
1461 pointee_type: *DIType,
1462 size_in_bits: u64,
1463 align_in_bits: u64,
1464 name: [*:0]const u8,
1465 ) *DIType;
1466
1467 pub const createBasicType = ZigLLVMCreateDebugBasicType;
1468 extern fn ZigLLVMCreateDebugBasicType(
1469 dib: *DIBuilder,
1470 name: [*:0]const u8,
1471 size_in_bits: u64,
1472 encoding: c_uint,
1473 ) *DIType;
1474
1475 pub const createArrayType = ZigLLVMCreateDebugArrayType;
1476 extern fn ZigLLVMCreateDebugArrayType(
1477 dib: *DIBuilder,
1478 size_in_bits: u64,
1479 align_in_bits: u64,
1480 elem_type: *DIType,
1481 elem_count: c_int,
1482 ) *DIType;
1483
1484 pub const createEnumerator = ZigLLVMCreateDebugEnumerator;
1485 extern fn ZigLLVMCreateDebugEnumerator(
1486 dib: *DIBuilder,
1487 name: [*:0]const u8,
1488 val: i64,
1489 ) *DIEnumerator;
1490
1491 pub const createEnumerationType = ZigLLVMCreateDebugEnumerationType;
1492 extern fn ZigLLVMCreateDebugEnumerationType(
1493 dib: *DIBuilder,
1494 scope: *DIScope,
1495 name: [*:0]const u8,
1496 file: *DIFile,
1497 line_number: c_uint,
1498 size_in_bits: u64,
1499 align_in_bits: u64,
1500 enumerator_array: [*]const *DIEnumerator,
1501 enumerator_array_len: c_int,
1502 underlying_type: *DIType,
1503 unique_id: [*:0]const u8,
1504 ) *DIType;
1505
1506 pub const createStructType = ZigLLVMCreateDebugStructType;
1507 extern fn ZigLLVMCreateDebugStructType(
1508 dib: *DIBuilder,
1509 scope: *DIScope,
1510 name: [*:0]const u8,
1511 file: ?*DIFile,
1512 line_number: c_uint,
1513 size_in_bits: u64,
1514 align_in_bits: u64,
1515 flags: c_uint,
1516 derived_from: ?*DIType,
1517 types_array: [*]const *DIType,
1518 types_array_len: c_int,
1519 run_time_lang: c_uint,
1520 vtable_holder: ?*DIType,
1521 unique_id: [*:0]const u8,
1522 ) *DIType;
1523
1524 pub const createUnionType = ZigLLVMCreateDebugUnionType;
1525 extern fn ZigLLVMCreateDebugUnionType(
1526 dib: *DIBuilder,
1527 scope: *DIScope,
1528 name: [*:0]const u8,
1529 file: *DIFile,
1530 line_number: c_uint,
1531 size_in_bits: u64,
1532 align_in_bits: u64,
1533 flags: c_uint,
1534 types_array: [*]const *DIType,
1535 types_array_len: c_int,
1536 run_time_lang: c_uint,
1537 unique_id: [*:0]const u8,
1538 ) *DIType;
1539
1540 pub const createMemberType = ZigLLVMCreateDebugMemberType;
1541 extern fn ZigLLVMCreateDebugMemberType(
1542 dib: *DIBuilder,
1543 scope: *DIScope,
1544 name: [*:0]const u8,
1545 file: ?*DIFile,
1546 line: c_uint,
1547 size_in_bits: u64,
1548 align_in_bits: u64,
1549 offset_in_bits: u64,
1550 flags: c_uint,
1551 ty: *DIType,
1552 ) *DIType;
1553
1554 pub const createReplaceableCompositeType = ZigLLVMCreateReplaceableCompositeType;
1555 extern fn ZigLLVMCreateReplaceableCompositeType(
1556 dib: *DIBuilder,
1557 tag: c_uint,
1558 name: [*:0]const u8,
1559 scope: *DIScope,
1560 file: ?*DIFile,
1561 line: c_uint,
1562 ) *DIType;
1563
1564 pub const createForwardDeclType = ZigLLVMCreateDebugForwardDeclType;
1565 extern fn ZigLLVMCreateDebugForwardDeclType(
1566 dib: *DIBuilder,
1567 tag: c_uint,
1568 name: [*:0]const u8,
1569 scope: *DIScope,
1570 file: *DIFile,
1571 line: c_uint,
1572 ) *DIType;
1573
1574 pub const replaceTemporary = ZigLLVMReplaceTemporary;
1575 extern fn ZigLLVMReplaceTemporary(dib: *DIBuilder, ty: *DIType, replacement: *DIType) void;
1576
1577 pub const replaceDebugArrays = ZigLLVMReplaceDebugArrays;
1578 extern fn ZigLLVMReplaceDebugArrays(
1579 dib: *DIBuilder,
1580 ty: *DIType,
1581 types_array: [*]const *DIType,
1582 types_array_len: c_int,
1583 ) void;
1584
1585 pub const createSubroutineType = ZigLLVMCreateSubroutineType;
1586 extern fn ZigLLVMCreateSubroutineType(
1587 dib: *DIBuilder,
1588 types_array: [*]const *DIType,
1589 types_array_len: c_int,
1590 flags: c_uint,
1591 ) *DIType;
1592
1593 pub const createAutoVariable = ZigLLVMCreateAutoVariable;
1594 extern fn ZigLLVMCreateAutoVariable(
1595 dib: *DIBuilder,
1596 scope: *DIScope,
1597 name: [*:0]const u8,
1598 file: *DIFile,
1599 line_no: c_uint,
1600 ty: *DIType,
1601 always_preserve: bool,
1602 flags: c_uint,
1603 ) *DILocalVariable;
1604
1605 pub const createGlobalVariable = ZigLLVMCreateGlobalVariable;
1606 extern fn ZigLLVMCreateGlobalVariable(
1607 dib: *DIBuilder,
1608 scope: *DIScope,
1609 name: [*:0]const u8,
1610 linkage_name: [*:0]const u8,
1611 file: *DIFile,
1612 line_no: c_uint,
1613 di_type: *DIType,
1614 is_local_to_unit: bool,
1615 ) *DIGlobalVariable;
1616
1617 pub const createParameterVariable = ZigLLVMCreateParameterVariable;
1618 extern fn ZigLLVMCreateParameterVariable(
1619 dib: *DIBuilder,
1620 scope: *DIScope,
1621 name: [*:0]const u8,
1622 file: *DIFile,
1623 line_no: c_uint,
1624 ty: *DIType,
1625 always_preserve: bool,
1626 flags: c_uint,
1627 arg_no: c_uint,
1628 ) *DILocalVariable;
1629
1630 pub const createLexicalBlock = ZigLLVMCreateLexicalBlock;
1631 extern fn ZigLLVMCreateLexicalBlock(
1632 dib: *DIBuilder,
1633 scope: *DIScope,
1634 file: *DIFile,
1635 line: c_uint,
1636 col: c_uint,
1637 ) *DILexicalBlock;
1638
1639 pub const createCompileUnit = ZigLLVMCreateCompileUnit;
1640 extern fn ZigLLVMCreateCompileUnit(
1641 dib: *DIBuilder,
1642 lang: c_uint,
1643 difile: *DIFile,
1644 producer: [*:0]const u8,
1645 is_optimized: bool,
1646 flags: [*:0]const u8,
1647 runtime_version: c_uint,
1648 split_name: [*:0]const u8,
1649 dwo_id: u64,
1650 emit_debug_info: bool,
1651 ) *DICompileUnit;
1652
1653 pub const createFile = ZigLLVMCreateFile;
1654 extern fn ZigLLVMCreateFile(
1655 dib: *DIBuilder,
1656 filename: [*:0]const u8,
1657 directory: [*:0]const u8,
1658 ) *DIFile;
1659
1660 pub const createFunction = ZigLLVMCreateFunction;
1661 extern fn ZigLLVMCreateFunction(
1662 dib: *DIBuilder,
1663 scope: *DIScope,
1664 name: [*:0]const u8,
1665 linkage_name: [*:0]const u8,
1666 file: *DIFile,
1667 lineno: c_uint,
1668 fn_di_type: *DIType,
1669 is_local_to_unit: bool,
1670 is_definition: bool,
1671 scope_line: c_uint,
1672 flags: c_uint,
1673 is_optimized: bool,
1674 decl_subprogram: ?*DISubprogram,
1675 ) *DISubprogram;
1676
1677 pub const createVectorType = ZigLLVMDIBuilderCreateVectorType;
1678 extern fn ZigLLVMDIBuilderCreateVectorType(
1679 dib: *DIBuilder,
1680 SizeInBits: u64,
1681 AlignInBits: u32,
1682 Ty: *DIType,
1683 elem_count: u32,
1684 ) *DIType;
1685
1686 pub const insertDeclareAtEnd = ZigLLVMInsertDeclareAtEnd;
1687 extern fn ZigLLVMInsertDeclareAtEnd(
1688 dib: *DIBuilder,
1689 storage: *const Value,
1690 var_info: *DILocalVariable,
1691 debug_loc: *DILocation,
1692 basic_block_ref: *const BasicBlock,
1693 ) *const Value;
1694
1695 pub const insertDeclare = ZigLLVMInsertDeclare;
1696 extern fn ZigLLVMInsertDeclare(
1697 dib: *DIBuilder,
1698 storage: *const Value,
1699 var_info: *DILocalVariable,
1700 debug_loc: *DILocation,
1701 insert_before_instr: *const Value,
1702 ) *const Value;
1703
1704 pub const insertDbgValueIntrinsicAtEnd = ZigLLVMInsertDbgValueIntrinsicAtEnd;
1705 extern fn ZigLLVMInsertDbgValueIntrinsicAtEnd(
1706 dib: *DIBuilder,
1707 val: *const Value,
1708 var_info: *DILocalVariable,
1709 debug_loc: *DILocation,
1710 basic_block_ref: *const BasicBlock,
1711 ) *const Value;
1712};
1713
1714pub const DIFlags = opaque {
1715 pub const Zero = 0;
1716 pub const Private = 1;
1717 pub const Protected = 2;
1718 pub const Public = 3;
1719
1720 pub const FwdDecl = 1 << 2;
1721 pub const AppleBlock = 1 << 3;
1722 pub const BlockByrefStruct = 1 << 4;
1723 pub const Virtual = 1 << 5;
1724 pub const Artificial = 1 << 6;
1725 pub const Explicit = 1 << 7;
1726 pub const Prototyped = 1 << 8;
1727 pub const ObjcClassComplete = 1 << 9;
1728 pub const ObjectPointer = 1 << 10;
1729 pub const Vector = 1 << 11;
1730 pub const StaticMember = 1 << 12;
1731 pub const LValueReference = 1 << 13;
1732 pub const RValueReference = 1 << 14;
1733 pub const Reserved = 1 << 15;
1734
1735 pub const SingleInheritance = 1 << 16;
1736 pub const MultipleInheritance = 2 << 16;
1737 pub const VirtualInheritance = 3 << 16;
1738
1739 pub const IntroducedVirtual = 1 << 18;
1740 pub const BitField = 1 << 19;
1741 pub const NoReturn = 1 << 20;
1742 pub const TypePassByValue = 1 << 22;
1743 pub const TypePassByReference = 1 << 23;
1744 pub const EnumClass = 1 << 24;
1745 pub const Thunk = 1 << 25;
1746 pub const NonTrivial = 1 << 26;
1747 pub const BigEndian = 1 << 27;
1748 pub const LittleEndian = 1 << 28;
1749 pub const AllCallsDescribed = 1 << 29;
1750};
src/link.zig+1-1
......@@ -72,7 +72,7 @@ pub const Options = struct {
7272 object_format: std.Target.ObjectFormat,
7373 optimize_mode: std.builtin.Mode,
7474 machine_code_model: std.builtin.CodeModel,
75 root_name: []const u8,
75 root_name: [:0]const u8,
7676 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
7777 module: ?*Module,
7878 dynamic_linker: ?[]const u8,
src/link/Dwarf.zig+1-1
......@@ -882,7 +882,7 @@ fn addDbgInfoType(
882882 const abi_size = ty.abiSize(target);
883883 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
884884 // DW.AT.name, DW.FORM.string
885 const struct_name = try ty.nameAlloc(arena);
885 const struct_name = try ty.nameAllocArena(arena);
886886 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
887887 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
888888 dbg_info_buffer.appendAssumeCapacity(0);
src/stage1/analyze.cpp+1-2
......@@ -9073,8 +9073,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
90739073 for (uint32_t i = 0; i < field_count; i += 1) {
90749074 TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i];
90759075
9076 // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t
9077 // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html
9076 // https://github.com/ziglang/zig/issues/645
90789077 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name),
90799078 bigint_as_signed(&enum_field->value));
90809079 }
src/type.zig+64-40
......@@ -1766,8 +1766,20 @@ pub const Type = extern union {
17661766 }
17671767 }
17681768
1769 pub fn nameAllocArena(ty: Type, arena: Allocator) Allocator.Error![:0]const u8 {
1770 return nameAllocAdvanced(ty, arena, true);
1771 }
1772
1773 pub fn nameAlloc(ty: Type, gpa: Allocator) Allocator.Error![:0]const u8 {
1774 return nameAllocAdvanced(ty, gpa, false);
1775 }
1776
17691777 /// Returns a name suitable for `@typeName`.
1770 pub fn nameAlloc(ty: Type, arena: Allocator) Allocator.Error![:0]const u8 {
1778 pub fn nameAllocAdvanced(
1779 ty: Type,
1780 ally: Allocator,
1781 is_arena: bool,
1782 ) Allocator.Error![:0]const u8 {
17711783 const t = ty.tag();
17721784 switch (t) {
17731785 .inferred_alloc_const => unreachable,
......@@ -1812,71 +1824,79 @@ pub const Type = extern union {
18121824 .noreturn,
18131825 .var_args_param,
18141826 .bound_fn,
1815 => return @tagName(t),
1827 => return maybeDupe(@tagName(t), ally, is_arena),
18161828
1817 .enum_literal => return "@Type(.EnumLiteral)",
1818 .@"null" => return "@Type(.Null)",
1819 .@"undefined" => return "@Type(.Undefined)",
1829 .enum_literal => return maybeDupe("@Type(.EnumLiteral)", ally, is_arena),
1830 .@"null" => return maybeDupe("@Type(.Null)", ally, is_arena),
1831 .@"undefined" => return maybeDupe("@Type(.Undefined)", ally, is_arena),
18201832
1821 .empty_struct, .empty_struct_literal => return "struct {}",
1833 .empty_struct, .empty_struct_literal => return maybeDupe("struct {}", ally, is_arena),
18221834
18231835 .@"struct" => {
18241836 const struct_obj = ty.castTag(.@"struct").?.data;
1825 return try arena.dupeZ(u8, std.mem.sliceTo(struct_obj.owner_decl.name, 0));
1837 return try ally.dupeZ(u8, std.mem.sliceTo(struct_obj.owner_decl.name, 0));
18261838 },
18271839 .@"union", .union_tagged => {
18281840 const union_obj = ty.cast(Payload.Union).?.data;
1829 return try arena.dupeZ(u8, std.mem.sliceTo(union_obj.owner_decl.name, 0));
1841 return try ally.dupeZ(u8, std.mem.sliceTo(union_obj.owner_decl.name, 0));
18301842 },
18311843 .enum_full, .enum_nonexhaustive => {
18321844 const enum_full = ty.cast(Payload.EnumFull).?.data;
1833 return try arena.dupeZ(u8, std.mem.sliceTo(enum_full.owner_decl.name, 0));
1845 return try ally.dupeZ(u8, std.mem.sliceTo(enum_full.owner_decl.name, 0));
18341846 },
18351847 .enum_simple => {
18361848 const enum_simple = ty.castTag(.enum_simple).?.data;
1837 return try arena.dupeZ(u8, std.mem.sliceTo(enum_simple.owner_decl.name, 0));
1849 return try ally.dupeZ(u8, std.mem.sliceTo(enum_simple.owner_decl.name, 0));
18381850 },
18391851 .enum_numbered => {
18401852 const enum_numbered = ty.castTag(.enum_numbered).?.data;
1841 return try arena.dupeZ(u8, std.mem.sliceTo(enum_numbered.owner_decl.name, 0));
1853 return try ally.dupeZ(u8, std.mem.sliceTo(enum_numbered.owner_decl.name, 0));
18421854 },
18431855 .@"opaque" => {
1844 // TODO use declaration name
1845 return "opaque {}";
1846 },
1847
1848 .anyerror_void_error_union => return "anyerror!void",
1849 .const_slice_u8 => return "[]const u8",
1850 .const_slice_u8_sentinel_0 => return "[:0]const u8",
1851 .fn_noreturn_no_args => return "fn() noreturn",
1852 .fn_void_no_args => return "fn() void",
1853 .fn_naked_noreturn_no_args => return "fn() callconv(.Naked) noreturn",
1854 .fn_ccc_void_no_args => return "fn() callconv(.C) void",
1855 .single_const_pointer_to_comptime_int => return "*const comptime_int",
1856 .manyptr_u8 => return "[*]u8",
1857 .manyptr_const_u8 => return "[*]const u8",
1858 .manyptr_const_u8_sentinel_0 => return "[*:0]const u8",
1859 .atomic_order => return "AtomicOrder",
1860 .atomic_rmw_op => return "AtomicRmwOp",
1861 .calling_convention => return "CallingConvention",
1862 .address_space => return "AddressSpace",
1863 .float_mode => return "FloatMode",
1864 .reduce_op => return "ReduceOp",
1865 .call_options => return "CallOptions",
1866 .prefetch_options => return "PrefetchOptions",
1867 .export_options => return "ExportOptions",
1868 .extern_options => return "ExternOptions",
1869 .type_info => return "Type",
1856 const opaque_obj = ty.cast(Payload.Opaque).?.data;
1857 return try ally.dupeZ(u8, std.mem.sliceTo(opaque_obj.owner_decl.name, 0));
1858 },
1859
1860 .anyerror_void_error_union => return maybeDupe("anyerror!void", ally, is_arena),
1861 .const_slice_u8 => return maybeDupe("[]const u8", ally, is_arena),
1862 .const_slice_u8_sentinel_0 => return maybeDupe("[:0]const u8", ally, is_arena),
1863 .fn_noreturn_no_args => return maybeDupe("fn() noreturn", ally, is_arena),
1864 .fn_void_no_args => return maybeDupe("fn() void", ally, is_arena),
1865 .fn_naked_noreturn_no_args => return maybeDupe("fn() callconv(.Naked) noreturn", ally, is_arena),
1866 .fn_ccc_void_no_args => return maybeDupe("fn() callconv(.C) void", ally, is_arena),
1867 .single_const_pointer_to_comptime_int => return maybeDupe("*const comptime_int", ally, is_arena),
1868 .manyptr_u8 => return maybeDupe("[*]u8", ally, is_arena),
1869 .manyptr_const_u8 => return maybeDupe("[*]const u8", ally, is_arena),
1870 .manyptr_const_u8_sentinel_0 => return maybeDupe("[*:0]const u8", ally, is_arena),
1871 .atomic_order => return maybeDupe("AtomicOrder", ally, is_arena),
1872 .atomic_rmw_op => return maybeDupe("AtomicRmwOp", ally, is_arena),
1873 .calling_convention => return maybeDupe("CallingConvention", ally, is_arena),
1874 .address_space => return maybeDupe("AddressSpace", ally, is_arena),
1875 .float_mode => return maybeDupe("FloatMode", ally, is_arena),
1876 .reduce_op => return maybeDupe("ReduceOp", ally, is_arena),
1877 .call_options => return maybeDupe("CallOptions", ally, is_arena),
1878 .prefetch_options => return maybeDupe("PrefetchOptions", ally, is_arena),
1879 .export_options => return maybeDupe("ExportOptions", ally, is_arena),
1880 .extern_options => return maybeDupe("ExternOptions", ally, is_arena),
1881 .type_info => return maybeDupe("Type", ally, is_arena),
18701882
18711883 else => {
18721884 // TODO this is wasteful and also an incorrect implementation of `@typeName`
1873 var buf = std.ArrayList(u8).init(arena);
1885 var buf = std.ArrayList(u8).init(ally);
18741886 try buf.writer().print("{}", .{ty});
18751887 return try buf.toOwnedSliceSentinel(0);
18761888 },
18771889 }
18781890 }
18791891
1892 fn maybeDupe(s: [:0]const u8, ally: Allocator, is_arena: bool) Allocator.Error![:0]const u8 {
1893 if (is_arena) {
1894 return s;
1895 } else {
1896 return try ally.dupeZ(u8, s);
1897 }
1898 }
1899
18801900 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
18811901 switch (self.tag()) {
18821902 .u1 => return Value.initTag(.u1_type),
......@@ -4683,7 +4703,10 @@ pub const Type = extern union {
46834703 const union_obj = ty.cast(Payload.Union).?.data;
46844704 return union_obj.owner_decl;
46854705 },
4686 .@"opaque" => @panic("TODO"),
4706 .@"opaque" => {
4707 const opaque_obj = ty.cast(Payload.Opaque).?.data;
4708 return opaque_obj.owner_decl;
4709 },
46874710 .atomic_order,
46884711 .atomic_rmw_op,
46894712 .calling_convention,
......@@ -4695,7 +4718,8 @@ pub const Type = extern union {
46954718 .export_options,
46964719 .extern_options,
46974720 .type_info,
4698 => @panic("TODO resolve std.builtin types"),
4721 => unreachable, // These need to be resolved earlier.
4722
46994723 else => unreachable,
47004724 }
47014725 }
src/zig_llvm.cpp+13
......@@ -942,6 +942,19 @@ LLVMValueRef ZigLLVMInsertDeclareAtEnd(ZigLLVMDIBuilder *dibuilder, LLVMValueRef
942942 return wrap(result);
943943}
944944
945LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(ZigLLVMDIBuilder *dib, LLVMValueRef val,
946 ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc,
947 LLVMBasicBlockRef basic_block_ref)
948{
949 Instruction *result = reinterpret_cast<DIBuilder*>(dib)->insertDbgValueIntrinsic(
950 unwrap(val),
951 reinterpret_cast<DILocalVariable *>(var_info),
952 reinterpret_cast<DIBuilder*>(dib)->createExpression(),
953 reinterpret_cast<DILocation*>(debug_loc),
954 static_cast<BasicBlock*>(unwrap(basic_block_ref)));
955 return wrap(result);
956}
957
945958LLVMValueRef ZigLLVMInsertDeclare(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
946959 ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr)
947960{
src/zig_llvm.h+13-6
......@@ -273,13 +273,20 @@ ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubpro
273273
274274ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
275275
276ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
277 struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc,
278 LLVMBasicBlockRef basic_block_ref);
276ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col,
277 struct ZigLLVMDIScope *scope);
278
279ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dib,
280 LLVMValueRef storage, struct ZigLLVMDILocalVariable *var_info,
281 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
282
283ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclare(struct ZigLLVMDIBuilder *dib,
284 LLVMValueRef storage, struct ZigLLVMDILocalVariable *var_info,
285 struct ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr);
279286
280ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclare(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
281 struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr);
282ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, struct ZigLLVMDIScope *scope);
287ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBuilder *dib,
288 LLVMValueRef val, struct ZigLLVMDILocalVariable *var_info,
289 struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
283290
284291ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
285292ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call);