authorgravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-03-14 16:21:11-07:00
committergravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-03-14 17:41:12-07:00
loga859f94644cb362d84d3f9d72bc02b00a75fc32a
treee3f4d09b74fb4bca327b192d311bb5bbe950d161
parent5ea94e7715607e986298908536cdd3d9dfdd0ce9
signaturelock-open Commit is signed but in an unrecognized format.

stage2: LLVM codegen of arrays should use type length, not value length

It is possible for the value length to be longer than the type because we allow in-memory coercing of types such as `[5:0]u8` to `[5]u8`. In such a case, the value length is 6 but the type length if 5. The `.repeated` value type already got this right, so this is extending similar logic out to `.aggregate` and `.bytes`. Both scenarios are tested in behavior tests. Fixes #11165

3 files changed, 47 insertions(+), 3 deletions(-)

src/codegen/llvm.zig+4-3
...@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {...@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {
1507 const bytes = tv.val.castTag(.bytes).?.data;1507 const bytes = tv.val.castTag(.bytes).?.data;
1508 return dg.context.constString(1508 return dg.context.constString(
1509 bytes.ptr,1509 bytes.ptr,
1510 @intCast(c_uint, bytes.len),1510 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()),
1511 .True, // don't null terminate. bytes has the sentinel, if any.1511 .True, // don't null terminate. bytes has the sentinel, if any.
1512 );1512 );
1513 },1513 },
...@@ -1515,10 +1515,11 @@ pub const DeclGen = struct {...@@ -1515,10 +1515,11 @@ pub const DeclGen = struct {
1515 const elem_vals = tv.val.castTag(.aggregate).?.data;1515 const elem_vals = tv.val.castTag(.aggregate).?.data;
1516 const elem_ty = tv.ty.elemType();1516 const elem_ty = tv.ty.elemType();
1517 const gpa = dg.gpa;1517 const gpa = dg.gpa;
1518 const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);1518 const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel());
1519 const llvm_elems = try gpa.alloc(*const llvm.Value, len);
1519 defer gpa.free(llvm_elems);1520 defer gpa.free(llvm_elems);
1520 var need_unnamed = false;1521 var need_unnamed = false;
1521 for (elem_vals) |elem_val, i| {1522 for (elem_vals[0..len]) |elem_val, i| {
1522 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });1523 llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
1523 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);1524 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
1524 }1525 }
test/behavior.zig+1
...@@ -62,6 +62,7 @@ test {...@@ -62,6 +62,7 @@ test {
62 _ = @import("behavior/bugs/11100.zig");62 _ = @import("behavior/bugs/11100.zig");
63 _ = @import("behavior/bugs/10970.zig");63 _ = @import("behavior/bugs/10970.zig");
64 _ = @import("behavior/bugs/11046.zig");64 _ = @import("behavior/bugs/11046.zig");
65 _ = @import("behavior/bugs/11165.zig");
65 _ = @import("behavior/call.zig");66 _ = @import("behavior/call.zig");
66 _ = @import("behavior/cast.zig");67 _ = @import("behavior/cast.zig");
67 _ = @import("behavior/comptime_memory.zig");68 _ = @import("behavior/comptime_memory.zig");
test/behavior/bugs/11165.zig created+42
...@@ -0,0 +1,42 @@
1const builtin = @import("builtin");
2
3test "bytes" {
4 const S = struct {
5 a: u32,
6 c: [5]u8,
7 };
8
9 const U = union {
10 s: S,
11 };
12
13 const s_1 = S{
14 .a = undefined,
15 .c = "12345".*, // this caused problems
16 };
17 _ = s_1;
18
19 const u_2 = U{ .s = s_1 };
20 _ = u_2;
21}
22
23test "aggregate" {
24 const S = struct {
25 a: u32,
26 c: [5]u8,
27 };
28
29 const U = union {
30 s: S,
31 };
32
33 const c = [5:0]u8{ 1, 2, 3, 4, 5 };
34 const s_1 = S{
35 .a = undefined,
36 .c = c, // this caused problems
37 };
38 _ = s_1;
39
40 const u_2 = U{ .s = s_1 };
41 _ = u_2;
42}