authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-04-28 12:45:50+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-28 13:13:42-04:00
log9902b604cb01072d4599035b59724731cf03fdbc
tree67d5deb790c0abca47b60b95c729dc0e10b93a38
parent205e501e42b9a2e1d35afa0873311165100863ae

Fix generation of container initializers

The code creates temporary ConstExprValue with global_refs set to nullptr and that's carried over to the final value. Doing so prevents the deduplication mechanism to work correctly, causing all sorts of runtime crashes. Fixes #1636 Fixes #1608 (Even though it was already fixed by #1991)

2 files changed, 26 insertions(+), 7 deletions(-)

src/ir.cpp+6-5
...@@ -9931,6 +9931,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t...@@ -9931,6 +9931,7 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *t
99319931
9932static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {9932static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
9933 ConstGlobalRefs *global_refs = dest->global_refs;9933 ConstGlobalRefs *global_refs = dest->global_refs;
9934 assert(!same_global_refs || src->global_refs != nullptr);
9934 *dest = *src;9935 *dest = *src;
9935 if (!same_global_refs) {9936 if (!same_global_refs) {
9936 dest->global_refs = global_refs;9937 dest->global_refs = global_refs;
...@@ -17468,6 +17469,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17468,6 +17469,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17468 ConstExprValue const_val = {};17469 ConstExprValue const_val = {};
17469 const_val.special = ConstValSpecialStatic;17470 const_val.special = ConstValSpecialStatic;
17470 const_val.type = container_type;17471 const_val.type = container_type;
17472 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
17471 const_val.data.x_struct.fields = create_const_vals(actual_field_count);17473 const_val.data.x_struct.fields = create_const_vals(actual_field_count);
17472 for (size_t i = 0; i < instr_field_count; i += 1) {17474 for (size_t i = 0; i < instr_field_count; i += 1) {
17473 IrInstructionContainerInitFieldsField *field = &fields[i];17475 IrInstructionContainerInitFieldsField *field = &fields[i];
...@@ -17531,7 +17533,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17531,7 +17533,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17531 if (const_val.special == ConstValSpecialStatic) {17533 if (const_val.special == ConstValSpecialStatic) {
17532 IrInstruction *result = ir_const(ira, instruction, nullptr);17534 IrInstruction *result = ir_const(ira, instruction, nullptr);
17533 ConstExprValue *out_val = &result->value;17535 ConstExprValue *out_val = &result->value;
17534 copy_const_val(out_val, &const_val, true);17536 copy_const_val(out_val, &const_val, false);
17535 out_val->type = container_type;17537 out_val->type = container_type;
1753617538
17537 for (size_t i = 0; i < instr_field_count; i += 1) {17539 for (size_t i = 0; i < instr_field_count; i += 1) {
...@@ -17603,6 +17605,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -17603,6 +17605,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17603 ConstExprValue const_val = {};17605 ConstExprValue const_val = {};
17604 const_val.special = ConstValSpecialStatic;17606 const_val.special = ConstValSpecialStatic;
17605 const_val.type = fixed_size_array_type;17607 const_val.type = fixed_size_array_type;
17608 // const_val.global_refs = allocate<ConstGlobalRefs>(1);
17606 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);17609 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1760717610
17608 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);17611 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
...@@ -17639,8 +17642,6 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -17639,8 +17642,6 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17639 if (const_val.special == ConstValSpecialStatic) {17642 if (const_val.special == ConstValSpecialStatic) {
17640 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);17643 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
17641 ConstExprValue *out_val = &result->value;17644 ConstExprValue *out_val = &result->value;
17642 // Make sure to pass same_global_refs=false here in order not to
17643 // zero the global_refs field for `result` (#1608)
17644 copy_const_val(out_val, &const_val, false);17645 copy_const_val(out_val, &const_val, false);
17645 result->value.type = fixed_size_array_type;17646 result->value.type = fixed_size_array_type;
17646 for (size_t i = 0; i < elem_count; i += 1) {17647 for (size_t i = 0; i < elem_count; i += 1) {
...@@ -21319,7 +21320,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -21319,7 +21320,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
21319 }21320 }
2132021321
21321 IrInstruction *result = ir_const(ira, target, result_type);21322 IrInstruction *result = ir_const(ira, target, result_type);
21322 copy_const_val(&result->value, val, false);21323 copy_const_val(&result->value, val, true);
21323 result->value.type = result_type;21324 result->value.type = result_type;
21324 return result;21325 return result;
21325 }21326 }
...@@ -21389,7 +21390,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -21389,7 +21390,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
21389 }21390 }
2139021391
21391 IrInstruction *result = ir_const(ira, source_instr, dest_type);21392 IrInstruction *result = ir_const(ira, source_instr, dest_type);
21392 copy_const_val(&result->value, val, false);21393 copy_const_val(&result->value, val, true);
21393 result->value.type = dest_type;21394 result->value.type = dest_type;
2139421395
21395 // Keep the bigger alignment, it can only help-21396 // Keep the bigger alignment, it can only help-
test/stage1/behavior/struct.zig+20-2
...@@ -2,8 +2,7 @@ const std = @import("std");...@@ -2,8 +2,7 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;3const expectEqualSlices = std.testing.expectEqualSlices;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
6
7const StructWithNoFields = struct {6const StructWithNoFields = struct {
8 fn add(a: i32, b: i32) i32 {7 fn add(a: i32, b: i32) i32 {
9 return a + b;8 return a + b;
...@@ -505,3 +504,22 @@ test "packed struct with u0 field access" {...@@ -505,3 +504,22 @@ test "packed struct with u0 field access" {
505 var s = S{ .f0 = 0 };504 var s = S{ .f0 = 0 };
506 comptime expect(s.f0 == 0);505 comptime expect(s.f0 == 0);
507}506}
507
508const S0 = struct{
509 bar: S1,
510
511 pub const S1 = struct{
512 value: u8,
513 };
514
515 fn init() @This() {
516 return S0{ .bar = S1{ .value = 123 } };
517 }
518};
519
520var g_foo: S0 = S0.init();
521
522test "access to global struct fields" {
523 g_foo.bar.value = 42;
524 expect(g_foo.bar.value == 42);
525}