| ... | ... | @@ -955,6 +955,126 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig |
| 955 | 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 | 1078 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| 959 | 1079 | ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); |
| 960 | 1080 | if (type_is_invalid(result->type)) |
| ... | ... | @@ -1604,14 +1724,38 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 1604 | 1724 | |
| 1605 | 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 |
| 1608 | | // loop has to look ahead. |
| 1727 | // Resolve types for fields and then resolve sizes of all the field types. |
| 1728 | // This is done before the offset loop because the offset loop has to look ahead. |
| 1609 | 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 | 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 | 1739 | if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) { |
| 1612 | 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 | 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 | 1761 | size_t packed_bits_offset = 0; |
| ... | ... | @@ -2133,40 +2277,33 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2133 | 2277 | return ErrorSemanticAnalyzeFail; |
| 2134 | 2278 | } |
| 2135 | 2279 | |
| 2136 | | ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2137 | | type_struct_field->type_entry = field_type; |
| 2138 | | if (type_is_invalid(field_type)) { |
| 2280 | ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope, |
| 2281 | field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true); |
| 2282 | if (type_is_invalid(field_type_val->type)) { |
| 2139 | 2283 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2140 | 2284 | return ErrorSemanticAnalyzeFail; |
| 2141 | 2285 | } |
| 2286 | assert(field_type_val->special != ConstValSpecialRuntime); |
| 2287 | type_struct_field->type_val = field_type_val; |
| 2142 | 2288 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) |
| 2143 | 2289 | return ErrorSemanticAnalyzeFail; |
| 2144 | 2290 | |
| 2145 | | if (struct_type->data.structure.layout == ContainerLayoutExtern && |
| 2146 | | !type_allowed_in_extern(g, field_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))); |
| 2291 | bool field_is_opaque_type; |
| 2292 | if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { |
| 2151 | 2293 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2152 | 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 | | |
| 2160 | | type_struct_field->src_index = i; |
| 2161 | | type_struct_field->gen_index = SIZE_MAX; |
| 2162 | | |
| 2163 | | if (field_type->id == ZigTypeIdOpaque) { |
| 2296 | if (field_is_opaque_type) { |
| 2164 | 2297 | add_node_error(g, field_node->data.struct_field.type, |
| 2165 | 2298 | buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); |
| 2166 | 2299 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2167 | 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 | 2307 | case ReqCompTimeYes: |
| 2171 | 2308 | struct_type->data.structure.requires_comptime = true; |
| 2172 | 2309 | break; |
| ... | ... | @@ -2177,7 +2314,12 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2177 | 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 | 2323 | continue; |
| 2182 | 2324 | |
| 2183 | 2325 | type_struct_field->gen_index = gen_field_index; |
| ... | ... | @@ -2234,21 +2376,17 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2234 | 2376 | if (field->gen_index == SIZE_MAX) |
| 2235 | 2377 | continue; |
| 2236 | 2378 | |
| 2237 | | src_assert(field->type_entry != nullptr, decl_node); |
| 2238 | | |
| 2379 | // TODO: https://github.com/ziglang/zig/issues/1512 |
| 2239 | 2380 | size_t this_field_align; |
| 2240 | 2381 | if (packed) { |
| 2241 | | // TODO: https://github.com/ziglang/zig/issues/1512 |
| 2242 | 2382 | this_field_align = 1; |
| 2243 | 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 | 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 | 2390 | if (this_field_align > struct_type->abi_align) { |
| 2253 | 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 | 4863 | case ZigTypeIdStruct: |
| 4726 | 4864 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { |
| 4727 | 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 | 4867 | case OnePossibleValueInvalid: |
| 4730 | 4868 | return OnePossibleValueInvalid; |
| 4731 | 4869 | case OnePossibleValueNo: |