authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-12 13:11:54+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-12 15:41:29+02:00
log87cf2783ebdf96e3dfa1c24a53dba301591d5f07
tree5496dc171c02f076952ffa303137d23b31aeb1c6
parenta760ce598c7656f7582d8305582e374af68254d9

llvm: check that tuple fields have runtime bits

Just checking that they aren't comptime isn't enough for `@Type` constructed tuples. Closes #13531

3 files changed, 15 insertions(+), 5 deletions(-)

src/codegen/llvm.zig+4-4
...@@ -1966,7 +1966,7 @@ pub const Object = struct {...@@ -1966,7 +1966,7 @@ pub const Object = struct {
19661966
1967 for (tuple.types) |field_ty, i| {1967 for (tuple.types) |field_ty, i| {
1968 const field_val = tuple.values[i];1968 const field_val = tuple.values[i];
1969 if (field_val.tag() != .unreachable_value) continue;1969 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
19701970
1971 const field_size = field_ty.abiSize(target);1971 const field_size = field_ty.abiSize(target);
1972 const field_align = field_ty.abiAlignment(target);1972 const field_align = field_ty.abiAlignment(target);
...@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {...@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
29012901
2902 for (tuple.types) |field_ty, i| {2902 for (tuple.types) |field_ty, i| {
2903 const field_val = tuple.values[i];2903 const field_val = tuple.values[i];
2904 if (field_val.tag() != .unreachable_value) continue;2904 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
29052905
2906 const field_align = field_ty.abiAlignment(target);2906 const field_align = field_ty.abiAlignment(target);
2907 big_align = @max(big_align, field_align);2907 big_align = @max(big_align, field_align);
...@@ -10207,7 +10207,7 @@ fn llvmFieldIndex(...@@ -10207,7 +10207,7 @@ fn llvmFieldIndex(
10207 const tuple = ty.tupleFields();10207 const tuple = ty.tupleFields();
10208 var llvm_field_index: c_uint = 0;10208 var llvm_field_index: c_uint = 0;
10209 for (tuple.types) |field_ty, i| {10209 for (tuple.types) |field_ty, i| {
10210 if (tuple.values[i].tag() != .unreachable_value) continue;10210 if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
1021110211
10212 const field_align = field_ty.abiAlignment(target);10212 const field_align = field_ty.abiAlignment(target);
10213 big_align = @max(big_align, field_align);10213 big_align = @max(big_align, field_align);
...@@ -10771,7 +10771,7 @@ fn isByRef(ty: Type) bool {...@@ -10771,7 +10771,7 @@ fn isByRef(ty: Type) bool {
10771 const tuple = ty.tupleFields();10771 const tuple = ty.tupleFields();
10772 var count: usize = 0;10772 var count: usize = 0;
10773 for (tuple.values) |field_val, i| {10773 for (tuple.values) |field_val, i| {
10774 if (field_val.tag() != .unreachable_value) continue;10774 if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;
1077510775
10776 count += 1;10776 count += 1;
10777 if (count > max_fields_byval) return true;10777 if (count > max_fields_byval) return true;
src/type.zig+1-1
...@@ -5759,7 +5759,7 @@ pub const Type = extern union {...@@ -5759,7 +5759,7 @@ pub const Type = extern union {
57595759
5760 for (tuple.types) |field_ty, i| {5760 for (tuple.types) |field_ty, i| {
5761 const field_val = tuple.values[i];5761 const field_val = tuple.values[i];
5762 if (field_val.tag() != .unreachable_value) {5762 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
5763 // comptime field5763 // comptime field
5764 if (i == index) return offset;5764 if (i == index) return offset;
5765 continue;5765 continue;
test/behavior/tuple.zig+10
...@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {...@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {
323 var s: State = undefined;323 var s: State = undefined;
324 try expect(s.do() == 0);324 try expect(s.do() == 0);
325}325}
326
327test "tuple type with void field and a runtime field" {
328 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
330 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
331
332 const T = std.meta.Tuple(&[_]type{ usize, void });
333 var t: T = .{ 5, {} };
334 try expect(t[0] == 5);
335}