Custom struct alignment

This commit is contained in:
Ginger Bill
2017-02-05 15:19:30 +00:00
parent 7944b7714f
commit 2a5b674d33
9 changed files with 485 additions and 350 deletions
+39
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -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"), \
+5
View File
@@ -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) {