authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-24 10:14:16+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-25 15:36:33-08:00
log58c2bec589d6d90db31744430407bc88695b5161
tree7105980173ee3114ac008590eec48362afe62afe
parent500fbdad57424dd963227e9cfb468a90147ad72f

stage1: Fix ICE when generating struct fields with padding

Make gen_const_ptr_struct_recursive aware of the possible presence of some trailing padding by always bitcasting the pointer to its expected type. Not an elegant solution but makes LLVM happy and is consistent with how the other callsites are handling this case. Fixes #5398

3 files changed, 40 insertions(+), 1 deletions(-)

src/stage1/codegen.cpp+8-1
...@@ -7038,7 +7038,14 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_...@@ -7038,7 +7038,14 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_
7038 LLVMConstNull(get_llvm_type(g, u32)),7038 LLVMConstNull(get_llvm_type(g, u32)),
7039 LLVMConstInt(get_llvm_type(g, u32), field_index, false),7039 LLVMConstInt(get_llvm_type(g, u32), field_index, false),
7040 };7040 };
7041 return LLVMConstInBoundsGEP(base_ptr, indices, 2);7041
7042 // The structure pointed by base_ptr may include trailing padding for
7043 // alignment purposes and have the following LLVM type: <{ %T, [N x i8] }>.
7044 // Add an extra bitcast as we're only interested in the %T part.
7045 assert(handle_is_ptr(g, struct_const_val->type));
7046 LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr,
7047 LLVMPointerType(get_llvm_type(g, struct_const_val->type), 0));
7048 return LLVMConstInBoundsGEP(casted_base_ptr, indices, 2);
7042}7049}
70437050
7044static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) {7051static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) {
test/stage1/behavior.zig+1
...@@ -50,6 +50,7 @@ comptime {...@@ -50,6 +50,7 @@ comptime {
50 _ = @import("behavior/bugs/4769_b.zig");50 _ = @import("behavior/bugs/4769_b.zig");
51 _ = @import("behavior/bugs/4769_c.zig");51 _ = @import("behavior/bugs/4769_c.zig");
52 _ = @import("behavior/bugs/4954.zig");52 _ = @import("behavior/bugs/4954.zig");
53 _ = @import("behavior/bugs/5398.zig");
53 _ = @import("behavior/bugs/5413.zig");54 _ = @import("behavior/bugs/5413.zig");
54 _ = @import("behavior/bugs/5474.zig");55 _ = @import("behavior/bugs/5474.zig");
55 _ = @import("behavior/bugs/5487.zig");56 _ = @import("behavior/bugs/5487.zig");
test/stage1/behavior/bugs/5398.zig created+31
...@@ -0,0 +1,31 @@
1const std = @import("std");
2const testing = std.testing;
3
4pub const Mesh = struct {
5 id: u32,
6};
7pub const Material = struct {
8 transparent: bool = true,
9 emits_shadows: bool = true,
10 render_color: bool = true,
11};
12pub const Renderable = struct {
13 material: Material,
14 // The compiler inserts some padding here to ensure Mesh is correctly aligned.
15 mesh: Mesh,
16};
17
18var renderable: Renderable = undefined;
19
20test "assignment of field with padding" {
21 renderable = Renderable{
22 .mesh = Mesh{ .id = 0 },
23 .material = Material{
24 .transparent = false,
25 .emits_shadows = false,
26 },
27 };
28 testing.expectEqual(false, renderable.material.transparent);
29 testing.expectEqual(false, renderable.material.emits_shadows);
30 testing.expectEqual(true, renderable.material.render_color);
31}