@@ -9701,7 +9701,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
9701
9701
fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
9702
9702
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
9703
9703
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);
9705
9706
const target = sema.mod.getTarget();
9706
9707
const bit_size = operand_ty.bitSize(target);
9707
9708
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
9891
9892
.Fn => {
9892
9893
// TODO: look into memoizing this result.
9893
9894
const info = ty.fnInfo();
9895
+
9894
9896
var params_anon_decl = try block.startAnonDecl(src);
9895
9897
defer params_anon_decl.deinit();
9896
9898
@@ -9948,19 +9950,24 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
9948
9950
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
9949
9951
};
9950
9952
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
+ };
9964
9971
9965
9972
return sema.addConstant(
9966
9973
type_info_ty,
@@ -10007,25 +10014,27 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10007
10014
const alignment = if (info.@"align" != 0)
10008
10015
info.@"align"
10009
10016
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
+ };
10029
10038
10030
10039
return sema.addConstant(
10031
10040
type_info_ty,
@@ -10377,7 +10386,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10377
10386
const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
10378
10387
const alignment = switch (layout) {
10379
10388
.Auto, .Extern => field.normalAlignment(target),
10380
- .Packed => field.packedAlignment() ,
10389
+ .Packed => 0 ,
10381
10390
};
10382
10391
10383
10392
struct_field_fields.* = .{
@@ -12120,6 +12129,7 @@ fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
12120
12129
12121
12130
fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12122
12131
const offset = try bitOffsetOf(sema, block, inst);
12132
+ // TODO reminder to make this a compile error for packed structs
12123
12133
return sema.addIntUnsigned(Type.comptime_int, offset / 8);
12124
12134
}
12125
12135
@@ -12143,7 +12153,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
12143
12153
);
12144
12154
}
12145
12155
12146
- const index = ty.structFields().getIndex(field_name) orelse {
12156
+ const fields = ty.structFields();
12157
+ const index = fields.getIndex(field_name) orelse {
12147
12158
return sema.fail(
12148
12159
block,
12149
12160
rhs_src,
@@ -12153,24 +12164,25 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
12153
12164
};
12154
12165
12155
12166
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
+ },
12171
12185
}
12172
-
12173
- unreachable;
12174
12186
}
12175
12187
12176
12188
/// Returns `true` if the type was a comptime_int.
@@ -14199,61 +14211,44 @@ fn structFieldPtrByIndex(
14199
14211
field_src: LazySrcLoc,
14200
14212
) CompileError!Air.Inst.Ref {
14201
14213
const field = struct_obj.fields.values()[field_index];
14202
-
14203
14214
const struct_ptr_ty = sema.typeOf(struct_ptr);
14215
+ const struct_ptr_ty_info = struct_ptr_ty.ptrInfo().data;
14216
+
14204
14217
var ptr_ty_data: Type.Payload.Pointer.Data = .{
14205
14218
.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" ,
14208
14221
};
14222
+
14209
14223
// TODO handle when the struct pointer is overaligned, we should return a potentially
14210
14224
// over-aligned field pointer too.
14211
- if (struct_obj.layout == .Packed) p: {
14225
+ if (struct_obj.layout == .Packed) {
14212
14226
const target = sema.mod.getTarget();
14213
- comptime assert(Type.packed_struct_layout_version == 1 );
14227
+ comptime assert(Type.packed_struct_layout_version == 2 );
14214
14228
14215
- var offset: u64 = 0;
14216
14229
var running_bits: u16 = 0;
14217
14230
for (struct_obj.fields.values()) |f, i| {
14218
14231
if (!(try sema.typeHasRuntimeBits(block, field_src, f.ty))) continue;
14219
14232
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;
14247
14235
}
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());
14248
14249
}
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));
14256
14250
}
14251
+
14257
14252
const ptr_field_ty = try Type.ptr(sema.arena, ptr_ty_data);
14258
14253
14259
14254
if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
@@ -15849,13 +15844,18 @@ fn beginComptimePtrLoad(
15849
15844
fn bitCast(
15850
15845
sema: *Sema,
15851
15846
block: *Block,
15852
- dest_ty : Type,
15847
+ dest_ty_unresolved : Type,
15853
15848
inst: Air.Inst.Ref,
15854
15849
inst_src: LazySrcLoc,
15855
15850
) 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
+
15856
15857
// TODO validate the type size and other compile errors
15857
15858
if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
15858
- const old_ty = sema.typeOf(inst);
15859
15859
const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty);
15860
15860
return sema.addConstant(dest_ty, result_val);
15861
15861
}
@@ -17506,6 +17506,9 @@ fn semaStructFields(
17506
17506
// But only resolve the source location if we need to emit a compile error.
17507
17507
try sema.resolveType(&block_scope, src, field_type_ref);
17508
17508
17509
+ // TODO emit compile errors for invalid field types
17510
+ // such as arrays and pointers inside packed structs.
17511
+
17509
17512
const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
17510
17513
assert(!gop.found_existing);
17511
17514
gop.value_ptr.* = .{
@@ -18690,6 +18693,12 @@ pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
18690
18693
return true;
18691
18694
}
18692
18695
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
+
18693
18702
/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
18694
18703
pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
18695
18704
const fn_info = ty.fnInfo();
0 commit comments