| ... | ... | @@ -2003,6 +2003,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2003 | 2003 | enum_type->abi_size = tag_int_type->abi_size; |
| 2004 | 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 | 2011 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2007 | 2012 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2008 | 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 | 2033 | |
| 2029 | 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 | 2036 | if (tag_value != nullptr) { |
| 2037 | // A user-specified value is available |
| 2034 | 2038 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2035 | 2039 | if (type_is_invalid(result->type)) { |
| 2036 | 2040 | enum_type->data.enumeration.is_invalid = true; |
| 2037 | 2041 | continue; |
| 2038 | 2042 | } |
| 2043 | |
| 2039 | 2044 | assert(result->special != ConstValSpecialRuntime); |
| 2040 | | assert(result->type->id == ZigTypeIdInt || |
| 2041 | | result->type->id == ZigTypeIdComptimeInt); |
| 2042 | | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); |
| 2043 | | if (entry == nullptr) { |
| 2044 | | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2045 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); |
| 2046 | |
| 2047 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2048 | } else { |
| 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 | 2053 | } else { |
| 2046 | | Buf *val_buf = buf_alloc(); |
| 2047 | | bigint_append_buf(val_buf, &result->data.x_bigint, 10); |
| 2054 | bigint_init_unsigned(&type_enum_field->value, 0); |
| 2055 | } |
| 2048 | 2056 | |
| 2049 | | ErrorMsg *msg = add_node_error(g, tag_value, |
| 2050 | | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| 2051 | | add_error_note(g, msg, entry->value, |
| 2052 | | buf_sprintf("other occurrence here")); |
| 2057 | // Make sure we can represent this number with tag_int_type |
| 2058 | if (!bigint_fits_in_bits(&type_enum_field->value, |
| 2059 | tag_int_type->size_in_bits, |
| 2060 | tag_int_type->data.integral.is_signed)) { |
| 2053 | 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 |
| 2060 | | BigInt next_maybe_unoccupied_index; |
| 2061 | | bigint_init_unsigned(&next_maybe_unoccupied_index, 0); |
| 2063 | Buf *val_buf = buf_alloc(); |
| 2064 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 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 |
| 2064 | | // available if the tag type is signed (eg. for a i8 we can only use (0,127)) |
| 2065 | | unsigned tag_bit_width = tag_int_type->size_in_bits; |
| 2066 | | if (tag_int_type->data.integral.is_signed) |
| 2067 | | tag_bit_width--; |
| 2069 | break; |
| 2070 | } |
| 2071 | } |
| 2068 | 2072 | |
| 2069 | | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2070 | | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2071 | | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| 2072 | | AstNode *tag_value = field_node->data.struct_field.value; |
| 2073 | // Make sure the value is unique |
| 2074 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); |
| 2075 | if (entry != nullptr) { |
| 2076 | enum_type->data.enumeration.is_invalid = true; |
| 2073 | 2077 | |
| 2074 | | // Already handled in the loop above |
| 2075 | | if (tag_value != nullptr) |
| 2076 | | continue; |
| 2078 | Buf *val_buf = buf_alloc(); |
| 2079 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 2077 | 2080 | |
| 2078 | | // Make sure we can represent this number with tag_int_type |
| 2079 | | const unsigned repr_bits = bigint_bits_needed(&next_maybe_unoccupied_index); |
| 2080 | | if (repr_bits > tag_bit_width) { |
| 2081 | | enum_type->data.enumeration.is_invalid = true; |
| 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; |
| 2081 | ErrorMsg *msg = add_node_error(g, field_node, |
| 2082 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| 2083 | add_error_note(g, msg, entry->value, |
| 2084 | buf_sprintf("other occurrence here")); |
| 2087 | 2085 | } |
| 2088 | 2086 | |
| 2089 | | if (occupied_tag_values.size() == 0) { |
| 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 | | } |
| 2087 | last_enum_field = type_enum_field; |
| 2101 | 2088 | } |
| 2102 | 2089 | |
| 2103 | 2090 | enum_type->data.enumeration.zero_bits_loop_flag = false; |