| author | |
| committer | |
| log | fb4ad37e0bd07513a0a56afb45e95c68036b1eea |
| tree | a735a6104ec10aae6417b7e11d4b893debb06776 |
| parent | 874b51d8d4d80f224e979adba11526a5dcec61da |
This required adjusting `Type.nameAlloc` to be used with a
general-purpose allocator and added `Type.nameAllocArena` for the arena
use case (avoids allocation sometimes).4 files changed, 80 insertions(+), 50 deletions(-)
src/Sema.zig+1-1| ... | @@ -12405,7 +12405,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12405,7 +12405,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12405 | var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); | 12405 | var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); |
| 12406 | defer anon_decl.deinit(); | 12406 | defer anon_decl.deinit(); |
| 12407 | 12407 | ||
| 12408 | const bytes = try ty.nameAlloc(anon_decl.arena()); | 12408 | const bytes = try ty.nameAllocArena(anon_decl.arena()); |
| 12409 | 12409 | ||
| 12410 | const new_decl = try anon_decl.finish( | 12410 | const new_decl = try anon_decl.finish( |
| 12411 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len), | 12411 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len), |
src/codegen/llvm.zig+20-10| ... | @@ -1922,7 +1922,8 @@ pub const DeclGen = struct { | ... | @@ -1922,7 +1922,8 @@ pub const DeclGen = struct { |
| 1922 | .Int => { | 1922 | .Int => { |
| 1923 | const info = ty.intInfo(target); | 1923 | const info = ty.intInfo(target); |
| 1924 | assert(info.bits != 0); | 1924 | assert(info.bits != 0); |
| 1925 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 1925 | const name = try ty.nameAlloc(gpa); |
| 1926 | defer gpa.free(name); | ||
| 1926 | const dwarf_encoding: c_uint = switch (info.signedness) { | 1927 | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 1927 | .signed => DW.ATE.signed, | 1928 | .signed => DW.ATE.signed, |
| 1928 | .unsigned => DW.ATE.unsigned, | 1929 | .unsigned => DW.ATE.unsigned, |
| ... | @@ -1967,7 +1968,8 @@ pub const DeclGen = struct { | ... | @@ -1967,7 +1968,8 @@ pub const DeclGen = struct { |
| 1967 | const di_file = try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope); | 1968 | const di_file = try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope); |
| 1968 | const di_scope = try dg.namespaceToDebugScope(owner_decl.src_namespace); | 1969 | const di_scope = try dg.namespaceToDebugScope(owner_decl.src_namespace); |
| 1969 | 1970 | ||
| 1970 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 1971 | const name = try ty.nameAlloc(gpa); |
| 1972 | defer gpa.free(name); | ||
| 1971 | var buffer: Type.Payload.Bits = undefined; | 1973 | var buffer: Type.Payload.Bits = undefined; |
| 1972 | const int_ty = ty.intTagType(&buffer); | 1974 | const int_ty = ty.intTagType(&buffer); |
| 1973 | 1975 | ||
| ... | @@ -1989,7 +1991,8 @@ pub const DeclGen = struct { | ... | @@ -1989,7 +1991,8 @@ pub const DeclGen = struct { |
| 1989 | }, | 1991 | }, |
| 1990 | .Float => { | 1992 | .Float => { |
| 1991 | const bits = ty.floatBits(target); | 1993 | const bits = ty.floatBits(target); |
| 1992 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 1994 | const name = try ty.nameAlloc(gpa); |
| 1995 | defer gpa.free(name); | ||
| 1993 | gop.value_ptr.* = dib.createBasicType(name, bits, DW.ATE.float); | 1996 | gop.value_ptr.* = dib.createBasicType(name, bits, DW.ATE.float); |
| 1994 | return gop.value_ptr.*; | 1997 | return gop.value_ptr.*; |
| 1995 | }, | 1998 | }, |
| ... | @@ -2039,7 +2042,8 @@ pub const DeclGen = struct { | ... | @@ -2039,7 +2042,8 @@ pub const DeclGen = struct { |
| 2039 | const ptr_ty = ty.slicePtrFieldType(&buf); | 2042 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 2040 | const len_ty = Type.usize; | 2043 | const len_ty = Type.usize; |
| 2041 | 2044 | ||
| 2042 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2045 | const name = try ty.nameAlloc(gpa); |
| 2046 | defer gpa.free(name); | ||
| 2043 | const di_file: ?*llvm.DIFile = null; | 2047 | const di_file: ?*llvm.DIFile = null; |
| 2044 | const line = 0; | 2048 | const line = 0; |
| 2045 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); | 2049 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| ... | @@ -2109,7 +2113,8 @@ pub const DeclGen = struct { | ... | @@ -2109,7 +2113,8 @@ pub const DeclGen = struct { |
| 2109 | } | 2113 | } |
| 2110 | 2114 | ||
| 2111 | const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); | 2115 | const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); |
| 2112 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2116 | const name = try ty.nameAlloc(gpa); |
| 2117 | defer gpa.free(name); | ||
| 2113 | const ptr_di_ty = dib.createPointerType( | 2118 | const ptr_di_ty = dib.createPointerType( |
| 2114 | elem_di_ty, | 2119 | elem_di_ty, |
| 2115 | target.cpu.arch.ptrBitWidth(), | 2120 | target.cpu.arch.ptrBitWidth(), |
| ... | @@ -2125,7 +2130,8 @@ pub const DeclGen = struct { | ... | @@ -2125,7 +2130,8 @@ pub const DeclGen = struct { |
| 2125 | gop.value_ptr.* = dib.createBasicType("anyopaque", 0, DW.ATE.signed); | 2130 | gop.value_ptr.* = dib.createBasicType("anyopaque", 0, DW.ATE.signed); |
| 2126 | return gop.value_ptr.*; | 2131 | return gop.value_ptr.*; |
| 2127 | } | 2132 | } |
| 2128 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2133 | const name = try ty.nameAlloc(gpa); |
| 2134 | defer gpa.free(name); | ||
| 2129 | const owner_decl = ty.getOwnerDecl(); | 2135 | const owner_decl = ty.getOwnerDecl(); |
| 2130 | const opaque_di_ty = dib.createForwardDeclType( | 2136 | const opaque_di_ty = dib.createForwardDeclType( |
| 2131 | DW.TAG.structure_type, | 2137 | DW.TAG.structure_type, |
| ... | @@ -2162,7 +2168,8 @@ pub const DeclGen = struct { | ... | @@ -2162,7 +2168,8 @@ pub const DeclGen = struct { |
| 2162 | return vector_di_ty; | 2168 | return vector_di_ty; |
| 2163 | }, | 2169 | }, |
| 2164 | .Optional => { | 2170 | .Optional => { |
| 2165 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2171 | const name = try ty.nameAlloc(gpa); |
| 2172 | defer gpa.free(name); | ||
| 2166 | var buf: Type.Payload.ElemType = undefined; | 2173 | var buf: Type.Payload.ElemType = undefined; |
| 2167 | const child_ty = ty.optionalChild(&buf); | 2174 | const child_ty = ty.optionalChild(&buf); |
| 2168 | if (!child_ty.hasRuntimeBits()) { | 2175 | if (!child_ty.hasRuntimeBits()) { |
| ... | @@ -2253,7 +2260,8 @@ pub const DeclGen = struct { | ... | @@ -2253,7 +2260,8 @@ pub const DeclGen = struct { |
| 2253 | try dg.object.di_type_map.put(gpa, ty, err_set_di_ty); | 2260 | try dg.object.di_type_map.put(gpa, ty, err_set_di_ty); |
| 2254 | return err_set_di_ty; | 2261 | return err_set_di_ty; |
| 2255 | } | 2262 | } |
| 2256 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2263 | const name = try ty.nameAlloc(gpa); |
| 2264 | defer gpa.free(name); | ||
| 2257 | const di_file: ?*llvm.DIFile = null; | 2265 | const di_file: ?*llvm.DIFile = null; |
| 2258 | const line = 0; | 2266 | const line = 0; |
| 2259 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); | 2267 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| ... | @@ -2329,7 +2337,8 @@ pub const DeclGen = struct { | ... | @@ -2329,7 +2337,8 @@ pub const DeclGen = struct { |
| 2329 | }, | 2337 | }, |
| 2330 | .Struct => { | 2338 | .Struct => { |
| 2331 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); | 2339 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| 2332 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2340 | const name = try ty.nameAlloc(gpa); |
| 2341 | defer gpa.free(name); | ||
| 2333 | const fwd_decl = dib.createReplaceableCompositeType( | 2342 | const fwd_decl = dib.createReplaceableCompositeType( |
| 2334 | DW.TAG.structure_type, | 2343 | DW.TAG.structure_type, |
| 2335 | name.ptr, | 2344 | name.ptr, |
| ... | @@ -2477,7 +2486,8 @@ pub const DeclGen = struct { | ... | @@ -2477,7 +2486,8 @@ pub const DeclGen = struct { |
| 2477 | .Union => { | 2486 | .Union => { |
| 2478 | const owner_decl = ty.getOwnerDecl(); | 2487 | const owner_decl = ty.getOwnerDecl(); |
| 2479 | 2488 | ||
| 2480 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2489 | const name = try ty.nameAlloc(gpa); |
| 2490 | defer gpa.free(name); | ||
| 2481 | const fwd_decl = dib.createReplaceableCompositeType( | 2491 | const fwd_decl = dib.createReplaceableCompositeType( |
| 2482 | DW.TAG.structure_type, | 2492 | DW.TAG.structure_type, |
| 2483 | name.ptr, | 2493 | name.ptr, |
src/link/Dwarf.zig+1-1| ... | @@ -882,7 +882,7 @@ fn addDbgInfoType( | ... | @@ -882,7 +882,7 @@ fn addDbgInfoType( |
| 882 | const abi_size = ty.abiSize(target); | 882 | const abi_size = ty.abiSize(target); |
| 883 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | 883 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 884 | // DW.AT.name, DW.FORM.string | 884 | // DW.AT.name, DW.FORM.string |
| 885 | const struct_name = try ty.nameAlloc(arena); | 885 | const struct_name = try ty.nameAllocArena(arena); |
| 886 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); | 886 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); |
| 887 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); | 887 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); |
| 888 | dbg_info_buffer.appendAssumeCapacity(0); | 888 | dbg_info_buffer.appendAssumeCapacity(0); |
src/type.zig+58-38| ... | @@ -1766,8 +1766,20 @@ pub const Type = extern union { | ... | @@ -1766,8 +1766,20 @@ pub const Type = extern union { |
| 1766 | } | 1766 | } |
| 1767 | } | 1767 | } |
| 1768 | 1768 | ||
| 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 | |||
| 1769 | /// Returns a name suitable for `@typeName`. | 1777 | /// 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 { | ||
| 1771 | const t = ty.tag(); | 1783 | const t = ty.tag(); |
| 1772 | switch (t) { | 1784 | switch (t) { |
| 1773 | .inferred_alloc_const => unreachable, | 1785 | .inferred_alloc_const => unreachable, |
| ... | @@ -1812,71 +1824,79 @@ pub const Type = extern union { | ... | @@ -1812,71 +1824,79 @@ pub const Type = extern union { |
| 1812 | .noreturn, | 1824 | .noreturn, |
| 1813 | .var_args_param, | 1825 | .var_args_param, |
| 1814 | .bound_fn, | 1826 | .bound_fn, |
| 1815 | => return @tagName(t), | 1827 | => return maybeDupe(@tagName(t), ally, is_arena), |
| 1816 | 1828 | ||
| 1817 | .enum_literal => return "@Type(.EnumLiteral)", | 1829 | .enum_literal => return maybeDupe("@Type(.EnumLiteral)", ally, is_arena), |
| 1818 | .@"null" => return "@Type(.Null)", | 1830 | .@"null" => return maybeDupe("@Type(.Null)", ally, is_arena), |
| 1819 | .@"undefined" => return "@Type(.Undefined)", | 1831 | .@"undefined" => return maybeDupe("@Type(.Undefined)", ally, is_arena), |
| 1820 | 1832 | ||
| 1821 | .empty_struct, .empty_struct_literal => return "struct {}", | 1833 | .empty_struct, .empty_struct_literal => return maybeDupe("struct {}", ally, is_arena), |
| 1822 | 1834 | ||
| 1823 | .@"struct" => { | 1835 | .@"struct" => { |
| 1824 | const struct_obj = ty.castTag(.@"struct").?.data; | 1836 | 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)); |
| 1826 | }, | 1838 | }, |
| 1827 | .@"union", .union_tagged => { | 1839 | .@"union", .union_tagged => { |
| 1828 | const union_obj = ty.cast(Payload.Union).?.data; | 1840 | 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)); |
| 1830 | }, | 1842 | }, |
| 1831 | .enum_full, .enum_nonexhaustive => { | 1843 | .enum_full, .enum_nonexhaustive => { |
| 1832 | const enum_full = ty.cast(Payload.EnumFull).?.data; | 1844 | 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)); |
| 1834 | }, | 1846 | }, |
| 1835 | .enum_simple => { | 1847 | .enum_simple => { |
| 1836 | const enum_simple = ty.castTag(.enum_simple).?.data; | 1848 | 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)); |
| 1838 | }, | 1850 | }, |
| 1839 | .enum_numbered => { | 1851 | .enum_numbered => { |
| 1840 | const enum_numbered = ty.castTag(.enum_numbered).?.data; | 1852 | 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)); |
| 1842 | }, | 1854 | }, |
| 1843 | .@"opaque" => { | 1855 | .@"opaque" => { |
| 1844 | // TODO use declaration name | 1856 | const opaque_obj = ty.cast(Payload.Opaque).?.data; |
| 1845 | return "opaque {}"; | 1857 | return try ally.dupeZ(u8, std.mem.sliceTo(opaque_obj.owner_decl.name, 0)); |
| 1846 | }, | 1858 | }, |
| 1847 | 1859 | ||
| 1848 | .anyerror_void_error_union => return "anyerror!void", | 1860 | .anyerror_void_error_union => return maybeDupe("anyerror!void", ally, is_arena), |
| 1849 | .const_slice_u8 => return "[]const u8", | 1861 | .const_slice_u8 => return maybeDupe("[]const u8", ally, is_arena), |
| 1850 | .const_slice_u8_sentinel_0 => return "[:0]const u8", | 1862 | .const_slice_u8_sentinel_0 => return maybeDupe("[:0]const u8", ally, is_arena), |
| 1851 | .fn_noreturn_no_args => return "fn() noreturn", | 1863 | .fn_noreturn_no_args => return maybeDupe("fn() noreturn", ally, is_arena), |
| 1852 | .fn_void_no_args => return "fn() void", | 1864 | .fn_void_no_args => return maybeDupe("fn() void", ally, is_arena), |
| 1853 | .fn_naked_noreturn_no_args => return "fn() callconv(.Naked) noreturn", | 1865 | .fn_naked_noreturn_no_args => return maybeDupe("fn() callconv(.Naked) noreturn", ally, is_arena), |
| 1854 | .fn_ccc_void_no_args => return "fn() callconv(.C) void", | 1866 | .fn_ccc_void_no_args => return maybeDupe("fn() callconv(.C) void", ally, is_arena), |
| 1855 | .single_const_pointer_to_comptime_int => return "*const comptime_int", | 1867 | .single_const_pointer_to_comptime_int => return maybeDupe("*const comptime_int", ally, is_arena), |
| 1856 | .manyptr_u8 => return "[*]u8", | 1868 | .manyptr_u8 => return maybeDupe("[*]u8", ally, is_arena), |
| 1857 | .manyptr_const_u8 => return "[*]const u8", | 1869 | .manyptr_const_u8 => return maybeDupe("[*]const u8", ally, is_arena), |
| 1858 | .manyptr_const_u8_sentinel_0 => return "[*:0]const u8", | 1870 | .manyptr_const_u8_sentinel_0 => return maybeDupe("[*:0]const u8", ally, is_arena), |
| 1859 | .atomic_order => return "AtomicOrder", | 1871 | .atomic_order => return maybeDupe("AtomicOrder", ally, is_arena), |
| 1860 | .atomic_rmw_op => return "AtomicRmwOp", | 1872 | .atomic_rmw_op => return maybeDupe("AtomicRmwOp", ally, is_arena), |
| 1861 | .calling_convention => return "CallingConvention", | 1873 | .calling_convention => return maybeDupe("CallingConvention", ally, is_arena), |
| 1862 | .address_space => return "AddressSpace", | 1874 | .address_space => return maybeDupe("AddressSpace", ally, is_arena), |
| 1863 | .float_mode => return "FloatMode", | 1875 | .float_mode => return maybeDupe("FloatMode", ally, is_arena), |
| 1864 | .reduce_op => return "ReduceOp", | 1876 | .reduce_op => return maybeDupe("ReduceOp", ally, is_arena), |
| 1865 | .call_options => return "CallOptions", | 1877 | .call_options => return maybeDupe("CallOptions", ally, is_arena), |
| 1866 | .prefetch_options => return "PrefetchOptions", | 1878 | .prefetch_options => return maybeDupe("PrefetchOptions", ally, is_arena), |
| 1867 | .export_options => return "ExportOptions", | 1879 | .export_options => return maybeDupe("ExportOptions", ally, is_arena), |
| 1868 | .extern_options => return "ExternOptions", | 1880 | .extern_options => return maybeDupe("ExternOptions", ally, is_arena), |
| 1869 | .type_info => return "Type", | 1881 | .type_info => return maybeDupe("Type", ally, is_arena), |
| 1870 | 1882 | ||
| 1871 | else => { | 1883 | else => { |
| 1872 | // TODO this is wasteful and also an incorrect implementation of `@typeName` | 1884 | // 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); |
| 1874 | try buf.writer().print("{}", .{ty}); | 1886 | try buf.writer().print("{}", .{ty}); |
| 1875 | return try buf.toOwnedSliceSentinel(0); | 1887 | return try buf.toOwnedSliceSentinel(0); |
| 1876 | }, | 1888 | }, |
| 1877 | } | 1889 | } |
| 1878 | } | 1890 | } |
| 1879 | 1891 | ||
| 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 | |||
| 1880 | pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { | 1900 | pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { |
| 1881 | switch (self.tag()) { | 1901 | switch (self.tag()) { |
| 1882 | .u1 => return Value.initTag(.u1_type), | 1902 | .u1 => return Value.initTag(.u1_type), |