| author | |
| committer | |
| log | cf5108f222107ed242d2dc2c37d76758157da542 |
| tree | 9fbf62f7c54929d18031ad42256fcc003ca428d9 |
| parent | 4709fe1176ce88a35e877622dc977948846a3a43 |
with byte aligned but non-power-of-2 fields such as 244 files changed, 70 insertions(+), 8 deletions(-)
src/analyze.cpp+18-4| ... | ... | @@ -254,15 +254,21 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { |
| 254 | 254 | |
| 255 | 255 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) { |
| 256 | 256 | assert(type_is_complete(type_entry)); |
| 257 | if (type_has_bits(type_entry)) { | |
| 258 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | |
| 259 | } else { | |
| 257 | TypeTableEntry *canon_type = get_underlying_type(type_entry); | |
| 258 | ||
| 259 | if (!type_has_bits(type_entry)) | |
| 260 | 260 | return 0; |
| 261 | ||
| 262 | if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) { | |
| 263 | uint64_t size_in_bits = type_size_bits(g, type_entry); | |
| 264 | return (size_in_bits + 7) / 8; | |
| 261 | 265 | } |
| 266 | ||
| 267 | return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | |
| 262 | 268 | } |
| 263 | 269 | |
| 264 | // This has to do with packed structs | |
| 265 | 270 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) { |
| 271 | assert(type_is_complete(type_entry)); | |
| 266 | 272 | TypeTableEntry *canon_type = get_underlying_type(type_entry); |
| 267 | 273 | |
| 268 | 274 | if (!type_has_bits(type_entry)) |
| ... | ... | @@ -531,6 +537,14 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 531 | 537 | |
| 532 | 538 | ensure_complete_type(g, child_type); |
| 533 | 539 | |
| 540 | TypeTableEntry *canon_child_type = get_underlying_type(child_type); | |
| 541 | if (canon_child_type->id == TypeTableEntryIdStruct && | |
| 542 | canon_child_type->data.structure.layout == ContainerLayoutPacked && | |
| 543 | type_size_bits(g, canon_child_type) != 8 * type_size(g, canon_child_type)) | |
| 544 | { | |
| 545 | zig_panic("TODO array of packed struct with unaligned size"); | |
| 546 | } | |
| 547 | ||
| 534 | 548 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); |
| 535 | 549 | entry->zero_bits = (array_size == 0) || child_type->zero_bits; |
| 536 | 550 |
src/ir.cpp-4| ... | ... | @@ -9566,10 +9566,6 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira, |
| 9566 | 9566 | return ira->codegen->builtin_types.entry_void; |
| 9567 | 9567 | } |
| 9568 | 9568 | |
| 9569 | static bool is_power_of_2(uint64_t x) { | |
| 9570 | return x != 0 && ((x & (~x + 1)) == x); | |
| 9571 | } | |
| 9572 | ||
| 9573 | 9569 | static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira, |
| 9574 | 9570 | IrInstructionSetGlobalAlign *instruction) |
| 9575 | 9571 | { |
src/util.hpp+4| ... | ... | @@ -99,6 +99,10 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) |
| 99 | 99 | return memcmp(mem, str, mem_len) == 0; |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | static inline bool is_power_of_2(uint64_t x) { | |
| 103 | return x != 0 && ((x & (~x + 1)) == x); | |
| 104 | } | |
| 105 | ||
| 102 | 106 | uint32_t int_hash(int i); |
| 103 | 107 | bool int_eq(int a, int b); |
| 104 | 108 | uint32_t uint64_hash(uint64_t i); |
test/cases/struct.zig+48| ... | ... | @@ -270,3 +270,51 @@ fn getB(data: &const BitField1) -> u3 { |
| 270 | 270 | fn getC(data: &const BitField1) -> u2 { |
| 271 | 271 | return data.c; |
| 272 | 272 | } |
| 273 | ||
| 274 | const u24 = @intType(false, 24); | |
| 275 | const Foo24Bits = packed struct { | |
| 276 | field: u24, | |
| 277 | }; | |
| 278 | const Foo96Bits = packed struct { | |
| 279 | a: u24, | |
| 280 | b: u24, | |
| 281 | c: u24, | |
| 282 | d: u24, | |
| 283 | }; | |
| 284 | ||
| 285 | fn packedStruct24Bits() { | |
| 286 | @setFnTest(this); | |
| 287 | ||
| 288 | comptime assert(@sizeOf(Foo24Bits) == 3); | |
| 289 | comptime assert(@sizeOf(Foo96Bits) == 12); | |
| 290 | ||
| 291 | var value = Foo96Bits { | |
| 292 | .a = 0, | |
| 293 | .b = 0, | |
| 294 | .c = 0, | |
| 295 | .d = 0, | |
| 296 | }; | |
| 297 | value.a += 1; | |
| 298 | assert(value.a == 1); | |
| 299 | assert(value.b == 0); | |
| 300 | assert(value.c == 0); | |
| 301 | assert(value.d == 0); | |
| 302 | ||
| 303 | value.b += 1; | |
| 304 | assert(value.a == 1); | |
| 305 | assert(value.b == 1); | |
| 306 | assert(value.c == 0); | |
| 307 | assert(value.d == 0); | |
| 308 | ||
| 309 | value.c += 1; | |
| 310 | assert(value.a == 1); | |
| 311 | assert(value.b == 1); | |
| 312 | assert(value.c == 1); | |
| 313 | assert(value.d == 0); | |
| 314 | ||
| 315 | value.d += 1; | |
| 316 | assert(value.a == 1); | |
| 317 | assert(value.b == 1); | |
| 318 | assert(value.c == 1); | |
| 319 | assert(value.d == 1); | |
| 320 | } |