| ... | @@ -955,6 +955,126 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig | ... | @@ -955,6 +955,126 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig |
| 955 | return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false); | 955 | return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false); |
| 956 | } | 956 | } |
| 957 | | 957 | |
| | 958 | static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type, |
| | 959 | bool *is_zero_bits) |
| | 960 | { |
| | 961 | Error err; |
| | 962 | if (type_val->special != ConstValSpecialLazy) { |
| | 963 | assert(type_val->special == ConstValSpecialStatic); |
| | 964 | if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown))) |
| | 965 | return err; |
| | 966 | *is_zero_bits = (type_val->data.x_type->abi_size == 0); |
| | 967 | return ErrorNone; |
| | 968 | } |
| | 969 | switch (type_val->data.x_lazy->id) { |
| | 970 | case LazyValueIdInvalid: |
| | 971 | case LazyValueIdAlignOf: |
| | 972 | zig_unreachable(); |
| | 973 | case LazyValueIdPtrType: { |
| | 974 | LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy); |
| | 975 | if (lazy_ptr_type->elem_type == parent_type) { |
| | 976 | // Does a struct which contains a pointer field to itself have bits? Yes. |
| | 977 | *is_zero_bits = false; |
| | 978 | return ErrorNone; |
| | 979 | } else { |
| | 980 | if ((err = type_resolve(g, lazy_ptr_type->elem_type, ResolveStatusZeroBitsKnown))) |
| | 981 | return err; |
| | 982 | *is_zero_bits = type_has_bits(lazy_ptr_type->elem_type); |
| | 983 | return ErrorNone; |
| | 984 | } |
| | 985 | } |
| | 986 | case LazyValueIdSliceType: |
| | 987 | *is_zero_bits = false; |
| | 988 | return ErrorNone; |
| | 989 | } |
| | 990 | zig_unreachable(); |
| | 991 | } |
| | 992 | |
| | 993 | static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) { |
| | 994 | if (type_val->special != ConstValSpecialLazy) { |
| | 995 | assert(type_val->special == ConstValSpecialStatic); |
| | 996 | *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque); |
| | 997 | return ErrorNone; |
| | 998 | } |
| | 999 | switch (type_val->data.x_lazy->id) { |
| | 1000 | case LazyValueIdInvalid: |
| | 1001 | case LazyValueIdAlignOf: |
| | 1002 | zig_unreachable(); |
| | 1003 | case LazyValueIdSliceType: |
| | 1004 | case LazyValueIdPtrType: |
| | 1005 | *is_opaque_type = false; |
| | 1006 | return ErrorNone; |
| | 1007 | } |
| | 1008 | zig_unreachable(); |
| | 1009 | } |
| | 1010 | |
| | 1011 | static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type) { |
| | 1012 | if (type_val->special != ConstValSpecialLazy) { |
| | 1013 | return type_requires_comptime(g, type_val->data.x_type, parent_type); |
| | 1014 | } |
| | 1015 | switch (type_val->data.x_lazy->id) { |
| | 1016 | case LazyValueIdInvalid: |
| | 1017 | case LazyValueIdAlignOf: |
| | 1018 | zig_unreachable(); |
| | 1019 | case LazyValueIdSliceType: { |
| | 1020 | LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy); |
| | 1021 | return type_requires_comptime(g, lazy_slice_type->elem_type, parent_type); |
| | 1022 | } |
| | 1023 | case LazyValueIdPtrType: { |
| | 1024 | LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy); |
| | 1025 | return type_requires_comptime(g, lazy_ptr_type->elem_type, parent_type); |
| | 1026 | } |
| | 1027 | } |
| | 1028 | zig_unreachable(); |
| | 1029 | } |
| | 1030 | |
| | 1031 | static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, size_t *abi_align) { |
| | 1032 | Error err; |
| | 1033 | if (type_val->special != ConstValSpecialLazy) { |
| | 1034 | assert(type_val->special == ConstValSpecialStatic); |
| | 1035 | if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusAlignmentKnown))) |
| | 1036 | return err; |
| | 1037 | *abi_align = type_val->data.x_type->abi_align; |
| | 1038 | return ErrorNone; |
| | 1039 | } |
| | 1040 | switch (type_val->data.x_lazy->id) { |
| | 1041 | case LazyValueIdInvalid: |
| | 1042 | case LazyValueIdAlignOf: |
| | 1043 | zig_unreachable(); |
| | 1044 | case LazyValueIdSliceType: |
| | 1045 | case LazyValueIdPtrType: |
| | 1046 | *abi_align = g->builtin_types.entry_usize->abi_align; |
| | 1047 | return ErrorNone; |
| | 1048 | } |
| | 1049 | zig_unreachable(); |
| | 1050 | } |
| | 1051 | |
| | 1052 | static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ConstExprValue *type_val) { |
| | 1053 | if (type_val->special != ConstValSpecialLazy) { |
| | 1054 | return type_has_one_possible_value(g, type_val->data.x_type); |
| | 1055 | } |
| | 1056 | switch (type_val->data.x_lazy->id) { |
| | 1057 | case LazyValueIdInvalid: |
| | 1058 | case LazyValueIdAlignOf: |
| | 1059 | zig_unreachable(); |
| | 1060 | case LazyValueIdSliceType: |
| | 1061 | return OnePossibleValueNo; // it has the len field |
| | 1062 | case LazyValueIdPtrType: { |
| | 1063 | Error err; |
| | 1064 | bool zero_bits; |
| | 1065 | if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, &zero_bits))) { |
| | 1066 | return OnePossibleValueInvalid; |
| | 1067 | } |
| | 1068 | if (zero_bits) { |
| | 1069 | return OnePossibleValueYes; |
| | 1070 | } else { |
| | 1071 | return OnePossibleValueNo; |
| | 1072 | } |
| | 1073 | } |
| | 1074 | } |
| | 1075 | zig_unreachable(); |
| | 1076 | } |
| | 1077 | |
| 958 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { | 1078 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| 959 | ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); | 1079 | ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); |
| 960 | if (type_is_invalid(result->type)) | 1080 | if (type_is_invalid(result->type)) |
| ... | @@ -1604,14 +1724,38 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -1604,14 +1724,38 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 1604 | | 1724 | |
| 1605 | uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr; | 1725 | uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr; |
| 1606 | | 1726 | |
| 1607 | // Resolve sizes of all the field types. Done before the offset loop because the offset | 1727 | // Resolve types for fields and then resolve sizes of all the field types. |
| 1608 | // loop has to look ahead. | 1728 | // This is done before the offset loop because the offset loop has to look ahead. |
| 1609 | for (size_t i = 0; i < field_count; i += 1) { | 1729 | for (size_t i = 0; i < field_count; i += 1) { |
| | 1730 | AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); |
| 1610 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 1731 | TypeStructField *field = &struct_type->data.structure.fields[i]; |
| | 1732 | |
| | 1733 | if ((err = ir_resolve_lazy(g, field_source_node, field->type_val))) { |
| | 1734 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| | 1735 | return err; |
| | 1736 | } |
| | 1737 | field->type_entry = field->type_val->data.x_type; |
| | 1738 | |
| 1611 | if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) { | 1739 | if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) { |
| 1612 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 1740 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| | 1741 | return err; |
| | 1742 | } |
| | 1743 | |
| | 1744 | if (struct_type->data.structure.layout == ContainerLayoutExtern && |
| | 1745 | !type_allowed_in_extern(g, field->type_entry)) |
| | 1746 | { |
| | 1747 | add_node_error(g, field_source_node, |
| | 1748 | buf_sprintf("extern structs cannot contain fields of type '%s'", |
| | 1749 | buf_ptr(&field->type_entry->name))); |
| | 1750 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 1613 | return ErrorSemanticAnalyzeFail; | 1751 | return ErrorSemanticAnalyzeFail; |
| | 1752 | } else if (packed) { |
| | 1753 | if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field->type_entry, field_source_node))) { |
| | 1754 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| | 1755 | return err; |
| | 1756 | } |
| 1614 | } | 1757 | } |
| | 1758 | |
| 1615 | } | 1759 | } |
| 1616 | | 1760 | |
| 1617 | size_t packed_bits_offset = 0; | 1761 | size_t packed_bits_offset = 0; |
| ... | @@ -2133,40 +2277,33 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2133,40 +2277,33 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2133 | return ErrorSemanticAnalyzeFail; | 2277 | return ErrorSemanticAnalyzeFail; |
| 2134 | } | 2278 | } |
| 2135 | | 2279 | |
| 2136 | ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); | 2280 | ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope, |
| 2137 | type_struct_field->type_entry = field_type; | 2281 | field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true); |
| 2138 | if (type_is_invalid(field_type)) { | 2282 | if (type_is_invalid(field_type_val->type)) { |
| 2139 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2283 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2140 | return ErrorSemanticAnalyzeFail; | 2284 | return ErrorSemanticAnalyzeFail; |
| 2141 | } | 2285 | } |
| | 2286 | assert(field_type_val->special != ConstValSpecialRuntime); |
| | 2287 | type_struct_field->type_val = field_type_val; |
| 2142 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) | 2288 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) |
| 2143 | return ErrorSemanticAnalyzeFail; | 2289 | return ErrorSemanticAnalyzeFail; |
| 2144 | | 2290 | |
| 2145 | if (struct_type->data.structure.layout == ContainerLayoutExtern && | 2291 | bool field_is_opaque_type; |
| 2146 | !type_allowed_in_extern(g, field_type)) | 2292 | if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { |
| 2147 | { | | |
| 2148 | add_node_error(g, field_node, | | |
| 2149 | buf_sprintf("extern structs cannot contain fields of type '%s'", | | |
| 2150 | buf_ptr(&field_type->name))); | | |
| 2151 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2293 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2152 | return ErrorSemanticAnalyzeFail; | 2294 | return ErrorSemanticAnalyzeFail; |
| 2153 | } else if (struct_type->data.structure.layout == ContainerLayoutPacked) { | | |
| 2154 | if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_node))) { | | |
| 2155 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | | |
| 2156 | return ErrorSemanticAnalyzeFail; | | |
| 2157 | } | | |
| 2158 | } | 2295 | } |
| 2159 | | 2296 | if (field_is_opaque_type) { |
| 2160 | type_struct_field->src_index = i; | | |
| 2161 | type_struct_field->gen_index = SIZE_MAX; | | |
| 2162 | | | |
| 2163 | if (field_type->id == ZigTypeIdOpaque) { | | |
| 2164 | add_node_error(g, field_node->data.struct_field.type, | 2297 | add_node_error(g, field_node->data.struct_field.type, |
| 2165 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); | 2298 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); |
| 2166 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2299 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2167 | return ErrorSemanticAnalyzeFail; | 2300 | return ErrorSemanticAnalyzeFail; |
| 2168 | } | 2301 | } |
| 2169 | switch (type_requires_comptime(g, field_type, struct_type)) { | 2302 | |
| | 2303 | type_struct_field->src_index = i; |
| | 2304 | type_struct_field->gen_index = SIZE_MAX; |
| | 2305 | |
| | 2306 | switch (type_val_resolve_requires_comptime(g, field_type_val, struct_type)) { |
| 2170 | case ReqCompTimeYes: | 2307 | case ReqCompTimeYes: |
| 2171 | struct_type->data.structure.requires_comptime = true; | 2308 | struct_type->data.structure.requires_comptime = true; |
| 2172 | break; | 2309 | break; |
| ... | @@ -2177,7 +2314,12 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2177,7 +2314,12 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2177 | break; | 2314 | break; |
| 2178 | } | 2315 | } |
| 2179 | | 2316 | |
| 2180 | if (!type_has_bits(field_type)) | 2317 | bool field_is_zero_bits; |
| | 2318 | if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, &field_is_zero_bits))) { |
| | 2319 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| | 2320 | return ErrorSemanticAnalyzeFail; |
| | 2321 | } |
| | 2322 | if (field_is_zero_bits) |
| 2181 | continue; | 2323 | continue; |
| 2182 | | 2324 | |
| 2183 | type_struct_field->gen_index = gen_field_index; | 2325 | type_struct_field->gen_index = gen_field_index; |
| ... | @@ -2234,21 +2376,17 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2234,21 +2376,17 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2234 | if (field->gen_index == SIZE_MAX) | 2376 | if (field->gen_index == SIZE_MAX) |
| 2235 | continue; | 2377 | continue; |
| 2236 | | 2378 | |
| 2237 | src_assert(field->type_entry != nullptr, decl_node); | 2379 | // TODO: https://github.com/ziglang/zig/issues/1512 |
| 2238 | | | |
| 2239 | size_t this_field_align; | 2380 | size_t this_field_align; |
| 2240 | if (packed) { | 2381 | if (packed) { |
| 2241 | // TODO: https://github.com/ziglang/zig/issues/1512 | | |
| 2242 | this_field_align = 1; | 2382 | this_field_align = 1; |
| 2243 | } else { | 2383 | } else { |
| 2244 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { | 2384 | if ((err = type_val_resolve_abi_align(g, field->type_val, &this_field_align))) { |
| 2245 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2385 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2246 | return ErrorSemanticAnalyzeFail; | 2386 | return err; |
| 2247 | } | 2387 | } |
| 2248 | this_field_align = field->type_entry->abi_align; | | |
| 2249 | } | 2388 | } |
| 2250 | | 2389 | |
| 2251 | // TODO: https://github.com/ziglang/zig/issues/1512 | | |
| 2252 | if (this_field_align > struct_type->abi_align) { | 2390 | if (this_field_align > struct_type->abi_align) { |
| 2253 | struct_type->abi_align = this_field_align; | 2391 | struct_type->abi_align = this_field_align; |
| 2254 | } | 2392 | } |
| ... | @@ -4725,7 +4863,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { | ... | @@ -4725,7 +4863,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 4725 | case ZigTypeIdStruct: | 4863 | case ZigTypeIdStruct: |
| 4726 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | 4864 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { |
| 4727 | TypeStructField *field = &type_entry->data.structure.fields[i]; | 4865 | TypeStructField *field = &type_entry->data.structure.fields[i]; |
| 4728 | switch (type_has_one_possible_value(g, field->type_entry)) { | 4866 | switch (type_val_resolve_has_one_possible_value(g, field->type_val)) { |
| 4729 | case OnePossibleValueInvalid: | 4867 | case OnePossibleValueInvalid: |
| 4730 | return OnePossibleValueInvalid; | 4868 | return OnePossibleValueInvalid; |
| 4731 | case OnePossibleValueNo: | 4869 | case OnePossibleValueNo: |