authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-17 05:00:17-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-20 23:48:36-05:00
log7768d2024bfbb4aad143fb8a4143e324445bfd93
tree4e664cbecf7a49e2feabce10e7e92c5166ea91f9
parentd8fada6b6325e07015fddd68bb4c6369a66f23f3

CBE: use CType for type rendering


1 files changed, 287 insertions(+), 287 deletions(-)

src/codegen/c.zig+287-287
...@@ -1954,291 +1954,311 @@ pub const DeclGen = struct {...@@ -1954,291 +1954,311 @@ pub const DeclGen = struct {
1954 return name;1954 return name;
1955 }1955 }
19561956
1957 fn indexToCType(dg: *DeclGen, idx: CType.Index) CType {
1958 return dg.ctypes.indexToCType(idx);
1959 }
1957 fn typeToCType(dg: *DeclGen, ty: Type) !CType {1960 fn typeToCType(dg: *DeclGen, ty: Type) !CType {
1958 return dg.ctypes.typeToCType(dg.gpa, ty, dg.module);1961 return dg.ctypes.typeToCType(dg.gpa, ty, dg.module);
1959 }1962 }
19601963 fn typeToIndex(dg: *DeclGen, ty: Type) !CType.Index {
1961 /// Renders a type as a single identifier, generating intermediate typedefs1964 return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module);
1962 /// if necessary.1965 }
1963 ///1966
1964 /// This is guaranteed to be valid in both typedefs and declarations/definitions.1967 const CTypeFix = enum { prefix, suffix };
1965 ///1968 const CQualifiers = std.enums.EnumSet(enum { @"const", @"volatile", restrict });
1966 /// There are three type formats in total that we support rendering:1969 const CTypeRenderTrailing = enum {
1967 /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) |1970 no_space,
1968 /// |---------------------|-----------------|---------------------|1971 maybe_space,
1969 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |1972
1970 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1973 pub fn format(
1971 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1974 self: @This(),
1972 ///1975 comptime fmt: []const u8,
1973 fn renderType(1976 _: std.fmt.FormatOptions,
1977 w: anytype,
1978 ) @TypeOf(w).Error!void {
1979 if (fmt.len != 0)
1980 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++
1981 @typeName(@This()) ++ "'");
1982 comptime assert(fmt.len == 0);
1983 switch (self) {
1984 .no_space => {},
1985 .maybe_space => try w.writeByte(' '),
1986 }
1987 }
1988 };
1989 fn renderTypePrefix(
1974 dg: *DeclGen,1990 dg: *DeclGen,
1975 w: anytype,1991 w: anytype,
1976 t: Type,1992 idx: CType.Index,
1977 kind: TypedefKind,1993 parent_fix: CTypeFix,
1978 ) error{ OutOfMemory, AnalysisFail }!void {1994 qualifiers: CQualifiers,
1979 _ = try dg.typeToCType(t);1995 ) @TypeOf(w).Error!CTypeRenderTrailing {
19801996 var trailing = CTypeRenderTrailing.maybe_space;
1981 const target = dg.module.getTarget();1997
19821998 const cty = dg.indexToCType(idx);
1983 switch (t.zigTypeTag()) {1999 switch (cty.tag()) {
1984 .Void => try w.writeAll("void"),2000 .void,
1985 .Bool => try w.writeAll("bool"),2001 .char,
1986 .NoReturn, .Float => {2002 .@"signed char",
1987 try w.writeAll("zig_");2003 .short,
1988 try t.print(w, dg.module);2004 .int,
1989 },2005 .long,
1990 .Int => {2006 .@"long long",
1991 if (t.isNamedInt()) {2007 ._Bool,
1992 try w.writeAll("zig_");2008 .@"unsigned char",
1993 try t.print(w, dg.module);2009 .@"unsigned short",
1994 } else {2010 .@"unsigned int",
1995 return renderTypeUnnamed(dg, w, t, kind);2011 .@"unsigned long",
1996 }2012 .@"unsigned long long",
1997 },2013 .float,
1998 .ErrorSet => {2014 .double,
1999 return renderTypeUnnamed(dg, w, t, kind);2015 .@"long double",
2016 .bool,
2017 .size_t,
2018 .ptrdiff_t,
2019 .zig_u8,
2020 .zig_i8,
2021 .zig_u16,
2022 .zig_i16,
2023 .zig_u32,
2024 .zig_i32,
2025 .zig_u64,
2026 .zig_i64,
2027 .zig_u128,
2028 .zig_i128,
2029 .zig_f16,
2030 .zig_f32,
2031 .zig_f64,
2032 .zig_f80,
2033 .zig_f128,
2034 => |tag| try w.writeAll(@tagName(tag)),
2035
2036 .pointer,
2037 .pointer_const,
2038 .pointer_volatile,
2039 .pointer_const_volatile,
2040 => |tag| {
2041 const child_idx = cty.cast(CType.Payload.Child).?.data;
2042 try w.print("{}*", .{try dg.renderTypePrefix(w, child_idx, .prefix, CQualifiers.init(.{
2043 .@"const" = switch (tag) {
2044 .pointer, .pointer_volatile => false,
2045 .pointer_const, .pointer_const_volatile => true,
2046 else => unreachable,
2047 },
2048 .@"volatile" = switch (tag) {
2049 .pointer, .pointer_const => false,
2050 .pointer_volatile, .pointer_const_volatile => true,
2051 else => unreachable,
2052 },
2053 }))});
2054 trailing = .no_space;
2000 },2055 },
2001 .Pointer => {
2002 const ptr_info = t.ptrInfo().data;
2003 if (ptr_info.size == .Slice) {
2004 var slice_pl = Type.Payload.ElemType{
2005 .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice },
2006 .data = ptr_info.pointee_type,
2007 };
2008 const slice_ty = Type.initPayload(&slice_pl.base);
2009
2010 const name = dg.getTypedefName(slice_ty) orelse
2011 try dg.renderSliceTypedef(slice_ty);
20122056
2013 return w.writeAll(name);2057 .array,
2014 }2058 .vector,
20152059 => {
2016 if (ptr_info.pointee_type.zigTypeTag() == .Fn) {2060 const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
2017 const name = dg.getTypedefName(ptr_info.pointee_type) orelse2061 const child_trailing = try dg.renderTypePrefix(w, child_idx, .suffix, qualifiers);
2018 try dg.renderPtrToFnTypedef(ptr_info.pointee_type);2062 switch (parent_fix) {
20192063 .prefix => {
2020 return w.writeAll(name);2064 try w.print("{}(", .{child_trailing});
2065 return .no_space;
2066 },
2067 .suffix => return child_trailing,
2021 }2068 }
2022
2023 if (ptr_info.host_size != 0) {
2024 var host_pl = Type.Payload.Bits{
2025 .base = .{ .tag = .int_unsigned },
2026 .data = ptr_info.host_size * 8,
2027 };
2028 const host_ty = Type.initPayload(&host_pl.base);
2029
2030 try dg.renderType(w, host_ty, .Forward);
2031 } else if (t.isCPtr() and ptr_info.pointee_type.eql(Type.u8, dg.module) and
2032 (dg.decl.val.tag() == .extern_fn or
2033 std.mem.eql(u8, std.mem.span(dg.decl.name), "main")))
2034 {
2035 // This is a hack, since the c compiler expects a lot of external
2036 // library functions to have char pointers in their signatures, but
2037 // u8 and i8 produce unsigned char and signed char respectively,
2038 // which in C are (not very usefully) different than char.
2039 try w.writeAll("char");
2040 } else try dg.renderType(w, switch (ptr_info.pointee_type.tag()) {
2041 .anyopaque => Type.void,
2042 else => ptr_info.pointee_type,
2043 }, .Forward);
2044 if (t.isConstPtr()) try w.writeAll(" const");
2045 if (t.isVolatilePtr()) try w.writeAll(" volatile");
2046 return w.writeAll(" *");
2047 },
2048 .Array, .Vector => {
2049 var array_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
2050 .len = t.arrayLenIncludingSentinel(),
2051 .elem_type = t.childType(),
2052 } };
2053 const array_ty = Type.initPayload(&array_pl.base);
2054
2055 const name = dg.getTypedefName(array_ty) orelse
2056 try dg.renderArrayTypedef(array_ty);
2057
2058 return w.writeAll(name);
2059 },2069 },
2060 .Optional => {
2061 var opt_buf: Type.Payload.ElemType = undefined;
2062 const child_ty = t.optionalChild(&opt_buf);
2063
2064 if (!child_ty.hasRuntimeBitsIgnoreComptime())
2065 return dg.renderType(w, Type.bool, kind);
2066
2067 if (t.optionalReprIsPayload())
2068 return dg.renderType(w, child_ty, kind);
20692070
2070 switch (kind) {2071 .fwd_struct,
2071 .Complete => {2072 .fwd_union,
2072 const name = dg.getTypedefName(t) orelse2073 .anon_struct,
2073 try dg.renderOptionalTypedef(t);2074 .packed_anon_struct,
20742075 => |tag| try w.print("{s} {}__{d}", .{
2075 try w.writeAll(name);2076 switch (tag) {
2076 },2077 .fwd_struct,
2077 .Forward => {2078 .anon_struct,
2078 var ptr_pl = Type.Payload.ElemType{2079 .packed_anon_struct,
2079 .base = .{ .tag = .single_const_pointer },2080 => "struct",
2080 .data = t,2081 .fwd_union => "union",
2081 };2082 else => unreachable,
2082 const ptr_ty = Type.initPayload(&ptr_pl.base);2083 },
20832084 fmtIdent(switch (tag) {
2084 const name = dg.getTypedefName(ptr_ty) orelse2085 .fwd_struct,
2085 try dg.renderFwdTypedef(ptr_ty);2086 .fwd_union,
2087 => mem.span(dg.module.declPtr(cty.cast(CType.Payload.FwdDecl).?.data).name),
2088 .anon_struct,
2089 .packed_anon_struct,
2090 => "anon",
2091 else => unreachable,
2092 }),
2093 idx,
2094 }),
20862095
2087 try w.writeAll(name);2096 .@"struct",
2097 .packed_struct,
2098 .@"union",
2099 .packed_union,
2100 => return dg.renderTypePrefix(
2101 w,
2102 cty.cast(CType.Payload.Aggregate).?.data.fwd_decl,
2103 parent_fix,
2104 qualifiers,
2105 ),
2106
2107 .function,
2108 .varargs_function,
2109 => {
2110 const child_trailing = try dg.renderTypePrefix(
2111 w,
2112 cty.cast(CType.Payload.Function).?.data.return_type,
2113 .suffix,
2114 CQualifiers.initEmpty(),
2115 );
2116 switch (parent_fix) {
2117 .prefix => {
2118 try w.print("{}(", .{child_trailing});
2119 return .no_space;
2088 },2120 },
2121 .suffix => return child_trailing,
2089 }2122 }
2090 },2123 },
2091 .ErrorUnion => {2124 }
2092 const payload_ty = t.errorUnionPayload();
20932125
2094 if (!payload_ty.hasRuntimeBitsIgnoreComptime())2126 var qualifier_it = qualifiers.iterator();
2095 return dg.renderType(w, Type.anyerror, kind);2127 while (qualifier_it.next()) |qualifier| {
2128 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });
2129 trailing = .maybe_space;
2130 }
20962131
2097 var error_union_pl = Type.Payload.ErrorUnion{2132 return trailing;
2098 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },2133 }
2099 };2134 fn renderTypeSuffix(
2100 const error_union_ty = Type.initPayload(&error_union_pl.base);2135 dg: *DeclGen,
2136 w: anytype,
2137 idx: CType.Index,
2138 parent_fix: CTypeFix,
2139 ) @TypeOf(w).Error!void {
2140 const cty = dg.indexToCType(idx);
2141 switch (cty.tag()) {
2142 .void,
2143 .char,
2144 .@"signed char",
2145 .short,
2146 .int,
2147 .long,
2148 .@"long long",
2149 ._Bool,
2150 .@"unsigned char",
2151 .@"unsigned short",
2152 .@"unsigned int",
2153 .@"unsigned long",
2154 .@"unsigned long long",
2155 .float,
2156 .double,
2157 .@"long double",
2158 .bool,
2159 .size_t,
2160 .ptrdiff_t,
2161 .zig_u8,
2162 .zig_i8,
2163 .zig_u16,
2164 .zig_i16,
2165 .zig_u32,
2166 .zig_i32,
2167 .zig_u64,
2168 .zig_i64,
2169 .zig_u128,
2170 .zig_i128,
2171 .zig_f16,
2172 .zig_f32,
2173 .zig_f64,
2174 .zig_f80,
2175 .zig_f128,
2176 => {},
2177
2178 .pointer,
2179 .pointer_const,
2180 .pointer_volatile,
2181 .pointer_const_volatile,
2182 => try dg.renderTypeSuffix(w, cty.cast(CType.Payload.Child).?.data, .prefix),
2183
2184 .array,
2185 .vector,
2186 => {
2187 switch (parent_fix) {
2188 .prefix => try w.writeByte(')'),
2189 .suffix => {},
2190 }
21012191
2102 switch (kind) {2192 try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len});
2103 .Complete => {2193 try dg.renderTypeSuffix(w, cty.cast(CType.Payload.Sequence).?.data.elem_type, .suffix);
2104 const name = dg.getTypedefName(error_union_ty) orelse2194 },
2105 try dg.renderErrorUnionTypedef(error_union_ty);
21062195
2107 try w.writeAll(name);2196 .fwd_struct,
2108 },2197 .fwd_union,
2109 .Forward => {2198 .anon_struct,
2110 var ptr_pl = Type.Payload.ElemType{2199 .packed_anon_struct,
2111 .base = .{ .tag = .single_const_pointer },2200 .@"struct",
2112 .data = error_union_ty,2201 .@"union",
2113 };2202 .packed_struct,
2114 const ptr_ty = Type.initPayload(&ptr_pl.base);2203 .packed_union,
2204 => {},
2205
2206 .function,
2207 .varargs_function,
2208 => |tag| {
2209 switch (parent_fix) {
2210 .prefix => try w.writeByte(')'),
2211 .suffix => {},
2212 }
21152213
2116 const name = dg.getTypedefName(ptr_ty) orelse2214 const data = cty.cast(CType.Payload.Function).?.data;
2117 try dg.renderFwdTypedef(ptr_ty);
21182215
2119 try w.writeAll(name);2216 try w.writeByte('(');
2120 },2217 var need_comma = false;
2218 for (data.param_types) |param_type| {
2219 if (need_comma) try w.writeAll(", ");
2220 need_comma = true;
2221 _ = try dg.renderTypePrefix(w, param_type, .suffix, CQualifiers.initEmpty());
2222 try dg.renderTypeSuffix(w, param_type, .suffix);
2121 }2223 }
2122 },2224 switch (tag) {
2123 .Struct, .Union => |tag| if (t.containerLayout() == .Packed) {2225 .function => {},
2124 if (t.castTag(.@"struct")) |struct_obj| {2226 .varargs_function => {
2125 try dg.renderType(w, struct_obj.data.backing_int_ty, kind);2227 if (need_comma) try w.writeAll(", ");
2126 } else {2228 need_comma = true;
2127 var buf: Type.Payload.Bits = .{2229 try w.writeAll("...");
2128 .base = .{ .tag = .int_unsigned },2230 },
2129 .data = @intCast(u16, t.bitSize(target)),2231 else => unreachable,
2130 };
2131 try dg.renderType(w, Type.initPayload(&buf.base), kind);
2132 }2232 }
2133 } else if (t.isSimpleTupleOrAnonStruct()) {2233 if (!need_comma) try w.writeAll("void");
2134 const ExpectedContents = struct { types: [8]Type, values: [8]Value };2234 try w.writeByte(')');
2135 var stack align(@alignOf(ExpectedContents)) =
2136 std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);
2137 const allocator = stack.get();
2138
2139 var tuple_storage = std.MultiArrayList(struct { type: Type, value: Value }){};
2140 defer tuple_storage.deinit(allocator);
2141 try tuple_storage.ensureTotalCapacity(allocator, t.structFieldCount());
2142
2143 const fields = t.tupleFields();
2144 for (fields.values, 0..) |value, index|
2145 if (value.tag() == .unreachable_value)
2146 tuple_storage.appendAssumeCapacity(.{
2147 .type = fields.types[index],
2148 .value = value,
2149 });
2150
2151 const tuple_slice = tuple_storage.slice();
2152 var tuple_pl = Type.Payload.Tuple{ .data = .{
2153 .types = tuple_slice.items(.type),
2154 .values = tuple_slice.items(.value),
2155 } };
2156 const tuple_ty = Type.initPayload(&tuple_pl.base);
2157
2158 const name = dg.getTypedefName(tuple_ty) orelse
2159 try dg.renderTupleTypedef(tuple_ty);
2160
2161 try w.writeAll(name);
2162 } else switch (kind) {
2163 .Complete => {
2164 const name = dg.getTypedefName(t) orelse switch (tag) {
2165 .Struct => try dg.renderStructTypedef(t),
2166 .Union => try dg.renderUnionTypedef(t),
2167 else => unreachable,
2168 };
2169
2170 try w.writeAll(name);
2171 },
2172 .Forward => {
2173 var ptr_pl = Type.Payload.ElemType{
2174 .base = .{ .tag = .single_const_pointer },
2175 .data = t,
2176 };
2177 const ptr_ty = Type.initPayload(&ptr_pl.base);
2178
2179 const name = dg.getTypedefName(ptr_ty) orelse
2180 try dg.renderFwdTypedef(ptr_ty);
2181
2182 try w.writeAll(name);
2183 },
2184 },
2185 .Enum => {
2186 // For enums, we simply use the integer tag type.
2187 var int_tag_buf: Type.Payload.Bits = undefined;
2188 const int_tag_ty = t.intTagType(&int_tag_buf);
21892235
2190 try dg.renderType(w, int_tag_ty, kind);2236 try dg.renderTypeSuffix(w, data.return_type, .suffix);
2191 },2237 },
2192 .Opaque => switch (t.tag()) {
2193 .@"opaque" => {
2194 const name = dg.getTypedefName(t) orelse
2195 try dg.renderOpaqueTypedef(t);
2196
2197 try w.writeAll(name);
2198 },
2199 else => unreachable,
2200 },
2201
2202 .Frame,
2203 .AnyFrame,
2204 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
2205 @tagName(tag),
2206 }),
2207
2208 .Fn => unreachable, // This is a function body, not a function pointer.
2209
2210 .Null,
2211 .Undefined,
2212 .EnumLiteral,
2213 .ComptimeFloat,
2214 .ComptimeInt,
2215 .Type,
2216 => unreachable, // must be const or comptime
2217 }2238 }
2218 }2239 }
22192240
2220 fn renderTypeUnnamed(2241 /// Renders a type as a single identifier, generating intermediate typedefs
2242 /// if necessary.
2243 ///
2244 /// This is guaranteed to be valid in both typedefs and declarations/definitions.
2245 ///
2246 /// There are three type formats in total that we support rendering:
2247 /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) |
2248 /// |---------------------|-----------------|---------------------|
2249 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
2250 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2251 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2252 ///
2253 fn renderType(
2221 dg: *DeclGen,2254 dg: *DeclGen,
2222 w: anytype,2255 w: anytype,
2223 t: Type,2256 t: Type,
2224 kind: TypedefKind,2257 _: TypedefKind,
2225 ) error{ OutOfMemory, AnalysisFail }!void {2258 ) error{ OutOfMemory, AnalysisFail }!void {
2226 const target = dg.module.getTarget();2259 const idx = try dg.typeToIndex(t);
2227 const int_info = t.intInfo(target);2260 _ = try dg.renderTypePrefix(w, idx, .suffix, CQualifiers.initEmpty());
2228 if (toCIntBits(int_info.bits)) |c_bits|2261 try dg.renderTypeSuffix(w, idx, .suffix);
2229 return w.print("zig_{c}{d}", .{ signAbbrev(int_info.signedness), c_bits })
2230 else if (loweredArrayInfo(t, target)) |array_info| {
2231 assert(array_info.sentinel == null);
2232 var array_pl = Type.Payload.Array{
2233 .base = .{ .tag = .array },
2234 .data = .{ .len = array_info.len, .elem_type = array_info.elem_type },
2235 };
2236 const array_ty = Type.initPayload(&array_pl.base);
2237
2238 return dg.renderType(w, array_ty, kind);
2239 } else return dg.fail("C backend: Unable to lower unnamed integer type {}", .{
2240 t.fmt(dg.module),
2241 });
2242 }2262 }
22432263
2244 const IntCastContext = union(enum) {2264 const IntCastContext = union(enum) {
...@@ -2348,10 +2368,10 @@ pub const DeclGen = struct {...@@ -2348,10 +2368,10 @@ pub const DeclGen = struct {
2348 /// |---------------------|-----------------|---------------------|2368 /// |---------------------|-----------------|---------------------|
2349 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |2369 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
2350 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |2370 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2351 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |2371 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2352 ///2372 ///
2353 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {2373 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {
2354 return renderTypeAndName(dg, w, ty, .{ .bytes = "" }, .Mut, 0, .Complete);2374 try dg.renderType(w, ty, undefined);
2355 }2375 }
23562376
2357 /// Renders a type and name in field declaration/definition format.2377 /// Renders a type and name in field declaration/definition format.
...@@ -2361,7 +2381,7 @@ pub const DeclGen = struct {...@@ -2361,7 +2381,7 @@ pub const DeclGen = struct {
2361 /// |---------------------|-----------------|---------------------|2381 /// |---------------------|-----------------|---------------------|
2362 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |2382 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
2363 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |2383 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2364 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |2384 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2365 ///2385 ///
2366 fn renderTypeAndName(2386 fn renderTypeAndName(
2367 dg: *DeclGen,2387 dg: *DeclGen,
...@@ -2370,46 +2390,26 @@ pub const DeclGen = struct {...@@ -2370,46 +2390,26 @@ pub const DeclGen = struct {
2370 name: CValue,2390 name: CValue,
2371 mutability: Mutability,2391 mutability: Mutability,
2372 alignment: u32,2392 alignment: u32,
2373 kind: TypedefKind,2393 _: TypedefKind,
2374 ) error{ OutOfMemory, AnalysisFail }!void {2394 ) error{ OutOfMemory, AnalysisFail }!void {
2375 var suffix = std.ArrayList(u8).init(dg.gpa);
2376 defer suffix.deinit();
2377 const suffix_writer = suffix.writer();
2378
2379 // Any top-level array types are rendered here as a suffix, which
2380 // avoids creating typedefs for every array type
2381 const target = dg.module.getTarget();
2382 var render_ty = ty;
2383 var depth: u32 = 0;
2384 while (loweredArrayInfo(render_ty, target)) |array_info| {
2385 const c_len = array_info.len + @boolToInt(array_info.sentinel != null);
2386 var c_len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = c_len };
2387 const c_len_val = Value.initPayload(&c_len_pl.base);
2388
2389 try suffix_writer.writeByte('[');
2390 if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("zig_const_arr ");
2391 try suffix.writer().print("{}]", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
2392 render_ty = array_info.elem_type;
2393 depth += 1;
2394 }
2395
2396 if (alignment != 0) {2395 if (alignment != 0) {
2397 const abi_alignment = ty.abiAlignment(target);2396 const abi_alignment = ty.abiAlignment(dg.module.getTarget());
2398 if (alignment < abi_alignment) {2397 if (alignment < abi_alignment) {
2399 try w.print("zig_under_align({}) ", .{alignment});2398 try w.print("zig_under_align({}) ", .{alignment});
2400 } else if (alignment > abi_alignment) {2399 } else if (alignment > abi_alignment) {
2401 try w.print("zig_align({}) ", .{alignment});2400 try w.print("zig_align({}) ", .{alignment});
2402 }2401 }
2403 }2402 }
2404 try dg.renderType(w, render_ty, kind);
24052403
2406 const const_prefix = switch (mutability) {2404 const idx = try dg.typeToIndex(ty);
2407 .Const, .ConstArgument => "const ",2405 try w.print("{}", .{try dg.renderTypePrefix(w, idx, .suffix, CQualifiers.init(.{
2408 .Mut => "",2406 .@"const" = switch (mutability) {
2409 };2407 .Const, .ConstArgument => true,
2410 try w.print(" {s}", .{const_prefix});2408 .Mut => false,
2409 },
2410 }))});
2411 try dg.writeCValue(w, name);2411 try dg.writeCValue(w, name);
2412 try w.writeAll(suffix.items);2412 try dg.renderTypeSuffix(w, idx, .suffix);
2413 }2413 }
24142414
2415 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {2415 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {