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
+9
View File
@@ -181,6 +181,13 @@ Type_Info_Matrix :: struct {
Type_Info_Soa_Pointer :: struct {
elem: ^Type_Info,
}
Type_Info_Bit_Field :: struct {
backing_type: ^Type_Info,
names: []string,
types: []^Type_Info,
bit_sizes: []uintptr,
bit_offsets: []uintptr,
}
Type_Info_Flag :: enum u8 {
Comparable = 0,
@@ -223,6 +230,7 @@ Type_Info :: struct {
Type_Info_Relative_Multi_Pointer,
Type_Info_Matrix,
Type_Info_Soa_Pointer,
Type_Info_Bit_Field,
},
}
@@ -256,6 +264,7 @@ Typeid_Kind :: enum u8 {
Relative_Multi_Pointer,
Matrix,
Soa_Pointer,
Bit_Field,
}
#assert(len(Typeid_Kind) < 32)
+14
View File
@@ -459,6 +459,20 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
}
print_byte(']')
case Type_Info_Bit_Field:
print_string("bit_field ")
print_type(info.backing_type)
print_string(" {")
for name, i in info.names {
if i > 0 { print_string(", ") }
print_string(name)
print_string(": ")
print_type(info.types[i])
print_string(" | ")
print_u64(u64(info.bit_sizes[i]))
}
print_byte('}')
case Type_Info_Simd_Vector:
print_string("#simd[")
+3
View File
@@ -228,6 +228,9 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case runtime.Type_Info_Matrix:
return .Unsupported_Type
case runtime.Type_Info_Bit_Field:
return .Unsupported_Type
case runtime.Type_Info_Array:
opt_write_start(w, opt, '[') or_return
for i in 0..<info.count {
+65
View File
@@ -2283,6 +2283,68 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix
fmt_write_indent(fi)
}
}
fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit_Field) {
read_bits :: proc(ptr: [^]byte, offset, size: uintptr) -> (res: u64) {
for i in 0..<size {
j := i+offset
B := ptr[j/8]
k := j&7
if B & (u8(1)<<k) != 0 {
res |= u64(1)<<u64(i)
}
}
return
}
io.write_string(fi.writer, "bit_field{", &fi.n)
hash := fi.hash; defer fi.hash = hash
indent := fi.indent; defer fi.indent -= 1
do_trailing_comma := hash
fi.indent += 1
if hash {
io.write_byte(fi.writer, '\n', &fi.n)
}
defer {
if hash {
for _ in 0..<indent { io.write_byte(fi.writer, '\t', &fi.n) }
}
io.write_byte(fi.writer, '}', &fi.n)
}
field_count := -1
for name, i in info.names {
_ = i
field_count += 1
if !do_trailing_comma && field_count > 0 {
io.write_string(fi.writer, ", ")
}
if hash {
fmt_write_indent(fi)
}
io.write_string(fi.writer, name, &fi.n)
io.write_string(fi.writer, " = ", &fi.n)
bit_offset := info.bit_offsets[i]
bit_size := info.bit_sizes[i]
value := read_bits(([^]byte)(v.data), bit_offset, bit_size)
fmt_value(fi, any{&value, info.types[i].id}, verb)
if do_trailing_comma { io.write_string(fi.writer, ",\n", &fi.n) }
}
}
// Formats a value based on its type and formatting verb
//
// Inputs:
@@ -2611,6 +2673,9 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
case runtime.Type_Info_Matrix:
fmt_matrix(fi, v, verb, info)
case runtime.Type_Info_Bit_Field:
fmt_bit_field(fi, v, verb, info)
}
}
// Formats a complex number based on the given formatting verb
+10
View File
@@ -35,6 +35,7 @@ Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer
Type_Info_Relative_Multi_Pointer :: runtime.Type_Info_Relative_Multi_Pointer
Type_Info_Matrix :: runtime.Type_Info_Matrix
Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer
Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field
Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value
@@ -70,6 +71,7 @@ Type_Kind :: enum {
Relative_Multi_Pointer,
Matrix,
Soa_Pointer,
Bit_Field,
}
@@ -106,6 +108,7 @@ type_kind :: proc(T: typeid) -> Type_Kind {
case Type_Info_Relative_Multi_Pointer: return .Relative_Multi_Pointer
case Type_Info_Matrix: return .Matrix
case Type_Info_Soa_Pointer: return .Soa_Pointer
case Type_Info_Bit_Field: return .Bit_Field
}
}
@@ -1604,6 +1607,13 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
}
return true
case Type_Info_Bit_Field:
x, y := a, b
x.id = v.backing_type.id
y.id = v.backing_type.id
return equal(x, y, including_indirect_array_recursion, recursion_level+0)
}
runtime.print_typeid(a.id)
+31
View File
@@ -174,6 +174,23 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
if x.row_count != y.row_count { return false }
if x.column_count != y.column_count { return false }
return are_types_identical(x.elem, y.elem)
case Type_Info_Bit_Field:
y := b.variant.(Type_Info_Bit_Field) or_return
if !are_types_identical(x.backing_type, y.backing_type) { return false }
if len(x.names) != len(y.names) { return false }
for _, i in x.names {
if x.names[i] != y.names[i] {
return false
}
if !are_types_identical(x.types[i], y.types[i]) {
return false
}
if x.bit_sizes[i] != y.bit_sizes[i] {
return false
}
}
return true
}
return false
@@ -639,6 +656,20 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
}
io.write_byte(w, ']', &n) or_return
case Type_Info_Bit_Field:
io.write_string(w, "bit_field ", &n) or_return
write_type(w, info.backing_type, &n) or_return
io.write_string(w, " {", &n) or_return
for name, i in info.names {
if i > 0 { io.write_string(w, ", ", &n) or_return }
io.write_string(w, name, &n) or_return
io.write_string(w, ": ", &n) or_return
write_type(w, info.types[i], &n) or_return
io.write_string(w, " | ", &n) or_return
io.write_u64(w, u64(info.bit_sizes[i]), 10, &n) or_return
}
io.write_string(w, "}", &n) or_return
case Type_Info_Simd_Vector:
io.write_string(w, "#simd[", &n) or_return
io.write_i64(w, i64(info.count), 10, &n) or_return
+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;
+18
View File
@@ -313,6 +313,7 @@ gb_internal void add_scope(CheckerContext *c, Ast *node, Scope *scope) {
case Ast_StructType: node->StructType.scope = scope; break;
case Ast_UnionType: node->UnionType.scope = scope; break;
case Ast_EnumType: node->EnumType.scope = scope; break;
case Ast_BitFieldType: node->BitFieldType.scope = scope; break;
default: GB_PANIC("Invalid node for add_scope: %.*s", LIT(ast_strings[node->kind]));
}
}
@@ -334,6 +335,7 @@ gb_internal Scope *scope_of_node(Ast *node) {
case Ast_StructType: return node->StructType.scope;
case Ast_UnionType: return node->UnionType.scope;
case Ast_EnumType: return node->EnumType.scope;
case Ast_BitFieldType: return node->BitFieldType.scope;
}
GB_PANIC("Invalid node for add_scope: %.*s", LIT(ast_strings[node->kind]));
return nullptr;
@@ -355,6 +357,7 @@ gb_internal void check_open_scope(CheckerContext *c, Ast *node) {
case Ast_EnumType:
case Ast_UnionType:
case Ast_BitSetType:
case Ast_BitFieldType:
scope->flags |= ScopeFlag_Type;
break;
}
@@ -2060,6 +2063,12 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) {
add_type_info_type_internal(c, bt->SoaPointer.elem);
break;
case Type_BitField:
add_type_info_type_internal(c, bt->BitField.backing_type);
for (Entity *f : bt->BitField.fields) {
add_type_info_type_internal(c, f->type);
}
break;
case Type_Generic:
break;
@@ -2309,6 +2318,13 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) {
add_min_dep_type_info(c, bt->SoaPointer.elem);
break;
case Type_BitField:
add_min_dep_type_info(c, bt->BitField.backing_type);
for (Entity *f : bt->BitField.fields) {
add_min_dep_type_info(c, f->type);
}
break;
default:
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
break;
@@ -2907,6 +2923,7 @@ gb_internal void init_core_type_info(Checker *c) {
t_type_info_relative_multi_pointer = find_core_type(c, str_lit("Type_Info_Relative_Multi_Pointer"));
t_type_info_matrix = find_core_type(c, str_lit("Type_Info_Matrix"));
t_type_info_soa_pointer = find_core_type(c, str_lit("Type_Info_Soa_Pointer"));
t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field"));
t_type_info_named_ptr = alloc_type_pointer(t_type_info_named);
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
@@ -2936,6 +2953,7 @@ gb_internal void init_core_type_info(Checker *c) {
t_type_info_relative_multi_pointer_ptr = alloc_type_pointer(t_type_info_relative_multi_pointer);
t_type_info_matrix_ptr = alloc_type_pointer(t_type_info_matrix);
t_type_info_soa_pointer_ptr = alloc_type_pointer(t_type_info_soa_pointer);
t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field);
}
gb_internal void init_mem_allocator(Checker *c) {
+7 -1
View File
@@ -2719,6 +2719,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
{ // Type info member buffer
// NOTE(bill): Removes need for heap allocation by making it global memory
isize count = 0;
isize offsets_extra = 0;
for (Type *t : m->info->type_info_types) {
isize index = lb_type_info_index(m->info, t, false);
@@ -2736,6 +2737,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
case Type_Tuple:
count += t->Tuple.variables.count;
break;
case Type_BitField:
count += t->BitField.fields.count;
// Twice is needed for the bit_offsets
offsets_extra += t->BitField.fields.count;
break;
}
}
@@ -2752,7 +2758,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
lb_global_type_info_member_types = global_type_info_make(m, LB_TYPE_INFO_TYPES_NAME, t_type_info_ptr, count);
lb_global_type_info_member_names = global_type_info_make(m, LB_TYPE_INFO_NAMES_NAME, t_string, count);
lb_global_type_info_member_offsets = global_type_info_make(m, LB_TYPE_INFO_OFFSETS_NAME, t_uintptr, count);
lb_global_type_info_member_offsets = global_type_info_make(m, LB_TYPE_INFO_OFFSETS_NAME, t_uintptr, count+offsets_extra);
lb_global_type_info_member_usings = global_type_info_make(m, LB_TYPE_INFO_USINGS_NAME, t_bool, count);
lb_global_type_info_member_tags = global_type_info_make(m, LB_TYPE_INFO_TAGS_NAME, t_string, count);
}
+36
View File
@@ -461,6 +461,42 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
lb_debug_type(m, type->Matrix.elem),
subscripts, gb_count_of(subscripts));
}
case Type_BitField: {
LLVMMetadataRef parent_scope = nullptr;
LLVMMetadataRef scope = nullptr;
LLVMMetadataRef file = nullptr;
unsigned line = 0;
u64 size_in_bits = 8*cast(u64)type_size_of(type);
u32 align_in_bits = 8*cast(u32)type_align_of(type);
LLVMDIFlags flags = LLVMDIFlagZero;
unsigned element_count = cast(unsigned)type->BitField.fields.count;
LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count);
u64 offset_in_bits = 0;
for (unsigned i = 0; i < element_count; i++) {
Entity *f = type->BitField.fields[i];
u8 bit_size = type->BitField.bit_sizes[i];
GB_ASSERT(f->kind == Entity_Variable);
String name = f->token.string;
unsigned field_line = 0;
LLVMDIFlags field_flags = LLVMDIFlagZero;
elements[i] = LLVMDIBuilderCreateBitFieldMemberType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, field_line,
bit_size, offset_in_bits, offset_in_bits,
field_flags, lb_debug_type(m, f->type)
);
offset_in_bits += bit_size;
}
return LLVMDIBuilderCreateStructType(m->debug_builder, parent_scope, "", 0, file, line,
size_in_bits, align_in_bits, flags,
nullptr, elements, element_count, 0, nullptr,
"", 0
);
}
}
GB_PANIC("Invalid type %s", type_to_string(type));
+3 -1
View File
@@ -2216,7 +2216,9 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
}
return LLVMStructTypeInContext(ctx, fields, field_count, false);
}
case Type_BitField:
return lb_type_internal(m, type->BitField.backing_type);
}
GB_PANIC("Invalid type %s", type_to_string(type));
+67
View File
@@ -1788,6 +1788,73 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
lb_emit_store(p, tag, res);
}
break;
case Type_BitField:
{
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_bit_field_ptr);
LLVMValueRef vals[5] = {};
vals[0] = lb_type_info(m, t->BitField.backing_type).value;
isize count = t->BitField.fields.count;
if (count > 0) {
i64 names_offset = 0;
i64 types_offset = 0;
i64 bit_sizes_offset = 0;
i64 bit_offsets_offset = 0;
lbValue memory_names = lb_type_info_member_names_offset (m, count, &names_offset);
lbValue memory_types = lb_type_info_member_types_offset (m, count, &types_offset);
lbValue memory_bit_sizes = lb_type_info_member_offsets_offset(m, count, &bit_sizes_offset);
lbValue memory_bit_offsets = lb_type_info_member_offsets_offset(m, count, &bit_offsets_offset);
u64 bit_offset = 0;
for (isize source_index = 0; source_index < count; source_index++) {
Entity *f = t->BitField.fields[source_index];
u64 bit_size = cast(u64)t->BitField.bit_sizes[source_index];
lbValue index = lb_const_int(m, t_int, source_index);
if (f->token.string.len > 0) {
lbValue name = lb_emit_ptr_offset(p, memory_names, index);
lb_emit_store(p, name, lb_const_string(m, f->token.string));
}
lbValue type_ptr = lb_emit_ptr_offset(p, memory_types, index);
lbValue bit_size_ptr = lb_emit_ptr_offset(p, memory_bit_sizes, index);
lbValue bit_offset_ptr = lb_emit_ptr_offset(p, memory_bit_offsets, index);
lb_emit_store(p, type_ptr, lb_type_info(m, f->type));
lb_emit_store(p, bit_size_ptr, lb_const_int(m, t_uintptr, bit_size));
lb_emit_store(p, bit_offset_ptr, lb_const_int(m, t_uintptr, bit_offset));
// lb_global_type_info_member_types_values [types_offset +source_index] = get_type_info_ptr(m, f->type);
// lb_global_type_info_member_offsets_values[bit_sizes_offset +source_index] = lb_const_int(m, t_uintptr, bit_size).value;
// lb_global_type_info_member_offsets_values[bit_offsets_offset+source_index] = lb_const_int(m, t_uintptr, bit_offset).value;
// if (f->token.string.len > 0) {
// lb_global_type_info_member_names_values[names_offset+source_index] = lb_const_string(m, f->token.string).value;
// }
bit_offset += bit_size;
}
lbValue cv = lb_const_int(m, t_int, count);
vals[1] = llvm_const_slice(m, memory_names, cv);
vals[2] = llvm_const_slice(m, memory_types, cv);
vals[3] = llvm_const_slice(m, memory_bit_sizes, cv);
vals[4] = llvm_const_slice(m, memory_bit_offsets, cv);
}
for (isize i = 0; i < gb_count_of(vals); i++) {
if (vals[i] == nullptr) {
vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag.type, i)));
}
}
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
}
+78
View File
@@ -350,6 +350,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
n->Field.names = clone_ast_array(n->Field.names, f);
n->Field.type = clone_ast(n->Field.type, f);
break;
case Ast_BitFieldField:
n->BitFieldField.name = clone_ast(n->BitFieldField.name, f);
n->BitFieldField.type = clone_ast(n->BitFieldField.type, f);
n->BitFieldField.bit_size = clone_ast(n->BitFieldField.bit_size, f);
break;
case Ast_FieldList:
n->FieldList.list = clone_ast_array(n->FieldList.list, f);
break;
@@ -406,6 +411,10 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
n->BitSetType.elem = clone_ast(n->BitSetType.elem, f);
n->BitSetType.underlying = clone_ast(n->BitSetType.underlying, f);
break;
case Ast_BitFieldType:
n->BitFieldType.backing_type = clone_ast(n->BitFieldType.backing_type, f);
n->BitFieldType.fields = clone_ast_array(n->BitFieldType.fields, f);
break;
case Ast_MapType:
n->MapType.count = clone_ast(n->MapType.count, f);
n->MapType.key = clone_ast(n->MapType.key, f);
@@ -1045,6 +1054,17 @@ gb_internal Ast *ast_field(AstFile *f, Array<Ast *> const &names, Ast *type, Ast
return result;
}
gb_internal Ast *ast_bit_field_field(AstFile *f, Ast *name, Ast *type, Ast *bit_size,
CommentGroup *docs, CommentGroup *comment) {
Ast *result = alloc_ast_node(f, Ast_BitFieldField);
result->BitFieldField.name = name;
result->BitFieldField.type = type;
result->BitFieldField.bit_size = bit_size;
result->BitFieldField.docs = docs;
result->BitFieldField.comment = comment;
return result;
}
gb_internal Ast *ast_field_list(AstFile *f, Token token, Array<Ast *> const &list) {
Ast *result = alloc_ast_node(f, Ast_FieldList);
result->FieldList.token = token;
@@ -1178,6 +1198,17 @@ gb_internal Ast *ast_bit_set_type(AstFile *f, Token token, Ast *elem, Ast *under
return result;
}
gb_internal Ast *ast_bit_field_type(AstFile *f, Token token, Ast *backing_type, Token open, Array<Ast *> const &fields, Token close) {
Ast *result = alloc_ast_node(f, Ast_BitFieldType);
result->BitFieldType.token = token;
result->BitFieldType.backing_type = backing_type;
result->BitFieldType.open = open;
result->BitFieldType.fields = slice_from_array(fields);
result->BitFieldType.close = close;
return result;
}
gb_internal Ast *ast_map_type(AstFile *f, Token token, Ast *key, Ast *value) {
Ast *result = alloc_ast_node(f, Ast_MapType);
result->MapType.token = token;
@@ -2549,6 +2580,53 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
return ast_matrix_type(f, token, row_count, column_count, type);
} break;
case Token_bit_field: {
Token token = expect_token(f, Token_bit_field);
isize prev_level;
prev_level = f->expr_level;
f->expr_level = -1;
Ast *backing_type = parse_type_or_ident(f);
if (backing_type == nullptr) {
Token token = advance_token(f);
syntax_error(token, "Expected a backing type for a 'bit_field'");
backing_type = ast_bad_expr(f, token, f->curr_token);
}
skip_possible_newline_for_literal(f);
Token open = expect_token_after(f, Token_OpenBrace, "bit_field");
auto fields = array_make<Ast *>(ast_allocator(f), 0, 0);
while (f->curr_token.kind != Token_CloseBrace &&
f->curr_token.kind != Token_EOF) {
CommentGroup *docs = nullptr;
CommentGroup *comment = nullptr;
Ast *name = parse_ident(f);
expect_token(f, Token_Colon);
Ast *type = parse_type(f);
expect_token(f, Token_Or);
Ast *bit_size = parse_expr(f, true);
Ast *bf_field = ast_bit_field_field(f, name, type, bit_size, docs, comment);
array_add(&fields, bf_field);
if (!allow_field_separator(f)) {
break;
}
}
Token close = expect_closing_brace_of_field_list(f);
f->expr_level = prev_level;
return ast_bit_field_type(f, token, backing_type, open, fields, close);
}
case Token_struct: {
Token token = expect_token(f, Token_struct);
Ast *polymorphic_params = nullptr;
+15
View File
@@ -650,6 +650,13 @@ AST_KIND(_DeclEnd, "", bool) \
CommentGroup * docs; \
CommentGroup * comment; \
}) \
AST_KIND(BitFieldField, "bit field field", struct { \
Ast * name; \
Ast * type; \
Ast * bit_size; \
CommentGroup *docs; \
CommentGroup *comment; \
}) \
AST_KIND(FieldList, "field list", struct { \
Token token; \
Slice<Ast *> list; \
@@ -742,6 +749,14 @@ AST_KIND(_TypeBegin, "", bool) \
Ast * elem; \
Ast * underlying; \
}) \
AST_KIND(BitFieldType, "bit field type", struct { \
Scope *scope; \
Token token; \
Ast * backing_type; \
Token open; \
Slice<Ast *> fields; /* BitFieldField */ \
Token close; \
}) \
AST_KIND(MapType, "map type", struct { \
Token token; \
Ast *count; \
+3
View File
@@ -111,6 +111,7 @@ gb_internal Token ast_token(Ast *node) {
case Ast_UnionType: return node->UnionType.token;
case Ast_EnumType: return node->EnumType.token;
case Ast_BitSetType: return node->BitSetType.token;
case Ast_BitFieldType: return node->BitFieldType.token;
case Ast_MapType: return node->MapType.token;
case Ast_MatrixType: return node->MatrixType.token;
}
@@ -364,6 +365,8 @@ Token ast_end_token(Ast *node) {
return ast_end_token(node->BitSetType.underlying);
}
return ast_end_token(node->BitSetType.elem);
case Ast_BitFieldType:
return node->BitFieldType.close;
case Ast_MapType: return ast_end_token(node->MapType.value);
case Ast_MatrixType: return ast_end_token(node->MatrixType.elem);
}
+24
View File
@@ -282,6 +282,13 @@ struct TypeProc {
Type *generic_column_count; \
i64 stride_in_bytes; \
}) \
TYPE_KIND(BitField, struct { \
Scope * scope; \
Type * backing_type; \
Slice<Entity *> fields; \
Slice<u8> bit_sizes; \
Ast * node; \
}) \
TYPE_KIND(SoaPointer, struct { Type *elem; })
@@ -355,6 +362,7 @@ enum Typeid_Kind : u8 {
Typeid_Relative_Multi_Pointer,
Typeid_Matrix,
Typeid_SoaPointer,
Typeid_Bit_Field,
};
// IMPORTANT NOTE(bill): This must match the same as the in core.odin
@@ -641,6 +649,7 @@ gb_global Type *t_type_info_relative_pointer = nullptr;
gb_global Type *t_type_info_relative_multi_pointer = nullptr;
gb_global Type *t_type_info_matrix = nullptr;
gb_global Type *t_type_info_soa_pointer = nullptr;
gb_global Type *t_type_info_bit_field = nullptr;
gb_global Type *t_type_info_named_ptr = nullptr;
gb_global Type *t_type_info_integer_ptr = nullptr;
@@ -670,6 +679,7 @@ gb_global Type *t_type_info_relative_pointer_ptr = nullptr;
gb_global Type *t_type_info_relative_multi_pointer_ptr = nullptr;
gb_global Type *t_type_info_matrix_ptr = nullptr;
gb_global Type *t_type_info_soa_pointer_ptr = nullptr;
gb_global Type *t_type_info_bit_field_ptr = nullptr;
gb_global Type *t_allocator = nullptr;
gb_global Type *t_allocator_ptr = nullptr;
@@ -1040,6 +1050,11 @@ gb_internal Type *alloc_type_enum() {
return t;
}
gb_internal Type *alloc_type_bit_field() {
Type *t = alloc_type(Type_BitField);
return t;
}
gb_internal Type *alloc_type_relative_pointer(Type *pointer_type, Type *base_integer) {
GB_ASSERT(is_type_pointer(pointer_type));
GB_ASSERT(is_type_integer(base_integer));
@@ -1707,6 +1722,10 @@ gb_internal bool is_type_bit_set(Type *t) {
t = base_type(t);
return (t->kind == Type_BitSet);
}
gb_internal bool is_type_bit_field(Type *t) {
t = base_type(t);
return (t->kind == Type_BitField);
}
gb_internal bool is_type_map(Type *t) {
t = base_type(t);
return t->kind == Type_Map;
@@ -3568,6 +3587,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
case Type_Slice:
return build_context.int_size;
case Type_BitField:
return type_align_of_internal(t->BitField.backing_type, path);
case Type_Tuple: {
i64 max = 1;
@@ -3943,6 +3964,9 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
return stride_in_bytes * t->Matrix.column_count;
}
case Type_BitField:
return type_size_of_internal(t->BitField.backing_type, path);
case Type_RelativePointer:
return type_size_of_internal(t->RelativePointer.base_integer, path);
case Type_RelativeMultiPointer: