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 {
19661966
19671967 for (tuple.types) |field_ty, i| {
19681968 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
19711971 const field_size = field_ty.abiSize(target);
19721972 const field_align = field_ty.abiAlignment(target);
......@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
29012901
29022902 for (tuple.types) |field_ty, i| {
29032903 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
29062906 const field_align = field_ty.abiAlignment(target);
29072907 big_align = @max(big_align, field_align);
......@@ -10207,7 +10207,7 @@ fn llvmFieldIndex(
1020710207 const tuple = ty.tupleFields();
1020810208 var llvm_field_index: c_uint = 0;
1020910209 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
1021210212 const field_align = field_ty.abiAlignment(target);
1021310213 big_align = @max(big_align, field_align);
......@@ -10771,7 +10771,7 @@ fn isByRef(ty: Type) bool {
1077110771 const tuple = ty.tupleFields();
1077210772 var count: usize = 0;
1077310773 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
1077610776 count += 1;
1077710777 if (count > max_fields_byval) return true;
src/type.zig+1-1
......@@ -5759,7 +5759,7 @@ pub const Type = extern union {
57595759
57605760 for (tuple.types) |field_ty, i| {
57615761 const field_val = tuple.values[i];
5762 if (field_val.tag() != .unreachable_value) {
5762 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
57635763 // comptime field
57645764 if (i == index) return offset;
57655765 continue;
test/behavior/tuple.zig+10
......@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {
323323 var s: State = undefined;
324324 try expect(s.do() == 0);
325325}
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}