authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-22 14:46:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-22 14:46:26-04:00
log26b79ac90ee8cf17f28b0584c773be759e0e49bd
tree78fc31e987e4d1ef8ee56d2da775ef1cea9b52d9
parent0d6a6c76eabcd020c5f58dc4667766b0e2756dfa
signaturelock-open Commit is signed but in an unrecognized format.

simple self-referential struct is working now


2 files changed, 182 insertions(+), 36 deletions(-)

src/analyze.cpp+169-31
......@@ -955,6 +955,126 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig
955955 return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false);
956956}
957957
958static 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
993static 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
1011static 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
1031static 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
1052static 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
9581078ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
9591079 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
9601080 if (type_is_invalid(result->type))
......@@ -1604,14 +1724,38 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
16041724
16051725 uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;
16061726
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.
16091729 for (size_t i = 0; i < field_count; i += 1) {
1730 AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
16101731 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
16111739 if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
16121740 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;
16131751 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 }
16141757 }
1758
16151759 }
16161760
16171761 size_t packed_bits_offset = 0;
......@@ -2133,40 +2277,33 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
21332277 return ErrorSemanticAnalyzeFail;
21342278 }
21352279
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)) {
21392283 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21402284 return ErrorSemanticAnalyzeFail;
21412285 }
2286 assert(field_type_val->special != ConstValSpecialRuntime);
2287 type_struct_field->type_val = field_type_val;
21422288 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
21432289 return ErrorSemanticAnalyzeFail;
21442290
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))) {
21512293 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21522294 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 }
21582295 }
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) {
21642297 add_node_error(g, field_node->data.struct_field.type,
21652298 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
21662299 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
21672300 return ErrorSemanticAnalyzeFail;
21682301 }
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)) {
21702307 case ReqCompTimeYes:
21712308 struct_type->data.structure.requires_comptime = true;
21722309 break;
......@@ -2177,7 +2314,12 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
21772314 break;
21782315 }
21792316
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)
21812323 continue;
21822324
21832325 type_struct_field->gen_index = gen_field_index;
......@@ -2234,21 +2376,17 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
22342376 if (field->gen_index == SIZE_MAX)
22352377 continue;
22362378
2237 src_assert(field->type_entry != nullptr, decl_node);
2238
2379 // TODO: https://github.com/ziglang/zig/issues/1512
22392380 size_t this_field_align;
22402381 if (packed) {
2241 // TODO: https://github.com/ziglang/zig/issues/1512
22422382 this_field_align = 1;
22432383 } 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))) {
22452385 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2246 return ErrorSemanticAnalyzeFail;
2386 return err;
22472387 }
2248 this_field_align = field->type_entry->abi_align;
22492388 }
22502389
2251 // TODO: https://github.com/ziglang/zig/issues/1512
22522390 if (this_field_align > struct_type->abi_align) {
22532391 struct_type->abi_align = this_field_align;
22542392 }
......@@ -4725,7 +4863,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
47254863 case ZigTypeIdStruct:
47264864 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
47274865 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)) {
47294867 case OnePossibleValueInvalid:
47304868 return OnePossibleValueInvalid;
47314869 case OnePossibleValueNo:
src/ir.cpp+13-5
......@@ -10814,10 +10814,6 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1081410814
1081510815 if (!allow_lazy) {
1081610816 if ((err = ir_resolve_lazy(codegen, node, result))) {
10817 if (codegen->trace_err != nullptr) {
10818 codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node,
10819 buf_create_from_str("referenced here"));
10820 }
1082110817 return &codegen->invalid_instruction->value;
1082210818 }
1082310819 }
......@@ -25429,7 +25425,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2542925425 zig_unreachable();
2543025426}
2543125427
25432Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
25428static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
2543325429 Error err;
2543425430 if (val->special != ConstValSpecialLazy)
2543525431 return ErrorNone;
......@@ -25491,3 +25487,15 @@ Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *va
2549125487 }
2549225488 zig_unreachable();
2549325489}
25490
25491Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
25492 Error err;
25493 if ((err = ir_resolve_lazy_raw(codegen, source_node, val))) {
25494 if (codegen->trace_err != nullptr) {
25495 codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node,
25496 buf_create_from_str("referenced here"));
25497 }
25498 return err;
25499 }
25500 return ErrorNone;
25501}