#min_field_align & #max_field_align; deprecate #field_align in favour of #min_field_align

This commit is contained in:
gingerBill
2024-09-30 13:05:28 +01:00
parent 4b6410e225
commit a7d7c92a53
7 changed files with 116 additions and 49 deletions
+12 -11
View File
@@ -776,17 +776,18 @@ Dynamic_Array_Type :: struct {
Struct_Type :: struct {
using node: Expr,
tok_pos: tokenizer.Pos,
poly_params: ^Field_List,
align: ^Expr,
field_align: ^Expr,
where_token: tokenizer.Token,
where_clauses: []^Expr,
is_packed: bool,
is_raw_union: bool,
is_no_copy: bool,
fields: ^Field_List,
name_count: int,
tok_pos: tokenizer.Pos,
poly_params: ^Field_List,
align: ^Expr,
min_field_align: ^Expr,
max_field_align: ^Expr,
where_token: tokenizer.Token,
where_clauses: []^Expr,
is_packed: bool,
is_raw_union: bool,
is_no_copy: bool,
fields: ^Field_List,
name_count: int,
}
Union_Type_Kind :: enum u8 {
+2 -1
View File
@@ -316,7 +316,8 @@ clone_node :: proc(node: ^Node) -> ^Node {
case ^Struct_Type:
r.poly_params = auto_cast clone(r.poly_params)
r.align = clone(r.align)
r.field_align = clone(r.field_align)
r.min_field_align = clone(r.min_field_align)
r.max_field_align = clone(r.max_field_align)
r.fields = auto_cast clone(r.fields)
case ^Union_Type:
r.poly_params = auto_cast clone(r.poly_params)
+28 -15
View File
@@ -2610,9 +2610,10 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
case .Struct:
tok := expect_token(p, .Struct)
poly_params: ^ast.Field_List
align: ^ast.Expr
field_align: ^ast.Expr
poly_params: ^ast.Field_List
align: ^ast.Expr
min_field_align: ^ast.Expr
max_field_align: ^ast.Expr
is_packed: bool
is_raw_union: bool
is_no_copy: bool
@@ -2645,10 +2646,21 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
}
align = parse_expr(p, true)
case "field_align":
if field_align != nil {
if min_field_align != nil {
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
}
field_align = parse_expr(p, true)
warn(p, tag.pos, "#field_align has been deprecated in favour of #min_field_align")
min_field_align = parse_expr(p, true)
case "min_field_align":
if min_field_align != nil {
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
}
min_field_align = parse_expr(p, true)
case "max_field_align":
if max_field_align != nil {
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
}
max_field_align = parse_expr(p, true)
case "raw_union":
if is_raw_union {
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
@@ -2689,16 +2701,17 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
close := expect_closing_brace_of_field_list(p)
st := ast.new(ast.Struct_Type, tok.pos, end_pos(close))
st.poly_params = poly_params
st.align = align
st.field_align = field_align
st.is_packed = is_packed
st.is_raw_union = is_raw_union
st.is_no_copy = is_no_copy
st.fields = fields
st.name_count = name_count
st.where_token = where_token
st.where_clauses = where_clauses
st.poly_params = poly_params
st.align = align
st.min_field_align = min_field_align
st.max_field_align = max_field_align
st.is_packed = is_packed
st.is_raw_union = is_raw_union
st.is_no_copy = is_no_copy
st.fields = fields
st.name_count = name_count
st.where_token = where_token
st.where_clauses = where_clauses
return st
case .Union:
+25 -6
View File
@@ -673,7 +673,7 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
#define ST_ALIGN(_name) if (st->_name != nullptr) { \
if (st->is_packed) { \
syntax_error(st->_name, "'#%s' cannot be applied with '#packed'", #_name); \
error(st->_name, "'#%s' cannot be applied with '#packed'", #_name); \
return; \
} \
i64 align = 1; \
@@ -682,12 +682,31 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
} \
}
ST_ALIGN(field_align);
ST_ALIGN(min_field_align);
ST_ALIGN(max_field_align);
ST_ALIGN(align);
if (struct_type->Struct.custom_align < struct_type->Struct.custom_field_align) {
warning(st->align, "#align(%lld) is defined to be less than #field_name(%lld)",
cast(long long)struct_type->Struct.custom_align,
cast(long long)struct_type->Struct.custom_field_align);
if (struct_type->Struct.custom_align < struct_type->Struct.custom_min_field_align) {
error(st->align, "#align(%lld) is defined to be less than #min_field_align(%lld)",
cast(long long)struct_type->Struct.custom_align,
cast(long long)struct_type->Struct.custom_min_field_align);
}
if (struct_type->Struct.custom_max_field_align != 0 &&
struct_type->Struct.custom_align > struct_type->Struct.custom_max_field_align) {
error(st->align, "#align(%lld) is defined to be greater than #max_field_align(%lld)",
cast(long long)struct_type->Struct.custom_align,
cast(long long)struct_type->Struct.custom_max_field_align);
}
if (struct_type->Struct.custom_max_field_align != 0 &&
struct_type->Struct.custom_min_field_align > struct_type->Struct.custom_max_field_align) {
error(st->align, "#min_field_align(%lld) is defined to be greater than #max_field_align(%lld)",
cast(long long)struct_type->Struct.custom_min_field_align,
cast(long long)struct_type->Struct.custom_max_field_align);
i64 a = gb_min(struct_type->Struct.custom_min_field_align, struct_type->Struct.custom_max_field_align);
i64 b = gb_max(struct_type->Struct.custom_min_field_align, struct_type->Struct.custom_max_field_align);
// NOTE(bill): sort them to keep code consistent
struct_type->Struct.custom_min_field_align = a;
struct_type->Struct.custom_max_field_align = b;
}
#undef ST_ALIGN
+39 -11
View File
@@ -448,7 +448,8 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
n->StructType.fields = clone_ast_array(n->StructType.fields, f);
n->StructType.polymorphic_params = clone_ast(n->StructType.polymorphic_params, f);
n->StructType.align = clone_ast(n->StructType.align, f);
n->StructType.field_align = clone_ast(n->StructType.field_align, f);
n->StructType.min_field_align = clone_ast(n->StructType.min_field_align, f);
n->StructType.max_field_align = clone_ast(n->StructType.max_field_align, f);
n->StructType.where_clauses = clone_ast_array(n->StructType.where_clauses, f);
break;
case Ast_UnionType:
@@ -1217,7 +1218,7 @@ gb_internal Ast *ast_dynamic_array_type(AstFile *f, Token token, Ast *elem) {
gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice<Ast *> fields, isize field_count,
Ast *polymorphic_params, bool is_packed, bool is_raw_union, bool is_no_copy,
Ast *align, Ast *field_align,
Ast *align, Ast *min_field_align, Ast *max_field_align,
Token where_token, Array<Ast *> const &where_clauses) {
Ast *result = alloc_ast_node(f, Ast_StructType);
result->StructType.token = token;
@@ -1228,7 +1229,8 @@ gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice<Ast *> fields, i
result->StructType.is_raw_union = is_raw_union;
result->StructType.is_no_copy = is_no_copy;
result->StructType.align = align;
result->StructType.field_align = field_align;
result->StructType.min_field_align = min_field_align;
result->StructType.max_field_align = max_field_align;
result->StructType.where_token = where_token;
result->StructType.where_clauses = slice_from_array(where_clauses);
return result;
@@ -2757,7 +2759,8 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
bool is_raw_union = false;
bool no_copy = false;
Ast *align = nullptr;
Ast *field_align = nullptr;
Ast *min_field_align = nullptr;
Ast *max_field_align = nullptr;
if (allow_token(f, Token_OpenParen)) {
isize param_count = 0;
@@ -2795,18 +2798,43 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
gb_string_free(s);
}
} else if (tag.string == "field_align") {
if (field_align) {
if (min_field_align) {
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
}
field_align = parse_expr(f, true);
if (field_align && field_align->kind != Ast_ParenExpr) {
syntax_warning(tag, "#field_align has been deprecated in favour of #min_field_align");
min_field_align = parse_expr(f, true);
if (min_field_align && min_field_align->kind != Ast_ParenExpr) {
ERROR_BLOCK();
gbString s = expr_to_string(field_align);
gbString s = expr_to_string(min_field_align);
syntax_warning(tag, "#field_align requires parentheses around the expression");
error_line("\tSuggestion: #field_align(%s)", s);
error_line("\tSuggestion: #min_field_align(%s)", s);
gb_string_free(s);
}
} else if (tag.string == "raw_union") {
} else if (tag.string == "min_field_align") {
if (min_field_align) {
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
}
min_field_align = parse_expr(f, true);
if (min_field_align && min_field_align->kind != Ast_ParenExpr) {
ERROR_BLOCK();
gbString s = expr_to_string(min_field_align);
syntax_warning(tag, "#min_field_align requires parentheses around the expression");
error_line("\tSuggestion: #min_field_align(%s)", s);
gb_string_free(s);
}
} else if (tag.string == "max_field_align") {
if (max_field_align) {
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
}
max_field_align = parse_expr(f, true);
if (max_field_align && max_field_align->kind != Ast_ParenExpr) {
ERROR_BLOCK();
gbString s = expr_to_string(max_field_align);
syntax_warning(tag, "#max_field_align requires parentheses around the expression");
error_line("\tSuggestion: #max_field_align(%s)", s);
gb_string_free(s);
}
}else if (tag.string == "raw_union") {
if (is_raw_union) {
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
}
@@ -2856,7 +2884,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
parser_check_polymorphic_record_parameters(f, polymorphic_params);
return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_raw_union, no_copy, align, field_align, where_token, where_clauses);
return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_raw_union, no_copy, align, min_field_align, max_field_align, where_token, where_clauses);
} break;
case Token_union: {
+2 -1
View File
@@ -736,7 +736,8 @@ AST_KIND(_TypeBegin, "", bool) \
isize field_count; \
Ast *polymorphic_params; \
Ast *align; \
Ast *field_align; \
Ast *min_field_align; \
Ast *max_field_align; \
Token where_token; \
Slice<Ast *> where_clauses; \
bool is_packed; \
+8 -4
View File
@@ -137,7 +137,8 @@ struct TypeStruct {
Scope * scope;
i64 custom_align;
i64 custom_field_align;
i64 custom_min_field_align;
i64 custom_max_field_align;
Type * polymorphic_params; // Type_Tuple
Type * polymorphic_parent;
Wait_Signal polymorphic_wait_signal;
@@ -3950,7 +3951,7 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align);
}
gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_packed, bool is_raw_union, i64 min_field_align) {
gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_packed, bool is_raw_union, i64 min_field_align, i64 max_field_align) {
gbAllocator a = permanent_allocator();
auto offsets = gb_alloc_array(a, i64, fields.count);
i64 curr_offset = 0;
@@ -3980,6 +3981,9 @@ gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_pack
} else {
Type *t = fields[i]->type;
i64 align = gb_max(type_align_of(t), min_field_align);
if (max_field_align > min_field_align) {
align = gb_min(align, max_field_align);
}
i64 size = gb_max(type_size_of( t), 0);
curr_offset = align_formula(curr_offset, align);
offsets[i] = curr_offset;
@@ -3996,7 +4000,7 @@ gb_internal bool type_set_offsets(Type *t) {
MUTEX_GUARD(&t->Struct.offset_mutex);
if (!t->Struct.are_offsets_set) {
t->Struct.are_offsets_being_processed = true;
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union, t->Struct.custom_field_align);
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union, t->Struct.custom_min_field_align, t->Struct.custom_max_field_align);
t->Struct.are_offsets_being_processed = false;
t->Struct.are_offsets_set = true;
return true;
@@ -4005,7 +4009,7 @@ gb_internal bool type_set_offsets(Type *t) {
MUTEX_GUARD(&t->Tuple.mutex);
if (!t->Tuple.are_offsets_set) {
t->Tuple.are_offsets_being_processed = true;
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false, 1);
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false, 1, 0);
t->Tuple.are_offsets_being_processed = false;
t->Tuple.are_offsets_set = true;
return true;