Begin work adding bit_field

This commit is contained in:
gingerBill
2024-02-22 15:55:20 +00:00
parent b12ba1508e
commit a4b8c1ea17
16 changed files with 535 additions and 2 deletions
+152
View File
@@ -925,6 +925,144 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam
enum_type->Enum.max_value_index = max_value_index;
}
gb_internal bool is_valid_bit_field_backing_type(Type *type) {
if (type == nullptr) {
return nullptr;
}
type = base_type(type);
if (is_type_untyped(type)) {
return false;
}
if (is_type_integer(type)) {
return true;
}
if (type->kind == Type_Array) {
return is_type_integer(type->Array.elem);
}
return false;
}
gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Type *named_type, Ast *node) {
ast_node(bf, BitFieldType, node);
GB_ASSERT(is_type_bit_field(bit_field_type));
Type *backing_type = check_type(ctx, bf->backing_type);
if (backing_type == nullptr || !is_valid_bit_field_backing_type(backing_type)) {
error(node, "Backing type for a bit_field must be an integer or an array of an integer");
return;
}
bit_field_type->BitField.backing_type = backing_type;
bit_field_type->BitField.scope = ctx->scope;
auto fields = array_make<Entity *>(permanent_allocator(), 0, bf->fields.count);
auto bit_sizes = array_make<u8> (permanent_allocator(), 0, bf->fields.count);
u64 maximum_bit_size = 8 * type_size_of(backing_type);
u64 total_bit_size = 0;
for_array(i, bf->fields) {
i32 field_src_index = cast(i32)i;
Ast *field = bf->fields[i];
if (field->kind != Ast_BitFieldField) {
error(field, "Invalid AST for a bit_field");
continue;
}
ast_node(f, BitFieldField, field);
if (f->name == nullptr || f->name->kind != Ast_Ident) {
error(field, "A bit_field's field name must be an identifier");
continue;
}
CommentGroup *docs = f->docs;
CommentGroup *comment = f->comment;
String name = f->name->Ident.token.string;
if (f->type == nullptr) {
error(field, "A bit_field's field must have a type");
continue;
}
Type *type = check_type(ctx, f->type);
if (type_size_of(type) > 8) {
error(f->type, "The type of a bit_field's field must be <= 8 bytes, got %lld", cast(long long)type_size_of(type));
}
if (is_type_untyped(type)) {
gbString s = type_to_string(type);
error(f->type, "The type of a bit_field's field must be a typed integer, enum, or boolean, got %s", s);
gb_string_free(s);
} else if (!(is_type_integer(type) || is_type_enum(type) || is_type_boolean(type))) {
gbString s = type_to_string(type);
error(f->type, "The type of a bit_field's field must be an integer, enum, or boolean, got %s", s);
gb_string_free(s);
}
if (f->bit_size == nullptr) {
error(field, "A bit_field's field must have a specified bit size");
continue;
}
Operand o = {};
check_expr(ctx, &o, f->bit_size);
if (o.mode != Addressing_Constant) {
error(f->bit_size, "A bit_field's specified bit size must be a constant");
o.mode = Addressing_Invalid;
}
if (o.value.kind == ExactValue_Float) {
o.value = exact_value_to_integer(o.value);
}
ExactValue bit_size = o.value;
if (bit_size.kind != ExactValue_Integer) {
gbString s = expr_to_string(f->bit_size);
error(f->bit_size, "Expected an integer constant value for the specified bit size, got %s", s);
gb_string_free(s);
}
if (scope_lookup_current(ctx->scope, name) != nullptr) {
error(f->name, "'%.*s' is already declared in this bit_field", LIT(name));
} else {
i64 bit_size_i64 = exact_value_to_i64(bit_size);
u8 bit_size_u8 = 0;
if (bit_size_i64 <= 0) {
error(f->bit_size, "A bit_field's specified bit size cannot be <= 0, got %lld", cast(long long)bit_size_i64);
bit_size_i64 = 1;
}
if (bit_size_i64 > 64) {
error(f->bit_size, "A bit_field's specified bit size cannot exceed 64 bits, got %lld", cast(long long)bit_size_i64);
bit_size_i64 = 64;
}
bit_size_u8 = cast(u8)bit_size_i64;
Entity *e = alloc_entity_field(ctx->scope, f->name->Ident.token, type, false, field_src_index);
e->Variable.docs = docs;
e->Variable.comment = comment;
add_entity(ctx, ctx->scope, nullptr, e);
array_add(&fields, e);
array_add(&bit_sizes, bit_size_u8);
add_entity_use(ctx, field, e);
}
}
GB_ASSERT(fields.count <= bf->fields.count);
if (total_bit_size > maximum_bit_size) {
gbString s = type_to_string(backing_type);
error(node, "The numbers required %llu exceeds the backing type's (%s) bit size %llu",
cast(unsigned long long)total_bit_size,
s,
cast(unsigned long long)maximum_bit_size);
gb_string_free(s);
}
bit_field_type->BitField.fields = slice_from_array(fields);
bit_field_type->BitField.bit_sizes = slice_from_array(bit_sizes);
}
gb_internal bool is_type_valid_bit_set_range(Type *t) {
if (is_type_integer(t)) {
return true;
@@ -3051,6 +3189,20 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
return true;
case_end;
case_ast_node(bf, BitFieldType, e);
bool ips = ctx->in_polymorphic_specialization;
defer (ctx->in_polymorphic_specialization = ips);
ctx->in_polymorphic_specialization = false;
*type = alloc_type_bit_field();
set_base_type(named_type, *type);
check_open_scope(ctx, e);
check_bit_field_type(ctx, *type, named_type, e);
check_close_scope(ctx);
(*type)->BitField.node = e;
return true;
case_end;
case_ast_node(pt, ProcType, e);
bool ips = ctx->in_polymorphic_specialization;