| author | |
| committer | |
| log | c1eb6c30e84b0b161b634f7410088f44c80caa90 |
| tree | 915141c29947e320175cd2c5ed73afaa88ddf259 |
| parent | 9b05474d797ea4600dbae36ae95d9eb042040bb2 |
| parent | 6bf529dc381cb2f5a83c5f9e303ffdab7779ac4d |
| signature |
stage2: fix handling of aggregates with mixed comptime-only fields6 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. |
| 11747 | 11747 | ||
| 11748 | fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 11748 | fn 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 | } |
| 11757 | 11757 | ||
| ... | @@ -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 | } |
| 25048 | 25048 | ||
| 25049 | pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { | 25049 | pub 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 | } |
| 25054 | 25052 | ||
| 25055 | fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 { | 25053 | fn 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, |
| 9187 | 9187 | ||
| 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; |
| 9208 | 9208 | ||
| 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.member | 356 | // 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 | } |
| 1039 | 1040 | ||
| 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)); |
| 1041 | 1043 | ||
| 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 | } |
| 1100 | 1102 | ||
| 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 | } |
| 1103 | 1106 | ||
| ... | @@ -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 | } |
| 1886 | 1896 | ||
| 1887 | fn writeDbgInfoNopsBuffered( | 1897 | fn 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, |
| 1898 | 1909 | )); | |
| 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 | } | ||
| 1913 | 1913 | ||
| 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 | } |
| 1918 | 1918 | ||
| ... | @@ -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); |
| 2250 | 2250 | ||
| 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); |
| 2254 | 2256 | ||
| 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, |
| 2369 | 2370 | ||
| 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 to | 2385 | // 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 { |
| 2464 | 2464 | ||
| 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 | } |
| 3552 | 3544 | ||
| 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 pointer | 3558 | .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer |
| 3557 | .fn_void_no_args => unreachable, // represents machine code; not a pointer | 3559 | .fn_void_no_args => unreachable, // represents machine code; not a pointer |
| 3558 | .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer | 3560 | .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, |
| 3578 | 3580 | ||
| 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, |
| 3588 | 3590 | ||
| 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; |
| 3592 | 3594 | 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 | }, |
| 3607 | 3599 | ||
| 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 | }, |
| 3622 | 3614 | ||
| 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()); |
| 3630 | 3619 | ||
| 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 | }, |
| 3637 | 3626 | ||
| 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 | }, |
| 3660 | 3651 | ||
| 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(), |
| 3666 | 3657 | ||
| 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 { |
| 3670 | 3661 | ||
| 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, |
| 3674 | 3665 | ||
| 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 | }, |
| 3690 | 3681 | ||
| 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 | }, |
| 3695 | 3686 | ||
| 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 type | 3708 | => return 16, // TODO revisit this when we have the concept of the error tag type |
| 3718 | 3709 | ||
| 3719 | .int_signed, .int_unsigned => ty.cast(Payload.Bits).?.data, | 3710 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data, |
| 3720 | 3711 | ||
| 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 is | 3721 | // 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 equal | 3722 | // 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 | }, |
| 3735 | 3727 | ||
| 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 | } |
| 3762 | 3754 | ||
| 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 | } |
| 1197 | 1197 | ||
| 1198 | test "storing an array of type in a field" { | 1198 | test "storing an array of type in a field" { |
| 1199 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | 1199 | 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 | ||
| 1200 | 1202 | ||
| 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" { |
| 1221 | 1223 | ||
| 1222 | S.doTheTest(); | 1224 | S.doTheTest(); |
| 1223 | } | 1225 | } |
| 1226 | |||
| 1227 | test "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 | } |
| 34 | 34 | ||
| 35 | test "flags in packed structs" { | 35 | test "flags in packed structs" { |
| 36 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | 36 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 37 | 37 | ||
| 38 | const Flags1 = packed struct { | 38 | const Flags1 = packed struct { |
| 39 | // byte 0 | 39 | // 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, |
| 48 | 48 | ||
| 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, |
| 57 | 57 | ||
| 58 | // some padding to fill to size 3 | 58 | // some padding to fill to 24 bits |
| 59 | _: u9, | 59 | _: u9, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 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)); |
| 64 | 64 | ||
| 65 | const Flags2 = packed struct { | 65 | const Flags2 = packed struct { |
| 66 | // byte 0 | 66 | // 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 | }; |
| 88 | 88 | ||
| 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)); |
| 91 | 91 | ||
| 92 | const Flags3 = packed struct { | 92 | const Flags3 = packed struct { |
| 93 | // byte 0 | 93 | // 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-based | 114 | _: u16, // it works, if the padding is 8-based |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 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 | } |
| 120 | 120 | ||
| 121 | test "arrays in packed structs" { | 121 | test "arrays in packed structs" { |
| 122 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | 122 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 123 | 123 | ||
| 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 }; |
| 126 | 126 | ||
| 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 | } |
| 132 | 132 | ||
| 133 | test "consistent size of packed structs" { | 133 | test "consistent size of packed structs" { |
| 134 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; | 134 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 135 | 135 | ||
| 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 }; |
| 138 | 138 | ||
| 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); |
| 141 | 141 | ||
| 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 }; |
| 152 | 152 | ||
| 153 | const expectedBitSize = 56; | 153 | const expectedBitSize = 56; |
| 154 | const expectedByteSize = expectedBitSize / 8; | 154 | const expectedByteSize = @sizeOf(u56); |
| 155 | 155 | ||
| 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 | } |
| 168 | 168 | ||
| 169 | test "correct sizeOf and offsets in packed structs" { | 169 | test "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 | ||
| 171 | 176 | ||
| 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" { |
| 234 | 239 | ||
| 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 | } |
| 239 | 244 | ||
| 240 | test "nested packed structs" { | 245 | test "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 | ||
| 242 | 252 | ||
| 243 | const S1 = packed struct { a: u8, b: u8, c: u8 }; | 253 | const S1 = packed struct { a: u8, b: u8, c: u8 }; |
| 244 | 254 | ||
| ... | @@ -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 }; |
| 249 | 259 | ||
| 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)); |
| 252 | 262 | ||
| 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 }; |
| 269 | 279 | ||
| 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)); |