Skip to content

Commit 3f776af

Browse files
committed
fix alignment of structs
closes #1248 closes #1052 closes #1154
1 parent 639c381 commit 3f776af

File tree

8 files changed

+524
-324
lines changed

8 files changed

+524
-324
lines changed

src/all_types.hpp

+25-22
Original file line numberDiff line numberDiff line change
@@ -1012,13 +1012,13 @@ enum PtrLen {
10121012

10131013
struct ZigTypePointer {
10141014
ZigType *child_type;
1015+
ZigType *slice_parent;
10151016
PtrLen ptr_len;
1016-
bool is_const;
1017-
bool is_volatile;
1018-
uint32_t alignment;
1017+
uint32_t explicit_alignment; // 0 means use ABI alignment
10191018
uint32_t bit_offset;
10201019
uint32_t unaligned_bit_count;
1021-
ZigType *slice_parent;
1020+
bool is_const;
1021+
bool is_volatile;
10221022
};
10231023

10241024
struct ZigTypeInt {
@@ -1046,32 +1046,35 @@ struct TypeStructField {
10461046
size_t unaligned_bit_count;
10471047
AstNode *decl_node;
10481048
};
1049+
1050+
enum ResolveStatus {
1051+
ResolveStatusUnstarted,
1052+
ResolveStatusInvalid,
1053+
ResolveStatusZeroBitsKnown,
1054+
ResolveStatusAlignmentKnown,
1055+
ResolveStatusSizeKnown,
1056+
};
1057+
10491058
struct ZigTypeStruct {
10501059
AstNode *decl_node;
1051-
ContainerLayout layout;
1052-
uint32_t src_field_count;
1053-
uint32_t gen_field_count;
10541060
TypeStructField *fields;
1055-
uint64_t size_bytes;
1056-
bool is_invalid; // true if any fields are invalid
1057-
bool is_slice;
10581061
ScopeDecls *decls_scope;
1062+
uint64_t size_bytes;
1063+
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
10591064

1060-
// set this flag temporarily to detect infinite loops
1061-
bool embedded_in_current;
1062-
bool reported_infinite_err;
1063-
// whether we've finished resolving it
1064-
bool complete;
1065+
uint32_t src_field_count;
1066+
uint32_t gen_field_count;
1067+
1068+
uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown
1069+
ContainerLayout layout;
1070+
ResolveStatus resolve_status;
10651071

1072+
bool is_slice;
1073+
bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1074+
bool reported_infinite_err;
10661075
// whether any of the fields require comptime
1067-
// the value is not valid until zero_bits_known == true
1076+
// known after ResolveStatusZeroBitsKnown
10681077
bool requires_comptime;
1069-
1070-
bool zero_bits_loop_flag;
1071-
bool zero_bits_known;
1072-
uint32_t abi_alignment; // also figured out with zero_bits pass
1073-
1074-
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
10751078
};
10761079

10771080
struct ZigTypeOptional {

src/analyze.cpp

+218-169
Large diffs are not rendered by default.

src/analyze.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ bool get_ptr_const(ZigType *type);
5959
ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
6060
ZigType *container_ref_type(ZigType *type_entry);
6161
bool type_is_complete(ZigType *type_entry);
62+
bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
6263
bool type_is_invalid(ZigType *type_entry);
6364
bool type_is_global_error_set(ZigType *err_set_type);
64-
bool type_has_zero_bits_known(ZigType *type_entry);
6565
void resolve_container_type(CodeGen *g, ZigType *type_entry);
6666
ScopeDecls *get_container_scope(ZigType *type_entry);
6767
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
@@ -89,7 +89,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
8989
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
9090
bool type_requires_comptime(ZigType *type_entry);
9191
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
92-
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry);
92+
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
9393
void complete_enum(CodeGen *g, ZigType *enum_type);
9494
bool ir_get_var_is_comptime(ZigVar *var);
9595
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);

src/codegen.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
775775

776776
static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
777777
assert(ptr_type->id == ZigTypeIdPointer);
778-
return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);
778+
uint32_t alignment = get_ptr_align(g, ptr_type);
779+
return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile);
779780
}
780781

781782
static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile,
@@ -793,7 +794,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig
793794

794795
static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
795796
assert(ptr_type->id == ZigTypeIdPointer);
796-
return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name);
797+
uint32_t alignment = get_ptr_align(g, ptr_type);
798+
return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name);
797799
}
798800

799801
static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
@@ -1795,7 +1797,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
17951797

17961798
ZigType *usize = g->builtin_types.entry_usize;
17971799
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);
1798-
uint64_t align_bytes = ptr_type->data.pointer.alignment;
1800+
uint64_t align_bytes = get_ptr_align(g, ptr_type);
17991801
assert(size_bytes > 0);
18001802
assert(align_bytes > 0);
18011803

@@ -4084,15 +4086,15 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
40844086
LLVMValueRef ptr_val;
40854087

40864088
if (target_type->id == ZigTypeIdPointer) {
4087-
align_bytes = target_type->data.pointer.alignment;
4089+
align_bytes = get_ptr_align(g, target_type);
40884090
ptr_val = target_val;
40894091
} else if (target_type->id == ZigTypeIdFn) {
40904092
align_bytes = target_type->data.fn.fn_type_id.alignment;
40914093
ptr_val = target_val;
40924094
} else if (target_type->id == ZigTypeIdOptional &&
40934095
target_type->data.maybe.child_type->id == ZigTypeIdPointer)
40944096
{
4095-
align_bytes = target_type->data.maybe.child_type->data.pointer.alignment;
4097+
align_bytes = get_ptr_align(g, target_type->data.maybe.child_type);
40964098
ptr_val = target_val;
40974099
} else if (target_type->id == ZigTypeIdOptional &&
40984100
target_type->data.maybe.child_type->id == ZigTypeIdFn)
@@ -4105,7 +4107,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
41054107
zig_panic("TODO audit this function");
41064108
} else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
41074109
ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
4108-
align_bytes = slice_ptr_type->data.pointer.alignment;
4110+
align_bytes = get_ptr_align(g, slice_ptr_type);
41094111

41104112
size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
41114113
LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, "");
@@ -4260,7 +4262,8 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
42604262
LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ?
42614263
LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
42624264

4263-
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false);
4265+
uint32_t alignment = get_ptr_align(g, ptr_type);
4266+
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), alignment, false);
42644267

42654268
LLVMValueRef params[] = {
42664269
dest_ptr_casted,
@@ -4293,7 +4296,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
42934296
LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ?
42944297
LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
42954298

4296-
uint32_t min_align_bytes = min(src_ptr_type->data.pointer.alignment, dest_ptr_type->data.pointer.alignment);
4299+
uint32_t min_align_bytes = min(get_ptr_align(g, src_ptr_type), get_ptr_align(g, dest_ptr_type));
42974300
LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), min_align_bytes, false);
42984301

42994302
LLVMValueRef params[] = {

0 commit comments

Comments
 (0)