| ... | ... | @@ -1075,15 +1075,13 @@ pub const DeclGen = struct { |
| 1075 | 1075 | }, |
| 1076 | 1076 | .Optional => { |
| 1077 | 1077 | var buf: Type.Payload.ElemType = undefined; |
| 1078 | | const child_type = t.optionalChild(&buf); |
| 1079 | | if (!child_type.hasRuntimeBits()) { |
| 1078 | const child_ty = t.optionalChild(&buf); |
| 1079 | if (!child_ty.hasRuntimeBits()) { |
| 1080 | 1080 | return dg.context.intType(1); |
| 1081 | 1081 | } |
| 1082 | | const payload_llvm_ty = try dg.llvmType(child_type); |
| 1082 | const payload_llvm_ty = try dg.llvmType(child_ty); |
| 1083 | 1083 | if (t.isPtrLikeOptional()) { |
| 1084 | 1084 | return payload_llvm_ty; |
| 1085 | | } else if (!child_type.hasRuntimeBits()) { |
| 1086 | | return dg.context.intType(1); |
| 1087 | 1085 | } |
| 1088 | 1086 | |
| 1089 | 1087 | const fields: [2]*const llvm.Type = .{ |
| ... | ... | @@ -1905,20 +1903,19 @@ pub const DeclGen = struct { |
| 1905 | 1903 | } |
| 1906 | 1904 | |
| 1907 | 1905 | fn lowerDebugType(dg: *DeclGen, ty: Type) Allocator.Error!*llvm.DIType { |
| 1908 | | const gop = try dg.object.di_type_map.getOrPut(dg.gpa, ty); |
| 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.*; |
| 1909 | 1911 | errdefer assert(dg.object.di_type_map.remove(ty)); |
| 1910 | | if (!gop.found_existing) { |
| 1911 | | gop.value_ptr.* = try lowerDebugTypeRaw(dg, ty); |
| 1912 | | } |
| 1913 | | return gop.value_ptr.*; |
| 1914 | | } |
| 1915 | | |
| 1916 | | fn lowerDebugTypeRaw(dg: *DeclGen, ty: Type) Allocator.Error!*llvm.DIType { |
| 1917 | 1912 | const target = dg.module.getTarget(); |
| 1918 | 1913 | const dib = dg.object.di_builder.?; |
| 1919 | | const gpa = dg.gpa; |
| 1920 | 1914 | switch (ty.zigTypeTag()) { |
| 1921 | | .Void, .NoReturn => return dib.createBasicType("void", 0, DW.ATE.signed), |
| 1915 | .Void, .NoReturn => { |
| 1916 | gop.value_ptr.* = dib.createBasicType("void", 0, DW.ATE.signed); |
| 1917 | return gop.value_ptr.*; |
| 1918 | }, |
| 1922 | 1919 | .Int => { |
| 1923 | 1920 | const info = ty.intInfo(target); |
| 1924 | 1921 | assert(info.bits != 0); |
| ... | ... | @@ -1927,13 +1924,18 @@ pub const DeclGen = struct { |
| 1927 | 1924 | .signed => DW.ATE.signed, |
| 1928 | 1925 | .unsigned => DW.ATE.unsigned, |
| 1929 | 1926 | }; |
| 1930 | | return dib.createBasicType(name, info.bits, dwarf_encoding); |
| 1927 | gop.value_ptr.* = dib.createBasicType(name, info.bits, dwarf_encoding); |
| 1928 | return gop.value_ptr.*; |
| 1931 | 1929 | }, |
| 1932 | 1930 | .Enum => { |
| 1933 | 1931 | const owner_decl = ty.getOwnerDecl(); |
| 1934 | 1932 | |
| 1935 | 1933 | if (!ty.hasRuntimeBits()) { |
| 1936 | | return dg.makeEmptyNamespaceDIType(owner_decl); |
| 1934 | const enum_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl); |
| 1935 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1936 | // means we can't use `gop` anymore. |
| 1937 | try dg.object.di_type_map.put(gpa, ty, enum_di_ty); |
| 1938 | return enum_di_ty; |
| 1937 | 1939 | } |
| 1938 | 1940 | |
| 1939 | 1941 | const field_names = ty.enumFields().keys(); |
| ... | ... | @@ -1966,7 +1968,7 @@ pub const DeclGen = struct { |
| 1966 | 1968 | var buffer: Type.Payload.Bits = undefined; |
| 1967 | 1969 | const int_ty = ty.intTagType(&buffer); |
| 1968 | 1970 | |
| 1969 | | return dib.createEnumerationType( |
| 1971 | const enum_di_ty = dib.createEnumerationType( |
| 1970 | 1972 | di_scope, |
| 1971 | 1973 | name, |
| 1972 | 1974 | di_file, |
| ... | ... | @@ -1978,79 +1980,264 @@ pub const DeclGen = struct { |
| 1978 | 1980 | try lowerDebugType(dg, int_ty), |
| 1979 | 1981 | "", |
| 1980 | 1982 | ); |
| 1983 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1984 | try dg.object.di_type_map.put(gpa, ty, enum_di_ty); |
| 1985 | return enum_di_ty; |
| 1981 | 1986 | }, |
| 1982 | 1987 | .Float => { |
| 1983 | 1988 | const bits = ty.floatBits(target); |
| 1984 | 1989 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 1985 | | return dib.createBasicType(name, bits, DW.ATE.float); |
| 1990 | gop.value_ptr.* = dib.createBasicType(name, bits, DW.ATE.float); |
| 1991 | return gop.value_ptr.*; |
| 1992 | }, |
| 1993 | .Bool => { |
| 1994 | gop.value_ptr.* = dib.createBasicType("bool", 1, DW.ATE.boolean); |
| 1995 | return gop.value_ptr.*; |
| 1986 | 1996 | }, |
| 1987 | | .Bool => return dib.createBasicType("bool", 1, DW.ATE.boolean), |
| 1988 | 1997 | .Pointer => { |
| 1998 | // Normalize everything that the debug info does not represent. |
| 1999 | const ptr_info = ty.ptrInfo().data; |
| 2000 | |
| 2001 | if (ptr_info.sentinel != null or |
| 2002 | ptr_info.@"addrspace" != .generic or |
| 2003 | ptr_info.bit_offset != 0 or |
| 2004 | ptr_info.host_size != 0 or |
| 2005 | ptr_info.@"allowzero" or |
| 2006 | !ptr_info.mutable or |
| 2007 | ptr_info.@"volatile" or |
| 2008 | ptr_info.size == .Many or ptr_info.size == .C) |
| 2009 | { |
| 2010 | var payload: Type.Payload.Pointer = .{ |
| 2011 | .data = .{ |
| 2012 | .pointee_type = ptr_info.pointee_type, |
| 2013 | .sentinel = null, |
| 2014 | .@"align" = ptr_info.@"align", |
| 2015 | .@"addrspace" = .generic, |
| 2016 | .bit_offset = 0, |
| 2017 | .host_size = 0, |
| 2018 | .@"allowzero" = false, |
| 2019 | .mutable = true, |
| 2020 | .@"volatile" = false, |
| 2021 | .size = switch (ptr_info.size) { |
| 2022 | .Many, .C, .One => .One, |
| 2023 | .Slice => .Slice, |
| 2024 | }, |
| 2025 | }, |
| 2026 | }; |
| 2027 | const bland_ptr_ty = Type.initPayload(&payload.base); |
| 2028 | const ptr_di_ty = try dg.lowerDebugType(bland_ptr_ty); |
| 2029 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2030 | try dg.object.di_type_map.put(gpa, ty, ptr_di_ty); |
| 2031 | return ptr_di_ty; |
| 2032 | } |
| 2033 | |
| 1989 | 2034 | if (ty.isSlice()) { |
| 1990 | | @panic("TODO debug info type for slices"); |
| 1991 | | //var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1992 | | //const ptr_type = ty.slicePtrFieldType(&buf); |
| 1993 | | |
| 1994 | | //const fields: [2]*const llvm.Type = .{ |
| 1995 | | // try dg.llvmType(ptr_type), |
| 1996 | | // try dg.llvmType(Type.usize), |
| 1997 | | //}; |
| 1998 | | //return dg.context.structType(&fields, fields.len, .False); |
| 2035 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2036 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 2037 | const len_ty = Type.usize; |
| 2038 | |
| 2039 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2040 | const di_file: ?*llvm.DIFile = null; |
| 2041 | const line = 0; |
| 2042 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| 2043 | const fwd_decl = dib.createReplaceableCompositeType( |
| 2044 | DW.TAG.structure_type, |
| 2045 | name.ptr, |
| 2046 | compile_unit_scope, |
| 2047 | di_file, |
| 2048 | line, |
| 2049 | ); |
| 2050 | gop.value_ptr.* = fwd_decl; |
| 2051 | |
| 2052 | const ptr_size = ptr_ty.abiSize(target); |
| 2053 | const ptr_align = ptr_ty.abiAlignment(target); |
| 2054 | const len_size = len_ty.abiSize(target); |
| 2055 | const len_align = len_ty.abiAlignment(target); |
| 2056 | |
| 2057 | var offset: u64 = 0; |
| 2058 | offset += ptr_size; |
| 2059 | offset = std.mem.alignForwardGeneric(u64, offset, len_align); |
| 2060 | const len_offset = offset; |
| 2061 | |
| 2062 | const fields: [2]*llvm.DIType = .{ |
| 2063 | dib.createMemberType( |
| 2064 | fwd_decl.toScope(), |
| 2065 | "ptr", |
| 2066 | di_file, |
| 2067 | line, |
| 2068 | ptr_size * 8, // size in bits |
| 2069 | ptr_align * 8, // align in bits |
| 2070 | 0, // offset in bits |
| 2071 | 0, // flags |
| 2072 | try dg.lowerDebugType(ptr_ty), |
| 2073 | ), |
| 2074 | dib.createMemberType( |
| 2075 | fwd_decl.toScope(), |
| 2076 | "len", |
| 2077 | di_file, |
| 2078 | line, |
| 2079 | len_size * 8, // size in bits |
| 2080 | len_align * 8, // align in bits |
| 2081 | len_offset * 8, // offset in bits |
| 2082 | 0, // flags |
| 2083 | try dg.lowerDebugType(len_ty), |
| 2084 | ), |
| 2085 | }; |
| 2086 | |
| 2087 | const replacement_di_type = dib.createStructType( |
| 2088 | compile_unit_scope, |
| 2089 | name.ptr, |
| 2090 | di_file, |
| 2091 | line, |
| 2092 | ty.abiSize(target) * 8, // size in bits |
| 2093 | ty.abiAlignment(target) * 8, // align in bits |
| 2094 | 0, // flags |
| 2095 | null, // derived from |
| 2096 | &fields, |
| 2097 | fields.len, |
| 2098 | 0, // run time lang |
| 2099 | null, // vtable holder |
| 2100 | "", // unique id |
| 2101 | ); |
| 2102 | dib.replaceTemporary(fwd_decl, replacement_di_type); |
| 2103 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2104 | try dg.object.di_type_map.put(gpa, ty, replacement_di_type); |
| 2105 | return replacement_di_type; |
| 1999 | 2106 | } |
| 2000 | 2107 | |
| 2001 | | const ptr_info = ty.ptrInfo().data; |
| 2002 | 2108 | const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); |
| 2003 | 2109 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2004 | | return dib.createPointerType( |
| 2110 | const ptr_di_ty = dib.createPointerType( |
| 2005 | 2111 | elem_di_ty, |
| 2006 | 2112 | target.cpu.arch.ptrBitWidth(), |
| 2007 | 2113 | ty.ptrAlignment(target) * 8, |
| 2008 | 2114 | name, |
| 2009 | 2115 | ); |
| 2116 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2117 | try dg.object.di_type_map.put(gpa, ty, ptr_di_ty); |
| 2118 | return ptr_di_ty; |
| 2010 | 2119 | }, |
| 2011 | 2120 | .Opaque => { |
| 2012 | | @panic("TODO debug info type for opaque"); |
| 2121 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2122 | const owner_decl = ty.getOwnerDecl(); |
| 2123 | const opaque_di_ty = dib.createForwardDeclType( |
| 2124 | DW.TAG.structure_type, |
| 2125 | name, |
| 2126 | try dg.namespaceToDebugScope(owner_decl.src_namespace), |
| 2127 | try dg.object.getDIFile(gpa, owner_decl.src_namespace.file_scope), |
| 2128 | owner_decl.src_node + 1, |
| 2129 | ); |
| 2130 | // The recursive call to `lowerDebugType` va `namespaceToDebugScope` |
| 2131 | // means we can't use `gop` anymore. |
| 2132 | try dg.object.di_type_map.put(gpa, ty, opaque_di_ty); |
| 2133 | return opaque_di_ty; |
| 2013 | 2134 | }, |
| 2014 | 2135 | .Array => { |
| 2015 | | const elem_di_ty = try lowerDebugType(dg, ty.childType()); |
| 2016 | | return dib.createArrayType( |
| 2136 | const array_di_ty = dib.createArrayType( |
| 2017 | 2137 | ty.abiSize(target) * 8, |
| 2018 | 2138 | ty.abiAlignment(target) * 8, |
| 2019 | | elem_di_ty, |
| 2139 | try lowerDebugType(dg, ty.childType()), |
| 2020 | 2140 | @intCast(c_int, ty.arrayLen()), |
| 2021 | 2141 | ); |
| 2142 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2143 | try dg.object.di_type_map.put(gpa, ty, array_di_ty); |
| 2144 | return array_di_ty; |
| 2022 | 2145 | }, |
| 2023 | 2146 | .Vector => { |
| 2024 | 2147 | @panic("TODO debug info type for vector"); |
| 2025 | 2148 | }, |
| 2026 | 2149 | .Optional => { |
| 2027 | | @panic("TODO debug info type for optional"); |
| 2028 | | //var buf: Type.Payload.ElemType = undefined; |
| 2029 | | //const child_type = ty.optionalChild(&buf); |
| 2030 | | //if (!child_type.hasRuntimeBits()) { |
| 2031 | | // return dg.context.intType(1); |
| 2032 | | //} |
| 2033 | | //const payload_llvm_ty = try dg.llvmType(child_type); |
| 2034 | | //if (ty.isPtrLikeOptional()) { |
| 2035 | | // return payload_llvm_ty; |
| 2036 | | //} else if (!child_type.hasRuntimeBits()) { |
| 2037 | | // return dg.context.intType(1); |
| 2038 | | //} |
| 2150 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2151 | var buf: Type.Payload.ElemType = undefined; |
| 2152 | const child_ty = ty.optionalChild(&buf); |
| 2153 | if (!child_ty.hasRuntimeBits()) { |
| 2154 | gop.value_ptr.* = dib.createBasicType(name, 1, DW.ATE.boolean); |
| 2155 | return gop.value_ptr.*; |
| 2156 | } |
| 2157 | if (ty.isPtrLikeOptional()) { |
| 2158 | const ptr_di_ty = try dg.lowerDebugType(child_ty); |
| 2159 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2160 | try dg.object.di_type_map.put(gpa, ty, ptr_di_ty); |
| 2161 | return ptr_di_ty; |
| 2162 | } |
| 2039 | 2163 | |
| 2040 | | //const fields: [2]*const llvm.Type = .{ |
| 2041 | | // payload_llvm_ty, dg.context.intType(1), |
| 2042 | | //}; |
| 2043 | | //return dg.context.structType(&fields, fields.len, .False); |
| 2164 | const di_file: ?*llvm.DIFile = null; |
| 2165 | const line = 0; |
| 2166 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| 2167 | const fwd_decl = dib.createReplaceableCompositeType( |
| 2168 | DW.TAG.structure_type, |
| 2169 | name.ptr, |
| 2170 | compile_unit_scope, |
| 2171 | di_file, |
| 2172 | line, |
| 2173 | ); |
| 2174 | gop.value_ptr.* = fwd_decl; |
| 2175 | |
| 2176 | const non_null_ty = Type.bool; |
| 2177 | const payload_size = child_ty.abiSize(target); |
| 2178 | const payload_align = child_ty.abiAlignment(target); |
| 2179 | const non_null_size = non_null_ty.abiSize(target); |
| 2180 | const non_null_align = non_null_ty.abiAlignment(target); |
| 2181 | |
| 2182 | var offset: u64 = 0; |
| 2183 | offset += payload_size; |
| 2184 | offset = std.mem.alignForwardGeneric(u64, offset, non_null_align); |
| 2185 | const non_null_offset = offset; |
| 2186 | |
| 2187 | const fields: [2]*llvm.DIType = .{ |
| 2188 | dib.createMemberType( |
| 2189 | fwd_decl.toScope(), |
| 2190 | "data", |
| 2191 | di_file, |
| 2192 | line, |
| 2193 | payload_size * 8, // size in bits |
| 2194 | payload_align * 8, // align in bits |
| 2195 | 0, // offset in bits |
| 2196 | 0, // flags |
| 2197 | try dg.lowerDebugType(child_ty), |
| 2198 | ), |
| 2199 | dib.createMemberType( |
| 2200 | fwd_decl.toScope(), |
| 2201 | "some", |
| 2202 | di_file, |
| 2203 | line, |
| 2204 | non_null_size * 8, // size in bits |
| 2205 | non_null_align * 8, // align in bits |
| 2206 | non_null_offset * 8, // offset in bits |
| 2207 | 0, // flags |
| 2208 | try dg.lowerDebugType(non_null_ty), |
| 2209 | ), |
| 2210 | }; |
| 2211 | |
| 2212 | const replacement_di_type = dib.createStructType( |
| 2213 | compile_unit_scope, |
| 2214 | name.ptr, |
| 2215 | di_file, |
| 2216 | line, |
| 2217 | ty.abiSize(target) * 8, // size in bits |
| 2218 | ty.abiAlignment(target) * 8, // align in bits |
| 2219 | 0, // flags |
| 2220 | null, // derived from |
| 2221 | &fields, |
| 2222 | fields.len, |
| 2223 | 0, // run time lang |
| 2224 | null, // vtable holder |
| 2225 | "", // unique id |
| 2226 | ); |
| 2227 | dib.replaceTemporary(fwd_decl, replacement_di_type); |
| 2228 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2229 | try dg.object.di_type_map.put(gpa, ty, replacement_di_type); |
| 2230 | return replacement_di_type; |
| 2044 | 2231 | }, |
| 2045 | 2232 | .ErrorUnion => { |
| 2046 | 2233 | const err_set_ty = ty.errorUnionSet(); |
| 2047 | | const err_set_di_ty = try dg.lowerDebugType(err_set_ty); |
| 2048 | 2234 | const payload_ty = ty.errorUnionPayload(); |
| 2049 | 2235 | if (!payload_ty.hasRuntimeBits()) { |
| 2236 | const err_set_di_ty = try dg.lowerDebugType(err_set_ty); |
| 2237 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2238 | try dg.object.di_type_map.put(gpa, ty, err_set_di_ty); |
| 2050 | 2239 | return err_set_di_ty; |
| 2051 | 2240 | } |
| 2052 | | const payload_di_ty = try dg.lowerDebugType(payload_ty); |
| 2053 | | |
| 2054 | 2241 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2055 | 2242 | const di_file: ?*llvm.DIFile = null; |
| 2056 | 2243 | const line = 0; |
| ... | ... | @@ -2062,6 +2249,7 @@ pub const DeclGen = struct { |
| 2062 | 2249 | di_file, |
| 2063 | 2250 | line, |
| 2064 | 2251 | ); |
| 2252 | gop.value_ptr.* = fwd_decl; |
| 2065 | 2253 | |
| 2066 | 2254 | const err_set_size = err_set_ty.abiSize(target); |
| 2067 | 2255 | const err_set_align = err_set_ty.abiAlignment(target); |
| ... | ... | @@ -2083,7 +2271,7 @@ pub const DeclGen = struct { |
| 2083 | 2271 | err_set_align * 8, // align in bits |
| 2084 | 2272 | 0, // offset in bits |
| 2085 | 2273 | 0, // flags |
| 2086 | | err_set_di_ty, |
| 2274 | try dg.lowerDebugType(err_set_ty), |
| 2087 | 2275 | ), |
| 2088 | 2276 | dib.createMemberType( |
| 2089 | 2277 | fwd_decl.toScope(), |
| ... | ... | @@ -2094,7 +2282,7 @@ pub const DeclGen = struct { |
| 2094 | 2282 | payload_align * 8, // align in bits |
| 2095 | 2283 | payload_offset * 8, // offset in bits |
| 2096 | 2284 | 0, // flags |
| 2097 | | payload_di_ty, |
| 2285 | try dg.lowerDebugType(payload_ty), |
| 2098 | 2286 | ), |
| 2099 | 2287 | }; |
| 2100 | 2288 | |
| ... | ... | @@ -2114,13 +2302,15 @@ pub const DeclGen = struct { |
| 2114 | 2302 | "", // unique id |
| 2115 | 2303 | ); |
| 2116 | 2304 | dib.replaceTemporary(fwd_decl, replacement_di_type); |
| 2117 | | |
| 2305 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2306 | try dg.object.di_type_map.put(gpa, ty, replacement_di_type); |
| 2118 | 2307 | return replacement_di_type; |
| 2119 | 2308 | }, |
| 2120 | 2309 | .ErrorSet => { |
| 2121 | 2310 | // TODO make this a proper enum with all the error codes in it. |
| 2122 | 2311 | // will need to consider how to take incremental compilation into account. |
| 2123 | | return dib.createBasicType("anyerror", 16, DW.ATE.unsigned); |
| 2312 | gop.value_ptr.* = dib.createBasicType("anyerror", 16, DW.ATE.unsigned); |
| 2313 | return gop.value_ptr.*; |
| 2124 | 2314 | }, |
| 2125 | 2315 | .Struct => { |
| 2126 | 2316 | @panic("TODO debug info type for struct"); |
| ... | ... | @@ -2347,11 +2537,14 @@ pub const DeclGen = struct { |
| 2347 | 2537 | } |
| 2348 | 2538 | } |
| 2349 | 2539 | |
| 2350 | | return dib.createSubroutineType( |
| 2540 | const fn_di_ty = dib.createSubroutineType( |
| 2351 | 2541 | param_di_types.items.ptr, |
| 2352 | 2542 | @intCast(c_int, param_di_types.items.len), |
| 2353 | 2543 | 0, |
| 2354 | 2544 | ); |
| 2545 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 2546 | try dg.object.di_type_map.put(gpa, ty, fn_di_ty); |
| 2547 | return fn_di_ty; |
| 2355 | 2548 | }, |
| 2356 | 2549 | .ComptimeInt => unreachable, |
| 2357 | 2550 | .ComptimeFloat => unreachable, |