mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-22 21:54:59 -07:00
Custom struct alignment
This commit is contained in:
@@ -553,6 +553,45 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
||||
}
|
||||
|
||||
type_set_offsets(c->sizes, c->allocator, struct_type);
|
||||
|
||||
if (st->align != NULL) {
|
||||
if (st->is_packed) {
|
||||
syntax_error_node(st->align, "`#align` cannot be applied with `#packed`");
|
||||
return;
|
||||
}
|
||||
|
||||
Operand o = {0};
|
||||
check_expr(c, &o, st->align);
|
||||
if (o.mode != Addressing_Constant) {
|
||||
if (o.mode != Addressing_Invalid) {
|
||||
error_node(st->align, "#align must be a constant");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Type *type = base_type(o.type);
|
||||
if (is_type_untyped(type) || is_type_integer(type)) {
|
||||
if (o.value.kind == ExactValue_Integer) {
|
||||
i64 align = o.value.value_integer;
|
||||
if (align < 1 || !gb_is_power_of_two(align)) {
|
||||
error_node(st->align, "#align must be a power of 2, got %lld", align);
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE(bill): Success!!!
|
||||
i64 custom_align = gb_clamp(align, 1, c->sizes.max_align);
|
||||
if (custom_align < align) {
|
||||
warning_node(st->align, "Custom alignment has been clamped to %lld from %lld", align, custom_align);
|
||||
}
|
||||
struct_type->Record.custom_align = custom_align;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error_node(st->align, "#align must be an integer");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
|
||||
+1
-1
@@ -799,7 +799,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
Token token = {0};
|
||||
token.pos = ast_node_token(ms->body).pos;
|
||||
token.string = str_lit("true");
|
||||
x.expr = make_ident(c->curr_ast_file, token);
|
||||
x.expr = ast_ident(c->curr_ast_file, token);
|
||||
}
|
||||
|
||||
// NOTE(bill): Check for multiple defaults
|
||||
|
||||
+23
-2
@@ -215,6 +215,12 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
ir_fprintf(f, "<");
|
||||
}
|
||||
ir_fprintf(f, "{");
|
||||
if (t->Record.custom_align > 0) {
|
||||
ir_fprintf(f, "[0 x <%lld x i8>]", t->Record.custom_align);
|
||||
if (t->Record.field_count > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
}
|
||||
}
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
if (i > 0) {
|
||||
ir_fprintf(f, ", ");
|
||||
@@ -755,6 +761,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
case irInstr_StructElementPtr: {
|
||||
Type *et = ir_type(instr->StructElementPtr.address);
|
||||
ir_fprintf(f, "%%%d = getelementptr inbounds ", value->index);
|
||||
i32 index = instr->StructElementPtr.elem_index;
|
||||
Type *st = base_type(type_deref(et));
|
||||
if (is_type_struct(st)) {
|
||||
if (st->Record.custom_align > 0) {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
ir_print_type(f, m, type_deref(et));
|
||||
ir_fprintf(f, ", ");
|
||||
@@ -765,7 +778,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, t_int);
|
||||
ir_fprintf(f, " 0, ");
|
||||
ir_print_type(f, m, t_i32);
|
||||
ir_fprintf(f, " %d", instr->StructElementPtr.elem_index);
|
||||
ir_fprintf(f, " %d", index);
|
||||
ir_fprintf(f, "\n");
|
||||
} break;
|
||||
|
||||
@@ -816,11 +829,19 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
case irInstr_StructExtractValue: {
|
||||
Type *et = ir_type(instr->StructExtractValue.address);
|
||||
ir_fprintf(f, "%%%d = extractvalue ", value->index);
|
||||
i32 index = instr->StructExtractValue.index;
|
||||
Type *st = base_type(et);
|
||||
if (is_type_struct(st)) {
|
||||
if (st->Record.custom_align > 0) {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ir_print_type(f, m, et);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, instr->StructExtractValue.address, et);
|
||||
ir_fprintf(f, ", %d\n", instr->StructExtractValue.index);
|
||||
ir_fprintf(f, ", %d\n", index);
|
||||
} break;
|
||||
|
||||
case irInstr_UnionTagPtr: {
|
||||
|
||||
+312
-261
File diff suppressed because it is too large
Load Diff
@@ -103,6 +103,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
TOKEN_KIND(Token_vector, "vector"), \
|
||||
TOKEN_KIND(Token_map, "map"), \
|
||||
TOKEN_KIND(Token_static, "static"), \
|
||||
TOKEN_KIND(Token_dynamic, "dynamic"), \
|
||||
TOKEN_KIND(Token_using, "using"), \
|
||||
|
||||
@@ -87,6 +87,8 @@ typedef struct TypeRecord {
|
||||
bool struct_is_ordered;
|
||||
Entity **fields_in_src_order; // Entity_Variable
|
||||
|
||||
i64 custom_align; // NOTE(bill): Only used in structs at the moment
|
||||
|
||||
Type * enum_base_type;
|
||||
Entity * enum_count;
|
||||
Entity * enum_min_value;
|
||||
@@ -1459,6 +1461,9 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
if (t->Record.custom_align > 0) {
|
||||
return gb_clamp(t->Record.custom_align, 1, s.max_align);
|
||||
}
|
||||
if (t->Record.field_count > 0) {
|
||||
// TODO(bill): What is this supposed to be?
|
||||
if (t->Record.struct_is_packed) {
|
||||
|
||||
Reference in New Issue
Block a user