@@ -9701,7 +9701,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
97019701fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
97029702 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
97039703 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9704- const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
9704+ const unresolved_operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
9705+ const operand_ty = try sema.resolveTypeFields(block, operand_src, unresolved_operand_ty);
97059706 const target = sema.mod.getTarget();
97069707 const bit_size = operand_ty.bitSize(target);
97079708 return sema.addIntUnsigned(Type.initTag(.comptime_int), bit_size);
@@ -9891,6 +9892,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
98919892 .Fn => {
98929893 // TODO: look into memoizing this result.
98939894 const info = ty.fnInfo();
9895+
98949896 var params_anon_decl = try block.startAnonDecl(src);
98959897 defer params_anon_decl.deinit();
98969898
@@ -9948,19 +9950,24 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
99489950 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
99499951 };
99509952
9951- const field_values = try sema.arena.alloc(Value, 6);
9952- // calling_convention: CallingConvention,
9953- field_values[0] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc));
9954- // alignment: comptime_int,
9955- field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target));
9956- // is_generic: bool,
9957- field_values[2] = Value.makeBool(info.is_generic);
9958- // is_var_args: bool,
9959- field_values[3] = Value.makeBool(info.is_var_args);
9960- // return_type: ?type,
9961- field_values[4] = try Value.Tag.ty.create(sema.arena, info.return_type);
9962- // args: []const Fn.Param,
9963- field_values[5] = args_val;
9953+ const field_values = try sema.arena.create([6]Value);
9954+ field_values.* = .{
9955+ // calling_convention: CallingConvention,
9956+ try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc)),
9957+ // alignment: comptime_int,
9958+ try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target)),
9959+ // is_generic: bool,
9960+ Value.makeBool(info.is_generic),
9961+ // is_var_args: bool,
9962+ Value.makeBool(info.is_var_args),
9963+ // return_type: ?type,
9964+ try Value.Tag.opt_payload.create(
9965+ sema.arena,
9966+ try Value.Tag.ty.create(sema.arena, info.return_type),
9967+ ),
9968+ // args: []const Fn.Param,
9969+ args_val,
9970+ };
99649971
99659972 return sema.addConstant(
99669973 type_info_ty,
@@ -10007,25 +10014,27 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1000710014 const alignment = if (info.@"align" != 0)
1000810015 info.@"align"
1000910016 else
10010- info.pointee_type.abiAlignment(target);
10011-
10012- const field_values = try sema.arena.alloc(Value, 8);
10013- // size: Size,
10014- field_values[0] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.size));
10015- // is_const: bool,
10016- field_values[1] = Value.makeBool(!info.mutable);
10017- // is_volatile: bool,
10018- field_values[2] = Value.makeBool(info.@"volatile");
10019- // alignment: comptime_int,
10020- field_values[3] = try Value.Tag.int_u64.create(sema.arena, alignment);
10021- // address_space: AddressSpace
10022- field_values[4] = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.@"addrspace"));
10023- // child: type,
10024- field_values[5] = try Value.Tag.ty.create(sema.arena, info.pointee_type);
10025- // is_allowzero: bool,
10026- field_values[6] = Value.makeBool(info.@"allowzero");
10027- // sentinel: ?*const anyopaque,
10028- field_values[7] = try sema.optRefValue(block, src, info.pointee_type, info.sentinel);
10017+ try sema.typeAbiAlignment(block, src, info.pointee_type);
10018+
10019+ const field_values = try sema.arena.create([8]Value);
10020+ field_values.* = .{
10021+ // size: Size,
10022+ try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.size)),
10023+ // is_const: bool,
10024+ Value.makeBool(!info.mutable),
10025+ // is_volatile: bool,
10026+ Value.makeBool(info.@"volatile"),
10027+ // alignment: comptime_int,
10028+ try Value.Tag.int_u64.create(sema.arena, alignment),
10029+ // address_space: AddressSpace
10030+ try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.@"addrspace")),
10031+ // child: type,
10032+ try Value.Tag.ty.create(sema.arena, info.pointee_type),
10033+ // is_allowzero: bool,
10034+ Value.makeBool(info.@"allowzero"),
10035+ // sentinel: ?*const anyopaque,
10036+ try sema.optRefValue(block, src, info.pointee_type, info.sentinel),
10037+ };
1002910038
1003010039 return sema.addConstant(
1003110040 type_info_ty,
@@ -10377,7 +10386,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1037710386 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
1037810387 const alignment = switch (layout) {
1037910388 .Auto, .Extern => field.normalAlignment(target),
10380- .Packed => field.packedAlignment() ,
10389+ .Packed => 0 ,
1038110390 };
1038210391
1038310392 struct_field_fields.* = .{
@@ -12120,6 +12129,7 @@ fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1212012129
1212112130fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1212212131 const offset = try bitOffsetOf(sema, block, inst);
12132+ // TODO reminder to make this a compile error for packed structs
1212312133 return sema.addIntUnsigned(Type.comptime_int, offset / 8);
1212412134}
1212512135
@@ -12143,7 +12153,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
1214312153 );
1214412154 }
1214512155
12146- const index = ty.structFields().getIndex(field_name) orelse {
12156+ const fields = ty.structFields();
12157+ const index = fields.getIndex(field_name) orelse {
1214712158 return sema.fail(
1214812159 block,
1214912160 rhs_src,
@@ -12153,24 +12164,25 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
1215312164 };
1215412165
1215512166 const target = sema.mod.getTarget();
12156- const layout = ty.containerLayout();
12157- if (layout == .Packed) {
12158- var it = ty.iteratePackedStructOffsets(target);
12159- while (it.next()) |field_offset| {
12160- if (field_offset.field == index) {
12161- return (field_offset.offset * 8) + field_offset.running_bits;
12162- }
12163- }
12164- } else {
12165- var it = ty.iterateStructOffsets(target);
12166- while (it.next()) |field_offset| {
12167- if (field_offset.field == index) {
12168- return field_offset.offset * 8;
12169- }
12170- }
12167+ switch (ty.containerLayout()) {
12168+ .Packed => {
12169+ var bit_sum: u64 = 0;
12170+ for (fields.values()) |field, i| {
12171+ if (i == index) {
12172+ return bit_sum;
12173+ }
12174+ bit_sum += field.ty.bitSize(target);
12175+ } else unreachable;
12176+ },
12177+ else => {
12178+ var it = ty.iterateStructOffsets(target);
12179+ while (it.next()) |field_offset| {
12180+ if (field_offset.field == index) {
12181+ return field_offset.offset * 8;
12182+ }
12183+ } else unreachable;
12184+ },
1217112185 }
12172-
12173- unreachable;
1217412186}
1217512187
1217612188/// Returns `true` if the type was a comptime_int.
@@ -14199,61 +14211,44 @@ fn structFieldPtrByIndex(
1419914211 field_src: LazySrcLoc,
1420014212) CompileError!Air.Inst.Ref {
1420114213 const field = struct_obj.fields.values()[field_index];
14202-
1420314214 const struct_ptr_ty = sema.typeOf(struct_ptr);
14215+ const struct_ptr_ty_info = struct_ptr_ty.ptrInfo().data;
14216+
1420414217 var ptr_ty_data: Type.Payload.Pointer.Data = .{
1420514218 .pointee_type = field.ty,
14206- .mutable = struct_ptr_ty.ptrIsMutable() ,
14207- .@"addrspace" = struct_ptr_ty.ptrAddressSpace() ,
14219+ .mutable = struct_ptr_ty_info.mutable ,
14220+ .@"addrspace" = struct_ptr_ty_info.@"addrspace" ,
1420814221 };
14222+
1420914223 // TODO handle when the struct pointer is overaligned, we should return a potentially
1421014224 // over-aligned field pointer too.
14211- if (struct_obj.layout == .Packed) p: {
14225+ if (struct_obj.layout == .Packed) {
1421214226 const target = sema.mod.getTarget();
14213- comptime assert(Type.packed_struct_layout_version == 1 );
14227+ comptime assert(Type.packed_struct_layout_version == 2 );
1421414228
14215- var offset: u64 = 0;
1421614229 var running_bits: u16 = 0;
1421714230 for (struct_obj.fields.values()) |f, i| {
1421814231 if (!(try sema.typeHasRuntimeBits(block, field_src, f.ty))) continue;
1421914232
14220- const field_align = f.packedAlignment();
14221- if (field_align == 0) {
14222- if (i == field_index) {
14223- ptr_ty_data.bit_offset = running_bits;
14224- }
14225- running_bits += @intCast(u16, f.ty.bitSize(target));
14226- } else {
14227- if (running_bits != 0) {
14228- var int_payload: Type.Payload.Bits = .{
14229- .base = .{ .tag = .int_unsigned },
14230- .data = running_bits,
14231- };
14232- const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
14233- if (i > field_index) {
14234- ptr_ty_data.host_size = @intCast(u16, int_ty.abiSize(target));
14235- break :p;
14236- }
14237- const int_align = int_ty.abiAlignment(target);
14238- offset = std.mem.alignForwardGeneric(u64, offset, int_align);
14239- offset += int_ty.abiSize(target);
14240- running_bits = 0;
14241- }
14242- offset = std.mem.alignForwardGeneric(u64, offset, field_align);
14243- if (i == field_index) {
14244- break :p;
14245- }
14246- offset += f.ty.abiSize(target);
14233+ if (i == field_index) {
14234+ ptr_ty_data.bit_offset = running_bits;
1424714235 }
14236+ running_bits += @intCast(u16, f.ty.bitSize(target));
14237+ }
14238+ ptr_ty_data.host_size = (running_bits + 7) / 8;
14239+
14240+ // If this is a packed struct embedded in another one, we need to offset
14241+ // the bits against each other.
14242+ if (struct_ptr_ty_info.host_size != 0) {
14243+ ptr_ty_data.host_size = struct_ptr_ty_info.host_size;
14244+ ptr_ty_data.bit_offset += struct_ptr_ty_info.bit_offset;
14245+ }
14246+ } else {
14247+ if (field.abi_align.tag() != .abi_align_default) {
14248+ ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());
1424814249 }
14249- assert(running_bits != 0);
14250- var int_payload: Type.Payload.Bits = .{
14251- .base = .{ .tag = .int_unsigned },
14252- .data = running_bits,
14253- };
14254- const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
14255- ptr_ty_data.host_size = @intCast(u16, int_ty.abiSize(target));
1425614250 }
14251+
1425714252 const ptr_field_ty = try Type.ptr(sema.arena, ptr_ty_data);
1425814253
1425914254 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
@@ -15849,13 +15844,18 @@ fn beginComptimePtrLoad(
1584915844fn bitCast(
1585015845 sema: *Sema,
1585115846 block: *Block,
15852- dest_ty : Type,
15847+ dest_ty_unresolved : Type,
1585315848 inst: Air.Inst.Ref,
1585415849 inst_src: LazySrcLoc,
1585515850) CompileError!Air.Inst.Ref {
15851+ const dest_ty = try sema.resolveTypeFields(block, inst_src, dest_ty_unresolved);
15852+ try sema.resolveTypeLayout(block, inst_src, dest_ty);
15853+
15854+ const old_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst));
15855+ try sema.resolveTypeLayout(block, inst_src, old_ty);
15856+
1585615857 // TODO validate the type size and other compile errors
1585715858 if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
15858- const old_ty = sema.typeOf(inst);
1585915859 const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty);
1586015860 return sema.addConstant(dest_ty, result_val);
1586115861 }
@@ -17506,6 +17506,9 @@ fn semaStructFields(
1750617506 // But only resolve the source location if we need to emit a compile error.
1750717507 try sema.resolveType(&block_scope, src, field_type_ref);
1750817508
17509+ // TODO emit compile errors for invalid field types
17510+ // such as arrays and pointers inside packed structs.
17511+
1750917512 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
1751017513 assert(!gop.found_existing);
1751117514 gop.value_ptr.* = .{
@@ -18690,6 +18693,12 @@ pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
1869018693 return true;
1869118694}
1869218695
18696+ fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32 {
18697+ try sema.resolveTypeLayout(block, src, ty);
18698+ const target = sema.mod.getTarget();
18699+ return ty.abiAlignment(target);
18700+ }
18701+
1869318702/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
1869418703pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
1869518704 const fn_info = ty.fnInfo();
0 commit comments