Browse Source

Add field tags to `bit_field`

gingerBill 1 year ago
parent
commit
54515af8cc
7 changed files with 63 additions and 19 deletions
  1. 1 0
      base/runtime/core.odin
  2. 23 2
      core/fmt/fmt.odin
  3. 10 0
      src/check_type.cpp
  4. 19 15
      src/llvm_backend_type.cpp
  5. 8 2
      src/parser.cpp
  6. 1 0
      src/parser.hpp
  7. 1 0
      src/types.cpp

+ 1 - 0
base/runtime/core.odin

@@ -187,6 +187,7 @@ Type_Info_Bit_Field :: struct {
 	types:        []^Type_Info,
 	bit_sizes:    []uintptr,
 	bit_offsets:  []uintptr,
+	tags:         []string,
 }
 
 Type_Info_Flag :: enum u8 {

+ 23 - 2
core/fmt/fmt.odin

@@ -2297,6 +2297,23 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit
 		return
 	}
 
+	handle_bit_field_tag :: proc(data: rawptr, info: reflect.Type_Info_Bit_Field, idx: int, verb: ^rune) -> (do_continue: bool) {
+		tag := info.tags[idx]
+		if vt, ok := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "fmt"); ok {
+			value := strings.trim_space(string(vt))
+			switch value {
+			case "": return false
+			case "-": return true
+			}
+			r, w := utf8.decode_rune_in_string(value)
+			value = value[w:]
+			if value == "" || value[0] == ',' {
+				verb^ = r
+			}
+		}
+		return false
+	}
+
 	io.write_string(fi.writer, "bit_field{", &fi.n)
 
 	hash   := fi.hash;   defer fi.hash = hash
@@ -2318,7 +2335,11 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit
 
 	field_count := -1
 	for name, i in info.names {
-		_ = i
+		field_verb := verb
+		if handle_bit_field_tag(v.data, info, i, &field_verb) {
+			continue
+		}
+
 		field_count += 1
 
 		if !do_trailing_comma && field_count > 0 {
@@ -2343,7 +2364,7 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit
 			value = (value ~ m) - m
 		}
 
-		fmt_value(fi, any{&value, type.id}, verb)
+		fmt_value(fi, any{&value, type.id}, field_verb)
 		if do_trailing_comma { io.write_string(fi.writer, ",\n", &fi.n) }
 
 	}

+ 10 - 0
src/check_type.cpp

@@ -959,6 +959,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
 
 	auto fields    = array_make<Entity *>(permanent_allocator(), 0, bf->fields.count);
 	auto bit_sizes = array_make<u8>      (permanent_allocator(), 0, bf->fields.count);
+	auto tags      = array_make<String>  (permanent_allocator(), 0, bf->fields.count);
 
 	u64 maximum_bit_size = 8 * type_size_of(backing_type);
 	u64 total_bit_size = 0;
@@ -1054,6 +1055,14 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
 			add_entity(ctx, ctx->scope, nullptr, e);
 			array_add(&fields, e);
 			array_add(&bit_sizes, bit_size_u8);
+
+			String tag = f->tag.string;
+			if (tag.len != 0 && !unquote_string(permanent_allocator(), &tag, 0, tag.text[0] == '`')) {
+				error(f->tag, "Invalid string literal");
+				tag = {};
+			}
+			array_add(&tags, tag);
+
 			add_entity_use(ctx, field, e);
 		}
 	}
@@ -1080,6 +1089,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
 	bit_field_type->BitField.fields      = slice_from_array(fields);
 	bit_field_type->BitField.bit_sizes   = slice_from_array(bit_sizes);
 	bit_field_type->BitField.bit_offsets = bit_offsets;
+	bit_field_type->BitField.tags        = tags.data;
 }
 
 gb_internal bool is_type_valid_bit_set_range(Type *t) {

+ 19 - 15
src/llvm_backend_type.cpp

@@ -1792,19 +1792,21 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
 		case Type_BitField:
 			{
 				tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_bit_field_ptr);
-				LLVMValueRef vals[5] = {};
+				LLVMValueRef vals[6] = {};
 
 				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 names_offset       = 0;
+					i64 types_offset       = 0;
+					i64 bit_sizes_offset   = 0;
 					i64 bit_offsets_offset = 0;
+					i64 tags_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);
+					lbValue memory_tags        = lb_type_info_member_tags_offset   (m, count, &tags_offset);
 
 					u64 bit_offset = 0;
 					for (isize source_index = 0; source_index < count; source_index++) {
@@ -1813,8 +1815,8 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
 
 						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 name_ptr = lb_emit_ptr_offset(p, memory_names, index);
+							lb_emit_store(p, name_ptr, 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);
@@ -1824,21 +1826,23 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
 						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;
-						// }
+						if (t->BitField.tags) {
+							String tag = t->BitField.tags[source_index];
+							if (tag.len > 0) {
+								lbValue tag_ptr = lb_emit_ptr_offset(p, memory_tags, index);
+								lb_emit_store(p, tag_ptr, lb_const_string(m, tag));
+							}
+						}
 
 						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[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);
+					vals[5] = llvm_const_slice(m, memory_tags,        cv);
 				}
 
 				for (isize i = 0; i < gb_count_of(vals); i++) {

+ 8 - 2
src/parser.cpp

@@ -1054,12 +1054,13 @@ 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,
+gb_internal Ast *ast_bit_field_field(AstFile *f, Ast *name, Ast *type, Ast *bit_size, Token tag,
                                      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.tag      = tag;
 	result->BitFieldField.docs     = docs;
 	result->BitFieldField.comment  = comment;
 	return result;
@@ -2611,7 +2612,12 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 			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);
+			Token tag = {};
+			if (f->curr_token.kind == Token_String) {
+				tag = expect_token(f, Token_String);
+			}
+
+			Ast *bf_field = ast_bit_field_field(f, name, type, bit_size, tag, docs, comment);
 			array_add(&fields, bf_field);
 
 			if (!allow_field_separator(f)) {

+ 1 - 0
src/parser.hpp

@@ -655,6 +655,7 @@ AST_KIND(_DeclEnd,   "", bool) \
 		Ast *         name;     \
 		Ast *         type;     \
 		Ast *         bit_size; \
+		Token         tag;      \
 		CommentGroup *docs;     \
 		CommentGroup *comment;  \
 	}) \

+ 1 - 0
src/types.cpp

@@ -286,6 +286,7 @@ struct TypeProc {
 		Scope *         scope;                            \
 		Type *          backing_type;                     \
 		Slice<Entity *> fields;                           \
+		String *        tags; /*count == fields.count*/   \
 		Slice<u8>       bit_sizes;                        \
 		Slice<i64>      bit_offsets;                      \
 		Ast *           node;                             \