authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-20 05:47:54-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log8b6a3ba74ea50602284543382ff1729a60b75122
treef2df9b5599c4a7d9ade4e581782248db33ddeb09
parent3d90ee50ff184dd7a94005f2769d055e460ad290

cbe: fix typedef declaration order


5 files changed, 153 insertions(+), 150 deletions(-)

src/codegen/c.zig+153-146
...@@ -48,6 +48,11 @@ const BlockData = struct {...@@ -48,6 +48,11 @@ const BlockData = struct {
48 result: CValue,48 result: CValue,
49};49};
5050
51const TypedefKind = enum {
52 Forward,
53 Complete,
54};
55
51pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);56pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
52pub const TypedefMap = std.ArrayHashMap(57pub const TypedefMap = std.ArrayHashMap(
53 Type,58 Type,
...@@ -249,13 +254,7 @@ pub const Function = struct {...@@ -249,13 +254,7 @@ pub const Function = struct {
249 const decl_c_value = f.allocLocalValue();254 const decl_c_value = f.allocLocalValue();
250 gop.value_ptr.* = decl_c_value;255 gop.value_ptr.* = decl_c_value;
251 try writer.writeAll("static ");256 try writer.writeAll("static ");
252 try f.object.dg.renderTypeAndName(257 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, 0, .Complete);
253 writer,
254 ty,
255 decl_c_value,
256 .Const,
257 0,
258 );
259 try writer.writeAll(" = ");258 try writer.writeAll(" = ");
260 try f.object.dg.renderValue(writer, ty, val, .Initializer);259 try f.object.dg.renderValue(writer, ty, val, .Initializer);
261 try writer.writeAll(";\n ");260 try writer.writeAll(";\n ");
...@@ -294,6 +293,7 @@ pub const Function = struct {...@@ -294,6 +293,7 @@ pub const Function = struct {
294 local_value,293 local_value,
295 mutability,294 mutability,
296 alignment,295 alignment,
296 .Complete,
297 );297 );
298 return local_value;298 return local_value;
299 }299 }
...@@ -328,7 +328,7 @@ pub const Function = struct {...@@ -328,7 +328,7 @@ pub const Function = struct {
328 }328 }
329329
330 fn renderType(f: *Function, w: anytype, t: Type) !void {330 fn renderType(f: *Function, w: anytype, t: Type) !void {
331 return f.object.dg.renderType(w, t);331 return f.object.dg.renderType(w, t, .Complete);
332 }332 }
333333
334 fn renderTypecast(f: *Function, w: anytype, t: Type) !void {334 fn renderTypecast(f: *Function, w: anytype, t: Type) !void {
...@@ -1024,10 +1024,7 @@ pub const DeclGen = struct {...@@ -1024,10 +1024,7 @@ pub const DeclGen = struct {
1024 }1024 }
1025 }1025 }
10261026
1027 fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void {1027 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {
1028 if (!is_global) {
1029 try w.writeAll("static ");
1030 }
1031 const fn_info = dg.decl.ty.fnInfo();1028 const fn_info = dg.decl.ty.fnInfo();
1032 if (fn_info.cc == .Naked) {1029 if (fn_info.cc == .Naked) {
1033 try w.writeAll("ZIG_NAKED ");1030 try w.writeAll("ZIG_NAKED ");
...@@ -1039,9 +1036,9 @@ pub const DeclGen = struct {...@@ -1039,9 +1036,9 @@ pub const DeclGen = struct {
1039 }1036 }
1040 }1037 }
1041 if (fn_info.return_type.hasRuntimeBits()) {1038 if (fn_info.return_type.hasRuntimeBits()) {
1042 try dg.renderType(w, fn_info.return_type);1039 try dg.renderType(w, fn_info.return_type, kind);
1043 } else if (fn_info.return_type.isError()) {1040 } else if (fn_info.return_type.isError()) {
1044 try dg.renderType(w, Type.anyerror);1041 try dg.renderType(w, Type.anyerror, kind);
1045 } else if (fn_info.return_type.zigTypeTag() == .NoReturn) {1042 } else if (fn_info.return_type.zigTypeTag() == .NoReturn) {
1046 try w.writeAll("zig_noreturn void");1043 try w.writeAll("zig_noreturn void");
1047 } else {1044 } else {
...@@ -1058,7 +1055,7 @@ pub const DeclGen = struct {...@@ -1058,7 +1055,7 @@ pub const DeclGen = struct {
1058 try w.writeAll(", ");1055 try w.writeAll(", ");
1059 }1056 }
1060 const name = CValue{ .arg = index };1057 const name = CValue{ .arg = index };
1061 try dg.renderTypeAndName(w, param_type, name, .Const, 0);1058 try dg.renderTypeAndName(w, param_type, name, .Const, 0, kind);
1062 index += 1;1059 index += 1;
1063 }1060 }
10641061
...@@ -1071,15 +1068,15 @@ pub const DeclGen = struct {...@@ -1071,15 +1068,15 @@ pub const DeclGen = struct {
1071 try w.writeByte(')');1068 try w.writeByte(')');
1072 }1069 }
10731070
1074 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type, fn_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1071 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1075 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1072 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1076 defer buffer.deinit();1073 defer buffer.deinit();
1077 const bw = buffer.writer();1074 const bw = buffer.writer();
10781075
1079 const fn_info = fn_ty.fnInfo();1076 const fn_info = t.fnInfo();
10801077
1081 try bw.writeAll("typedef ");1078 try bw.writeAll("typedef ");
1082 try dg.renderType(bw, fn_info.return_type);1079 try dg.renderType(bw, fn_info.return_type, .Forward);
1083 try bw.writeAll(" (*");1080 try bw.writeAll(" (*");
10841081
1085 const name_begin = buffer.items.len;1082 const name_begin = buffer.items.len;
...@@ -1092,11 +1089,12 @@ pub const DeclGen = struct {...@@ -1092,11 +1089,12 @@ pub const DeclGen = struct {
1092 var params_written: usize = 0;1089 var params_written: usize = 0;
1093 var index: usize = 0;1090 var index: usize = 0;
1094 while (index < param_len) : (index += 1) {1091 while (index < param_len) : (index += 1) {
1095 if (!fn_info.param_types[index].hasRuntimeBitsIgnoreComptime()) continue;1092 const param_ty = fn_info.param_types[index];
1093 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
1096 if (params_written > 0) {1094 if (params_written > 0) {
1097 try bw.writeAll(", ");1095 try bw.writeAll(", ");
1098 }1096 }
1099 try dg.renderTypecast(bw, fn_info.param_types[index]);1097 try dg.renderTypeAndName(bw, param_ty, .{ .bytes = "" }, .Mut, 0, .Forward);
1100 params_written += 1;1098 params_written += 1;
1101 }1099 }
11021100
...@@ -1133,7 +1131,7 @@ pub const DeclGen = struct {...@@ -1133,7 +1131,7 @@ pub const DeclGen = struct {
1133 var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined;1131 var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1134 const ptr_type = t.slicePtrFieldType(&ptr_type_buf);1132 const ptr_type = t.slicePtrFieldType(&ptr_type_buf);
1135 const ptr_name = CValue{ .bytes = "ptr" };1133 const ptr_name = CValue{ .bytes = "ptr" };
1136 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0);1134 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0, .Complete);
11371135
1138 try bw.writeAll("; size_t len; } ");1136 try bw.writeAll("; size_t len; } ");
1139 const name_begin = buffer.items.len;1137 const name_begin = buffer.items.len;
...@@ -1157,27 +1155,33 @@ pub const DeclGen = struct {...@@ -1157,27 +1155,33 @@ pub const DeclGen = struct {
1157 return name;1155 return name;
1158 }1156 }
11591157
1160 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1158 fn renderFwdTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1161 const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere.1159 // The forward declaration for T is stored with a key of *const T.
1162 const fqn = try struct_obj.getFullyQualifiedName(dg.module);1160 const child_ty = t.childType();
1163 defer dg.typedefs.allocator.free(fqn);1161
1162 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1163 defer fqn_buf.deinit();
1164
1165 const owner_decl = dg.module.declPtr(child_ty.getOwnerDecl());
1166 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
11641167
1165 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1168 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1166 defer buffer.deinit();1169 defer buffer.deinit();
11671170
1168 const tag = "struct";1171 const tag = switch (child_ty.zigTypeTag()) {
1169 const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;1172 .Struct => "struct ",
1170 try buffer.writer().print("typedef " ++ tag ++ " zig_S_{} ", .{fmtIdent(fqn)});1173 .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ",
1171 const tagged_name_end = buffer.items.len - " ".len;1174 else => unreachable,
1172 try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);1175 };
1173 const name_begin = buffer.items.len;1176 const name_begin = buffer.items.len + "typedef ".len + tag.len;
1174 buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);1177 try buffer.writer().print("typedef {s}zig_S_{} ", .{ tag, fmtIdent(fqn_buf.items) });
1175 const name_end = buffer.items.len;1178 const name_end = buffer.items.len - " ".len;
1179 try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len);
1180 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);
1176 buffer.appendSliceAssumeCapacity(";\n");1181 buffer.appendSliceAssumeCapacity(";\n");
11771182
1178 const rendered = buffer.toOwnedSlice();1183 const rendered = buffer.toOwnedSlice();
1179 errdefer dg.typedefs.allocator.free(rendered);1184 errdefer dg.typedefs.allocator.free(rendered);
1180 const tagged_name = rendered[tagged_name_begin..tagged_name_end];
1181 const name = rendered[name_begin..name_end];1185 const name = rendered[name_begin..name_end];
11821186
1183 try dg.typedefs.ensureUnusedCapacity(1);1187 try dg.typedefs.ensureUnusedCapacity(1);
...@@ -1186,20 +1190,32 @@ pub const DeclGen = struct {...@@ -1186,20 +1190,32 @@ pub const DeclGen = struct {
1186 .{ .name = name, .rendered = rendered },1190 .{ .name = name, .rendered = rendered },
1187 );1191 );
11881192
1189 try buffer.appendSlice(tag ++ " ");1193 return name;
1190 try buffer.appendSlice(tagged_name);1194 }
1195
1196 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1197 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1198 const ptr_ty = Type.initPayload(&ptr_pl.base);
1199 const name = dg.getTypedefName(ptr_ty) orelse
1200 try dg.renderFwdTypedef(ptr_ty);
1201
1202 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1203 defer buffer.deinit();
1204
1205 try buffer.appendSlice("struct ");
1206 try buffer.appendSlice(name);
1191 try buffer.appendSlice(" {\n");1207 try buffer.appendSlice(" {\n");
1192 {1208 {
1193 var it = struct_obj.fields.iterator();1209 var it = t.structFields().iterator();
1194 var empty = true;1210 var empty = true;
1195 while (it.next()) |entry| {1211 while (it.next()) |field| {
1196 const field_ty = entry.value_ptr.ty;1212 const field_ty = field.value_ptr.ty;
1197 if (!field_ty.hasRuntimeBits()) continue;1213 if (!field_ty.hasRuntimeBits()) continue;
11981214
1199 const alignment = entry.value_ptr.abi_align;1215 const alignment = field.value_ptr.abi_align;
1200 const field_name: CValue = .{ .identifier = entry.key_ptr.* };1216 const field_name = CValue{ .identifier = field.key_ptr.* };
1201 try buffer.append(' ');1217 try buffer.append(' ');
1202 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);1218 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
1203 try buffer.appendSlice(";\n");1219 try buffer.appendSlice(";\n");
12041220
1205 empty = false;1221 empty = false;
...@@ -1208,16 +1224,13 @@ pub const DeclGen = struct {...@@ -1208,16 +1224,13 @@ pub const DeclGen = struct {
1208 }1224 }
1209 try buffer.appendSlice("};\n");1225 try buffer.appendSlice("};\n");
12101226
1211 const rendered_body = buffer.toOwnedSlice();1227 const rendered = buffer.toOwnedSlice();
1212 errdefer dg.typedefs.allocator.free(rendered_body);1228 errdefer dg.typedefs.allocator.free(rendered);
12131229
1214 // We need to add another item to the TypedefMap, so we need a distinct
1215 // type that is not used anywhere, but is still uniquely associated with
1216 // this type, so use an empty struct which references our unique decls.
1217 try dg.typedefs.ensureUnusedCapacity(1);1230 try dg.typedefs.ensureUnusedCapacity(1);
1218 dg.typedefs.putAssumeCapacityNoClobber(1231 dg.typedefs.putAssumeCapacityNoClobber(
1219 try Type.Tag.empty_struct.create(dg.typedefs_arena, &struct_obj.namespace),1232 try t.copy(dg.typedefs_arena),
1220 .{ .name = undefined, .rendered = rendered_body },1233 .{ .name = name, .rendered = rendered },
1221 );1234 );
12221235
1223 return name;1236 return name;
...@@ -1240,7 +1253,7 @@ pub const DeclGen = struct {...@@ -1240,7 +1253,7 @@ pub const DeclGen = struct {
1240 defer dg.typedefs.allocator.free(field_name);1253 defer dg.typedefs.allocator.free(field_name);
12411254
1242 try buffer.append(' ');1255 try buffer.append(' ');
1243 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0);1256 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0, .Complete);
1244 try buffer.appendSlice(";\n");1257 try buffer.appendSlice(";\n");
12451258
1246 empty = false;1259 empty = false;
...@@ -1265,37 +1278,16 @@ pub const DeclGen = struct {...@@ -1265,37 +1278,16 @@ pub const DeclGen = struct {
1265 }1278 }
12661279
1267 fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1280 fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1268 const union_obj = t.cast(Type.Payload.Union).?.data;1281 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1269 const fqn = try union_obj.getFullyQualifiedName(dg.module);1282 const ptr_ty = Type.initPayload(&ptr_pl.base);
1270 defer dg.typedefs.allocator.free(fqn);1283 const name = dg.getTypedefName(ptr_ty) orelse
1284 try dg.renderFwdTypedef(ptr_ty);
12711285
1272 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1286 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1273 defer buffer.deinit();1287 defer buffer.deinit();
12741288
1275 const tag: []const u8 = if (t.unionTagTypeSafety()) |_| "struct" else "union";1289 try buffer.appendSlice(if (t.unionTagTypeSafety()) |_| "struct " else "union ");
1276 const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;1290 try buffer.appendSlice(name);
1277 try buffer.writer().print("typedef {s} zig_S_{} ", .{ tag, fmtIdent(fqn) });
1278 const tagged_name_end = buffer.items.len - " ".len;
1279 try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);
1280 const name_begin = buffer.items.len;
1281 buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);
1282 const name_end = buffer.items.len;
1283 buffer.appendSliceAssumeCapacity(";\n");
1284
1285 const rendered = buffer.toOwnedSlice();
1286 errdefer dg.typedefs.allocator.free(rendered);
1287 const tagged_name = rendered[tagged_name_begin..tagged_name_end];
1288 const name = rendered[name_begin..name_end];
1289
1290 try dg.typedefs.ensureUnusedCapacity(1);
1291 dg.typedefs.putAssumeCapacityNoClobber(
1292 try t.copy(dg.typedefs_arena),
1293 .{ .name = name, .rendered = rendered },
1294 );
1295
1296 try buffer.appendSlice(tag);
1297 try buffer.append(' ');
1298 try buffer.appendSlice(tagged_name);
1299 try buffer.appendSlice(" {\n");1291 try buffer.appendSlice(" {\n");
13001292
1301 const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {1293 const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {
...@@ -1303,7 +1295,7 @@ pub const DeclGen = struct {...@@ -1303,7 +1295,7 @@ pub const DeclGen = struct {
1303 const layout = t.unionGetLayout(target);1295 const layout = t.unionGetLayout(target);
1304 if (layout.tag_size != 0) {1296 if (layout.tag_size != 0) {
1305 try buffer.append(' ');1297 try buffer.append(' ');
1306 try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0);1298 try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0, .Complete);
1307 try buffer.appendSlice(";\n");1299 try buffer.appendSlice(";\n");
1308 }1300 }
1309 try buffer.appendSlice(" union {\n");1301 try buffer.appendSlice(" union {\n");
...@@ -1313,14 +1305,14 @@ pub const DeclGen = struct {...@@ -1313,14 +1305,14 @@ pub const DeclGen = struct {
1313 {1305 {
1314 var it = t.unionFields().iterator();1306 var it = t.unionFields().iterator();
1315 var empty = true;1307 var empty = true;
1316 while (it.next()) |entry| {1308 while (it.next()) |field| {
1317 const field_ty = entry.value_ptr.ty;1309 const field_ty = field.value_ptr.ty;
1318 if (!field_ty.hasRuntimeBits()) continue;1310 if (!field_ty.hasRuntimeBits()) continue;
13191311
1320 const alignment = entry.value_ptr.abi_align;1312 const alignment = field.value_ptr.abi_align;
1321 const field_name: CValue = .{ .identifier = entry.key_ptr.* };1313 const field_name = CValue{ .identifier = field.key_ptr.* };
1322 try buffer.appendSlice(indent);1314 try buffer.appendSlice(indent);
1323 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);1315 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
1324 try buffer.appendSlice(";\n");1316 try buffer.appendSlice(";\n");
13251317
1326 empty = false;1318 empty = false;
...@@ -1334,16 +1326,13 @@ pub const DeclGen = struct {...@@ -1334,16 +1326,13 @@ pub const DeclGen = struct {
1334 if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");1326 if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");
1335 try buffer.appendSlice("};\n");1327 try buffer.appendSlice("};\n");
13361328
1337 const rendered_body = buffer.toOwnedSlice();1329 const rendered = buffer.toOwnedSlice();
1338 errdefer dg.typedefs.allocator.free(rendered_body);1330 errdefer dg.typedefs.allocator.free(rendered);
13391331
1340 // We need to add another item to the TypedefMap, so we need a distinct
1341 // type that is not used anywhere, but is still uniquely associated with
1342 // this type, so use an empty struct which references our unique decls.
1343 try dg.typedefs.ensureUnusedCapacity(1);1332 try dg.typedefs.ensureUnusedCapacity(1);
1344 dg.typedefs.putAssumeCapacityNoClobber(1333 dg.typedefs.putAssumeCapacityNoClobber(
1345 try Type.Tag.empty_struct.create(dg.typedefs_arena, &union_obj.namespace),1334 try t.copy(dg.typedefs_arena),
1346 .{ .name = undefined, .rendered = rendered_body },1335 .{ .name = name, .rendered = rendered },
1347 );1336 );
13481337
1349 return name;1338 return name;
...@@ -1363,11 +1352,11 @@ pub const DeclGen = struct {...@@ -1363,11 +1352,11 @@ pub const DeclGen = struct {
1363 const error_align = Type.anyerror.abiAlignment(target);1352 const error_align = Type.anyerror.abiAlignment(target);
1364 if (error_align > payload_align) {1353 if (error_align > payload_align) {
1365 try bw.writeAll("typedef struct { ");1354 try bw.writeAll("typedef struct { ");
1366 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0);1355 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1367 try bw.writeAll("; uint16_t error; } ");1356 try bw.writeAll("; uint16_t error; } ");
1368 } else {1357 } else {
1369 try bw.writeAll("typedef struct { uint16_t error; ");1358 try bw.writeAll("typedef struct { uint16_t error; ");
1370 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0);1359 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1371 try bw.writeAll("; } ");1360 try bw.writeAll("; } ");
1372 }1361 }
13731362
...@@ -1398,7 +1387,7 @@ pub const DeclGen = struct {...@@ -1398,7 +1387,7 @@ pub const DeclGen = struct {
1398 const bw = buffer.writer();1387 const bw = buffer.writer();
13991388
1400 try bw.writeAll("typedef ");1389 try bw.writeAll("typedef ");
1401 try dg.renderType(bw, info.elem_type);1390 try dg.renderType(bw, info.elem_type, .Complete);
14021391
1403 const name_begin = buffer.items.len + " ".len;1392 const name_begin = buffer.items.len + " ".len;
1404 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len });1393 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len });
...@@ -1426,7 +1415,7 @@ pub const DeclGen = struct {...@@ -1426,7 +1415,7 @@ pub const DeclGen = struct {
14261415
1427 try bw.writeAll("typedef struct { ");1416 try bw.writeAll("typedef struct { ");
1428 const payload_name = CValue{ .bytes = "payload" };1417 const payload_name = CValue{ .bytes = "payload" };
1429 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);1418 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0, .Complete);
1430 try bw.writeAll("; bool is_null; } ");1419 try bw.writeAll("; bool is_null; } ");
14311420
1432 const name_begin = buffer.items.len;1421 const name_begin = buffer.items.len;
...@@ -1488,7 +1477,12 @@ pub const DeclGen = struct {...@@ -1488,7 +1477,12 @@ pub const DeclGen = struct {
1488 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1477 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
1489 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1478 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
1490 ///1479 ///
1491 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {1480 fn renderType(
1481 dg: *DeclGen,
1482 w: anytype,
1483 t: Type,
1484 kind: TypedefKind,
1485 ) error{ OutOfMemory, AnalysisFail }!void {
1492 const target = dg.module.getTarget();1486 const target = dg.module.getTarget();
14931487
1494 switch (t.zigTypeTag()) {1488 switch (t.zigTypeTag()) {
...@@ -1540,10 +1534,11 @@ pub const DeclGen = struct {...@@ -1540,10 +1534,11 @@ pub const DeclGen = struct {
1540 }1534 }
1541 },1535 },
1542 .Pointer => {1536 .Pointer => {
1537 const child_ty = t.childType();
1543 if (t.isSlice()) {1538 if (t.isSlice()) {
1544 var slice_pl = Type.Payload.ElemType{1539 var slice_pl = Type.Payload.ElemType{
1545 .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice },1540 .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice },
1546 .data = t.childType(),1541 .data = child_ty,
1547 };1542 };
1548 const slice_ty = Type.initPayload(&slice_pl.base);1543 const slice_ty = Type.initPayload(&slice_pl.base);
15491544
...@@ -1553,31 +1548,27 @@ pub const DeclGen = struct {...@@ -1553,31 +1548,27 @@ pub const DeclGen = struct {
1553 return w.writeAll(name);1548 return w.writeAll(name);
1554 }1549 }
15551550
1556 if (t.castPtrToFn()) |fn_ty| {1551 if (child_ty.zigTypeTag() == .Fn) {
1557 const name = dg.getTypedefName(t) orelse1552 const name = dg.getTypedefName(child_ty) orelse
1558 try dg.renderPtrToFnTypedef(t, fn_ty);1553 try dg.renderPtrToFnTypedef(child_ty);
15591554
1560 return w.writeAll(name);1555 return w.writeAll(name);
1561 }1556 }
15621557
1563 const child_ty = t.childType();
1564 if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and1558 if (t.isCPtr() and child_ty.eql(Type.u8, dg.module) and
1565 (dg.decl.val.tag() == .extern_fn or std.mem.eql(u8, std.mem.span(dg.decl.name), "main")))1559 (dg.decl.val.tag() == .extern_fn or
1560 std.mem.eql(u8, std.mem.span(dg.decl.name), "main")))
1566 {1561 {
1567 // This is a hack, since the c compiler expects a lot of external1562 // This is a hack, since the c compiler expects a lot of external
1568 // library functions to have char pointers in their signatures, but1563 // library functions to have char pointers in their signatures, but
1569 // u8 and i8 produce unsigned char and signed char respectively,1564 // u8 and i8 produce unsigned char and signed char respectively,
1570 // which in C are not very usefully different than char.1565 // which in C are (not very usefully) different than char.
1571 try w.writeAll("char");1566 try w.writeAll("char");
1572 } else {1567 } else {
1573 try dg.renderType(w, child_ty);1568 try dg.renderType(w, child_ty, .Forward);
1574 }
1575 if (t.isConstPtr()) {
1576 try w.writeAll(" const");
1577 }
1578 if (t.isVolatilePtr()) {
1579 try w.writeAll(" volatile");
1580 }1569 }
1570 if (t.isConstPtr()) try w.writeAll(" const");
1571 if (t.isVolatilePtr()) try w.writeAll(" volatile");
1581 return w.writeAll(" *");1572 return w.writeAll(" *");
1582 },1573 },
1583 .Array => {1574 .Array => {
...@@ -1601,7 +1592,7 @@ pub const DeclGen = struct {...@@ -1601,7 +1592,7 @@ pub const DeclGen = struct {
1601 }1592 }
16021593
1603 if (t.optionalReprIsPayload()) {1594 if (t.optionalReprIsPayload()) {
1604 return dg.renderType(w, child_type);1595 return dg.renderType(w, child_type, .Complete);
1605 }1596 }
16061597
1607 const name = dg.getTypedefName(t) orelse1598 const name = dg.getTypedefName(t) orelse
...@@ -1617,7 +1608,7 @@ pub const DeclGen = struct {...@@ -1617,7 +1608,7 @@ pub const DeclGen = struct {
1617 const payload_ty = t.errorUnionPayload();1608 const payload_ty = t.errorUnionPayload();
16181609
1619 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1610 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1620 return dg.renderType(w, Type.anyerror);1611 return dg.renderType(w, Type.anyerror, .Complete);
1621 }1612 }
16221613
1623 var error_union_pl = Type.Payload.ErrorUnion{1614 var error_union_pl = Type.Payload.ErrorUnion{
...@@ -1630,17 +1621,26 @@ pub const DeclGen = struct {...@@ -1630,17 +1621,26 @@ pub const DeclGen = struct {
16301621
1631 return w.writeAll(name);1622 return w.writeAll(name);
1632 },1623 },
1633 .Struct => {1624 .Struct, .Union => |tag| if (kind == .Complete or t.isTupleOrAnonStruct()) {
1634 const name = dg.getTypedefName(t) orelse if (t.isTupleOrAnonStruct())1625 const name = dg.getTypedefName(t) orelse switch (tag) {
1635 try dg.renderTupleTypedef(t)1626 .Struct => if (t.isTupleOrAnonStruct())
1636 else1627 try dg.renderTupleTypedef(t)
1637 try dg.renderStructTypedef(t);1628 else
1629 try dg.renderStructTypedef(t),
1630 .Union => try dg.renderUnionTypedef(t),
1631 else => unreachable,
1632 };
16381633
1639 return w.writeAll(name);1634 return w.writeAll(name);
1640 },1635 } else {
1641 .Union => {1636 var ptr_pl = Type.Payload.ElemType{
1642 const name = dg.getTypedefName(t) orelse1637 .base = .{ .tag = .single_const_pointer },
1643 try dg.renderUnionTypedef(t);1638 .data = t,
1639 };
1640 const ptr_ty = Type.initPayload(&ptr_pl.base);
1641
1642 const name = dg.getTypedefName(ptr_ty) orelse
1643 try dg.renderFwdTypedef(ptr_ty);
16441644
1645 return w.writeAll(name);1645 return w.writeAll(name);
1646 },1646 },
...@@ -1649,7 +1649,7 @@ pub const DeclGen = struct {...@@ -1649,7 +1649,7 @@ pub const DeclGen = struct {
1649 var int_tag_buf: Type.Payload.Bits = undefined;1649 var int_tag_buf: Type.Payload.Bits = undefined;
1650 const int_tag_ty = t.intTagType(&int_tag_buf);1650 const int_tag_ty = t.intTagType(&int_tag_buf);
16511651
1652 try dg.renderType(w, int_tag_ty);1652 try dg.renderType(w, int_tag_ty, kind);
1653 },1653 },
1654 .Opaque => switch (t.tag()) {1654 .Opaque => switch (t.tag()) {
1655 .anyopaque => try w.writeAll("void"),1655 .anyopaque => try w.writeAll("void"),
...@@ -1701,7 +1701,7 @@ pub const DeclGen = struct {...@@ -1701,7 +1701,7 @@ pub const DeclGen = struct {
1701 ty: Type,1701 ty: Type,
1702 ) error{ OutOfMemory, AnalysisFail }!void {1702 ) error{ OutOfMemory, AnalysisFail }!void {
1703 const name = CValue{ .bytes = "" };1703 const name = CValue{ .bytes = "" };
1704 return renderTypeAndName(dg, w, ty, name, .Mut, 0);1704 return renderTypeAndName(dg, w, ty, name, .Mut, 0, .Complete);
1705 }1705 }
17061706
1707 /// Renders a type and name in field declaration/definition format.1707 /// Renders a type and name in field declaration/definition format.
...@@ -1720,6 +1720,7 @@ pub const DeclGen = struct {...@@ -1720,6 +1720,7 @@ pub const DeclGen = struct {
1720 name: CValue,1720 name: CValue,
1721 mutability: Mutability,1721 mutability: Mutability,
1722 alignment: u32,1722 alignment: u32,
1723 kind: TypedefKind,
1723 ) error{ OutOfMemory, AnalysisFail }!void {1724 ) error{ OutOfMemory, AnalysisFail }!void {
1724 var suffix = std.ArrayList(u8).init(dg.gpa);1725 var suffix = std.ArrayList(u8).init(dg.gpa);
1725 defer suffix.deinit();1726 defer suffix.deinit();
...@@ -1736,7 +1737,7 @@ pub const DeclGen = struct {...@@ -1736,7 +1737,7 @@ pub const DeclGen = struct {
17361737
1737 if (alignment != 0)1738 if (alignment != 0)
1738 try w.print("ZIG_ALIGN({}) ", .{alignment});1739 try w.print("ZIG_ALIGN({}) ", .{alignment});
1739 try dg.renderType(w, render_ty);1740 try dg.renderType(w, render_ty, kind);
17401741
1741 const const_prefix = switch (mutability) {1742 const const_prefix = switch (mutability) {
1742 .Const => "const ",1743 .Const => "const ",
...@@ -1755,11 +1756,11 @@ pub const DeclGen = struct {...@@ -1755,11 +1756,11 @@ pub const DeclGen = struct {
1755 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);1756 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
17561757
1757 try buffer.appendSlice("static ");1758 try buffer.appendSlice("static ");
1758 try dg.renderType(bw, name_slice_ty);1759 try dg.renderType(bw, name_slice_ty, .Complete);
1759 const name_begin = buffer.items.len + " ".len;1760 const name_begin = buffer.items.len + " ".len;
1760 try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)});1761 try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)});
1761 const name_end = buffer.items.len - "(".len;1762 const name_end = buffer.items.len - "(".len;
1762 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0);1763 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);
1763 try buffer.appendSlice(") {\n switch (tag) {\n");1764 try buffer.appendSlice(") {\n switch (tag) {\n");
1764 for (enum_ty.enumFields().keys()) |name, index| {1765 for (enum_ty.enumFields().keys()) |name, index| {
1765 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);1766 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);
...@@ -1785,7 +1786,7 @@ pub const DeclGen = struct {...@@ -1785,7 +1786,7 @@ pub const DeclGen = struct {
1785 const len_val = Value.initPayload(&len_pl.base);1786 const len_val = Value.initPayload(&len_pl.base);
17861787
1787 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});1788 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
1788 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0);1789 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0, .Complete);
1789 try buffer.appendSlice(" = ");1790 try buffer.appendSlice(" = ");
1790 try dg.renderValue(bw, name_ty, name_val, .Initializer);1791 try dg.renderValue(bw, name_ty, name_val, .Initializer);
1791 try buffer.appendSlice(";\n return (");1792 try buffer.appendSlice(";\n return (");
...@@ -1948,7 +1949,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1948,7 +1949,7 @@ pub fn genErrDecls(o: *Object) !void {
1948 const name_val = Value.initPayload(&name_pl.base);1949 const name_val = Value.initPayload(&name_pl.base);
19491950
1950 try writer.writeAll("static ");1951 try writer.writeAll("static ");
1951 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0);1952 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete);
1952 try writer.writeAll(" = ");1953 try writer.writeAll(" = ");
1953 try o.dg.renderValue(writer, name_ty, name_val, .Initializer);1954 try o.dg.renderValue(writer, name_ty, name_val, .Initializer);
1954 try writer.writeAll(";\n");1955 try writer.writeAll(";\n");
...@@ -1961,7 +1962,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1961,7 +1962,7 @@ pub fn genErrDecls(o: *Object) !void {
1961 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);1962 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
19621963
1963 try writer.writeAll("static ");1964 try writer.writeAll("static ");
1964 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0);1965 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0, .Complete);
1965 try writer.writeAll(" = {");1966 try writer.writeAll(" = {");
1966 for (o.dg.module.error_name_list.items) |name, value| {1967 for (o.dg.module.error_name_list.items) |name, value| {
1967 if (value != 0) try writer.writeByte(',');1968 if (value != 0) try writer.writeByte(',');
...@@ -1988,14 +1989,13 @@ pub fn genFunc(f: *Function) !void {...@@ -1988,14 +1989,13 @@ pub fn genFunc(f: *Function) !void {
19881989
1989 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);1990 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
1990 const fwd_decl_writer = o.dg.fwd_decl.writer();1991 const fwd_decl_writer = o.dg.fwd_decl.writer();
1991 if (is_global) {1992 try fwd_decl_writer.writeAll(if (is_global) "ZIG_EXTERN_C " else "static ");
1992 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");1993 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
1993 }
1994 try o.dg.renderFunctionSignature(fwd_decl_writer, is_global);
1995 try fwd_decl_writer.writeAll(";\n");1994 try fwd_decl_writer.writeAll(";\n");
19961995
1997 try o.indent_writer.insertNewline();1996 try o.indent_writer.insertNewline();
1998 try o.dg.renderFunctionSignature(o.writer(), is_global);1997 if (!is_global) try o.writer().writeAll("static ");
1998 try o.dg.renderFunctionSignature(o.writer(), .Complete);
1999 try o.writer().writeByte(' ');1999 try o.writer().writeByte(' ');
20002000
2001 // In case we need to use the header, populate it with a copy of the function2001 // In case we need to use the header, populate it with a copy of the function
...@@ -2029,7 +2029,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2029,7 +2029,7 @@ pub fn genDecl(o: *Object) !void {
2029 if (tv.val.tag() == .extern_fn) {2029 if (tv.val.tag() == .extern_fn) {
2030 const writer = o.writer();2030 const writer = o.writer();
2031 try writer.writeAll("ZIG_EXTERN_C ");2031 try writer.writeAll("ZIG_EXTERN_C ");
2032 try o.dg.renderFunctionSignature(writer, true);2032 try o.dg.renderFunctionSignature(writer, .Forward);
2033 try writer.writeAll(";\n");2033 try writer.writeAll(";\n");
2034 } else if (tv.val.castTag(.variable)) |var_payload| {2034 } else if (tv.val.castTag(.variable)) |var_payload| {
2035 const variable: *Module.Var = var_payload.data;2035 const variable: *Module.Var = var_payload.data;
...@@ -2048,7 +2048,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2048,7 +2048,7 @@ pub fn genDecl(o: *Object) !void {
2048 .decl = o.dg.decl_index,2048 .decl = o.dg.decl_index,
2049 };2049 };
20502050
2051 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");2051 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2052 try fwd_decl_writer.writeAll(";\n");2052 try fwd_decl_writer.writeAll(";\n");
20532053
2054 if (variable.is_extern or variable.init.isUndefDeep()) {2054 if (variable.is_extern or variable.init.isUndefDeep()) {
...@@ -2057,7 +2057,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2057,7 +2057,7 @@ pub fn genDecl(o: *Object) !void {
20572057
2058 try o.indent_writer.insertNewline();2058 try o.indent_writer.insertNewline();
2059 const w = o.writer();2059 const w = o.writer();
2060 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");2060 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2061 try w.writeAll(" = ");2061 try w.writeAll(" = ");
2062 if (variable.init.tag() != .unreachable_value) {2062 if (variable.init.tag() != .unreachable_value) {
2063 try o.dg.renderValue(w, tv.ty, variable.init, .Initializer);2063 try o.dg.renderValue(w, tv.ty, variable.init, .Initializer);
...@@ -2072,7 +2072,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2072,7 +2072,7 @@ pub fn genDecl(o: *Object) !void {
2072 // https://github.com/ziglang/zig/issues/75822072 // https://github.com/ziglang/zig/issues/7582
20732073
2074 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };2074 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
2075 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");2075 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
20762076
2077 try writer.writeAll(" = ");2077 try writer.writeAll(" = ");
2078 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);2078 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
...@@ -2095,7 +2095,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2095,7 +2095,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2095 const is_global = dg.declIsGlobal(tv);2095 const is_global = dg.declIsGlobal(tv);
2096 if (is_global) {2096 if (is_global) {
2097 try writer.writeAll("ZIG_EXTERN_C ");2097 try writer.writeAll("ZIG_EXTERN_C ");
2098 try dg.renderFunctionSignature(writer, is_global);2098 try dg.renderFunctionSignature(writer, .Complete);
2099 try dg.fwd_decl.appendSlice(";\n");2099 try dg.fwd_decl.appendSlice(";\n");
2100 }2100 }
2101 },2101 },
...@@ -2760,8 +2760,10 @@ fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name:...@@ -2760,8 +2760,10 @@ fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name:
2760 const bits = int_info.bits;2760 const bits = int_info.bits;
27612761
2762 // if it's an unsigned int with non-arbitrary bit size then we can just add2762 // if it's an unsigned int with non-arbitrary bit size then we can just add
2763 if (int_info.signedness == .unsigned and bits == toCIntBits(bits)) {2763 if (toCIntBits(bits)) |c_bits| {
2764 return try airBinOp(f, inst, operator);2764 if (int_info.signedness == .unsigned and bits == c_bits) {
2765 return try airBinOp(f, inst, operator);
2766 }
2765 }2767 }
27662768
2767 if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{});2769 if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{});
...@@ -3899,9 +3901,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -3899,9 +3901,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
3899 }3901 }
3900 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";3902 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";
39013903
3904 // Ensure complete type definition is visible before accessing fields.
3905 try f.renderType(std.io.null_writer, struct_ty);
3906
3902 const inst_ty = f.air.typeOfIndex(inst);3907 const inst_ty = f.air.typeOfIndex(inst);
3903 const local = try f.allocLocal(inst_ty, .Const);3908 const local = try f.allocLocal(inst_ty, .Const);
3904
3905 if (field_val_ty.hasRuntimeBitsIgnoreComptime()) {3909 if (field_val_ty.hasRuntimeBitsIgnoreComptime()) {
3906 try writer.writeAll(" = &");3910 try writer.writeAll(" = &");
3907 try f.writeCValueDeref(writer, struct_ptr);3911 try f.writeCValueDeref(writer, struct_ptr);
...@@ -3941,6 +3945,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3941,6 +3945,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
3941 };3945 };
3942 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";3946 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";
39433947
3948 // Ensure complete type definition is visible before accessing fields.
3949 try f.renderType(std.io.null_writer, struct_ty);
3950
3944 const inst_ty = f.air.typeOfIndex(inst);3951 const inst_ty = f.air.typeOfIndex(inst);
3945 const is_array = inst_ty.zigTypeTag() == .Array;3952 const is_array = inst_ty.zigTypeTag() == .Array;
3946 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);3953 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
...@@ -4326,7 +4333,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -4326,7 +4333,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
4326 try writer.writeAll("if (");4333 try writer.writeAll("if (");
4327 }4334 }
4328 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});4335 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
4329 try f.object.dg.renderTypecast(writer, ptr_ty.elemType());4336 try f.renderTypecast(writer, ptr_ty.elemType());
4330 try writer.writeByte(')');4337 try writer.writeByte(')');
4331 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");4338 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4332 try writer.writeAll(" *)");4339 try writer.writeAll(" *)");
...@@ -4371,12 +4378,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4371,12 +4378,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
4371 switch (extra.op()) {4378 switch (extra.op()) {
4372 else => {4379 else => {
4373 try writer.writeAll("zig_atomic(");4380 try writer.writeAll("zig_atomic(");
4374 try f.object.dg.renderTypecast(writer, ptr_ty.elemType());4381 try f.renderTypecast(writer, ptr_ty.elemType());
4375 try writer.writeByte(')');4382 try writer.writeByte(')');
4376 },4383 },
4377 .Nand, .Min, .Max => {4384 .Nand, .Min, .Max => {
4378 // These are missing from stdatomic.h, so no atomic types for now.4385 // These are missing from stdatomic.h, so no atomic types for now.
4379 try f.object.dg.renderTypecast(writer, ptr_ty.elemType());4386 try f.renderTypecast(writer, ptr_ty.elemType());
4380 },4387 },
4381 }4388 }
4382 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");4389 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
...@@ -4403,7 +4410,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4403,7 +4410,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
4403 const writer = f.object.writer();4410 const writer = f.object.writer();
44044411
4405 try writer.writeAll(" = zig_atomic_load((zig_atomic(");4412 try writer.writeAll(" = zig_atomic_load((zig_atomic(");
4406 try f.object.dg.renderTypecast(writer, ptr_ty.elemType());4413 try f.renderTypecast(writer, ptr_ty.elemType());
4407 try writer.writeByte(')');4414 try writer.writeByte(')');
4408 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");4415 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4409 try writer.writeAll(" *)");4416 try writer.writeAll(" *)");
...@@ -4423,7 +4430,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa...@@ -4423,7 +4430,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
4423 const writer = f.object.writer();4430 const writer = f.object.writer();
44244431
4425 try writer.writeAll("zig_atomic_store((zig_atomic(");4432 try writer.writeAll("zig_atomic_store((zig_atomic(");
4426 try f.object.dg.renderTypecast(writer, ptr_ty.elemType());4433 try f.renderTypecast(writer, ptr_ty.elemType());
4427 try writer.writeByte(')');4434 try writer.writeByte(')');
4428 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");4435 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4429 try writer.writeAll(" *)");4436 try writer.writeAll(" *)");
test/behavior/bugs/1735.zig-1
...@@ -43,7 +43,6 @@ const a = struct {...@@ -43,7 +43,6 @@ const a = struct {
4343
44test "initialization" {44test "initialization" {
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
47 var t = a.init();46 var t = a.init();
48 try std.testing.expect(t.foo.len == 0);47 try std.testing.expect(t.foo.len == 0);
49}48}
test/behavior/bugs/1914.zig-1
...@@ -12,7 +12,6 @@ const b_list: []B = &[_]B{};...@@ -12,7 +12,6 @@ const b_list: []B = &[_]B{};
12const a = A{ .b_list_pointer = &b_list };12const a = A{ .b_list_pointer = &b_list };
1313
14test "segfault bug" {14test "segfault bug" {
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16 const assert = std.debug.assert;15 const assert = std.debug.assert;
17 const obj = B{ .a_pointer = &a };16 const obj = B{ .a_pointer = &a };
18 assert(obj.a_pointer == &a); // this makes zig crash17 assert(obj.a_pointer == &a); // this makes zig crash
test/behavior/error.zig-1
...@@ -470,7 +470,6 @@ test "function pointer with return type that is error union with payload which i...@@ -470,7 +470,6 @@ test "function pointer with return type that is error union with payload which i
470 return error.SkipZigTest;470 return error.SkipZigTest;
471 }471 }
472472
473 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
474 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
476475
test/behavior/saturating_arithmetic.zig-1
...@@ -8,7 +8,6 @@ test "saturating add" {...@@ -8,7 +8,6 @@ test "saturating add" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
13 const S = struct {12 const S = struct {
14 fn doTheTest() !void {13 fn doTheTest() !void {