| ... | @@ -2003,6 +2003,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2003,6 +2003,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2003 | enum_type->abi_size = tag_int_type->abi_size; | 2003 | enum_type->abi_size = tag_int_type->abi_size; |
| 2004 | enum_type->abi_align = tag_int_type->abi_align; | 2004 | enum_type->abi_align = tag_int_type->abi_align; |
| 2005 | | 2005 | |
| | 2006 | BigInt bi_one; |
| | 2007 | bigint_init_unsigned(&bi_one, 1); |
| | 2008 | |
| | 2009 | TypeEnumField *last_enum_field = nullptr; |
| | 2010 | |
| 2006 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | 2011 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2007 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | 2012 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2008 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | 2013 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| ... | @@ -2028,76 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2028,76 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2028 | | 2033 | |
| 2029 | AstNode *tag_value = field_node->data.struct_field.value; | 2034 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2030 | | 2035 | |
| 2031 | // In this first pass we resolve explicit tag values. | | |
| 2032 | // In a second pass we will fill in the unspecified ones. | | |
| 2033 | if (tag_value != nullptr) { | 2036 | if (tag_value != nullptr) { |
| | 2037 | // A user-specified value is available |
| 2034 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | 2038 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2035 | if (type_is_invalid(result->type)) { | 2039 | if (type_is_invalid(result->type)) { |
| 2036 | enum_type->data.enumeration.is_invalid = true; | 2040 | enum_type->data.enumeration.is_invalid = true; |
| 2037 | continue; | 2041 | continue; |
| 2038 | } | 2042 | } |
| | 2043 | |
| 2039 | assert(result->special != ConstValSpecialRuntime); | 2044 | assert(result->special != ConstValSpecialRuntime); |
| 2040 | assert(result->type->id == ZigTypeIdInt || | 2045 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); |
| 2041 | result->type->id == ZigTypeIdComptimeInt); | 2046 | |
| 2042 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); | 2047 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2043 | if (entry == nullptr) { | 2048 | } else { |
| 2044 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | 2049 | // No value was explicitly specified: allocate the last value + 1 |
| | 2050 | // or, if this is the first element, zero |
| | 2051 | if (last_enum_field != nullptr) { |
| | 2052 | bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one); |
| 2045 | } else { | 2053 | } else { |
| 2046 | Buf *val_buf = buf_alloc(); | 2054 | bigint_init_unsigned(&type_enum_field->value, 0); |
| 2047 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); | 2055 | } |
| 2048 | | 2056 | |
| 2049 | ErrorMsg *msg = add_node_error(g, tag_value, | 2057 | // Make sure we can represent this number with tag_int_type |
| 2050 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | 2058 | if (!bigint_fits_in_bits(&type_enum_field->value, |
| 2051 | add_error_note(g, msg, entry->value, | 2059 | tag_int_type->size_in_bits, |
| 2052 | buf_sprintf("other occurrence here")); | 2060 | tag_int_type->data.integral.is_signed)) { |
| 2053 | enum_type->data.enumeration.is_invalid = true; | 2061 | enum_type->data.enumeration.is_invalid = true; |
| 2054 | continue; | | |
| 2055 | } | | |
| 2056 | } | | |
| 2057 | } | | |
| 2058 | | 2062 | |
| 2059 | // Now iterate again and populate the unspecified tag values | 2063 | Buf *val_buf = buf_alloc(); |
| 2060 | BigInt next_maybe_unoccupied_index; | 2064 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 2061 | bigint_init_unsigned(&next_maybe_unoccupied_index, 0); | 2065 | add_node_error(g, field_node, |
| | 2066 | buf_sprintf("enumeration value %s too large for type '%s'", |
| | 2067 | buf_ptr(val_buf), buf_ptr(&tag_int_type->name))); |
| 2062 | | 2068 | |
| 2063 | // Since we're allocating positive values only we have one less bit | 2069 | break; |
| 2064 | // available if the tag type is signed (eg. for a i8 we can only use (0,127)) | 2070 | } |
| 2065 | unsigned tag_bit_width = tag_int_type->size_in_bits; | 2071 | } |
| 2066 | if (tag_int_type->data.integral.is_signed) | | |
| 2067 | tag_bit_width--; | | |
| 2068 | | 2072 | |
| 2069 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | 2073 | // Make sure the value is unique |
| 2070 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | 2074 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); |
| 2071 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | 2075 | if (entry != nullptr) { |
| 2072 | AstNode *tag_value = field_node->data.struct_field.value; | 2076 | enum_type->data.enumeration.is_invalid = true; |
| 2073 | | 2077 | |
| 2074 | // Already handled in the loop above | 2078 | Buf *val_buf = buf_alloc(); |
| 2075 | if (tag_value != nullptr) | 2079 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 2076 | continue; | | |
| 2077 | | 2080 | |
| 2078 | // Make sure we can represent this number with tag_int_type | 2081 | ErrorMsg *msg = add_node_error(g, field_node, |
| 2079 | const unsigned repr_bits = bigint_bits_needed(&next_maybe_unoccupied_index); | 2082 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| 2080 | if (repr_bits > tag_bit_width) { | 2083 | add_error_note(g, msg, entry->value, |
| 2081 | enum_type->data.enumeration.is_invalid = true; | 2084 | buf_sprintf("other occurrence here")); |
| 2082 | add_node_error(g, field_node, | | |
| 2083 | buf_sprintf("enumeration value %" ZIG_PRI_u64 " too large for type '%s'", | | |
| 2084 | bigint_as_unsigned(&next_maybe_unoccupied_index), | | |
| 2085 | buf_ptr(&tag_int_type->name))); | | |
| 2086 | break; | | |
| 2087 | } | 2085 | } |
| 2088 | | 2086 | |
| 2089 | if (occupied_tag_values.size() == 0) { | 2087 | last_enum_field = type_enum_field; |
| 2090 | type_enum_field->value = next_maybe_unoccupied_index; | | |
| 2091 | bigint_incr(&next_maybe_unoccupied_index); | | |
| 2092 | } else { | | |
| 2093 | for (;;) { | | |
| 2094 | auto entry = occupied_tag_values.put_unique(next_maybe_unoccupied_index, field_node); | | |
| 2095 | if (entry == nullptr) | | |
| 2096 | break; | | |
| 2097 | bigint_incr(&next_maybe_unoccupied_index); | | |
| 2098 | } | | |
| 2099 | type_enum_field->value = next_maybe_unoccupied_index; | | |
| 2100 | } | | |
| 2101 | } | 2088 | } |
| 2102 | | 2089 | |
| 2103 | enum_type->data.enumeration.zero_bits_loop_flag = false; | 2090 | enum_type->data.enumeration.zero_bits_loop_flag = false; |