| ... | ... | @@ -1914,6 +1914,15 @@ pub const Object = struct { |
| 1914 | 1914 | |
| 1915 | 1915 | const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); |
| 1916 | 1916 | |
| 1917 | // lldb cannot handle non-byte-sized types, so in the logic below, bit sizes are padded up. |
| 1918 | // For instance, `bool` is considered to be 8 bits, and `u60` is considered to be 64 bits. |
| 1919 | |
| 1920 | // I tried using variants (DW_TAG_variant_part + DW_TAG_variant) to encode error unions, |
| 1921 | // tagged unions, etc; this would have told debuggers which field was active, which could |
| 1922 | // improve UX significantly. GDB handles this perfectly fine, but unfortunately, LLDB has no |
| 1923 | // handling for variants at all, and will never print fields in them, so I opted not to use |
| 1924 | // them for now. |
| 1925 | |
| 1917 | 1926 | switch (ty.zigTypeTag(zcu)) { |
| 1918 | 1927 | .void, |
| 1919 | 1928 | .noreturn, |
| ... | ... | @@ -1925,23 +1934,19 @@ pub const Object = struct { |
| 1925 | 1934 | .enum_literal, |
| 1926 | 1935 | => return o.builder.debugSignedType(name, 0), |
| 1927 | 1936 | |
| 1937 | .float => return o.builder.debugFloatType(name, ty.floatBits(target)), |
| 1938 | |
| 1939 | .bool => return o.builder.debugBoolType(name, 8), |
| 1940 | |
| 1928 | 1941 | .int => { |
| 1929 | 1942 | const info = ty.intInfo(zcu); |
| 1930 | | const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types |
| 1943 | const bits = ty.abiSize(zcu) * 8; |
| 1931 | 1944 | return switch (info.signedness) { |
| 1932 | 1945 | .signed => try o.builder.debugSignedType(name, bits), |
| 1933 | 1946 | .unsigned => try o.builder.debugUnsignedType(name, bits), |
| 1934 | 1947 | }; |
| 1935 | 1948 | }, |
| 1936 | | .float => { |
| 1937 | | return o.builder.debugFloatType(name, ty.floatBits(target)); |
| 1938 | | }, |
| 1939 | | .bool => { |
| 1940 | | return o.builder.debugBoolType( |
| 1941 | | name, |
| 1942 | | 8, // lldb cannot handle non-byte sized types |
| 1943 | | ); |
| 1944 | | }, |
| 1949 | |
| 1945 | 1950 | .pointer => { |
| 1946 | 1951 | const ptr_size = Type.ptrAbiSize(zcu.getTarget()); |
| 1947 | 1952 | const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); |
| ... | ... | @@ -1949,20 +1954,20 @@ pub const Object = struct { |
| 1949 | 1954 | if (ty.isSlice(zcu)) { |
| 1950 | 1955 | const debug_ptr_type = try o.builder.debugMemberType( |
| 1951 | 1956 | try o.builder.metadataString("ptr"), |
| 1952 | | null, // File |
| 1957 | null, // file |
| 1953 | 1958 | ty_fwd_ref, |
| 1954 | | 0, // Line |
| 1959 | 0, // line |
| 1955 | 1960 | try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), |
| 1956 | 1961 | ptr_size * 8, |
| 1957 | 1962 | ptr_align.toByteUnits().? * 8, |
| 1958 | | 0, // Offset |
| 1963 | 0, // offset |
| 1959 | 1964 | ); |
| 1960 | 1965 | |
| 1961 | 1966 | const debug_len_type = try o.builder.debugMemberType( |
| 1962 | 1967 | try o.builder.metadataString("len"), |
| 1963 | | null, // File |
| 1968 | null, // file |
| 1964 | 1969 | ty_fwd_ref, |
| 1965 | | 0, // Line |
| 1970 | 0, // line |
| 1966 | 1971 | try o.getDebugType(pt, .usize), |
| 1967 | 1972 | ptr_size * 8, |
| 1968 | 1973 | ptr_align.toByteUnits().? * 8, |
| ... | ... | @@ -1971,10 +1976,10 @@ pub const Object = struct { |
| 1971 | 1976 | |
| 1972 | 1977 | return o.builder.debugStructType( |
| 1973 | 1978 | name, |
| 1974 | | null, // File |
| 1975 | | o.debug_compile_unit.unwrap().?, // Scope |
| 1976 | | 0, // Line |
| 1977 | | null, // Underlying type |
| 1979 | null, // file |
| 1980 | o.debug_compile_unit.unwrap().?, // scope |
| 1981 | 0, // line |
| 1982 | null, // underlying type |
| 1978 | 1983 | ptr_size * 2 * 8, |
| 1979 | 1984 | ptr_align.toByteUnits().? * 8, |
| 1980 | 1985 | try o.builder.metadataTuple(&.{ |
| ... | ... | @@ -1986,36 +1991,34 @@ pub const Object = struct { |
| 1986 | 1991 | |
| 1987 | 1992 | return o.builder.debugPointerType( |
| 1988 | 1993 | name, |
| 1989 | | null, // File |
| 1990 | | null, // Scope |
| 1991 | | 0, // Line |
| 1994 | null, // file |
| 1995 | o.debug_compile_unit.unwrap().?, // scope |
| 1996 | 0, // line |
| 1992 | 1997 | try o.getDebugType(pt, ty.childType(zcu)), |
| 1993 | 1998 | ptr_size * 8, |
| 1994 | 1999 | ptr_align.toByteUnits().? * 8, |
| 1995 | | 0, // Offset |
| 1996 | | ); |
| 1997 | | }, |
| 1998 | | .array => { |
| 1999 | | return o.builder.debugArrayType( |
| 2000 | | null, // Name |
| 2001 | | null, // File |
| 2002 | | null, // Scope |
| 2003 | | 0, // Line |
| 2004 | | try o.getDebugType(pt, ty.childType(zcu)), |
| 2005 | | ty.abiSize(zcu) * 8, |
| 2006 | | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, |
| 2007 | | try o.builder.metadataTuple(&.{ |
| 2008 | | try o.builder.debugSubrange( |
| 2009 | | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), |
| 2010 | | try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), |
| 2011 | | ), |
| 2012 | | }), |
| 2000 | 0, // offset |
| 2013 | 2001 | ); |
| 2014 | 2002 | }, |
| 2003 | .array => return o.builder.debugArrayType( |
| 2004 | name, |
| 2005 | null, // file |
| 2006 | o.debug_compile_unit.unwrap().?, // scope |
| 2007 | 0, // line |
| 2008 | try o.getDebugType(pt, ty.childType(zcu)), |
| 2009 | ty.abiSize(zcu) * 8, |
| 2010 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2011 | try o.builder.metadataTuple(&.{ |
| 2012 | try o.builder.debugSubrange( |
| 2013 | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), |
| 2014 | try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), |
| 2015 | ), |
| 2016 | }), |
| 2017 | ), |
| 2015 | 2018 | .vector => { |
| 2016 | 2019 | const elem_ty = ty.childType(zcu); |
| 2017 | 2020 | // Vector elements cannot be padded since that would make |
| 2018 | | // @bitSizOf(elem) * len > @bitSizOf(vec). |
| 2021 | // @bitSizeOf(elem) * len > @bitSizOf(vec). |
| 2019 | 2022 | // Neither gdb nor lldb seem to be able to display non-byte sized |
| 2020 | 2023 | // vectors properly. |
| 2021 | 2024 | const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -2027,18 +2030,19 @@ pub const Object = struct { |
| 2027 | 2030 | }; |
| 2028 | 2031 | }, |
| 2029 | 2032 | .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1), |
| 2033 | // We don't pad pointers or floats, so we can lower those normally. |
| 2030 | 2034 | .pointer, .optional, .float => try o.getDebugType(pt, elem_ty), |
| 2031 | 2035 | else => unreachable, |
| 2032 | 2036 | }; |
| 2033 | 2037 | |
| 2034 | 2038 | return o.builder.debugVectorType( |
| 2035 | | null, // Name |
| 2036 | | null, // File |
| 2037 | | null, // Scope |
| 2038 | | 0, // Line |
| 2039 | name, |
| 2040 | null, // file |
| 2041 | o.debug_compile_unit.unwrap().?, // scope |
| 2042 | 0, // line |
| 2039 | 2043 | debug_elem_type, |
| 2040 | 2044 | ty.abiSize(zcu) * 8, |
| 2041 | | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, |
| 2045 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2042 | 2046 | try o.builder.metadataTuple(&.{ |
| 2043 | 2047 | try o.builder.debugSubrange( |
| 2044 | 2048 | try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), |
| ... | ... | @@ -2050,26 +2054,15 @@ pub const Object = struct { |
| 2050 | 2054 | .optional => { |
| 2051 | 2055 | const payload_ty = ty.optionalChild(zcu); |
| 2052 | 2056 | if (ty.optionalReprIsPayload(zcu)) { |
| 2053 | | // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. |
| 2054 | | const payload_member = try o.builder.debugMemberType( |
| 2055 | | try o.builder.metadataString("payload"), |
| 2056 | | null, // file |
| 2057 | | ty_fwd_ref, |
| 2058 | | 0, // line |
| 2059 | | try o.getDebugType(pt, .anyerror), |
| 2060 | | ty.abiSize(zcu) * 8, |
| 2061 | | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2062 | | 0, // offset |
| 2063 | | ); |
| 2064 | | return o.builder.debugStructType( |
| 2057 | return o.builder.debugTypedefType( |
| 2065 | 2058 | name, |
| 2066 | 2059 | null, // file |
| 2067 | 2060 | o.debug_compile_unit.unwrap().?, // scope |
| 2068 | 2061 | 0, // line |
| 2069 | | null, // underlying type |
| 2062 | try o.getDebugType(pt, payload_ty), |
| 2070 | 2063 | ty.abiSize(zcu) * 8, |
| 2071 | 2064 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2072 | | try o.builder.metadataTuple(&.{payload_member}), |
| 2065 | 0, // offset |
| 2073 | 2066 | ); |
| 2074 | 2067 | } |
| 2075 | 2068 | |
| ... | ... | @@ -2083,7 +2076,7 @@ pub const Object = struct { |
| 2083 | 2076 | const debug_payload_type = try o.builder.debugMemberType( |
| 2084 | 2077 | try o.builder.metadataString("payload"), |
| 2085 | 2078 | null, // file |
| 2086 | | ty_fwd_ref, |
| 2079 | ty_fwd_ref, // scope |
| 2087 | 2080 | 0, // line |
| 2088 | 2081 | try o.getDebugType(pt, payload_ty), |
| 2089 | 2082 | payload_size * 8, |
| ... | ... | @@ -2104,12 +2097,12 @@ pub const Object = struct { |
| 2104 | 2097 | |
| 2105 | 2098 | return o.builder.debugStructType( |
| 2106 | 2099 | name, |
| 2107 | | null, // File |
| 2108 | | o.debug_compile_unit.unwrap().?, // Scope |
| 2109 | | 0, // Line |
| 2110 | | null, // Underlying type |
| 2100 | null, // file |
| 2101 | o.debug_compile_unit.unwrap().?, // scope |
| 2102 | 0, // line |
| 2103 | null, // underlying type |
| 2111 | 2104 | ty.abiSize(zcu) * 8, |
| 2112 | | (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, |
| 2105 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2113 | 2106 | try o.builder.metadataTuple(&.{ |
| 2114 | 2107 | debug_payload_type, |
| 2115 | 2108 | debug_some_type, |
| ... | ... | @@ -2125,30 +2118,29 @@ pub const Object = struct { |
| 2125 | 2118 | const payload_size = payload_ty.abiSize(zcu); |
| 2126 | 2119 | const payload_align = payload_ty.abiAlignment(zcu); |
| 2127 | 2120 | |
| 2128 | | const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: { |
| 2121 | const error_offset: u64, const payload_offset: u64 = offsets: { |
| 2129 | 2122 | if (error_align.compare(.gt, payload_align)) { |
| 2130 | | break :fields .{ 0, 1, 0, payload_align.forward(error_size) }; |
| 2123 | break :offsets .{ 0, payload_align.forward(error_size) }; |
| 2131 | 2124 | } else { |
| 2132 | | break :fields .{ 1, 0, error_align.forward(payload_size), 0 }; |
| 2125 | break :offsets .{ error_align.forward(payload_size), 0 }; |
| 2133 | 2126 | } |
| 2134 | 2127 | }; |
| 2135 | 2128 | |
| 2136 | | var fields: [2]Builder.Metadata = undefined; |
| 2137 | | fields[error_index] = try o.builder.debugMemberType( |
| 2129 | const error_field = try o.builder.debugMemberType( |
| 2138 | 2130 | try o.builder.metadataString("error"), |
| 2139 | | null, // File |
| 2131 | null, // file |
| 2140 | 2132 | ty_fwd_ref, |
| 2141 | | 0, // Line |
| 2133 | 0, // line |
| 2142 | 2134 | try o.getDebugType(pt, error_ty), |
| 2143 | 2135 | error_size * 8, |
| 2144 | 2136 | error_align.toByteUnits().? * 8, |
| 2145 | 2137 | error_offset * 8, |
| 2146 | 2138 | ); |
| 2147 | | fields[payload_index] = try o.builder.debugMemberType( |
| 2139 | const payload_field = try o.builder.debugMemberType( |
| 2148 | 2140 | try o.builder.metadataString("payload"), |
| 2149 | | null, // File |
| 2150 | | ty_fwd_ref, |
| 2151 | | 0, // Line |
| 2141 | null, // file |
| 2142 | ty_fwd_ref, // scope |
| 2143 | 0, // line |
| 2152 | 2144 | try o.getDebugType(pt, payload_ty), |
| 2153 | 2145 | payload_size * 8, |
| 2154 | 2146 | payload_align.toByteUnits().? * 8, |
| ... | ... | @@ -2163,32 +2155,21 @@ pub const Object = struct { |
| 2163 | 2155 | null, // Underlying type |
| 2164 | 2156 | ty.abiSize(zcu) * 8, |
| 2165 | 2157 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2166 | | try o.builder.metadataTuple(&fields), |
| 2158 | try o.builder.metadataTuple(&.{ error_field, payload_field }), |
| 2167 | 2159 | ); |
| 2168 | 2160 | }, |
| 2169 | 2161 | .error_set => { |
| 2170 | 2162 | assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead |
| 2171 | 2163 | // Error sets are just named wrappers around `anyerror`. |
| 2172 | | // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. |
| 2173 | | const anyerror_member = try o.builder.debugMemberType( |
| 2174 | | try o.builder.metadataString("error"), |
| 2175 | | null, // file |
| 2176 | | ty_fwd_ref, |
| 2177 | | 0, // line |
| 2178 | | try o.getDebugType(pt, .anyerror), |
| 2179 | | ty.abiSize(zcu) * 8, |
| 2180 | | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2181 | | 0, // offset |
| 2182 | | ); |
| 2183 | | return o.builder.debugStructType( |
| 2164 | return o.builder.debugTypedefType( |
| 2184 | 2165 | name, |
| 2185 | 2166 | null, // file |
| 2186 | 2167 | o.debug_compile_unit.unwrap().?, // scope |
| 2187 | 2168 | 0, // line |
| 2188 | | null, // underlying type |
| 2169 | try o.getDebugType(pt, .anyerror), |
| 2189 | 2170 | ty.abiSize(zcu) * 8, |
| 2190 | 2171 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2191 | | try o.builder.metadataTuple(&.{anyerror_member}), |
| 2172 | 0, // offset |
| 2192 | 2173 | ); |
| 2193 | 2174 | }, |
| 2194 | 2175 | .@"fn" => { |
| ... | ... | @@ -2570,14 +2551,22 @@ pub const Object = struct { |
| 2570 | 2551 | const error_set_bits = zcu.errorSetBits(); |
| 2571 | 2552 | const error_names = ip.global_error_set.getNamesFromMainThread(); |
| 2572 | 2553 | |
| 2573 | | const enumerators = try gpa.alloc(Builder.Metadata, error_names.len); |
| 2554 | const enumerators = try gpa.alloc(Builder.Metadata, error_names.len + 1); |
| 2574 | 2555 | defer gpa.free(enumerators); |
| 2575 | 2556 | |
| 2576 | | for (enumerators, error_names, 1..) |*out, error_name, error_value| { |
| 2557 | // The value 0 means "no error" in optionals and error unions. |
| 2558 | enumerators[0] = try o.builder.debugEnumerator( |
| 2559 | try o.builder.metadataString("null"), |
| 2560 | true, // unsigned, |
| 2561 | error_set_bits, |
| 2562 | .{ .limbs = &.{0}, .positive = true }, // zero |
| 2563 | ); |
| 2564 | |
| 2565 | for (enumerators[1..], error_names, 1..) |*out, error_name, error_value| { |
| 2577 | 2566 | var space: Value.BigIntSpace = undefined; |
| 2578 | 2567 | var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value); |
| 2579 | 2568 | out.* = try o.builder.debugEnumerator( |
| 2580 | | try o.builder.metadataString(error_name.toSlice(ip)), |
| 2569 | try o.builder.metadataStringFmt("error.{f}", .{error_name.fmtId(ip)}), |
| 2581 | 2570 | true, // unsigned |
| 2582 | 2571 | error_set_bits, |
| 2583 | 2572 | bigint.toConst(), |
| ... | ... | @@ -3452,84 +3441,6 @@ pub const Object = struct { |
| 3452 | 3441 | ); |
| 3453 | 3442 | } |
| 3454 | 3443 | |
| 3455 | | fn lowerValueToInt(o: *Object, pt: Zcu.PerThread, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant { |
| 3456 | | const zcu = pt.zcu; |
| 3457 | | const ip = &zcu.intern_pool; |
| 3458 | | const target = zcu.getTarget(); |
| 3459 | | |
| 3460 | | const val = Value.fromInterned(arg_val); |
| 3461 | | const val_key = ip.indexToKey(val.toIntern()); |
| 3462 | | |
| 3463 | | if (val.isUndef(zcu)) return o.builder.undefConst(llvm_int_ty); |
| 3464 | | |
| 3465 | | const ty = Type.fromInterned(val_key.typeOf()); |
| 3466 | | switch (val_key) { |
| 3467 | | .@"extern" => |@"extern"| { |
| 3468 | | const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); |
| 3469 | | const ptr = function_index.ptrConst(&o.builder).global.toConst(); |
| 3470 | | return o.builder.convConst(ptr, llvm_int_ty); |
| 3471 | | }, |
| 3472 | | .func => |func| { |
| 3473 | | const function_index = try o.resolveLlvmFunction(pt, func.owner_nav); |
| 3474 | | const ptr = function_index.ptrConst(&o.builder).global.toConst(); |
| 3475 | | return o.builder.convConst(ptr, llvm_int_ty); |
| 3476 | | }, |
| 3477 | | .ptr => return o.builder.convConst(try o.lowerPtr(pt, arg_val, 0), llvm_int_ty), |
| 3478 | | .aggregate => switch (ip.indexToKey(ty.toIntern())) { |
| 3479 | | .struct_type, .vector_type => {}, |
| 3480 | | else => unreachable, |
| 3481 | | }, |
| 3482 | | .un => |un| { |
| 3483 | | const layout = ty.unionGetLayout(zcu); |
| 3484 | | if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); |
| 3485 | | |
| 3486 | | const union_obj = zcu.typeToUnion(ty).?; |
| 3487 | | const container_layout = union_obj.layout; |
| 3488 | | |
| 3489 | | assert(container_layout == .@"packed"); |
| 3490 | | |
| 3491 | | var need_unnamed = false; |
| 3492 | | if (un.tag == .none) { |
| 3493 | | assert(layout.tag_size == 0); |
| 3494 | | const union_val = try o.lowerValueToInt(pt, llvm_int_ty, un.val); |
| 3495 | | |
| 3496 | | need_unnamed = true; |
| 3497 | | return union_val; |
| 3498 | | } |
| 3499 | | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; |
| 3500 | | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 3501 | | if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(llvm_int_ty, 0); |
| 3502 | | return o.lowerValueToInt(pt, llvm_int_ty, un.val); |
| 3503 | | }, |
| 3504 | | .simple_value => |simple_value| switch (simple_value) { |
| 3505 | | .false, .true => {}, |
| 3506 | | else => unreachable, |
| 3507 | | }, |
| 3508 | | .int, |
| 3509 | | .float, |
| 3510 | | .enum_tag, |
| 3511 | | => {}, |
| 3512 | | .opt => {}, // pointer like optional expected |
| 3513 | | else => unreachable, |
| 3514 | | } |
| 3515 | | var stack = std.heap.stackFallback(32, o.gpa); |
| 3516 | | const allocator = stack.get(); |
| 3517 | | |
| 3518 | | const bits: usize = @intCast(ty.bitSize(zcu)); |
| 3519 | | |
| 3520 | | const buffer = try allocator.alloc(u8, (bits + 7) / 8); |
| 3521 | | defer allocator.free(buffer); |
| 3522 | | const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits)); |
| 3523 | | defer allocator.free(limbs); |
| 3524 | | |
| 3525 | | val.writeToPackedMemory(pt, buffer, 0) catch unreachable; |
| 3526 | | |
| 3527 | | var big: std.math.big.int.Mutable = .init(limbs, 0); |
| 3528 | | big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned); |
| 3529 | | |
| 3530 | | return o.builder.bigIntConst(llvm_int_ty, big.toConst()); |
| 3531 | | } |
| 3532 | | |
| 3533 | 3444 | fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant { |
| 3534 | 3445 | const zcu = pt.zcu; |
| 3535 | 3446 | const ip = &zcu.intern_pool; |