Commit cf5108f222
Changed files (4)
test
cases
src/analyze.cpp
@@ -254,15 +254,21 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
assert(type_is_complete(type_entry));
- if (type_has_bits(type_entry)) {
- return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
- } else {
+ TypeTableEntry *canon_type = get_underlying_type(type_entry);
+
+ if (!type_has_bits(type_entry))
return 0;
+
+ if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) {
+ uint64_t size_in_bits = type_size_bits(g, type_entry);
+ return (size_in_bits + 7) / 8;
}
+
+ return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
}
-// This has to do with packed structs
uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) {
+ assert(type_is_complete(type_entry));
TypeTableEntry *canon_type = get_underlying_type(type_entry);
if (!type_has_bits(type_entry))
@@ -531,6 +537,14 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
ensure_complete_type(g, child_type);
+ TypeTableEntry *canon_child_type = get_underlying_type(child_type);
+ if (canon_child_type->id == TypeTableEntryIdStruct &&
+ canon_child_type->data.structure.layout == ContainerLayoutPacked &&
+ type_size_bits(g, canon_child_type) != 8 * type_size(g, canon_child_type))
+ {
+ zig_panic("TODO array of packed struct with unaligned size");
+ }
+
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
entry->zero_bits = (array_size == 0) || child_type->zero_bits;
src/ir.cpp
@@ -9566,10 +9566,6 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
return ira->codegen->builtin_types.entry_void;
}
-static bool is_power_of_2(uint64_t x) {
- return x != 0 && ((x & (~x + 1)) == x);
-}
-
static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira,
IrInstructionSetGlobalAlign *instruction)
{
src/util.hpp
@@ -99,6 +99,10 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str)
return memcmp(mem, str, mem_len) == 0;
}
+static inline bool is_power_of_2(uint64_t x) {
+ return x != 0 && ((x & (~x + 1)) == x);
+}
+
uint32_t int_hash(int i);
bool int_eq(int a, int b);
uint32_t uint64_hash(uint64_t i);
test/cases/struct.zig
@@ -270,3 +270,51 @@ fn getB(data: &const BitField1) -> u3 {
fn getC(data: &const BitField1) -> u2 {
return data.c;
}
+
+const u24 = @intType(false, 24);
+const Foo24Bits = packed struct {
+ field: u24,
+};
+const Foo96Bits = packed struct {
+ a: u24,
+ b: u24,
+ c: u24,
+ d: u24,
+};
+
+fn packedStruct24Bits() {
+ @setFnTest(this);
+
+ comptime assert(@sizeOf(Foo24Bits) == 3);
+ comptime assert(@sizeOf(Foo96Bits) == 12);
+
+ var value = Foo96Bits {
+ .a = 0,
+ .b = 0,
+ .c = 0,
+ .d = 0,
+ };
+ value.a += 1;
+ assert(value.a == 1);
+ assert(value.b == 0);
+ assert(value.c == 0);
+ assert(value.d == 0);
+
+ value.b += 1;
+ assert(value.a == 1);
+ assert(value.b == 1);
+ assert(value.c == 0);
+ assert(value.d == 0);
+
+ value.c += 1;
+ assert(value.a == 1);
+ assert(value.b == 1);
+ assert(value.c == 1);
+ assert(value.d == 0);
+
+ value.d += 1;
+ assert(value.a == 1);
+ assert(value.b == 1);
+ assert(value.c == 1);
+ assert(value.d == 1);
+}