Commit cbce61a209

Andrew Kelley <andrew@ziglang.org>
2019-02-21 22:09:14
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
1 parent 1066004
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -13779,16 +13779,26 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
         return ir_const_void(ira, source_instr);
     }
 
+    ZigType *child_type = ptr->value.type->data.pointer.child_type;
+
     if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
         ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
         return ira->codegen->invalid_instruction;
     }
 
-    ZigType *child_type = ptr->value.type->data.pointer.child_type;
     IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
     if (value == ira->codegen->invalid_instruction)
         return ira->codegen->invalid_instruction;
 
+    switch (type_has_one_possible_value(ira->codegen, child_type)) {
+        case OnePossibleValueInvalid:
+            return ira->codegen->invalid_instruction;
+        case OnePossibleValueYes:
+            return ir_const_void(ira, source_instr);
+        case OnePossibleValueNo:
+            break;
+    }
+
     if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
         if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
             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
                     bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
                     copy_const_val(dest_val, &value->value, same_global_refs);
                     if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
-                        switch (type_has_one_possible_value(ira->codegen, child_type)) {
-                            case OnePossibleValueInvalid:
-                                return ira->codegen->invalid_instruction;
-                            case OnePossibleValueNo:
-                                ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
-                                break;
-                            case OnePossibleValueYes:
-                                break;
-                        }
+                        ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
                     }
                     return ir_const_void(ira, source_instr);
                 }
@@ -15346,6 +15348,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
     if (bare_type->id == ZigTypeIdStruct) {
         TypeStructField *field = find_struct_type_field(bare_type, field_name);
         if (field) {
+            switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
+                case OnePossibleValueInvalid:
+                    return ira->codegen->invalid_instruction;
+                case OnePossibleValueYes: {
+                    IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
+                    return ir_get_ref(ira, source_instr, elem, false, false);
+                }
+                case OnePossibleValueNo:
+                    break;
+            }
             bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
             uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
             uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
test/stage1/behavior/struct.zig
@@ -491,3 +491,11 @@ test "non-byte-aligned array inside packed struct" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "packed struct with u0 field access" {
+    const S = packed struct {
+        f0: u0,
+    };
+    var s = S{ .f0 = 0 };
+    comptime expect(s.f0 == 0);
+}