authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-08 08:54:49-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:28-04:00
log6a4266d62aacf887a81549d81ae6f312992d2b2c
treec06696c4224bebe1927779948441aed4f0808b39
parent7c9a9a0fd4560d8ce5d61ab96b9403d27dd872b3

cbe: fix infinite recursion on recursive types


23 files changed, 181 insertions(+), 152 deletions(-)

lib/include/zig.h+1
......@@ -162,6 +162,7 @@
162162#include <stdint.h>
163163#include <stddef.h>
164164#include <limits.h>
165#include <math.h>
165166
166167#define int128_t __int128
167168#define uint128_t unsigned __int128
src/Compilation.zig+8-5
......@@ -3099,13 +3099,16 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30993099 .decl_index = decl_index,
31003100 .decl = decl,
31013101 .fwd_decl = fwd_decl.toManaged(gpa),
3102 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{
3103 .mod = module,
3104 }),
3102 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),
31053103 .typedefs_arena = typedefs_arena.allocator(),
31063104 };
3107 defer dg.fwd_decl.deinit();
3108 defer dg.typedefs.deinit();
3105 defer {
3106 for (dg.typedefs.values()) |typedef| {
3107 module.gpa.free(typedef.rendered);
3108 }
3109 dg.typedefs.deinit();
3110 dg.fwd_decl.deinit();
3111 }
31093112
31103113 c_codegen.genHeader(&dg) catch |err| switch (err) {
31113114 error.AnalysisFail => {
src/codegen/c.zig+140-91
......@@ -372,8 +372,8 @@ pub const DeclGen = struct {
372372 }
373373
374374 fn getTypedefName(dg: *DeclGen, t: Type) ?[]const u8 {
375 if (dg.typedefs.get(t)) |some| {
376 return some.name;
375 if (dg.typedefs.get(t)) |typedef| {
376 return typedef.name;
377377 } else {
378378 return null;
379379 }
......@@ -1025,9 +1025,10 @@ pub const DeclGen = struct {
10251025 try dg.renderType(bw, fn_info.return_type);
10261026 try bw.writeAll(" (*");
10271027
1028 const name_start = buffer.items.len;
1029 try bw.print("zig_F_{})(", .{typeToCIdentifier(t, dg.module)});
1030 const name_end = buffer.items.len - 2;
1028 const name_begin = buffer.items.len;
1029 try bw.print("zig_F_{}", .{typeToCIdentifier(t, dg.module)});
1030 const name_end = buffer.items.len;
1031 try bw.writeAll(")(");
10311032
10321033 const param_len = fn_info.param_types.len;
10331034
......@@ -1052,7 +1053,7 @@ pub const DeclGen = struct {
10521053
10531054 const rendered = buffer.toOwnedSlice();
10541055 errdefer dg.typedefs.allocator.free(rendered);
1055 const name = rendered[name_start..name_end];
1056 const name = rendered[name_begin..name_end];
10561057
10571058 try dg.typedefs.ensureUnusedCapacity(1);
10581059 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1079,12 +1080,11 @@ pub const DeclGen = struct {
10791080 const child_type = t.childType();
10801081
10811082 try bw.writeAll("; size_t len; } ");
1082 const name_index = buffer.items.len;
1083 if (t.isConstPtr()) {
1084 try bw.print("zig_L_{}", .{typeToCIdentifier(child_type, dg.module)});
1085 } else {
1086 try bw.print("zig_M_{}", .{typeToCIdentifier(child_type, dg.module)});
1087 }
1083 const name_begin = buffer.items.len;
1084 try bw.print("zig_{c}_{}", .{
1085 @as(u8, if (t.isConstPtr()) 'L' else 'M'),
1086 typeToCIdentifier(child_type, dg.module),
1087 });
10881088 if (ptr_sentinel) |s| {
10891089 var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
10901090 defer sentinel_buffer.deinit();
......@@ -1092,11 +1092,12 @@ pub const DeclGen = struct {
10921092 try dg.renderValue(sentinel_buffer.writer(), child_type, s, .Identifier);
10931093 try bw.print("_s_{}", .{fmtIdent(sentinel_buffer.items)});
10941094 }
1095 const name_end = buffer.items.len;
10951096 try bw.writeAll(";\n");
10961097
10971098 const rendered = buffer.toOwnedSlice();
10981099 errdefer dg.typedefs.allocator.free(rendered);
1099 const name = rendered[name_index .. rendered.len - 2];
1100 const name = rendered[name_begin..name_end];
11001101
11011102 try dg.typedefs.ensureUnusedCapacity(1);
11021103 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1115,7 +1116,30 @@ pub const DeclGen = struct {
11151116 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
11161117 defer buffer.deinit();
11171118
1118 try buffer.appendSlice("typedef struct {\n");
1119 const tag = "struct";
1120 const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;
1121 try buffer.writer().print("typedef " ++ tag ++ " zig_S_{} ", .{fmtIdent(fqn)});
1122 const tagged_name_end = buffer.items.len - " ".len;
1123 try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);
1124 const name_begin = buffer.items.len;
1125 buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);
1126 const name_end = buffer.items.len;
1127 buffer.appendSliceAssumeCapacity(";\n");
1128
1129 const rendered = buffer.toOwnedSlice();
1130 errdefer dg.typedefs.allocator.free(rendered);
1131 const tagged_name = rendered[tagged_name_begin..tagged_name_end];
1132 const name = rendered[name_begin..name_end];
1133
1134 try dg.typedefs.ensureUnusedCapacity(1);
1135 dg.typedefs.putAssumeCapacityNoClobber(
1136 try t.copy(dg.typedefs_arena),
1137 .{ .name = name, .rendered = rendered },
1138 );
1139
1140 try buffer.appendSlice(tag ++ " ");
1141 try buffer.appendSlice(tagged_name);
1142 try buffer.appendSlice(" {\n");
11191143 {
11201144 var it = struct_obj.fields.iterator();
11211145 var empty = true;
......@@ -1124,68 +1148,63 @@ pub const DeclGen = struct {
11241148 if (!field_ty.hasRuntimeBits()) continue;
11251149
11261150 const alignment = entry.value_ptr.abi_align;
1127 const name: CValue = .{ .identifier = entry.key_ptr.* };
1151 const field_name: CValue = .{ .identifier = entry.key_ptr.* };
11281152 try buffer.append(' ');
1129 try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
1153 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);
11301154 try buffer.appendSlice(";\n");
11311155
11321156 empty = false;
11331157 }
11341158 if (empty) try buffer.appendSlice(" char empty_struct;\n");
11351159 }
1136 try buffer.appendSlice("} ");
1160 try buffer.appendSlice("};\n");
11371161
1138 const name_start = buffer.items.len;
1139 try buffer.writer().print("zig_S_{};\n", .{fmtIdent(fqn)});
1140
1141 const rendered = buffer.toOwnedSlice();
1142 errdefer dg.typedefs.allocator.free(rendered);
1143 const name = rendered[name_start .. rendered.len - 2];
1162 const rendered_body = buffer.toOwnedSlice();
1163 errdefer dg.typedefs.allocator.free(rendered_body);
11441164
1165 // We need to add another item to the TypedefMap, so we need a distinct
1166 // type that is not used anywhere, but is still uniquely associated with
1167 // this type, so use an empty struct which references our unique decls.
11451168 try dg.typedefs.ensureUnusedCapacity(1);
11461169 dg.typedefs.putAssumeCapacityNoClobber(
1147 try t.copy(dg.typedefs_arena),
1148 .{ .name = name, .rendered = rendered },
1170 try Type.Tag.empty_struct.create(dg.typedefs_arena, &struct_obj.namespace),
1171 .{ .name = undefined, .rendered = rendered_body },
11491172 );
11501173
11511174 return name;
11521175 }
11531176
11541177 fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1155 const tuple = t.tupleFields();
1156
11571178 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
11581179 defer buffer.deinit();
1159 const writer = buffer.writer();
11601180
11611181 try buffer.appendSlice("typedef struct {\n");
11621182 {
1183 const fields = t.tupleFields();
11631184 var empty = true;
1164 for (tuple.types) |field_ty, i| {
1185 for (fields.types) |field_ty, i| {
11651186 if (!field_ty.hasRuntimeBits()) continue;
1166 const val = tuple.values[i];
1187 const val = fields.values[i];
11671188 if (val.tag() != .unreachable_value) continue;
11681189
1169 var name = std.ArrayList(u8).init(dg.gpa);
1170 defer name.deinit();
1171 try name.writer().print("field_{d}", .{i});
1190 const field_name = try std.fmt.allocPrint(dg.typedefs.allocator, "field_{d}", .{i});
1191 defer dg.typedefs.allocator.free(field_name);
11721192
11731193 try buffer.append(' ');
1174 try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, 0);
1194 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0);
11751195 try buffer.appendSlice(";\n");
11761196
11771197 empty = false;
11781198 }
11791199 if (empty) try buffer.appendSlice(" char empty_tuple;\n");
11801200 }
1181 try buffer.appendSlice("} ");
1182
1183 const name_start = buffer.items.len;
1184 try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
1201 const name_begin = buffer.items.len + "} ".len;
1202 try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
1203 const name_end = buffer.items.len - ";\n".len;
11851204
11861205 const rendered = buffer.toOwnedSlice();
11871206 errdefer dg.typedefs.allocator.free(rendered);
1188 const name = rendered[name_start .. rendered.len - 2];
1207 const name = rendered[name_begin..name_end];
11891208
11901209 try dg.typedefs.ensureUnusedCapacity(1);
11911210 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1197,62 +1216,85 @@ pub const DeclGen = struct {
11971216 }
11981217
11991218 fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1200 const union_ty = t.cast(Type.Payload.Union).?.data;
1201 const fqn = try union_ty.getFullyQualifiedName(dg.module);
1219 const union_obj = t.cast(Type.Payload.Union).?.data;
1220 const fqn = try union_obj.getFullyQualifiedName(dg.module);
12021221 defer dg.typedefs.allocator.free(fqn);
12031222
1204 const target = dg.module.getTarget();
1205 const layout = t.unionGetLayout(target);
1206
12071223 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
12081224 defer buffer.deinit();
12091225
1210 try buffer.appendSlice("typedef ");
1211 if (t.unionTagTypeSafety()) |tag_ty| {
1212 const name: CValue = .{ .bytes = "tag" };
1213 try buffer.appendSlice("struct {\n ");
1226 const tag: []const u8 = if (t.unionTagTypeSafety()) |_| "struct" else "union";
1227 const tagged_name_begin = buffer.items.len + "typedef ".len + tag.len + " ".len;
1228 try buffer.writer().print("typedef {s} zig_S_{} ", .{ tag, fmtIdent(fqn) });
1229 const tagged_name_end = buffer.items.len - " ".len;
1230 try buffer.ensureUnusedCapacity(tagged_name_end - tagged_name_begin + ";\n".len);
1231 const name_begin = buffer.items.len;
1232 buffer.appendSliceAssumeCapacity(buffer.items[tagged_name_begin..tagged_name_end]);
1233 const name_end = buffer.items.len;
1234 buffer.appendSliceAssumeCapacity(";\n");
1235
1236 const rendered = buffer.toOwnedSlice();
1237 errdefer dg.typedefs.allocator.free(rendered);
1238 const tagged_name = rendered[tagged_name_begin..tagged_name_end];
1239 const name = rendered[name_begin..name_end];
1240
1241 try dg.typedefs.ensureUnusedCapacity(1);
1242 dg.typedefs.putAssumeCapacityNoClobber(
1243 try t.copy(dg.typedefs_arena),
1244 .{ .name = name, .rendered = rendered },
1245 );
1246
1247 try buffer.appendSlice(tag);
1248 try buffer.append(' ');
1249 try buffer.appendSlice(tagged_name);
1250 try buffer.appendSlice(" {\n");
1251
1252 const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {
1253 const target = dg.module.getTarget();
1254 const layout = t.unionGetLayout(target);
12141255 if (layout.tag_size != 0) {
1215 try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, 0);
1256 try buffer.append(' ');
1257 try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0);
12161258 try buffer.appendSlice(";\n");
12171259 }
1218 }
1260 try buffer.appendSlice(" union {\n");
1261 break :indent " ";
1262 } else " ";
12191263
1220 try buffer.appendSlice("union {\n");
1221 const fields = t.unionFields();
12221264 {
1223 var it = fields.iterator();
1265 var it = t.unionFields().iterator();
12241266 var empty = true;
12251267 while (it.next()) |entry| {
12261268 const field_ty = entry.value_ptr.ty;
12271269 if (!field_ty.hasRuntimeBits()) continue;
12281270
12291271 const alignment = entry.value_ptr.abi_align;
1230 const name: CValue = .{ .identifier = entry.key_ptr.* };
1231 try buffer.append(' ');
1232 try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
1272 const field_name: CValue = .{ .identifier = entry.key_ptr.* };
1273 try buffer.appendSlice(indent);
1274 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment);
12331275 try buffer.appendSlice(";\n");
12341276
12351277 empty = false;
12361278 }
1237 if (empty) try buffer.appendSlice(" char empty_union;\n");
1238 }
1239 try buffer.appendSlice("} ");
1240
1241 if (t.unionTagTypeSafety()) |_| {
1242 try buffer.appendSlice("payload;\n} ");
1279 if (empty) {
1280 try buffer.appendSlice(indent);
1281 try buffer.appendSlice("char empty_union;\n");
1282 }
12431283 }
12441284
1245 const name_start = buffer.items.len;
1246 try buffer.writer().print("zig_U_{};\n", .{fmtIdent(fqn)});
1285 if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");
1286 try buffer.appendSlice("};\n");
12471287
1248 const rendered = buffer.toOwnedSlice();
1249 errdefer dg.typedefs.allocator.free(rendered);
1250 const name = rendered[name_start .. rendered.len - 2];
1288 const rendered_body = buffer.toOwnedSlice();
1289 errdefer dg.typedefs.allocator.free(rendered_body);
12511290
1291 // We need to add another item to the TypedefMap, so we need a distinct
1292 // type that is not used anywhere, but is still uniquely associated with
1293 // this type, so use an empty struct which references our unique decls.
12521294 try dg.typedefs.ensureUnusedCapacity(1);
12531295 dg.typedefs.putAssumeCapacityNoClobber(
1254 try t.copy(dg.typedefs_arena),
1255 .{ .name = name, .rendered = rendered },
1296 try Type.Tag.empty_struct.create(dg.typedefs_arena, &union_obj.namespace),
1297 .{ .name = undefined, .rendered = rendered_body },
12561298 );
12571299
12581300 return name;
......@@ -1280,21 +1322,22 @@ pub const DeclGen = struct {
12801322 try bw.writeAll("; } ");
12811323 }
12821324
1283 const name_index = buffer.items.len;
1325 const name_begin = buffer.items.len;
12841326 if (error_ty.castTag(.error_set_inferred)) |inf_err_set_payload| {
12851327 const func = inf_err_set_payload.data.func;
12861328 try bw.writeAll("zig_E_");
12871329 try dg.renderDeclName(bw, func.owner_decl);
1288 try bw.writeAll(";\n");
12891330 } else {
1290 try bw.print("zig_E_{}_{};\n", .{
1331 try bw.print("zig_E_{}_{}", .{
12911332 typeToCIdentifier(error_ty, dg.module), typeToCIdentifier(payload_ty, dg.module),
12921333 });
12931334 }
1335 const name_end = buffer.items.len;
1336 try bw.writeAll(";\n");
12941337
12951338 const rendered = buffer.toOwnedSlice();
12961339 errdefer dg.typedefs.allocator.free(rendered);
1297 const name = rendered[name_index .. rendered.len - 2];
1340 const name = rendered[name_begin..name_end];
12981341
12991342 try dg.typedefs.ensureUnusedCapacity(1);
13001343 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1315,7 +1358,7 @@ pub const DeclGen = struct {
13151358 try bw.writeAll("typedef ");
13161359 try dg.renderType(bw, elem_type);
13171360
1318 const name_start = buffer.items.len + 1;
1361 const name_begin = buffer.items.len + " ".len;
13191362 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(elem_type, dg.module), t.arrayLen() });
13201363 if (t.sentinel()) |s| {
13211364 var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
......@@ -1331,7 +1374,7 @@ pub const DeclGen = struct {
13311374
13321375 const rendered = buffer.toOwnedSlice();
13331376 errdefer dg.typedefs.allocator.free(rendered);
1334 const name = rendered[name_start..name_end];
1377 const name = rendered[name_begin..name_end];
13351378
13361379 try dg.typedefs.ensureUnusedCapacity(1);
13371380 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1351,12 +1394,15 @@ pub const DeclGen = struct {
13511394 const payload_name = CValue{ .bytes = "payload" };
13521395 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
13531396 try bw.writeAll("; bool is_null; } ");
1354 const name_index = buffer.items.len;
1355 try bw.print("zig_Q_{};\n", .{typeToCIdentifier(child_type, dg.module)});
1397
1398 const name_begin = buffer.items.len;
1399 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
1400 const name_end = buffer.items.len;
1401 try bw.writeAll(";\n");
13561402
13571403 const rendered = buffer.toOwnedSlice();
13581404 errdefer dg.typedefs.allocator.free(rendered);
1359 const name = rendered[name_index .. rendered.len - 2];
1405 const name = rendered[name_begin..name_end];
13601406
13611407 try dg.typedefs.ensureUnusedCapacity(1);
13621408 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1378,12 +1424,14 @@ pub const DeclGen = struct {
13781424
13791425 try buffer.writer().print("typedef struct { } ", .{fmtIdent(std.mem.span(unqualified_name))});
13801426
1381 const name_start = buffer.items.len;
1382 try buffer.writer().print("zig_O_{};\n", .{fmtIdent(fqn)});
1427 const name_begin = buffer.items.len;
1428 try buffer.writer().print("zig_O_{}", .{fmtIdent(fqn)});
1429 const name_end = buffer.items.len;
1430 try buffer.appendSlice(";\n");
13831431
13841432 const rendered = buffer.toOwnedSlice();
13851433 errdefer dg.typedefs.allocator.free(rendered);
1386 const name = rendered[name_start .. rendered.len - 2];
1434 const name = rendered[name_begin..name_end];
13871435
13881436 try dg.typedefs.ensureUnusedCapacity(1);
13891437 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1530,7 +1578,7 @@ pub const DeclGen = struct {
15301578 return w.writeAll(name);
15311579 },
15321580 .Struct => {
1533 const name = dg.getTypedefName(t) orelse if (t.isTuple() or t.tag() == .anon_struct)
1581 const name = dg.getTypedefName(t) orelse if (t.isTupleOrAnonStruct())
15341582 try dg.renderTupleTypedef(t)
15351583 else
15361584 try dg.renderStructTypedef(t);
......@@ -3597,8 +3645,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
35973645 var field_name: []const u8 = undefined;
35983646 var field_val_ty: Type = undefined;
35993647
3600 var buf = std.ArrayList(u8).init(f.object.dg.gpa);
3601 defer buf.deinit();
3648 var field_name_buf: []const u8 = "";
3649 defer f.object.dg.gpa.free(field_name_buf);
36023650 switch (struct_ty.tag()) {
36033651 .@"struct" => {
36043652 const fields = struct_ty.structFields();
......@@ -3614,8 +3662,8 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
36143662 const tuple = struct_ty.tupleFields();
36153663 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
36163664
3617 try buf.writer().print("field_{d}", .{index});
3618 field_name = buf.items;
3665 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});
3666 field_name = field_name_buf;
36193667 field_val_ty = tuple.types[index];
36203668 },
36213669 else => unreachable,
......@@ -3648,8 +3696,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
36483696 const writer = f.object.writer();
36493697 const struct_byval = try f.resolveInst(extra.struct_operand);
36503698 const struct_ty = f.air.typeOf(extra.struct_operand);
3651 var buf = std.ArrayList(u8).init(f.object.dg.gpa);
3652 defer buf.deinit();
3699 var field_name_buf: []const u8 = "";
3700 defer f.object.dg.gpa.free(field_name_buf);
36533701 const field_name = switch (struct_ty.tag()) {
36543702 .@"struct" => struct_ty.structFields().keys()[extra.field_index],
36553703 .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[extra.field_index],
......@@ -3657,8 +3705,8 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
36573705 const tuple = struct_ty.tupleFields();
36583706 if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
36593707
3660 try buf.writer().print("field_{d}", .{extra.field_index});
3661 break :blk buf.items;
3708 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{extra.field_index});
3709 break :blk field_name_buf;
36623710 },
36633711 else => unreachable,
36643712 };
......@@ -4125,8 +4173,9 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
41254173 const layout = union_ty.unionGetLayout(target);
41264174 if (layout.tag_size == 0) return CValue.none;
41274175
4176 try writer.writeByte('(');
41284177 try f.writeCValue(writer, union_ptr);
4129 try writer.writeAll("->tag = ");
4178 try writer.writeAll(")->tag = ");
41304179 try f.writeCValue(writer, new_tag);
41314180 try writer.writeAll(";\n");
41324181
src/link/C.zig+32-27
......@@ -108,10 +108,8 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
108108 const typedefs = &gop.value_ptr.typedefs;
109109 const code = &gop.value_ptr.code;
110110 fwd_decl.shrinkRetainingCapacity(0);
111 {
112 for (typedefs.values()) |value| {
113 module.gpa.free(value.rendered);
114 }
111 for (typedefs.values()) |typedef| {
112 module.gpa.free(typedef.rendered);
115113 }
116114 typedefs.clearRetainingCapacity();
117115 code.shrinkRetainingCapacity(0);
......@@ -139,14 +137,14 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
139137
140138 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
141139 defer {
142 function.value_map.deinit();
143140 function.blocks.deinit(module.gpa);
141 function.value_map.deinit();
144142 function.object.code.deinit();
145 function.object.dg.fwd_decl.deinit();
146 for (function.object.dg.typedefs.values()) |value| {
147 module.gpa.free(value.rendered);
143 for (function.object.dg.typedefs.values()) |typedef| {
144 module.gpa.free(typedef.rendered);
148145 }
149146 function.object.dg.typedefs.deinit();
147 function.object.dg.fwd_decl.deinit();
150148 }
151149
152150 codegen.genFunc(&function) catch |err| switch (err) {
......@@ -179,10 +177,8 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
179177 const typedefs = &gop.value_ptr.typedefs;
180178 const code = &gop.value_ptr.code;
181179 fwd_decl.shrinkRetainingCapacity(0);
182 {
183 for (typedefs.values()) |value| {
184 module.gpa.free(value.rendered);
185 }
180 for (typedefs.values()) |value| {
181 module.gpa.free(value.rendered);
186182 }
187183 typedefs.clearRetainingCapacity();
188184 code.shrinkRetainingCapacity(0);
......@@ -206,11 +202,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
206202 object.indent_writer = .{ .underlying_writer = object.code.writer() };
207203 defer {
208204 object.code.deinit();
209 object.dg.fwd_decl.deinit();
210 for (object.dg.typedefs.values()) |value| {
211 module.gpa.free(value.rendered);
205 for (object.dg.typedefs.values()) |typedef| {
206 module.gpa.free(typedef.rendered);
212207 }
213208 object.dg.typedefs.deinit();
209 object.dg.fwd_decl.deinit();
214210 }
215211
216212 codegen.genDecl(&object) catch |err| switch (err) {
......@@ -307,10 +303,10 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
307303}
308304
309305const Flush = struct {
306 err_decls: DeclBlock = .{},
310307 remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
311308 typedefs: Typedefs = .{},
312309 typedef_buf: std.ArrayListUnmanaged(u8) = .{},
313 err_buf: std.ArrayListUnmanaged(u8) = .{},
314310 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
315311 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
316312 /// Keeps track of the total bytes of `all_buffers`.
......@@ -332,10 +328,10 @@ const Flush = struct {
332328
333329 fn deinit(f: *Flush, gpa: Allocator) void {
334330 f.all_buffers.deinit(gpa);
335 f.err_buf.deinit(gpa);
336331 f.typedef_buf.deinit(gpa);
337332 f.typedefs.deinit(gpa);
338333 f.remaining_decls.deinit(gpa);
334 f.err_decls.deinit(gpa);
339335 }
340336};
341337
......@@ -365,6 +361,10 @@ fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) Fl
365361fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
366362 const module = self.base.options.module.?;
367363
364 const fwd_decl = &f.err_decls.fwd_decl;
365 const typedefs = &f.err_decls.typedefs;
366 const code = &f.err_decls.code;
367
368368 var object = codegen.Object{
369369 .dg = .{
370370 .gpa = module.gpa,
......@@ -372,20 +372,21 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
372372 .error_msg = null,
373373 .decl_index = undefined,
374374 .decl = undefined,
375 .fwd_decl = undefined,
376 .typedefs = codegen.TypedefMap.initContext(module.gpa, .{ .mod = module }),
375 .fwd_decl = fwd_decl.toManaged(module.gpa),
376 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
377377 .typedefs_arena = self.arena.allocator(),
378378 },
379 .code = f.err_buf.toManaged(module.gpa),
379 .code = code.toManaged(module.gpa),
380380 .indent_writer = undefined, // set later so we can get a pointer to object.code
381381 };
382382 object.indent_writer = .{ .underlying_writer = object.code.writer() };
383383 defer {
384 f.err_buf = object.code.moveToUnmanaged();
385 for (object.dg.typedefs.values()) |value| {
386 module.gpa.free(value.rendered);
384 object.code.deinit();
385 for (object.dg.typedefs.values()) |typedef| {
386 module.gpa.free(typedef.rendered);
387387 }
388388 object.dg.typedefs.deinit();
389 object.dg.fwd_decl.deinit();
389390 }
390391
391392 codegen.genErrDecls(&object) catch |err| switch (err) {
......@@ -393,11 +394,15 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
393394 else => |e| return e,
394395 };
395396
396 const gpa = self.base.allocator;
397 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
398 typedefs.* = object.dg.typedefs.unmanaged;
399 object.dg.typedefs.unmanaged = .{};
400 code.* = object.code.moveToUnmanaged();
397401
398 try self.flushTypedefs(f, object.dg.typedefs.unmanaged);
399 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
400 f.appendBufAssumeCapacity(object.code.items);
402 try self.flushTypedefs(f, typedefs.*);
403 try f.all_buffers.ensureUnusedCapacity(self.base.allocator, 1);
404 f.appendBufAssumeCapacity(fwd_decl.items);
405 f.appendBufAssumeCapacity(code.items);
401406}
402407
403408/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
test/behavior/align.zig-1
......@@ -476,7 +476,6 @@ test "read 128-bit field from default aligned struct in global memory" {
476476}
477477
478478test "struct field explicit alignment" {
479 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
480479 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
481480 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
482481 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/atomics.zig-1
......@@ -33,7 +33,6 @@ fn testCmpxchg() !void {
3333}
3434
3535test "fence" {
36 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3736 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
3837 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3938 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/basic.zig-1
......@@ -590,7 +590,6 @@ test "equality compare fn ptrs" {
590590
591591test "self reference through fn ptr field" {
592592 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
593 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
594593
595594 const S = struct {
596595 const A = struct {
test/behavior/bugs/1310.zig-1
......@@ -24,6 +24,5 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
2424
2525test "fixed" {
2626 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2827 try expect(agent_callback(undefined, undefined) == 11);
2928}
test/behavior/bugs/1500.zig-1
......@@ -6,7 +6,6 @@ const A = struct {
66const B = *const fn (A) void;
77
88test "allow these dependencies" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
109 var a: A = undefined;
1110 var b: B = undefined;
1211 if (false) {
test/behavior/bugs/2006.zig-1
......@@ -6,7 +6,6 @@ const S = struct {
66 p: *S,
77};
88test "bug 2006" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
109 var a: S = undefined;
1110 a = S{ .p = undefined };
1211 try expect(@sizeOf(S) != 0);
test/behavior/cast.zig-4
......@@ -410,7 +410,6 @@ fn testCastIntToErr(err: anyerror) !void {
410410
411411test "peer resolve array and const slice" {
412412 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
413 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
414413 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
415414 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
416415
......@@ -546,7 +545,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
546545
547546test "single-item pointer of array to slice to unknown length pointer" {
548547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
550548
551549 try testCastPtrOfArrayToSliceAndPtr();
552550 comptime try testCastPtrOfArrayToSliceAndPtr();
......@@ -575,7 +573,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
575573
576574test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
577575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
579576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
580577
581578 const window_name = [1][*]const u8{"window name"};
......@@ -1235,7 +1232,6 @@ test "cast from array reference to fn: runtime fn ptr" {
12351232
12361233test "*const [N]null u8 to ?[]const u8" {
12371234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1238 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12391235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12401236
12411237 const S = struct {
test/behavior/floatop.zig-2
......@@ -21,7 +21,6 @@ fn epsForType(comptime T: type) T {
2121
2222test "floating point comparisons" {
2323 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2524 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2625
2726 try testFloatComparisons();
......@@ -91,7 +90,6 @@ fn testDifferentSizedFloatComparisons() !void {
9190
9291test "negative f128 floatToInt at compile-time" {
9392 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9593 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9694 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9795
test/behavior/generics.zig-1
......@@ -204,7 +204,6 @@ fn foo2(arg: anytype) bool {
204204}
205205
206206test "generic struct" {
207 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
208207 var a1 = GenNode(i32){
209208 .value = 13,
210209 .next = null,
test/behavior/math.zig-3
......@@ -603,7 +603,6 @@ fn should_not_be_zero(x: f128) !void {
603603}
604604
605605test "128-bit multiplication" {
606 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
607606 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
608607 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
609608 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -650,8 +649,6 @@ test "@addWithOverflow" {
650649}
651650
652651test "small int addition" {
653 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
654
655652 var x: u2 = 0;
656653 try expect(x == 0);
657654
test/behavior/maximum_minimum.zig-2
......@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
66
77test "@max" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1211
......@@ -55,7 +54,6 @@ test "@min" {
5554 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5957
6058 const S = struct {
6159 fn doTheTest() !void {
test/behavior/muladd.zig-1
......@@ -2,7 +2,6 @@ const builtin = @import("builtin");
22const expect = @import("std").testing.expect;
33
44test "@mulAdd" {
5 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/packed-struct.zig-1
......@@ -293,7 +293,6 @@ test "regular in irregular packed struct" {
293293test "byte-aligned field pointer offsets" {
294294 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
295295 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
297296 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
298297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig-1
......@@ -239,7 +239,6 @@ test "saturating shl uses the LHS type" {
239239 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
240240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
241241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
243242
244243 const lhs_const: u8 = 1;
245244 var lhs_var: u8 = 1;
test/behavior/struct.zig-2
......@@ -284,7 +284,6 @@ const Val = struct {
284284
285285test "struct point to self" {
286286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
287 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
288287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
289288
290289 var root: Node = undefined;
......@@ -393,7 +392,6 @@ const APackedStruct = packed struct {
393392test "packed struct" {
394393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
395394 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
397395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
398396 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
399397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/struct_contains_null_ptr_itself.zig-1
......@@ -5,7 +5,6 @@ const builtin = @import("builtin");
55test "struct contains null pointer which contains original struct" {
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98 var x: ?*NodeLineComment = null;
109 try expect(x == null);
1110}
test/behavior/switch_prong_implicit_cast.zig-1
......@@ -18,7 +18,6 @@ test "switch prong implicit cast" {
1818 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1919 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2020 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2221 const result = switch (foo(2) catch unreachable) {
2322 FormValue.One => false,
2423 FormValue.Two => |x| x,
test/behavior/union.zig-3
......@@ -1186,7 +1186,6 @@ test "comptime equality of extern unions with same tag" {
11861186}
11871187
11881188test "union tag is set when initiated as a temporary value at runtime" {
1189 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11901189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11911190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11921191
......@@ -1350,7 +1349,6 @@ test "@unionInit uses tag value instead of field index" {
13501349}
13511350
13521351test "union field ptr - zero sized payload" {
1353 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13541352 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13551353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13561354
......@@ -1364,7 +1362,6 @@ test "union field ptr - zero sized payload" {
13641362}
13651363
13661364test "union field ptr - zero sized field" {
1367 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13681365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13691366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13701367
test/behavior/vector.zig-1
......@@ -811,7 +811,6 @@ test "vector reduce operation" {
811811test "vector @reduce comptime" {
812812 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
813813 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
815814 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
816815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
817816 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO