| ... | @@ -1909,6 +1909,9 @@ pub const DeclGen = struct { | ... | @@ -1909,6 +1909,9 @@ pub const DeclGen = struct { |
| 1909 | const gop = try dg.object.di_type_map.getOrPut(gpa, ty); | 1909 | const gop = try dg.object.di_type_map.getOrPut(gpa, ty); |
| 1910 | if (gop.found_existing) return gop.value_ptr.*; | 1910 | if (gop.found_existing) return gop.value_ptr.*; |
| 1911 | errdefer assert(dg.object.di_type_map.remove(ty)); | 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()); |
| 1912 | const target = dg.module.getTarget(); | 1915 | const target = dg.module.getTarget(); |
| 1913 | const dib = dg.object.di_builder.?; | 1916 | const dib = dg.object.di_builder.?; |
| 1914 | switch (ty.zigTypeTag()) { | 1917 | switch (ty.zigTypeTag()) { |
| ... | @@ -2084,7 +2087,7 @@ pub const DeclGen = struct { | ... | @@ -2084,7 +2087,7 @@ pub const DeclGen = struct { |
| 2084 | ), | 2087 | ), |
| 2085 | }; | 2088 | }; |
| 2086 | | 2089 | |
| 2087 | const replacement_di_type = dib.createStructType( | 2090 | const replacement_di_ty = dib.createStructType( |
| 2088 | compile_unit_scope, | 2091 | compile_unit_scope, |
| 2089 | name.ptr, | 2092 | name.ptr, |
| 2090 | di_file, | 2093 | di_file, |
| ... | @@ -2099,10 +2102,10 @@ pub const DeclGen = struct { | ... | @@ -2099,10 +2102,10 @@ pub const DeclGen = struct { |
| 2099 | null, // vtable holder | 2102 | null, // vtable holder |
| 2100 | "", // unique id | 2103 | "", // unique id |
| 2101 | ); | 2104 | ); |
| 2102 | dib.replaceTemporary(fwd_decl, replacement_di_type); | 2105 | dib.replaceTemporary(fwd_decl, replacement_di_ty); |
| 2103 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 2106 | // 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); | 2107 | try dg.object.di_type_map.put(gpa, ty, replacement_di_ty); |
| 2105 | return replacement_di_type; | 2108 | return replacement_di_ty; |
| 2106 | } | 2109 | } |
| 2107 | | 2110 | |
| 2108 | const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); | 2111 | const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); |
| ... | @@ -2118,6 +2121,10 @@ pub const DeclGen = struct { | ... | @@ -2118,6 +2121,10 @@ pub const DeclGen = struct { |
| 2118 | return ptr_di_ty; | 2121 | return ptr_di_ty; |
| 2119 | }, | 2122 | }, |
| 2120 | .Opaque => { | 2123 | .Opaque => { |
| | 2124 | if (ty.tag() == .anyopaque) { |
| | 2125 | gop.value_ptr.* = dib.createBasicType("anyopaque", 0, DW.ATE.signed); |
| | 2126 | return gop.value_ptr.*; |
| | 2127 | } |
| 2121 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2128 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2122 | const owner_decl = ty.getOwnerDecl(); | 2129 | const owner_decl = ty.getOwnerDecl(); |
| 2123 | const opaque_di_ty = dib.createForwardDeclType( | 2130 | const opaque_di_ty = dib.createForwardDeclType( |
| ... | @@ -2144,7 +2151,15 @@ pub const DeclGen = struct { | ... | @@ -2144,7 +2151,15 @@ pub const DeclGen = struct { |
| 2144 | return array_di_ty; | 2151 | return array_di_ty; |
| 2145 | }, | 2152 | }, |
| 2146 | .Vector => { | 2153 | .Vector => { |
| 2147 | @panic("TODO debug info type for vector"); | 2154 | const vector_di_ty = dib.createVectorType( |
| | 2155 | ty.abiSize(target) * 8, |
| | 2156 | ty.abiAlignment(target) * 8, |
| | 2157 | try lowerDebugType(dg, ty.childType()), |
| | 2158 | ty.vectorLen(), |
| | 2159 | ); |
| | 2160 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| | 2161 | try dg.object.di_type_map.put(gpa, ty, vector_di_ty); |
| | 2162 | return vector_di_ty; |
| 2148 | }, | 2163 | }, |
| 2149 | .Optional => { | 2164 | .Optional => { |
| 2150 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2165 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| ... | @@ -2209,7 +2224,7 @@ pub const DeclGen = struct { | ... | @@ -2209,7 +2224,7 @@ pub const DeclGen = struct { |
| 2209 | ), | 2224 | ), |
| 2210 | }; | 2225 | }; |
| 2211 | | 2226 | |
| 2212 | const replacement_di_type = dib.createStructType( | 2227 | const replacement_di_ty = dib.createStructType( |
| 2213 | compile_unit_scope, | 2228 | compile_unit_scope, |
| 2214 | name.ptr, | 2229 | name.ptr, |
| 2215 | di_file, | 2230 | di_file, |
| ... | @@ -2224,10 +2239,10 @@ pub const DeclGen = struct { | ... | @@ -2224,10 +2239,10 @@ pub const DeclGen = struct { |
| 2224 | null, // vtable holder | 2239 | null, // vtable holder |
| 2225 | "", // unique id | 2240 | "", // unique id |
| 2226 | ); | 2241 | ); |
| 2227 | dib.replaceTemporary(fwd_decl, replacement_di_type); | 2242 | dib.replaceTemporary(fwd_decl, replacement_di_ty); |
| 2228 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 2243 | // 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); | 2244 | try dg.object.di_type_map.put(gpa, ty, replacement_di_ty); |
| 2230 | return replacement_di_type; | 2245 | return replacement_di_ty; |
| 2231 | }, | 2246 | }, |
| 2232 | .ErrorUnion => { | 2247 | .ErrorUnion => { |
| 2233 | const err_set_ty = ty.errorUnionSet(); | 2248 | const err_set_ty = ty.errorUnionSet(); |
| ... | @@ -2286,7 +2301,7 @@ pub const DeclGen = struct { | ... | @@ -2286,7 +2301,7 @@ pub const DeclGen = struct { |
| 2286 | ), | 2301 | ), |
| 2287 | }; | 2302 | }; |
| 2288 | | 2303 | |
| 2289 | const replacement_di_type = dib.createStructType( | 2304 | const replacement_di_ty = dib.createStructType( |
| 2290 | compile_unit_scope, | 2305 | compile_unit_scope, |
| 2291 | name.ptr, | 2306 | name.ptr, |
| 2292 | di_file, | 2307 | di_file, |
| ... | @@ -2301,10 +2316,10 @@ pub const DeclGen = struct { | ... | @@ -2301,10 +2316,10 @@ pub const DeclGen = struct { |
| 2301 | null, // vtable holder | 2316 | null, // vtable holder |
| 2302 | "", // unique id | 2317 | "", // unique id |
| 2303 | ); | 2318 | ); |
| 2304 | dib.replaceTemporary(fwd_decl, replacement_di_type); | 2319 | dib.replaceTemporary(fwd_decl, replacement_di_ty); |
| 2305 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 2320 | // 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); | 2321 | try dg.object.di_type_map.put(gpa, ty, replacement_di_ty); |
| 2307 | return replacement_di_type; | 2322 | return replacement_di_ty; |
| 2308 | }, | 2323 | }, |
| 2309 | .ErrorSet => { | 2324 | .ErrorSet => { |
| 2310 | // TODO make this a proper enum with all the error codes in it. | 2325 | // TODO make this a proper enum with all the error codes in it. |
| ... | @@ -2313,20 +2328,80 @@ pub const DeclGen = struct { | ... | @@ -2313,20 +2328,80 @@ pub const DeclGen = struct { |
| 2313 | return gop.value_ptr.*; | 2328 | return gop.value_ptr.*; |
| 2314 | }, | 2329 | }, |
| 2315 | .Struct => { | 2330 | .Struct => { |
| 2316 | const owner_decl = ty.getOwnerDecl(); | 2331 | const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); |
| 2317 | | | |
| 2318 | const name = try ty.nameAlloc(gpa); // TODO this is a leak | 2332 | const name = try ty.nameAlloc(gpa); // TODO this is a leak |
| 2319 | const fwd_decl = dib.createReplaceableCompositeType( | 2333 | const fwd_decl = dib.createReplaceableCompositeType( |
| 2320 | DW.TAG.structure_type, | 2334 | DW.TAG.structure_type, |
| 2321 | name.ptr, | 2335 | name.ptr, |
| 2322 | dg.object.di_compile_unit.?.toScope(), | 2336 | compile_unit_scope, |
| 2323 | null, // file | 2337 | null, // file |
| 2324 | 0, // line | 2338 | 0, // line |
| 2325 | ); | 2339 | ); |
| 2326 | gop.value_ptr.* = fwd_decl; | 2340 | gop.value_ptr.* = fwd_decl; |
| 2327 | | 2341 | |
| | 2342 | if (ty.isTupleOrAnonStruct()) { |
| | 2343 | const tuple = ty.tupleFields(); |
| | 2344 | |
| | 2345 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| | 2346 | defer di_fields.deinit(gpa); |
| | 2347 | |
| | 2348 | try di_fields.ensureUnusedCapacity(gpa, tuple.types.len); |
| | 2349 | |
| | 2350 | comptime assert(struct_layout_version == 2); |
| | 2351 | var offset: u64 = 0; |
| | 2352 | |
| | 2353 | for (tuple.types) |field_ty, i| { |
| | 2354 | const field_val = tuple.values[i]; |
| | 2355 | if (field_val.tag() != .unreachable_value) continue; |
| | 2356 | |
| | 2357 | const field_size = field_ty.abiSize(target); |
| | 2358 | const field_align = field_ty.abiAlignment(target); |
| | 2359 | const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align); |
| | 2360 | offset = field_offset + field_size; |
| | 2361 | |
| | 2362 | const field_name = if (ty.castTag(.anon_struct)) |payload| |
| | 2363 | try gpa.dupeZ(u8, payload.data.names[i]) |
| | 2364 | else |
| | 2365 | try std.fmt.allocPrintZ(gpa, "{d}", .{i}); |
| | 2366 | defer gpa.free(field_name); |
| | 2367 | |
| | 2368 | try di_fields.append(gpa, dib.createMemberType( |
| | 2369 | fwd_decl.toScope(), |
| | 2370 | field_name, |
| | 2371 | null, // file |
| | 2372 | 0, // line |
| | 2373 | field_size * 8, // size in bits |
| | 2374 | field_align * 8, // align in bits |
| | 2375 | field_offset * 8, // offset in bits |
| | 2376 | 0, // flags |
| | 2377 | try dg.lowerDebugType(field_ty), |
| | 2378 | )); |
| | 2379 | } |
| | 2380 | |
| | 2381 | const replacement_di_ty = dib.createStructType( |
| | 2382 | compile_unit_scope, |
| | 2383 | name.ptr, |
| | 2384 | null, // file |
| | 2385 | 0, // line |
| | 2386 | ty.abiSize(target) * 8, // size in bits |
| | 2387 | ty.abiAlignment(target) * 8, // align in bits |
| | 2388 | 0, // flags |
| | 2389 | null, // derived from |
| | 2390 | di_fields.items.ptr, |
| | 2391 | @intCast(c_int, di_fields.items.len), |
| | 2392 | 0, // run time lang |
| | 2393 | null, // vtable holder |
| | 2394 | "", // unique id |
| | 2395 | ); |
| | 2396 | dib.replaceTemporary(fwd_decl, replacement_di_ty); |
| | 2397 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| | 2398 | try dg.object.di_type_map.put(gpa, ty, replacement_di_ty); |
| | 2399 | return replacement_di_ty; |
| | 2400 | } |
| | 2401 | |
| 2328 | const TODO_implement_this = true; // TODO | 2402 | const TODO_implement_this = true; // TODO |
| 2329 | if (TODO_implement_this or !ty.hasRuntimeBits()) { | 2403 | if (TODO_implement_this or !ty.hasRuntimeBits()) { |
| | 2404 | const owner_decl = ty.getOwnerDecl(); |
| 2330 | const struct_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl); | 2405 | const struct_di_ty = try dg.makeEmptyNamespaceDIType(owner_decl); |
| 2331 | dib.replaceTemporary(fwd_decl, struct_di_ty); | 2406 | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| 2332 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` | 2407 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| ... | @@ -2336,65 +2411,6 @@ pub const DeclGen = struct { | ... | @@ -2336,65 +2411,6 @@ pub const DeclGen = struct { |
| 2336 | } | 2411 | } |
| 2337 | @panic("TODO debug info type for struct"); | 2412 | @panic("TODO debug info type for struct"); |
| 2338 | | 2413 | |
| 2339 | //const gop = try dg.object.type_map.getOrPut(gpa, ty); | | |
| 2340 | //if (gop.found_existing) return gop.value_ptr.*; | | |
| 2341 | | | |
| 2342 | //// The Type memory is ephemeral; since we want to store a longer-lived | | |
| 2343 | //// reference, we need to copy it here. | | |
| 2344 | //gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator()); | | |
| 2345 | | | |
| 2346 | //if (ty.isTupleOrAnonStruct()) { | | |
| 2347 | // const tuple = ty.tupleFields(); | | |
| 2348 | // const llvm_struct_ty = dg.context.structCreateNamed(""); | | |
| 2349 | // gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls | | |
| 2350 | | | |
| 2351 | // var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{}; | | |
| 2352 | // defer llvm_field_types.deinit(gpa); | | |
| 2353 | | | |
| 2354 | // try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len); | | |
| 2355 | | | |
| 2356 | // comptime assert(struct_layout_version == 2); | | |
| 2357 | // var offset: u64 = 0; | | |
| 2358 | // var big_align: u32 = 0; | | |
| 2359 | | | |
| 2360 | // for (tuple.types) |field_ty, i| { | | |
| 2361 | // const field_val = tuple.values[i]; | | |
| 2362 | // if (field_val.tag() != .unreachable_value) continue; | | |
| 2363 | | | |
| 2364 | // const field_align = field_ty.abiAlignment(target); | | |
| 2365 | // big_align = @maximum(big_align, field_align); | | |
| 2366 | // const prev_offset = offset; | | |
| 2367 | // offset = std.mem.alignForwardGeneric(u64, offset, field_align); | | |
| 2368 | | | |
| 2369 | // const padding_len = offset - prev_offset; | | |
| 2370 | // if (padding_len > 0) { | | |
| 2371 | // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); | | |
| 2372 | // try llvm_field_types.append(gpa, llvm_array_ty); | | |
| 2373 | // } | | |
| 2374 | // const field_llvm_ty = try dg.llvmType(field_ty); | | |
| 2375 | // try llvm_field_types.append(gpa, field_llvm_ty); | | |
| 2376 | | | |
| 2377 | // offset += field_ty.abiSize(target); | | |
| 2378 | // } | | |
| 2379 | // { | | |
| 2380 | // const prev_offset = offset; | | |
| 2381 | // offset = std.mem.alignForwardGeneric(u64, offset, big_align); | | |
| 2382 | // const padding_len = offset - prev_offset; | | |
| 2383 | // if (padding_len > 0) { | | |
| 2384 | // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); | | |
| 2385 | // try llvm_field_types.append(gpa, llvm_array_ty); | | |
| 2386 | // } | | |
| 2387 | // } | | |
| 2388 | | | |
| 2389 | // llvm_struct_ty.structSetBody( | | |
| 2390 | // llvm_field_types.items.ptr, | | |
| 2391 | // @intCast(c_uint, llvm_field_types.items.len), | | |
| 2392 | // .False, | | |
| 2393 | // ); | | |
| 2394 | | | |
| 2395 | // return llvm_struct_ty; | | |
| 2396 | //} | | |
| 2397 | | | |
| 2398 | //const struct_obj = ty.castTag(.@"struct").?.data; | 2414 | //const struct_obj = ty.castTag(.@"struct").?.data; |
| 2399 | | 2415 | |
| 2400 | //if (struct_obj.layout == .Packed) { | 2416 | //if (struct_obj.layout == .Packed) { |
| ... | @@ -2554,7 +2570,10 @@ pub const DeclGen = struct { | ... | @@ -2554,7 +2570,10 @@ pub const DeclGen = struct { |
| 2554 | defer param_di_types.deinit(); | 2570 | defer param_di_types.deinit(); |
| 2555 | | 2571 | |
| 2556 | // Return type goes first. | 2572 | // Return type goes first. |
| 2557 | const di_ret_ty = if (sret) Type.void else fn_info.return_type; | 2573 | const di_ret_ty = if (sret or !fn_info.return_type.hasRuntimeBits()) |
| | 2574 | Type.void |
| | 2575 | else |
| | 2576 | fn_info.return_type; |
| 2558 | try param_di_types.append(try dg.lowerDebugType(di_ret_ty)); | 2577 | try param_di_types.append(try dg.lowerDebugType(di_ret_ty)); |
| 2559 | | 2578 | |
| 2560 | if (sret) { | 2579 | if (sret) { |