authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-10-02 02:56:18+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-02 02:56:18+03:00
log0228887b943dd7e70f7c5cc56e3993769342abf2
tree9290c5cdca1974f095efd8ee5dfa9c7ced56689b
parenta4fe438d3940d0beff16c939e991fdff24eb6ba2
parent362c87f1aab1db7f0019130115f7cadfef782a56
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6428 from tadeokondrak/alignment-typeinfo-struct-union

Add alignment field to TypeInfo.UnionField and TypeInfo.StructField

7 files changed, 103 insertions(+), 67 deletions(-)

lib/std/builtin.zig+2
......@@ -262,6 +262,7 @@ pub const TypeInfo = union(enum) {
262262 field_type: type,
263263 default_value: anytype,
264264 is_comptime: bool,
265 alignment: comptime_int,
265266 };
266267
267268 /// This data structure is used by the Zig language code generation and
......@@ -318,6 +319,7 @@ pub const TypeInfo = union(enum) {
318319 pub const UnionField = struct {
319320 name: []const u8,
320321 field_type: type,
322 alignment: comptime_int,
321323 };
322324
323325 /// This data structure is used by the Zig language code generation and
lib/std/meta.zig+2
......@@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type {
854854 .field_type = arg.arg_type.?,
855855 .default_value = @as(?(arg.arg_type.?), null),
856856 .is_comptime = false,
857 .alignment = @alignOf(arg.arg_type.?),
857858 };
858859 }
859860
......@@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type {
884885 .field_type = T,
885886 .default_value = @as(?T, null),
886887 .is_comptime = false,
888 .alignment = @alignOf(T),
887889 };
888890 }
889891
lib/std/meta/trailer_flags.zig+1
......@@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
4747 @as(?struct_field.field_type, null),
4848 ),
4949 .is_comptime = false,
50 .alignment = @alignOf(?struct_field.field_type),
5051 };
5152 }
5253 break :blk @Type(.{
src/stage1/ir.cpp+27-6
......@@ -25027,7 +25027,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, IrInst *source_instr,
2502725027 fields[2]->special = ConstValSpecialStatic;
2502825028 fields[2]->type = ira->codegen->builtin_types.entry_bool;
2502925029 fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;
25030 // alignment: u32
25030 // alignment: comptime_int
2503125031 ensure_field_index(result->type, "alignment", 3);
2503225032 fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int;
2503325033 if (attrs_type->data.pointer.explicit_alignment != 0) {
......@@ -25431,11 +25431,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2543125431 union_field_val->special = ConstValSpecialStatic;
2543225432 union_field_val->type = type_info_union_field_type;
2543325433
25434 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);
25434 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);
25435 // field_type: type
2543525436 inner_fields[1]->special = ConstValSpecialStatic;
2543625437 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
2543725438 inner_fields[1]->data.x_type = union_field->type_entry;
2543825439
25440 // alignment: comptime_int
25441 inner_fields[2]->special = ConstValSpecialStatic;
25442 inner_fields[2]->type = ira->codegen->builtin_types.entry_num_lit_int;
25443 bigint_init_unsigned(&inner_fields[2]->data.x_bigint, union_field->align);
25444
2543925445 ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
2544025446 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
2544125447
......@@ -25502,7 +25508,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2550225508 struct_field_val->special = ConstValSpecialStatic;
2550325509 struct_field_val->type = type_info_struct_field_type;
2550425510
25505 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4);
25511 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 5);
2550625512
2550725513 inner_fields[1]->special = ConstValSpecialStatic;
2550825514 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
......@@ -25518,10 +25524,16 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2551825524 }
2551925525 set_optional_payload(inner_fields[2], struct_field->init_val);
2552025526
25527 // is_comptime: bool
2552125528 inner_fields[3]->special = ConstValSpecialStatic;
2552225529 inner_fields[3]->type = ira->codegen->builtin_types.entry_bool;
2552325530 inner_fields[3]->data.x_bool = struct_field->is_comptime;
2552425531
25532 // alignment: comptime_int
25533 inner_fields[4]->special = ConstValSpecialStatic;
25534 inner_fields[4]->type = ira->codegen->builtin_types.entry_num_lit_int;
25535 bigint_init_unsigned(&inner_fields[4]->data.x_bigint, struct_field->align);
25536
2552525537 ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
2552625538 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
2552725539
......@@ -25868,8 +25880,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2586825880 buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
2586925881 return ira->codegen->invalid_inst_gen->value->type;
2587025882 }
25871 BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
25872 if (bi == nullptr)
25883
25884 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
25885 if (alignment == nullptr)
2587325886 return ira->codegen->invalid_inst_gen->value->type;
2587425887
2587525888 bool is_const;
......@@ -25896,7 +25909,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2589625909 is_const,
2589725910 is_volatile,
2589825911 ptr_len,
25899 bigint_as_u32(bi),
25912 bigint_as_u32(alignment),
2590025913 0, // bit_offset_in_host
2590125914 0, // host_int_bytes
2590225915 is_allowzero,
......@@ -26133,6 +26146,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2613326146 }
2613426147 if ((err = get_const_field_bool(ira, source_instr->source_node, field_value, "is_comptime", 3, &field->is_comptime)))
2613526148 return ira->codegen->invalid_inst_gen->value->type;
26149 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 4);
26150 if (alignment == nullptr)
26151 return ira->codegen->invalid_inst_gen->value->type;
26152 field->align = bigint_as_u32(alignment);
2613626153 }
2613726154
2613826155 return entry;
......@@ -26302,6 +26319,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2630226319 return ira->codegen->invalid_inst_gen->value->type;
2630326320 field->type_val = type_value;
2630426321 field->type_entry = type_value->data.x_type;
26322 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 2);
26323 if (alignment == nullptr)
26324 return ira->codegen->invalid_inst_gen->value->type;
26325 field->align = bigint_as_u32(alignment);
2630526326 }
2630626327 return entry;
2630726328 }
test/compile_errors.zig+51-52
......@@ -38,20 +38,39 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3838 "tmp.zig:2:20: error: TypeInfo.Enum.tag_type must be an integer type, not 'bool'",
3939 });
4040
41 cases.add("slice sentinel mismatch",
42 \\export fn entry() void {
43 \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };
44 \\}
45 , &[_][]const u8{
46 "tmp.zig:2:62: error: index 3 outside vector of size 3",
47 });
48
49 cases.add("slice sentinel mismatch",
41 cases.add("@Type for tagged union with extra enum field",
42 \\const TypeInfo = @import("builtin").TypeInfo;
43 \\const Tag = @Type(.{
44 \\ .Enum = .{
45 \\ .layout = .Auto,
46 \\ .tag_type = u2,
47 \\ .fields = &[_]TypeInfo.EnumField{
48 \\ .{ .name = "signed", .value = 0 },
49 \\ .{ .name = "unsigned", .value = 1 },
50 \\ .{ .name = "arst", .value = 2 },
51 \\ },
52 \\ .decls = &[_]TypeInfo.Declaration{},
53 \\ .is_exhaustive = true,
54 \\ },
55 \\});
56 \\const Tagged = @Type(.{
57 \\ .Union = .{
58 \\ .layout = .Auto,
59 \\ .tag_type = Tag,
60 \\ .fields = &[_]TypeInfo.UnionField{
61 \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
62 \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
63 \\ },
64 \\ .decls = &[_]TypeInfo.Declaration{},
65 \\ },
66 \\});
5067 \\export fn entry() void {
51 \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
68 \\ var tagged = Tagged{ .signed = -1 };
69 \\ tagged = .{ .unsigned = 1 };
5270 \\}
5371 , &[_][]const u8{
54 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
72 "tmp.zig:15:23: error: enum field missing: 'arst'",
73 "tmp.zig:27:24: note: referenced here",
5574 });
5675
5776 cases.add("@Type for union with opaque field",
......@@ -61,7 +80,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6180 \\ .layout = .Auto,
6281 \\ .tag_type = null,
6382 \\ .fields = &[_]TypeInfo.UnionField{
64 \\ .{ .name = "foo", .field_type = @Type(.Opaque) },
83 \\ .{ .name = "foo", .field_type = @Type(.Opaque), .alignment = 1 },
6584 \\ },
6685 \\ .decls = &[_]TypeInfo.Declaration{},
6786 \\ },
......@@ -74,6 +93,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7493 "tmp.zig:13:17: note: referenced here",
7594 });
7695
96 cases.add("slice sentinel mismatch",
97 \\export fn entry() void {
98 \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };
99 \\}
100 , &[_][]const u8{
101 "tmp.zig:2:62: error: index 3 outside vector of size 3",
102 });
103
104 cases.add("slice sentinel mismatch",
105 \\export fn entry() void {
106 \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
107 \\}
108 , &[_][]const u8{
109 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
110 });
111
77112 cases.add("@Type for union with zero fields",
78113 \\const TypeInfo = @import("builtin").TypeInfo;
79114 \\const Untagged = @Type(.{
......@@ -130,9 +165,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
130165 \\ .layout = .Auto,
131166 \\ .tag_type = Tag,
132167 \\ .fields = &[_]TypeInfo.UnionField{
133 \\ .{ .name = "signed", .field_type = i32 },
134 \\ .{ .name = "unsigned", .field_type = u32 },
135 \\ .{ .name = "arst", .field_type = f32 },
168 \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
169 \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
170 \\ .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) },
136171 \\ },
137172 \\ .decls = &[_]TypeInfo.Declaration{},
138173 \\ },
......@@ -147,42 +182,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
147182 "tmp.zig:27:24: note: referenced here",
148183 });
149184
150 cases.add("@Type for tagged union with extra enum field",
151 \\const TypeInfo = @import("builtin").TypeInfo;
152 \\const Tag = @Type(.{
153 \\ .Enum = .{
154 \\ .layout = .Auto,
155 \\ .tag_type = u2,
156 \\ .fields = &[_]TypeInfo.EnumField{
157 \\ .{ .name = "signed", .value = 0 },
158 \\ .{ .name = "unsigned", .value = 1 },
159 \\ .{ .name = "arst", .field_type = 2 },
160 \\ },
161 \\ .decls = &[_]TypeInfo.Declaration{},
162 \\ .is_exhaustive = true,
163 \\ },
164 \\});
165 \\const Tagged = @Type(.{
166 \\ .Union = .{
167 \\ .layout = .Auto,
168 \\ .tag_type = Tag,
169 \\ .fields = &[_]TypeInfo.UnionField{
170 \\ .{ .name = "signed", .field_type = i32 },
171 \\ .{ .name = "unsigned", .field_type = u32 },
172 \\ },
173 \\ .decls = &[_]TypeInfo.Declaration{},
174 \\ },
175 \\});
176 \\export fn entry() void {
177 \\ var tagged = Tagged{ .signed = -1 };
178 \\ tagged = .{ .unsigned = 1 };
179 \\}
180 , &[_][]const u8{
181 "tmp.zig:9:32: error: no member named 'field_type' in struct 'std.builtin.EnumField'",
182 "tmp.zig:18:21: note: referenced here",
183 "tmp.zig:27:18: note: referenced here",
184 });
185
186185 cases.add("@Type with undefined",
187186 \\comptime {
188187 \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
......@@ -7592,7 +7591,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
75927591 });
75937592
75947593 cases.add( // fixed bug #2032
7595 "compile diagnostic string for top level decl type",
7594 "compile diagnostic string for top level decl type",
75967595 \\export fn entry() void {
75977596 \\ var foo: u32 = @This(){};
75987597 \\}
test/stage1/behavior/type.zig+8-8
......@@ -320,8 +320,8 @@ test "Type.Union" {
320320 .layout = .Auto,
321321 .tag_type = null,
322322 .fields = &[_]TypeInfo.UnionField{
323 .{ .name = "int", .field_type = i32 },
324 .{ .name = "float", .field_type = f32 },
323 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
324 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
325325 },
326326 .decls = &[_]TypeInfo.Declaration{},
327327 },
......@@ -336,8 +336,8 @@ test "Type.Union" {
336336 .layout = .Packed,
337337 .tag_type = null,
338338 .fields = &[_]TypeInfo.UnionField{
339 .{ .name = "signed", .field_type = i32 },
340 .{ .name = "unsigned", .field_type = u32 },
339 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
340 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
341341 },
342342 .decls = &[_]TypeInfo.Declaration{},
343343 },
......@@ -363,8 +363,8 @@ test "Type.Union" {
363363 .layout = .Auto,
364364 .tag_type = Tag,
365365 .fields = &[_]TypeInfo.UnionField{
366 .{ .name = "signed", .field_type = i32 },
367 .{ .name = "unsigned", .field_type = u32 },
366 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
367 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
368368 },
369369 .decls = &[_]TypeInfo.Declaration{},
370370 },
......@@ -392,7 +392,7 @@ test "Type.Union from Type.Enum" {
392392 .layout = .Auto,
393393 .tag_type = Tag,
394394 .fields = &[_]TypeInfo.UnionField{
395 .{ .name = "working_as_expected", .field_type = u32 },
395 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
396396 },
397397 .decls = &[_]TypeInfo.Declaration{},
398398 },
......@@ -408,7 +408,7 @@ test "Type.Union from regular enum" {
408408 .layout = .Auto,
409409 .tag_type = E,
410410 .fields = &[_]TypeInfo.UnionField{
411 .{ .name = "working_as_expected", .field_type = u32 },
411 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
412412 },
413413 .decls = &[_]TypeInfo.Declaration{},
414414 },
test/stage1/behavior/type_info.zig+12-1
......@@ -211,7 +211,9 @@ fn testUnion() void {
211211 expect(notag_union_info.Union.tag_type == null);
212212 expect(notag_union_info.Union.layout == .Auto);
213213 expect(notag_union_info.Union.fields.len == 2);
214 expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
214215 expect(notag_union_info.Union.fields[1].field_type == u32);
216 expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
215217
216218 const TestExternUnion = extern union {
217219 foo: *c_void,
......@@ -229,13 +231,18 @@ test "type info: struct info" {
229231}
230232
231233fn testStruct() void {
234 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
235 expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
236
232237 const struct_info = @typeInfo(TestStruct);
233238 expect(struct_info == .Struct);
234239 expect(struct_info.Struct.layout == .Packed);
235240 expect(struct_info.Struct.fields.len == 4);
241 expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
236242 expect(struct_info.Struct.fields[2].field_type == *TestStruct);
237243 expect(struct_info.Struct.fields[2].default_value == null);
238244 expect(struct_info.Struct.fields[3].default_value.? == 4);
245 expect(struct_info.Struct.fields[3].alignment == 1);
239246 expect(struct_info.Struct.decls.len == 2);
240247 expect(struct_info.Struct.decls[0].is_pub);
241248 expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
......@@ -244,8 +251,12 @@ fn testStruct() void {
244251 expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
245252}
246253
254const TestUnpackedStruct = struct {
255 fieldA: u32 = 4,
256};
257
247258const TestStruct = packed struct {
248 fieldA: usize,
259 fieldA: usize align(2 * @alignOf(usize)),
249260 fieldB: void,
250261 fieldC: *Self,
251262 fieldD: u32 = 4,