authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-21 16:09:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-21 16:09:14-05:00
logcbce61a209897598cf093180ef6b5d71c9566d6a
tree57af17f813a3a23008feb7e636e4613076d91b80
parent1066004b79d014b4c3d10da19c84c679e21b88e5
signaturelock-open Commit is signed but in an unrecognized format.

better field access of types which have one possible value

* When you do field access of a type which only has one possible value, the result is comptime-known. * StorePtr instructions which operate on pointers to types which only have one possible value, the result is a comptime no-op. closes #1554

2 files changed, 30 insertions(+), 10 deletions(-)

src/ir.cpp+22-10
...@@ -13779,16 +13779,26 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -13779,16 +13779,26 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
13779 return ir_const_void(ira, source_instr);13779 return ir_const_void(ira, source_instr);
13780 }13780 }
1378113781
13782 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13783
13782 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {13784 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13783 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));13785 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13784 return ira->codegen->invalid_instruction;13786 return ira->codegen->invalid_instruction;
13785 }13787 }
1378613788
13787 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13788 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);13789 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13789 if (value == ira->codegen->invalid_instruction)13790 if (value == ira->codegen->invalid_instruction)
13790 return ira->codegen->invalid_instruction;13791 return ira->codegen->invalid_instruction;
1379113792
13793 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13794 case OnePossibleValueInvalid:
13795 return ira->codegen->invalid_instruction;
13796 case OnePossibleValueYes:
13797 return ir_const_void(ira, source_instr);
13798 case OnePossibleValueNo:
13799 break;
13800 }
13801
13792 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {13802 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13793 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {13803 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13794 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));13804 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
...@@ -13809,15 +13819,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -13809,15 +13819,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
13809 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;13819 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13810 copy_const_val(dest_val, &value->value, same_global_refs);13820 copy_const_val(dest_val, &value->value, same_global_refs);
13811 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {13821 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13812 switch (type_has_one_possible_value(ira->codegen, child_type)) {13822 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13813 case OnePossibleValueInvalid:
13814 return ira->codegen->invalid_instruction;
13815 case OnePossibleValueNo:
13816 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13817 break;
13818 case OnePossibleValueYes:
13819 break;
13820 }
13821 }13823 }
13822 return ir_const_void(ira, source_instr);13824 return ir_const_void(ira, source_instr);
13823 }13825 }
...@@ -15346,6 +15348,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15346,6 +15348,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
15346 if (bare_type->id == ZigTypeIdStruct) {15348 if (bare_type->id == ZigTypeIdStruct) {
15347 TypeStructField *field = find_struct_type_field(bare_type, field_name);15349 TypeStructField *field = find_struct_type_field(bare_type, field_name);
15348 if (field) {15350 if (field) {
15351 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
15352 case OnePossibleValueInvalid:
15353 return ira->codegen->invalid_instruction;
15354 case OnePossibleValueYes: {
15355 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
15356 return ir_get_ref(ira, source_instr, elem, false, false);
15357 }
15358 case OnePossibleValueNo:
15359 break;
15360 }
15349 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);15361 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
15350 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);15362 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
15351 uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;15363 uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
test/stage1/behavior/struct.zig+8
...@@ -491,3 +491,11 @@ test "non-byte-aligned array inside packed struct" {...@@ -491,3 +491,11 @@ test "non-byte-aligned array inside packed struct" {
491 S.doTheTest();491 S.doTheTest();
492 comptime S.doTheTest();492 comptime S.doTheTest();
493}493}
494
495test "packed struct with u0 field access" {
496 const S = packed struct {
497 f0: u0,
498 };
499 var s = S{ .f0 = 0 };
500 comptime expect(s.f0 == 0);
501}