authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-26 20:21:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
logfc358435cb5cbcc21967af438b190d4e18bba9ae
tree4f5fcbc488a55bb954bec3fbd4d81c172a372478
parenta596ea683c35d90c6af3e1fbeae2e06312ce392f

C backend: InternPool fixes


2 files changed, 174 insertions(+), 124 deletions(-)

src/codegen.zig+2-1
......@@ -443,7 +443,8 @@ pub fn generateSymbol(
443443 },
444444 .anon_struct_type => |tuple| {
445445 const struct_begin = code.items.len;
446 for (tuple.types, 0..) |field_ty, index| {
446 for (tuple.types, tuple.values, 0..) |field_ty, comptime_val, index| {
447 if (comptime_val != .none) continue;
447448 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
448449
449450 const field_val = switch (aggregate.storage) {
src/codegen/c.zig+172-123
......@@ -1110,14 +1110,16 @@ pub const DeclGen = struct {
11101110
11111111 .undef, .runtime_value => unreachable, // handled above
11121112 .simple_value => |simple_value| switch (simple_value) {
1113 .undefined,
1114 .void,
1115 .null,
1116 .empty_struct,
1117 .@"unreachable",
1118 .generic_poison,
1119 => unreachable, // non-runtime values
1120 .false, .true => try writer.writeAll(@tagName(simple_value)),
1113 // non-runtime values
1114 .undefined => unreachable,
1115 .void => unreachable,
1116 .null => unreachable,
1117 .empty_struct => unreachable,
1118 .@"unreachable" => unreachable,
1119 .generic_poison => unreachable,
1120
1121 .false => try writer.writeAll("false"),
1122 .true => try writer.writeAll("true"),
11211123 },
11221124 .variable,
11231125 .extern_func,
......@@ -1138,10 +1140,10 @@ pub const DeclGen = struct {
11381140 .error_union => |error_union| {
11391141 const payload_ty = ty.errorUnionPayload(mod);
11401142 const error_ty = ty.errorUnionSet(mod);
1141 const error_val = if (val.errorUnionIsPayload(mod)) try mod.intValue(Type.anyerror, 0) else val;
1143 const error_val = if (val.errorUnionIsPayload(mod)) try mod.intValue(Type.err_int, 0) else val;
11421144
11431145 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1144 return dg.renderValue(writer, error_ty, error_val, location);
1146 return dg.renderValue(writer, Type.err_int, error_val, location);
11451147 }
11461148
11471149 if (!location.isInitializer()) {
......@@ -1305,12 +1307,10 @@ pub const DeclGen = struct {
13051307 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
13061308 return dg.renderValue(writer, Type.bool, is_null_val, location);
13071309
1308 if (ty.optionalReprIsPayload(mod)) {
1309 return dg.renderValue(writer, payload_ty, switch (opt.val) {
1310 .none => try mod.intValue(payload_ty, 0),
1311 else => opt.val.toValue(),
1312 }, location);
1313 }
1310 if (ty.optionalReprIsPayload(mod)) switch (opt.val) {
1311 .none => return writer.writeByte('0'),
1312 else => return dg.renderValue(writer, payload_ty, opt.val.toValue(), location),
1313 };
13141314
13151315 if (!location.isInitializer()) {
13161316 try writer.writeByte('(');
......@@ -1327,7 +1327,7 @@ pub const DeclGen = struct {
13271327 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
13281328 try writer.writeAll(" }");
13291329 },
1330 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1330 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
13311331 .array_type, .vector_type => {
13321332 if (location == .FunctionArgument) {
13331333 try writer.writeByte('(');
......@@ -1385,131 +1385,179 @@ pub const DeclGen = struct {
13851385 try writer.writeByte('}');
13861386 }
13871387 },
1388 .struct_type, .anon_struct_type => switch (ty.containerLayout(mod)) {
1389 .Auto, .Extern => {
1390 const field_vals = val.castTag(.aggregate).?.data;
1391
1392 if (!location.isInitializer()) {
1393 try writer.writeByte('(');
1394 try dg.renderType(writer, ty);
1395 try writer.writeByte(')');
1396 }
1397
1398 try writer.writeByte('{');
1399 var empty = true;
1400 for (field_vals, 0..) |field_val, field_i| {
1401 if (ty.structFieldIsComptime(field_i, mod)) continue;
1402 const field_ty = ty.structFieldType(field_i, mod);
1403 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1404
1405 if (!empty) try writer.writeByte(',');
1406 try dg.renderValue(writer, field_ty, field_val, initializer_type);
1388 .anon_struct_type => |tuple| {
1389 if (!location.isInitializer()) {
1390 try writer.writeByte('(');
1391 try dg.renderType(writer, ty);
1392 try writer.writeByte(')');
1393 }
14071394
1408 empty = false;
1409 }
1410 try writer.writeByte('}');
1411 },
1412 .Packed => {
1413 const field_vals = val.castTag(.aggregate).?.data;
1414 const int_info = ty.intInfo(mod);
1395 try writer.writeByte('{');
1396 var empty = true;
1397 for (tuple.types, tuple.values, 0..) |field_ty, comptime_ty, field_i| {
1398 if (comptime_ty != .none) continue;
1399 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
14151400
1416 const bits = Type.smallestUnsignedBits(int_info.bits - 1);
1417 const bit_offset_ty = try mod.intType(.unsigned, bits);
1401 if (!empty) try writer.writeByte(',');
14181402
1419 var bit_offset: u64 = 0;
1403 const field_val = switch (aggregate.storage) {
1404 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1405 .ty = field_ty,
1406 .storage = .{ .u64 = bytes[field_i] },
1407 } }),
1408 .elems => |elems| elems[field_i],
1409 .repeated_elem => |elem| elem,
1410 };
1411 try dg.renderValue(writer, field_ty.toType(), field_val.toValue(), initializer_type);
14201412
1421 var eff_num_fields: usize = 0;
1422 for (0..field_vals.len) |field_i| {
1423 if (ty.structFieldIsComptime(field_i, mod)) continue;
1424 const field_ty = ty.structFieldType(field_i, mod);
1425 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1413 empty = false;
1414 }
1415 try writer.writeByte('}');
1416 },
1417 .struct_type => |struct_type| {
1418 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1419 switch (struct_obj.layout) {
1420 .Auto, .Extern => {
1421 if (!location.isInitializer()) {
1422 try writer.writeByte('(');
1423 try dg.renderType(writer, ty);
1424 try writer.writeByte(')');
1425 }
14261426
1427 eff_num_fields += 1;
1428 }
1427 try writer.writeByte('{');
1428 var empty = true;
1429 for (struct_obj.fields.values(), 0..) |field, field_i| {
1430 if (field.is_comptime) continue;
1431 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1432
1433 if (!empty) try writer.writeByte(',');
1434 const field_val = switch (aggregate.storage) {
1435 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1436 .ty = field.ty.toIntern(),
1437 .storage = .{ .u64 = bytes[field_i] },
1438 } }),
1439 .elems => |elems| elems[field_i],
1440 .repeated_elem => |elem| elem,
1441 };
1442 try dg.renderValue(writer, field.ty, field_val.toValue(), initializer_type);
14291443
1430 if (eff_num_fields == 0) {
1431 try writer.writeByte('(');
1432 try dg.renderValue(writer, ty, Value.undef, initializer_type);
1433 try writer.writeByte(')');
1434 } else if (ty.bitSize(mod) > 64) {
1435 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1436 var num_or = eff_num_fields - 1;
1437 while (num_or > 0) : (num_or -= 1) {
1438 try writer.writeAll("zig_or_");
1439 try dg.renderTypeForBuiltinFnName(writer, ty);
1440 try writer.writeByte('(');
1444 empty = false;
14411445 }
1446 try writer.writeByte('}');
1447 },
1448 .Packed => {
1449 const int_info = ty.intInfo(mod);
14421450
1443 var eff_index: usize = 0;
1444 var needs_closing_paren = false;
1445 for (field_vals, 0..) |field_val, field_i| {
1446 if (ty.structFieldIsComptime(field_i, mod)) continue;
1447 const field_ty = ty.structFieldType(field_i, mod);
1448 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1451 const bits = Type.smallestUnsignedBits(int_info.bits - 1);
1452 const bit_offset_ty = try mod.intType(.unsigned, bits);
14491453
1450 const cast_context = IntCastContext{ .value = .{ .value = field_val } };
1451 if (bit_offset != 0) {
1452 try writer.writeAll("zig_shl_");
1453 try dg.renderTypeForBuiltinFnName(writer, ty);
1454 try writer.writeByte('(');
1455 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1456 try writer.writeAll(", ");
1457 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1458 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1459 try writer.writeByte(')');
1460 } else {
1461 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1462 }
1454 var bit_offset: u64 = 0;
1455 var eff_num_fields: usize = 0;
14631456
1464 if (needs_closing_paren) try writer.writeByte(')');
1465 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
1457 for (struct_obj.fields.values()) |field| {
1458 if (field.is_comptime) continue;
1459 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14661460
1467 bit_offset += field_ty.bitSize(mod);
1468 needs_closing_paren = true;
1469 eff_index += 1;
1461 eff_num_fields += 1;
14701462 }
1471 } else {
1472 try writer.writeByte('(');
1473 // a << a_off | b << b_off | c << c_off
1474 var empty = true;
1475 for (field_vals, 0..) |field_val, field_i| {
1476 if (ty.structFieldIsComptime(field_i, mod)) continue;
1477 const field_ty = ty.structFieldType(field_i, mod);
1478 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14791463
1480 if (!empty) try writer.writeAll(" | ");
1464 if (eff_num_fields == 0) {
14811465 try writer.writeByte('(');
1482 try dg.renderType(writer, ty);
1466 try dg.renderValue(writer, ty, Value.undef, initializer_type);
14831467 try writer.writeByte(')');
1468 } else if (ty.bitSize(mod) > 64) {
1469 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1470 var num_or = eff_num_fields - 1;
1471 while (num_or > 0) : (num_or -= 1) {
1472 try writer.writeAll("zig_or_");
1473 try dg.renderTypeForBuiltinFnName(writer, ty);
1474 try writer.writeByte('(');
1475 }
14841476
1485 if (bit_offset != 0) {
1486 try dg.renderValue(writer, field_ty, field_val, .Other);
1487 try writer.writeAll(" << ");
1488 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1489 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1490 } else {
1491 try dg.renderValue(writer, field_ty, field_val, .Other);
1477 var eff_index: usize = 0;
1478 var needs_closing_paren = false;
1479 for (struct_obj.fields.values(), 0..) |field, field_i| {
1480 if (field.is_comptime) continue;
1481 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1482
1483 const field_val = switch (aggregate.storage) {
1484 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1485 .ty = field.ty.toIntern(),
1486 .storage = .{ .u64 = bytes[field_i] },
1487 } }),
1488 .elems => |elems| elems[field_i],
1489 .repeated_elem => |elem| elem,
1490 };
1491 const cast_context = IntCastContext{ .value = .{ .value = field_val.toValue() } };
1492 if (bit_offset != 0) {
1493 try writer.writeAll("zig_shl_");
1494 try dg.renderTypeForBuiltinFnName(writer, ty);
1495 try writer.writeByte('(');
1496 try dg.renderIntCast(writer, ty, cast_context, field.ty, .FunctionArgument);
1497 try writer.writeAll(", ");
1498 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1499 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1500 try writer.writeByte(')');
1501 } else {
1502 try dg.renderIntCast(writer, ty, cast_context, field.ty, .FunctionArgument);
1503 }
1504
1505 if (needs_closing_paren) try writer.writeByte(')');
1506 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
1507
1508 bit_offset += field.ty.bitSize(mod);
1509 needs_closing_paren = true;
1510 eff_index += 1;
14921511 }
1512 } else {
1513 try writer.writeByte('(');
1514 // a << a_off | b << b_off | c << c_off
1515 var empty = true;
1516 for (struct_obj.fields.values(), 0..) |field, field_i| {
1517 if (field.is_comptime) continue;
1518 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14931519
1494 bit_offset += field_ty.bitSize(mod);
1495 empty = false;
1520 if (!empty) try writer.writeAll(" | ");
1521 try writer.writeByte('(');
1522 try dg.renderType(writer, ty);
1523 try writer.writeByte(')');
1524
1525 const field_val = switch (aggregate.storage) {
1526 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1527 .ty = field.ty.toIntern(),
1528 .storage = .{ .u64 = bytes[field_i] },
1529 } }),
1530 .elems => |elems| elems[field_i],
1531 .repeated_elem => |elem| elem,
1532 };
1533
1534 if (bit_offset != 0) {
1535 try dg.renderValue(writer, field.ty, field_val.toValue(), .Other);
1536 try writer.writeAll(" << ");
1537 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1538 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1539 } else {
1540 try dg.renderValue(writer, field.ty, field_val.toValue(), .Other);
1541 }
1542
1543 bit_offset += field.ty.bitSize(mod);
1544 empty = false;
1545 }
1546 try writer.writeByte(')');
14961547 }
1497 try writer.writeByte(')');
1498 }
1499 },
1548 },
1549 }
15001550 },
15011551 else => unreachable,
15021552 },
1503 .un => {
1504 const union_obj = val.castTag(.@"union").?.data;
1505
1553 .un => |un| {
15061554 if (!location.isInitializer()) {
15071555 try writer.writeByte('(');
15081556 try dg.renderType(writer, ty);
15091557 try writer.writeByte(')');
15101558 }
15111559
1512 const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?;
1560 const field_i = ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
15131561 const field_ty = ty.unionFields(mod).values()[field_i].ty;
15141562 const field_name = ty.unionFields(mod).keys()[field_i];
15151563 if (ty.containerLayout(mod) == .Packed) {
......@@ -1523,7 +1571,7 @@ pub const DeclGen = struct {
15231571 try dg.renderType(writer, ty);
15241572 try writer.writeByte(')');
15251573 }
1526 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);
1574 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
15271575 } else {
15281576 try writer.writeAll("0");
15291577 }
......@@ -1535,7 +1583,7 @@ pub const DeclGen = struct {
15351583 const layout = ty.unionGetLayout(mod);
15361584 if (layout.tag_size != 0) {
15371585 try writer.writeAll(" .tag = ");
1538 try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);
1586 try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
15391587 }
15401588 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
15411589 if (layout.tag_size != 0) try writer.writeByte(',');
......@@ -1543,7 +1591,7 @@ pub const DeclGen = struct {
15431591 }
15441592 if (field_ty.hasRuntimeBits(mod)) {
15451593 try writer.print(" .{ } = ", .{fmtIdent(field_name)});
1546 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);
1594 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
15471595 try writer.writeByte(' ');
15481596 } else for (ty.unionFields(mod).values()) |field| {
15491597 if (!field.ty.hasRuntimeBits(mod)) continue;
......@@ -5113,13 +5161,14 @@ fn airIsNull(
51135161 TypedValue{ .ty = Type.bool, .val = Value.true }
51145162 else if (optional_ty.isPtrLikeOptional(mod))
51155163 // operand is a regular pointer, test `operand !=/== NULL`
5116 TypedValue{ .ty = optional_ty, .val = Value.null }
5164 TypedValue{ .ty = optional_ty, .val = try mod.nullValue(optional_ty) }
51175165 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5118 TypedValue{ .ty = payload_ty, .val = try mod.intValue(payload_ty, 0) }
5166 TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) }
51195167 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
51205168 try writer.writeAll(".ptr");
51215169 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
5122 break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null };
5170 const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());
5171 break :rhs TypedValue{ .ty = opt_slice_ptr_ty, .val = try mod.nullValue(opt_slice_ptr_ty) };
51235172 } else rhs: {
51245173 try writer.writeAll(".is_null");
51255174 break :rhs TypedValue{ .ty = Type.bool, .val = Value.true };
......@@ -5781,7 +5830,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
57815830 else
57825831 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
57835832 try a.assign(f, writer);
5784 try f.object.dg.renderValue(writer, err_ty, try mod.intValue(err_ty, 0), .Other);
5833 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
57855834 try a.end(f, writer);
57865835 }
57875836 return local;
......@@ -5812,11 +5861,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
58125861 else
58135862 try f.writeCValue(writer, operand, .Other)
58145863 else
5815 try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
5864 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
58165865 try writer.writeByte(' ');
58175866 try writer.writeAll(operator);
58185867 try writer.writeByte(' ');
5819 try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
5868 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
58205869 try writer.writeAll(";\n");
58215870 return local;
58225871}