authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-19 14:35:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-19 14:35:59-04:00
logb588a803bf4493d2fd1892fe172b9ce8cfb0ca30
tree8d5c9306669cc5d185568ec45445d26e326a3fd9
parent79671efd3a5b67e359aa60c66e4007c03342b28e
signaturelock-open Commit is signed but in an unrecognized format.

fix comptime modification of const struct field


6 files changed, 41 insertions(+), 27 deletions(-)

src/all_types.hpp+3
...@@ -334,6 +334,9 @@ struct ConstExprValue {...@@ -334,6 +334,9 @@ struct ConstExprValue {
334 RuntimeHintPtr rh_ptr;334 RuntimeHintPtr rh_ptr;
335 RuntimeHintSlice rh_slice;335 RuntimeHintSlice rh_slice;
336 } data;336 } data;
337
338 ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
339 ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
337};340};
338341
339enum ReturnKnowledge {342enum ReturnKnowledge {
src/analyze.cpp+1-1
...@@ -4711,7 +4711,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {...@@ -4711,7 +4711,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
4711void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {4711void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
4712 auto entry = g->string_literals_table.maybe_get(str);4712 auto entry = g->string_literals_table.maybe_get(str);
4713 if (entry != nullptr) {4713 if (entry != nullptr) {
4714 *const_val = *entry->value;4714 memcpy(const_val, entry->value, sizeof(ConstExprValue));
4715 return;4715 return;
4716 }4716 }
47174717
src/codegen.cpp+1-1
...@@ -6676,7 +6676,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6676,7 +6676,7 @@ static void do_code_gen(CodeGen *g) {
6676 zig_panic("TODO debug info for var with ptr casted value");6676 zig_panic("TODO debug info for var with ptr casted value");
6677 }6677 }
6678 ZigType *var_type = g->builtin_types.entry_f128;6678 ZigType *var_type = g->builtin_types.entry_f128;
6679 ConstExprValue coerced_value;6679 ConstExprValue coerced_value = {};
6680 coerced_value.special = ConstValSpecialStatic;6680 coerced_value.special = ConstValSpecialStatic;
6681 coerced_value.type = var_type;6681 coerced_value.type = var_type;
6682 coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);6682 coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
src/ir.cpp+27-16
...@@ -10624,13 +10624,16 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10624,13 +10624,16 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1062410624
10625static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {10625static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
10626 ConstGlobalRefs *global_refs = dest->global_refs;10626 ConstGlobalRefs *global_refs = dest->global_refs;
10627 assert(!same_global_refs || src->global_refs != nullptr);10627 memcpy(dest, src, sizeof(ConstExprValue));
10628 *dest = *src;
10629 if (!same_global_refs) {10628 if (!same_global_refs) {
10630 dest->global_refs = global_refs;10629 dest->global_refs = global_refs;
10630 if (src->special == ConstValSpecialUndef)
10631 return;
10631 if (dest->type->id == ZigTypeIdStruct) {10632 if (dest->type->id == ZigTypeIdStruct) {
10632 dest->data.x_struct.fields = allocate_nonzero<ConstExprValue>(dest->type->data.structure.src_field_count);10633 dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);
10633 memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count);10634 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
10635 copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false);
10636 }
10634 }10637 }
10635 }10638 }
10636}10639}
...@@ -13579,7 +13582,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in...@@ -13579,7 +13582,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in
13579 }13582 }
13580 } else {13583 } else {
13581 float_div_trunc(out_val, op1_val, op2_val);13584 float_div_trunc(out_val, op1_val, op2_val);
13582 ConstExprValue remainder;13585 ConstExprValue remainder = {};
13583 float_rem(&remainder, op1_val, op2_val);13586 float_rem(&remainder, op1_val, op2_val);
13584 if (float_cmp_zero(&remainder) != CmpEQ) {13587 if (float_cmp_zero(&remainder) != CmpEQ) {
13585 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));13588 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
...@@ -13954,8 +13957,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -13954,8 +13957,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
13954 // have a remainder function ambiguity problem13957 // have a remainder function ambiguity problem
13955 ok = true;13958 ok = true;
13956 } else {13959 } else {
13957 ConstExprValue rem_result;13960 ConstExprValue rem_result = {};
13958 ConstExprValue mod_result;13961 ConstExprValue mod_result = {};
13959 float_rem(&rem_result, op1_val, op2_val);13962 float_rem(&rem_result, op1_val, op2_val);
13960 float_mod(&mod_result, op1_val, op2_val);13963 float_mod(&mod_result, op1_val, op2_val);
13961 ok = float_cmp(&rem_result, &mod_result) == CmpEQ;13964 ok = float_cmp(&rem_result, &mod_result) == CmpEQ;
...@@ -14178,10 +14181,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14178,10 +14181,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1417814181
14179 size_t next_index = 0;14182 size_t next_index = 0;
14180 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {14183 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
14181 out_array_val->data.x_array.data.s_none.elements[next_index] = op1_array_val->data.x_array.data.s_none.elements[i];14184 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14185 &op1_array_val->data.x_array.data.s_none.elements[i], true);
14182 }14186 }
14183 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {14187 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
14184 out_array_val->data.x_array.data.s_none.elements[next_index] = op2_array_val->data.x_array.data.s_none.elements[i];14188 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14189 &op2_array_val->data.x_array.data.s_none.elements[i], true);
14185 }14190 }
14186 if (next_index < new_len) {14191 if (next_index < new_len) {
14187 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];14192 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];
...@@ -14242,7 +14247,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -14242,7 +14247,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
14242 uint64_t i = 0;14247 uint64_t i = 0;
14243 for (uint64_t x = 0; x < mult_amt; x += 1) {14248 for (uint64_t x = 0; x < mult_amt; x += 1) {
14244 for (uint64_t y = 0; y < old_array_len; y += 1) {14249 for (uint64_t y = 0; y < old_array_len; y += 1) {
14245 out_val->data.x_array.data.s_none.elements[i] = array_val->data.x_array.data.s_none.elements[y];14250 copy_const_val(&out_val->data.x_array.data.s_none.elements[i],
14251 &array_val->data.x_array.data.s_none.elements[y], true);
14246 i += 1;14252 i += 1;
14247 }14253 }
14248 }14254 }
...@@ -14382,7 +14388,12 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14382,7 +14388,12 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14382 if (instr_is_comptime(var_ptr) && var_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {14388 if (instr_is_comptime(var_ptr) && var_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
14383 init_val = const_ptr_pointee(ira, ira->codegen, &var_ptr->value, decl_var_instruction->base.source_node);14389 init_val = const_ptr_pointee(ira, ira->codegen, &var_ptr->value, decl_var_instruction->base.source_node);
14384 if (is_comptime_var) {14390 if (is_comptime_var) {
14385 var->const_value = init_val;14391 if (var->gen_is_const) {
14392 var->const_value = init_val;
14393 } else {
14394 var->const_value = create_const_vals(1);
14395 copy_const_val(var->const_value, init_val, false);
14396 }
14386 }14397 }
14387 }14398 }
1438814399
...@@ -15291,7 +15302,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -15291,7 +15302,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
15291 arg_val = create_const_runtime(casted_arg->value.type);15302 arg_val = create_const_runtime(casted_arg->value.type);
15292 }15303 }
15293 if (arg_part_of_generic_id) {15304 if (arg_part_of_generic_id) {
15294 generic_id->params[generic_id->param_count] = *arg_val;15305 copy_const_val(&generic_id->params[generic_id->param_count], arg_val, true);
15295 generic_id->param_count += 1;15306 generic_id->param_count += 1;
15296 }15307 }
1529715308
...@@ -15476,7 +15487,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15476,7 +15487,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15476 // * "string literal used as comptime slice is memoized"15487 // * "string literal used as comptime slice is memoized"
15477 // * "comptime modification of const struct field" - except modified to avoid15488 // * "comptime modification of const struct field" - except modified to avoid
15478 // ConstPtrMutComptimeVar, thus defeating the logic below.15489 // ConstPtrMutComptimeVar, thus defeating the logic below.
15479 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;15490 bool same_global_refs = ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
15480 copy_const_val(dest_val, &value->value, same_global_refs);15491 copy_const_val(dest_val, &value->value, same_global_refs);
15481 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {15492 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
15482 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;15493 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
...@@ -15877,7 +15888,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15877,7 +15888,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15877 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);15888 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
15878 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,15889 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
15879 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);15890 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
15880 const_instruction->base.value = *align_result;15891 copy_const_val(&const_instruction->base.value, align_result, true);
1588115892
15882 uint32_t align_bytes = 0;15893 uint32_t align_bytes = 0;
15883 ir_resolve_align(ira, &const_instruction->base, &align_bytes);15894 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
...@@ -21667,7 +21678,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -21667,7 +21678,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
2166721678
21668 ConstExprValue *byte_val = &casted_byte->value;21679 ConstExprValue *byte_val = &casted_byte->value;
21669 for (size_t i = start; i < end; i += 1) {21680 for (size_t i = start; i < end; i += 1) {
21670 dest_elements[i] = *byte_val;21681 copy_const_val(&dest_elements[i], byte_val, true);
21671 }21682 }
2167221683
21673 return ir_const_void(ira, &instruction->base);21684 return ir_const_void(ira, &instruction->base);
...@@ -21835,7 +21846,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -21835,7 +21846,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
21835 // TODO check for noalias violations - this should be generalized to work for any function21846 // TODO check for noalias violations - this should be generalized to work for any function
2183621847
21837 for (size_t i = 0; i < count; i += 1) {21848 for (size_t i = 0; i < count; i += 1) {
21838 dest_elements[dest_start + i] = src_elements[src_start + i];21849 copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
21839 }21850 }
2184021851
21841 return ir_const_void(ira, &instruction->base);21852 return ir_const_void(ira, &instruction->base);
test/stage1/behavior.zig+1-1
...@@ -48,7 +48,7 @@ comptime {...@@ -48,7 +48,7 @@ comptime {
48 _ = @import("behavior/enum.zig"); // TODO48 _ = @import("behavior/enum.zig"); // TODO
49 _ = @import("behavior/enum_with_members.zig");49 _ = @import("behavior/enum_with_members.zig");
50 _ = @import("behavior/error.zig"); // TODO50 _ = @import("behavior/error.zig"); // TODO
51 _ = @import("behavior/eval.zig"); // TODO51 _ = @import("behavior/eval.zig");
52 _ = @import("behavior/field_parent_ptr.zig");52 _ = @import("behavior/field_parent_ptr.zig");
53 _ = @import("behavior/fn.zig");53 _ = @import("behavior/fn.zig");
54 _ = @import("behavior/fn_in_struct_in_comptime.zig");54 _ = @import("behavior/fn_in_struct_in_comptime.zig");
test/stage1/behavior/eval.zig+8-8
...@@ -583,14 +583,14 @@ pub const Info = struct {...@@ -583,14 +583,14 @@ pub const Info = struct {
583583
584pub const diamond_info = Info{ .version = 0 };584pub const diamond_info = Info{ .version = 0 };
585585
586//test "comptime modification of const struct field" {586test "comptime modification of const struct field" {
587// comptime {587 comptime {
588// var res = diamond_info;588 var res = diamond_info;
589// res.version = 1;589 res.version = 1;
590// expect(diamond_info.version == 0);590 expect(diamond_info.version == 0);
591// expect(res.version == 1);591 expect(res.version == 1);
592// }592 }
593//}593}
594594
595test "pointer to type" {595test "pointer to type" {
596 comptime {596 comptime {