authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-11 00:27:41-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-06-11 00:27:41-04:00
logc1eb6c30e84b0b161b634f7410088f44c80caa90
tree915141c29947e320175cd2c5ed73afaa88ddf259
parent9b05474d797ea4600dbae36ae95d9eb042040bb2
parent6bf529dc381cb2f5a83c5f9e303ffdab7779ac4d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11835 from ziglang/stage2-behavior

stage2: fix handling of aggregates with mixed comptime-only fields

6 files changed, 153 insertions(+), 119 deletions(-)

src/Sema.zig+4-6
...@@ -11747,11 +11747,11 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -11747,11 +11747,11 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1174711747
11748fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {11748fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11749 const inst_data = sema.code.instructions.items(.data)[inst].un_node;11749 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
11750 const src = inst_data.src();
11750 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };11751 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
11751 const unresolved_operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);11752 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
11752 const operand_ty = try sema.resolveTypeFields(block, operand_src, unresolved_operand_ty);
11753 const target = sema.mod.getTarget();11753 const target = sema.mod.getTarget();
11754 const bit_size = operand_ty.bitSize(target);11754 const bit_size = try operand_ty.bitSizeAdvanced(target, sema.kit(block, src));
11755 return sema.addIntUnsigned(Type.comptime_int, bit_size);11755 return sema.addIntUnsigned(Type.comptime_int, bit_size);
11756}11756}
1175711757
...@@ -25047,9 +25047,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ...@@ -25047,9 +25047,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
25047}25047}
2504825048
25049pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {25049pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
25050 if ((try sema.typeHasOnePossibleValue(block, src, ty)) != null) return false;25050 return ty.hasRuntimeBitsAdvanced(false, sema.kit(block, src));
25051 if (try sema.typeRequiresComptime(block, src, ty)) return false;
25052 return true;
25053}25051}
2505425052
25055fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {25053fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {
src/codegen/llvm.zig+3-3
...@@ -9185,7 +9185,7 @@ fn isByRef(ty: Type) bool {...@@ -9185,7 +9185,7 @@ fn isByRef(ty: Type) bool {
9185 .AnyFrame,9185 .AnyFrame,
9186 => return false,9186 => return false,
91879187
9188 .Array, .Frame => return ty.hasRuntimeBitsIgnoreComptime(),9188 .Array, .Frame => return ty.hasRuntimeBits(),
9189 .Struct => {9189 .Struct => {
9190 // Packed structs are represented to LLVM as integers.9190 // Packed structs are represented to LLVM as integers.
9191 if (ty.containerLayout() == .Packed) return false;9191 if (ty.containerLayout() == .Packed) return false;
...@@ -9204,7 +9204,7 @@ fn isByRef(ty: Type) bool {...@@ -9204,7 +9204,7 @@ fn isByRef(ty: Type) bool {
9204 var count: usize = 0;9204 var count: usize = 0;
9205 const fields = ty.structFields();9205 const fields = ty.structFields();
9206 for (fields.values()) |field| {9206 for (fields.values()) |field| {
9207 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;9207 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
92089208
9209 count += 1;9209 count += 1;
9210 if (count > max_fields_byval) return true;9210 if (count > max_fields_byval) return true;
...@@ -9212,7 +9212,7 @@ fn isByRef(ty: Type) bool {...@@ -9212,7 +9212,7 @@ fn isByRef(ty: Type) bool {
9212 }9212 }
9213 return false;9213 return false;
9214 },9214 },
9215 .Union => return ty.hasRuntimeBitsIgnoreComptime(),9215 .Union => return ty.hasRuntimeBits(),
9216 .ErrorUnion => return isByRef(ty.errorUnionPayload()),9216 .ErrorUnion => return isByRef(ty.errorUnionPayload()),
9217 .Optional => {9217 .Optional => {
9218 var buf: Type.Payload.ElemType = undefined;9218 var buf: Type.Payload.ElemType = undefined;
src/link/Dwarf.zig+28-26
...@@ -352,6 +352,7 @@ pub const DeclState = struct {...@@ -352,6 +352,7 @@ pub const DeclState = struct {
352 const fields = ty.structFields();352 const fields = ty.structFields();
353 for (fields.keys()) |field_name, field_index| {353 for (fields.keys()) |field_name, field_index| {
354 const field = fields.get(field_name).?;354 const field = fields.get(field_name).?;
355 if (!field.ty.hasRuntimeBits()) continue;
355 // DW.AT.member356 // DW.AT.member
356 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);357 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
357 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));358 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
...@@ -1037,6 +1038,7 @@ pub fn commitDeclState(...@@ -1037,6 +1038,7 @@ pub fn commitDeclState(
1037 }1038 }
1038 }1039 }
10391040
1041 log.debug("updateDeclDebugInfoAllocation for '{s}'", .{decl.name});
1040 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));1042 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
10411043
1042 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {1044 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
...@@ -1098,6 +1100,7 @@ pub fn commitDeclState(...@@ -1098,6 +1100,7 @@ pub fn commitDeclState(
1098 }1100 }
1099 }1101 }
11001102
1103 log.debug("writeDeclDebugInfo for '{s}", .{decl.name});
1101 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);1104 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
1102}1105}
11031106
...@@ -1141,7 +1144,10 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3...@@ -1141,7 +1144,10 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
1141 },1144 },
1142 .wasm => {1145 .wasm => {
1143 const wasm_file = file.cast(File.Wasm).?;1146 const wasm_file = file.cast(File.Wasm).?;
1144 writeDbgInfoNopsBuffered(wasm_file.debug_info.items, atom.off, 0, &.{0}, atom.len, false);1147 const segment_index = try wasm_file.getDebugInfoIndex();
1148 const segment = &wasm_file.segments.items[segment_index];
1149 const offset = segment.offset + atom.off;
1150 try writeDbgInfoNopsToArrayList(gpa, &wasm_file.debug_info, offset, 0, &.{0}, atom.len, false);
1145 },1151 },
1146 else => unreachable,1152 else => unreachable,
1147 }1153 }
...@@ -1283,8 +1289,12 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co...@@ -1283,8 +1289,12 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
1283 debug_info.items.len = needed_size;1289 debug_info.items.len = needed_size;
1284 }1290 }
1285 const offset = segment.offset + atom.off;1291 const offset = segment.offset + atom.off;
1286 writeDbgInfoNopsBuffered(1292 log.debug(" writeDbgInfoNopsToArrayList debug_info_len={d} offset={d} content_len={d} next_padding_size={d}", .{
1287 debug_info.items,1293 debug_info.items.len, offset, dbg_info_buf.len, next_padding_size,
1294 });
1295 try writeDbgInfoNopsToArrayList(
1296 gpa,
1297 debug_info,
1288 offset,1298 offset,
1289 prev_padding_size,1299 prev_padding_size,
1290 dbg_info_buf,1300 dbg_info_buf,
...@@ -1678,7 +1688,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6...@@ -1678,7 +1688,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
1678 },1688 },
1679 .wasm => {1689 .wasm => {
1680 const wasm_file = file.cast(File.Wasm).?;1690 const wasm_file = file.cast(File.Wasm).?;
1681 writeDbgInfoNopsBuffered(wasm_file.debug_info.items, 0, 0, di_buf.items, jmp_amt, false);1691 try writeDbgInfoNopsToArrayList(self.allocator, &wasm_file.debug_info, 0, 0, di_buf.items, jmp_amt, false);
1682 },1692 },
1683 else => unreachable,1693 else => unreachable,
1684 }1694 }
...@@ -1884,35 +1894,25 @@ fn pwriteDbgInfoNops(...@@ -1884,35 +1894,25 @@ fn pwriteDbgInfoNops(
1884 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);1894 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
1885}1895}
18861896
1887fn writeDbgInfoNopsBuffered(1897fn writeDbgInfoNopsToArrayList(
1888 buf: []u8,1898 gpa: Allocator,
1899 buffer: *std.ArrayListUnmanaged(u8),
1889 offset: u32,1900 offset: u32,
1890 prev_padding_size: usize,1901 prev_padding_size: usize,
1891 content: []const u8,1902 content: []const u8,
1892 next_padding_size: usize,1903 next_padding_size: usize,
1893 trailing_zero: bool,1904 trailing_zero: bool,
1894) void {1905) Allocator.Error!void {
1895 assert(buf.len >= content.len + prev_padding_size + next_padding_size + @boolToInt(trailing_zero));1906 try buffer.resize(gpa, @maximum(
1896 const tracy = trace(@src());1907 buffer.items.len,
1897 defer tracy.end();1908 offset + content.len + next_padding_size + 1,
18981909 ));
1899 {1910 mem.set(u8, buffer.items[offset - prev_padding_size .. offset], @enumToInt(AbbrevKind.pad1));
1900 var padding_left = prev_padding_size;1911 mem.copy(u8, buffer.items[offset..], content);
1901 while (padding_left > 0) : (padding_left -= 1) {1912 mem.set(u8, buffer.items[offset + content.len ..][0..next_padding_size], @enumToInt(AbbrevKind.pad1));
1902 buf[offset - padding_left] = @enumToInt(AbbrevKind.pad1);
1903 }
1904 }
1905
1906 mem.copy(u8, buf[offset..], content);
1907 {
1908 var padding_left = next_padding_size;
1909 while (padding_left > 0) : (padding_left -= 1) {
1910 buf[offset + content.len + padding_left] = @enumToInt(AbbrevKind.pad1);
1911 }
1912 }
19131913
1914 if (trailing_zero) {1914 if (trailing_zero) {
1915 buf[offset + content.len + next_padding_size] = 0;1915 buffer.items[offset + content.len + next_padding_size] = 0;
1916 }1916 }
1917}1917}
19181918
...@@ -2249,7 +2249,9 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {...@@ -2249,7 +2249,9 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
2249 try addDbgInfoErrorSet(arena, module, error_ty, self.target, &dbg_info_buffer);2249 try addDbgInfoErrorSet(arena, module, error_ty, self.target, &dbg_info_buffer);
22502250
2251 try self.managed_atoms.append(gpa, atom);2251 try self.managed_atoms.append(gpa, atom);
2252 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
2252 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));2253 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
2254 log.debug("writeDeclDebugInfo in flushModule", .{});
2253 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);2255 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
22542256
2255 const file_pos = blk: {2257 const file_pos = blk: {
src/type.zig+53-60
...@@ -2365,6 +2365,7 @@ pub const Type = extern union {...@@ -2365,6 +2365,7 @@ pub const Type = extern union {
2365 .@"anyframe",2365 .@"anyframe",
2366 .anyopaque,2366 .anyopaque,
2367 .@"opaque",2367 .@"opaque",
2368 .type_info,
2368 => return true,2369 => return true,
23692370
2370 // These are false because they are comptime-only types.2371 // These are false because they are comptime-only types.
...@@ -2379,7 +2380,6 @@ pub const Type = extern union {...@@ -2379,7 +2380,6 @@ pub const Type = extern union {
2379 .enum_literal,2380 .enum_literal,
2380 .empty_struct,2381 .empty_struct,
2381 .empty_struct_literal,2382 .empty_struct_literal,
2382 .type_info,
2383 .bound_fn,2383 .bound_fn,
2384 // These are function *bodies*, not pointers.2384 // These are function *bodies*, not pointers.
2385 // Special exceptions have to be made when emitting functions due to2385 // Special exceptions have to be made when emitting functions due to
...@@ -2464,14 +2464,6 @@ pub const Type = extern union {...@@ -2464,14 +2464,6 @@ pub const Type = extern union {
24642464
2465 .@"struct" => {2465 .@"struct" => {
2466 const struct_obj = ty.castTag(.@"struct").?.data;2466 const struct_obj = ty.castTag(.@"struct").?.data;
2467 if (sema_kit) |sk| {
2468 _ = try sk.sema.typeRequiresComptime(sk.block, sk.src, ty);
2469 }
2470 switch (struct_obj.requires_comptime) {
2471 .yes => return false,
2472 .wip, .no => if (struct_obj.known_non_opv) return true,
2473 .unknown => {},
2474 }
2475 if (struct_obj.status == .field_types_wip) {2467 if (struct_obj.status == .field_types_wip) {
2476 // In this case, we guess that hasRuntimeBits() for this type is true,2468 // In this case, we guess that hasRuntimeBits() for this type is true,
2477 // and then later if our guess was incorrect, we emit a compile error.2469 // and then later if our guess was incorrect, we emit a compile error.
...@@ -3550,9 +3542,19 @@ pub const Type = extern union {...@@ -3550,9 +3542,19 @@ pub const Type = extern union {
3550 );3542 );
3551 }3543 }
35523544
3553 /// Asserts the type has the bit size already resolved.
3554 pub fn bitSize(ty: Type, target: Target) u64 {3545 pub fn bitSize(ty: Type, target: Target) u64 {
3555 return switch (ty.tag()) {3546 return bitSizeAdvanced(ty, target, null) catch unreachable;
3547 }
3548
3549 /// If you pass `sema_kit`, any recursive type resolutions will happen if
3550 /// necessary, possibly returning a CompileError. Passing `null` instead asserts
3551 /// the type is fully resolved, and there will be no error, guaranteed.
3552 pub fn bitSizeAdvanced(
3553 ty: Type,
3554 target: Target,
3555 sema_kit: ?Module.WipAnalysis,
3556 ) Module.CompileError!u64 {
3557 switch (ty.tag()) {
3556 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer3558 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
3557 .fn_void_no_args => unreachable, // represents machine code; not a pointer3559 .fn_void_no_args => unreachable, // represents machine code; not a pointer
3558 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer3560 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
...@@ -3576,40 +3578,30 @@ pub const Type = extern union {...@@ -3576,40 +3578,30 @@ pub const Type = extern union {
3576 .generic_poison => unreachable,3578 .generic_poison => unreachable,
3577 .bound_fn => unreachable,3579 .bound_fn => unreachable,
35783580
3579 .void => 0,3581 .void => return 0,
3580 .bool, .u1 => 1,3582 .bool, .u1 => return 1,
3581 .u8, .i8 => 8,3583 .u8, .i8 => return 8,
3582 .i16, .u16, .f16 => 16,3584 .i16, .u16, .f16 => return 16,
3583 .u29 => 29,3585 .u29 => return 29,
3584 .i32, .u32, .f32 => 32,3586 .i32, .u32, .f32 => return 32,
3585 .i64, .u64, .f64 => 64,3587 .i64, .u64, .f64 => return 64,
3586 .f80 => 80,3588 .f80 => return 80,
3587 .u128, .i128, .f128 => 128,3589 .u128, .i128, .f128 => return 128,
35883590
3589 .@"struct" => {3591 .@"struct" => {
3590 const field_count = ty.structFieldCount();3592 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3591 if (field_count == 0) return 0;3593 var total: u64 = 0;
35923594 for (ty.structFields().values()) |field| {
3593 const struct_obj = ty.castTag(.@"struct").?.data;3595 total += try bitSizeAdvanced(field.ty, target, sema_kit);
3594 assert(struct_obj.haveFieldTypes());
3595
3596 switch (struct_obj.layout) {
3597 .Auto, .Extern => {
3598 var total: u64 = 0;
3599 for (struct_obj.fields.values()) |field| {
3600 total += field.ty.bitSize(target);
3601 }
3602 return total;
3603 },
3604 .Packed => return struct_obj.packedIntegerBits(target),
3605 }3596 }
3597 return total;
3606 },3598 },
36073599
3608 .tuple, .anon_struct => {3600 .tuple, .anon_struct => {
3609 const tuple = ty.tupleFields();3601 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3610 var total: u64 = 0;3602 var total: u64 = 0;
3611 for (tuple.types) |field_ty| {3603 for (ty.tupleFields().types) |field_ty| {
3612 total += field_ty.bitSize(target);3604 total += try bitSizeAdvanced(field_ty, target, sema_kit);
3613 }3605 }
3614 return total;3606 return total;
3615 },3607 },
...@@ -3617,37 +3609,35 @@ pub const Type = extern union {...@@ -3617,37 +3609,35 @@ pub const Type = extern union {
3617 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {3609 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
3618 var buffer: Payload.Bits = undefined;3610 var buffer: Payload.Bits = undefined;
3619 const int_tag_ty = ty.intTagType(&buffer);3611 const int_tag_ty = ty.intTagType(&buffer);
3620 return int_tag_ty.bitSize(target);3612 return try bitSizeAdvanced(int_tag_ty, target, sema_kit);
3621 },3613 },
36223614
3623 .@"union", .union_tagged => {3615 .@"union", .union_tagged => {
3616 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3624 const union_obj = ty.cast(Payload.Union).?.data;3617 const union_obj = ty.cast(Payload.Union).?.data;
3625
3626 const fields = union_obj.fields;
3627 if (fields.count() == 0) return 0;
3628
3629 assert(union_obj.haveFieldTypes());3618 assert(union_obj.haveFieldTypes());
36303619
3631 var size: u64 = 0;3620 var size: u64 = 0;
3632 for (fields.values()) |field| {3621 for (union_obj.fields.values()) |field| {
3633 size = @maximum(size, field.ty.bitSize(target));3622 size = @maximum(size, try bitSizeAdvanced(field.ty, target, sema_kit));
3634 }3623 }
3635 return size;3624 return size;
3636 },3625 },
36373626
3638 .vector => {3627 .vector => {
3639 const payload = ty.castTag(.vector).?.data;3628 const payload = ty.castTag(.vector).?.data;
3640 const elem_bit_size = payload.elem_type.bitSize(target);3629 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, sema_kit);
3641 return elem_bit_size * payload.len;3630 return elem_bit_size * payload.len;
3642 },3631 },
3643 .array_u8 => 8 * ty.castTag(.array_u8).?.data,3632 .array_u8 => return 8 * ty.castTag(.array_u8).?.data,
3644 .array_u8_sentinel_0 => 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1),3633 .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1),
3645 .array => {3634 .array => {
3646 const payload = ty.castTag(.array).?.data;3635 const payload = ty.castTag(.array).?.data;
3647 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));3636 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
3648 if (elem_size == 0 or payload.len == 0)3637 if (elem_size == 0 or payload.len == 0)
3649 return 0;3638 return @as(u64, 0);
3650 return (payload.len - 1) * 8 * elem_size + payload.elem_type.bitSize(target);3639 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, sema_kit);
3640 return (payload.len - 1) * 8 * elem_size + elem_bit_size;
3651 },3641 },
3652 .array_sentinel => {3642 .array_sentinel => {
3653 const payload = ty.castTag(.array_sentinel).?.data;3643 const payload = ty.castTag(.array_sentinel).?.data;
...@@ -3655,14 +3645,15 @@ pub const Type = extern union {...@@ -3655,14 +3645,15 @@ pub const Type = extern union {
3655 payload.elem_type.abiAlignment(target),3645 payload.elem_type.abiAlignment(target),
3656 payload.elem_type.abiSize(target),3646 payload.elem_type.abiSize(target),
3657 );3647 );
3658 return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);3648 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, sema_kit);
3649 return payload.len * 8 * elem_size + elem_bit_size;
3659 },3650 },
36603651
3661 .isize,3652 .isize,
3662 .usize,3653 .usize,
3663 .@"anyframe",3654 .@"anyframe",
3664 .anyframe_T,3655 .anyframe_T,
3665 => target.cpu.arch.ptrBitWidth(),3656 => return target.cpu.arch.ptrBitWidth(),
36663657
3667 .const_slice,3658 .const_slice,
3668 .mut_slice,3659 .mut_slice,
...@@ -3670,7 +3661,7 @@ pub const Type = extern union {...@@ -3670,7 +3661,7 @@ pub const Type = extern union {
36703661
3671 .const_slice_u8,3662 .const_slice_u8,
3672 .const_slice_u8_sentinel_0,3663 .const_slice_u8_sentinel_0,
3673 => target.cpu.arch.ptrBitWidth() * 2,3664 => return target.cpu.arch.ptrBitWidth() * 2,
36743665
3675 .optional_single_const_pointer,3666 .optional_single_const_pointer,
3676 .optional_single_mut_pointer,3667 .optional_single_mut_pointer,
...@@ -3689,8 +3680,8 @@ pub const Type = extern union {...@@ -3689,8 +3680,8 @@ pub const Type = extern union {
3689 },3680 },
36903681
3691 .pointer => switch (ty.castTag(.pointer).?.data.size) {3682 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3692 .Slice => target.cpu.arch.ptrBitWidth() * 2,3683 .Slice => return target.cpu.arch.ptrBitWidth() * 2,
3693 else => target.cpu.arch.ptrBitWidth(),3684 else => return target.cpu.arch.ptrBitWidth(),
3694 },3685 },
36953686
3696 .manyptr_u8,3687 .manyptr_u8,
...@@ -3716,7 +3707,7 @@ pub const Type = extern union {...@@ -3716,7 +3707,7 @@ pub const Type = extern union {
3716 .error_set_merged,3707 .error_set_merged,
3717 => return 16, // TODO revisit this when we have the concept of the error tag type3708 => return 16, // TODO revisit this when we have the concept of the error tag type
37183709
3719 .int_signed, .int_unsigned => ty.cast(Payload.Bits).?.data,3710 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data,
37203711
3721 .optional => {3712 .optional => {
3722 var buf: Payload.ElemType = undefined;3713 var buf: Payload.ElemType = undefined;
...@@ -3730,7 +3721,8 @@ pub const Type = extern union {...@@ -3730,7 +3721,8 @@ pub const Type = extern union {
3730 // field and a boolean as the second. Since the child type's abi alignment is3721 // field and a boolean as the second. Since the child type's abi alignment is
3731 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal3722 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
3732 // to the child type's ABI alignment.3723 // to the child type's ABI alignment.
3733 return child_type.bitSize(target) + 1;3724 const child_bit_size = try bitSizeAdvanced(child_type, target, sema_kit);
3725 return child_bit_size + 1;
3734 },3726 },
37353727
3736 .error_union => {3728 .error_union => {
...@@ -3738,9 +3730,9 @@ pub const Type = extern union {...@@ -3738,9 +3730,9 @@ pub const Type = extern union {
3738 if (!payload.error_set.hasRuntimeBits() and !payload.payload.hasRuntimeBits()) {3730 if (!payload.error_set.hasRuntimeBits() and !payload.payload.hasRuntimeBits()) {
3739 return 0;3731 return 0;
3740 } else if (!payload.error_set.hasRuntimeBits()) {3732 } else if (!payload.error_set.hasRuntimeBits()) {
3741 return payload.payload.bitSize(target);3733 return payload.payload.bitSizeAdvanced(target, sema_kit);
3742 } else if (!payload.payload.hasRuntimeBits()) {3734 } else if (!payload.payload.hasRuntimeBits()) {
3743 return payload.error_set.bitSize(target);3735 return payload.error_set.bitSizeAdvanced(target, sema_kit);
3744 }3736 }
3745 @panic("TODO bitSize error union");3737 @panic("TODO bitSize error union");
3746 },3738 },
...@@ -3757,7 +3749,7 @@ pub const Type = extern union {...@@ -3757,7 +3749,7 @@ pub const Type = extern union {
3757 .extern_options,3749 .extern_options,
3758 .type_info,3750 .type_info,
3759 => @panic("TODO at some point we gotta resolve builtin types"),3751 => @panic("TODO at some point we gotta resolve builtin types"),
3760 };3752 }
3761 }3753 }
37623754
3763 pub fn isSinglePointer(self: Type) bool {3755 pub fn isSinglePointer(self: Type) bool {
...@@ -5514,6 +5506,7 @@ pub const Type = extern union {...@@ -5514,6 +5506,7 @@ pub const Type = extern union {
5514 switch (ty.tag()) {5506 switch (ty.tag()) {
5515 .@"struct" => {5507 .@"struct" => {
5516 const struct_obj = ty.castTag(.@"struct").?.data;5508 const struct_obj = ty.castTag(.@"struct").?.data;
5509 assert(struct_obj.haveFieldTypes());
5517 return struct_obj.fields.count();5510 return struct_obj.fields.count();
5518 },5511 },
5519 .empty_struct, .empty_struct_literal => return 0,5512 .empty_struct, .empty_struct_literal => return 0,
test/behavior/eval.zig+32-1
...@@ -1196,7 +1196,9 @@ test "equality of pointers to comptime const" {...@@ -1196,7 +1196,9 @@ test "equality of pointers to comptime const" {
1196}1196}
11971197
1198test "storing an array of type in a field" {1198test "storing an array of type in a field" {
1199 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1199 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12001202
1201 const S = struct {1203 const S = struct {
1202 fn doTheTest() void {1204 fn doTheTest() void {
...@@ -1221,3 +1223,32 @@ test "storing an array of type in a field" {...@@ -1221,3 +1223,32 @@ test "storing an array of type in a field" {
12211223
1222 S.doTheTest();1224 S.doTheTest();
1223}1225}
1226
1227test "pass pointer to field of comptime-only type as a runtime parameter" {
1228 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1230 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1231
1232 const S = struct {
1233 const Mixed = struct {
1234 T: type,
1235 x: i32,
1236 };
1237 const bag: Mixed = .{
1238 .T = bool,
1239 .x = 1234,
1240 };
1241
1242 var ok = false;
1243
1244 fn doTheTest() !void {
1245 foo(&bag.x);
1246 try expect(ok);
1247 }
1248
1249 fn foo(ptr: *const i32) void {
1250 ok = ptr.* == 1234;
1251 }
1252 };
1253 try S.doTheTest();
1254}
test/behavior/packed-struct.zig+33-23
...@@ -33,10 +33,10 @@ test "correct size of packed structs" {...@@ -33,10 +33,10 @@ test "correct size of packed structs" {
33}33}
3434
35test "flags in packed structs" {35test "flags in packed structs" {
36 if (builtin.zig_backend != .stage1) return error.SkipZigTest;36 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
3737
38 const Flags1 = packed struct {38 const Flags1 = packed struct {
39 // byte 039 // first 8 bits
40 b0_0: u1,40 b0_0: u1,
41 b0_1: u1,41 b0_1: u1,
42 b0_2: u1,42 b0_2: u1,
...@@ -46,7 +46,7 @@ test "flags in packed structs" {...@@ -46,7 +46,7 @@ test "flags in packed structs" {
46 b0_6: u1,46 b0_6: u1,
47 b0_7: u1,47 b0_7: u1,
4848
49 // partial byte 1 (but not 8 bits)49 // 7 more bits
50 b1_0: u1,50 b1_0: u1,
51 b1_1: u1,51 b1_1: u1,
52 b1_2: u1,52 b1_2: u1,
...@@ -55,12 +55,12 @@ test "flags in packed structs" {...@@ -55,12 +55,12 @@ test "flags in packed structs" {
55 b1_5: u1,55 b1_5: u1,
56 b1_6: u1,56 b1_6: u1,
5757
58 // some padding to fill to size 358 // some padding to fill to 24 bits
59 _: u9,59 _: u9,
60 };60 };
6161
62 try expectEqual(3, @sizeOf(Flags1));62 try expectEqual(@sizeOf(u24), @sizeOf(Flags1));
63 try expectEqual(3 * 8, @bitSizeOf(Flags1));63 try expectEqual(24, @bitSizeOf(Flags1));
6464
65 const Flags2 = packed struct {65 const Flags2 = packed struct {
66 // byte 066 // byte 0
...@@ -86,8 +86,8 @@ test "flags in packed structs" {...@@ -86,8 +86,8 @@ test "flags in packed structs" {
86 _: u10,86 _: u10,
87 };87 };
8888
89 try expectEqual(4, @sizeOf(Flags2));89 try expectEqual(@sizeOf(u25), @sizeOf(Flags2));
90 try expectEqual(8 + 7 + 10, @bitSizeOf(Flags2));90 try expectEqual(25, @bitSizeOf(Flags2));
9191
92 const Flags3 = packed struct {92 const Flags3 = packed struct {
93 // byte 093 // byte 0
...@@ -114,30 +114,30 @@ test "flags in packed structs" {...@@ -114,30 +114,30 @@ test "flags in packed structs" {
114 _: u16, // it works, if the padding is 8-based114 _: u16, // it works, if the padding is 8-based
115 };115 };
116116
117 try expectEqual(4, @sizeOf(Flags3));117 try expectEqual(@sizeOf(u32), @sizeOf(Flags3));
118 try expectEqual(4 * 8, @bitSizeOf(Flags3));118 try expectEqual(32, @bitSizeOf(Flags3));
119}119}
120120
121test "arrays in packed structs" {121test "arrays in packed structs" {
122 if (builtin.zig_backend != .stage1) return error.SkipZigTest;122 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
123123
124 const T1 = packed struct { array: [3][3]u8 };124 const T1 = packed struct { array: [3][3]u8 };
125 const T2 = packed struct { array: [9]u8 };125 const T2 = packed struct { array: [9]u8 };
126126
127 try expectEqual(9, @sizeOf(T1));127 try expectEqual(@sizeOf(u72), @sizeOf(T1));
128 try expectEqual(9 * 8, @bitSizeOf(T1));128 try expectEqual(72, @bitSizeOf(T1));
129 try expectEqual(9, @sizeOf(T2));129 try expectEqual(@sizeOf(u72), @sizeOf(T2));
130 try expectEqual(9 * 8, @bitSizeOf(T2));130 try expectEqual(72, @bitSizeOf(T2));
131}131}
132132
133test "consistent size of packed structs" {133test "consistent size of packed structs" {
134 if (builtin.zig_backend != .stage1) return error.SkipZigTest;134 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
135135
136 const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };136 const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };
137 const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };137 const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };
138138
139 const register_size_bits = 32;139 const register_size_bits = 32;
140 const register_size_bytes = register_size_bits / 8;140 const register_size_bytes = @sizeOf(u32);
141141
142 try expectEqual(register_size_bits, @bitSizeOf(TxData1));142 try expectEqual(register_size_bits, @bitSizeOf(TxData1));
143 try expectEqual(register_size_bytes, @sizeOf(TxData1));143 try expectEqual(register_size_bytes, @sizeOf(TxData1));
...@@ -151,7 +151,7 @@ test "consistent size of packed structs" {...@@ -151,7 +151,7 @@ test "consistent size of packed structs" {
151 const TxData6 = packed struct { a: u24, b: u32 };151 const TxData6 = packed struct { a: u24, b: u32 };
152152
153 const expectedBitSize = 56;153 const expectedBitSize = 56;
154 const expectedByteSize = expectedBitSize / 8;154 const expectedByteSize = @sizeOf(u56);
155155
156 try expectEqual(expectedBitSize, @bitSizeOf(TxData3));156 try expectEqual(expectedBitSize, @bitSizeOf(TxData3));
157 try expectEqual(expectedByteSize, @sizeOf(TxData3));157 try expectEqual(expectedByteSize, @sizeOf(TxData3));
...@@ -167,7 +167,12 @@ test "consistent size of packed structs" {...@@ -167,7 +167,12 @@ test "consistent size of packed structs" {
167}167}
168168
169test "correct sizeOf and offsets in packed structs" {169test "correct sizeOf and offsets in packed structs" {
170 if (builtin.zig_backend != .stage1) return error.SkipZigTest;170 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
172 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
173 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
175 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
171176
172 const PStruct = packed struct {177 const PStruct = packed struct {
173 bool_a: bool,178 bool_a: bool,
...@@ -234,11 +239,16 @@ test "correct sizeOf and offsets in packed structs" {...@@ -234,11 +239,16 @@ test "correct sizeOf and offsets in packed structs" {
234239
235 try expectEqual(16, @offsetOf(S, "b"));240 try expectEqual(16, @offsetOf(S, "b"));
236 try expectEqual(128, @bitOffsetOf(S, "b"));241 try expectEqual(128, @bitOffsetOf(S, "b"));
237 try expectEqual(20, @sizeOf(S));242 try expectEqual(@sizeOf(u160), @sizeOf(S));
238}243}
239244
240test "nested packed structs" {245test "nested packed structs" {
241 if (builtin.zig_backend != .stage1) return error.SkipZigTest;246 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
247 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242252
243 const S1 = packed struct { a: u8, b: u8, c: u8 };253 const S1 = packed struct { a: u8, b: u8, c: u8 };
244254
...@@ -248,7 +258,7 @@ test "nested packed structs" {...@@ -248,7 +258,7 @@ test "nested packed structs" {
248 const S3Padded = packed struct { s3: S3, pad: u16 };258 const S3Padded = packed struct { s3: S3, pad: u16 };
249259
250 try expectEqual(48, @bitSizeOf(S3));260 try expectEqual(48, @bitSizeOf(S3));
251 try expectEqual(6, @sizeOf(S3));261 try expectEqual(@sizeOf(u48), @sizeOf(S3));
252262
253 try expectEqual(3, @offsetOf(S3, "y"));263 try expectEqual(3, @offsetOf(S3, "y"));
254 try expectEqual(24, @bitOffsetOf(S3, "y"));264 try expectEqual(24, @bitOffsetOf(S3, "y"));
...@@ -268,7 +278,7 @@ test "nested packed structs" {...@@ -268,7 +278,7 @@ test "nested packed structs" {
268 const S6 = packed struct { a: i32, b: S4, c: i8 };278 const S6 = packed struct { a: i32, b: S4, c: i8 };
269279
270 const expectedBitSize = 80;280 const expectedBitSize = 80;
271 const expectedByteSize = expectedBitSize / 8;281 const expectedByteSize = @sizeOf(u80);
272 try expectEqual(expectedBitSize, @bitSizeOf(S5));282 try expectEqual(expectedBitSize, @bitSizeOf(S5));
273 try expectEqual(expectedByteSize, @sizeOf(S5));283 try expectEqual(expectedByteSize, @sizeOf(S5));
274 try expectEqual(expectedBitSize, @bitSizeOf(S6));284 try expectEqual(expectedBitSize, @bitSizeOf(S6));