| author | |
| committer | |
| log | dcfd15a7f0ed5159afad47915a11d1dd8315cbe8 |
| tree | f582f0697e06ae95d9962d4720ac3573a8be4be6 |
| parent | 631851f8b55b78363c9bc773230d9ee1e7122f5e |
| signature |
See #112111 files changed, 124 insertions(+), 95 deletions(-)
src/all_types.hpp+7-10| ... | @@ -664,7 +664,7 @@ struct AstNodePointerType { | ... | @@ -664,7 +664,7 @@ struct AstNodePointerType { |
| 664 | Token *star_token; | 664 | Token *star_token; |
| 665 | AstNode *align_expr; | 665 | AstNode *align_expr; |
| 666 | BigInt *bit_offset_start; | 666 | BigInt *bit_offset_start; |
| 667 | BigInt *bit_offset_end; | 667 | BigInt *host_int_bytes; |
| 668 | bool is_const; | 668 | bool is_const; |
| 669 | bool is_volatile; | 669 | bool is_volatile; |
| 670 | AstNode *op_expr; | 670 | AstNode *op_expr; |
| ... | @@ -1020,8 +1020,8 @@ struct ZigTypePointer { | ... | @@ -1020,8 +1020,8 @@ struct ZigTypePointer { |
| 1020 | ZigType *slice_parent; | 1020 | ZigType *slice_parent; |
| 1021 | PtrLen ptr_len; | 1021 | PtrLen ptr_len; |
| 1022 | uint32_t explicit_alignment; // 0 means use ABI alignment | 1022 | uint32_t explicit_alignment; // 0 means use ABI alignment |
| 1023 | uint32_t bit_offset; | 1023 | uint32_t bit_offset_in_host; |
| 1024 | uint32_t unaligned_bit_count; | 1024 | uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned |
| 1025 | bool is_const; | 1025 | bool is_const; |
| 1026 | bool is_volatile; | 1026 | bool is_volatile; |
| 1027 | }; | 1027 | }; |
| ... | @@ -1045,10 +1045,7 @@ struct TypeStructField { | ... | @@ -1045,10 +1045,7 @@ struct TypeStructField { |
| 1045 | ZigType *type_entry; | 1045 | ZigType *type_entry; |
| 1046 | size_t src_index; | 1046 | size_t src_index; |
| 1047 | size_t gen_index; | 1047 | size_t gen_index; |
| 1048 | // offset from the memory at gen_index | 1048 | uint32_t bit_offset_in_host; // offset from the memory at gen_index |
| 1049 | size_t packed_bits_offset; | ||
| 1050 | size_t packed_bits_size; | ||
| 1051 | size_t unaligned_bit_count; | ||
| 1052 | AstNode *decl_node; | 1049 | AstNode *decl_node; |
| 1053 | }; | 1050 | }; |
| 1054 | 1051 | ||
| ... | @@ -1470,8 +1467,8 @@ struct TypeId { | ... | @@ -1470,8 +1467,8 @@ struct TypeId { |
| 1470 | bool is_const; | 1467 | bool is_const; |
| 1471 | bool is_volatile; | 1468 | bool is_volatile; |
| 1472 | uint32_t alignment; | 1469 | uint32_t alignment; |
| 1473 | uint32_t bit_offset; | 1470 | uint32_t bit_offset_in_host; |
| 1474 | uint32_t unaligned_bit_count; | 1471 | uint32_t host_int_bytes; |
| 1475 | } pointer; | 1472 | } pointer; |
| 1476 | struct { | 1473 | struct { |
| 1477 | ZigType *child_type; | 1474 | ZigType *child_type; |
| ... | @@ -2510,7 +2507,7 @@ struct IrInstructionPtrType { | ... | @@ -2510,7 +2507,7 @@ struct IrInstructionPtrType { |
| 2510 | IrInstruction *align_value; | 2507 | IrInstruction *align_value; |
| 2511 | IrInstruction *child_type; | 2508 | IrInstruction *child_type; |
| 2512 | uint32_t bit_offset_start; | 2509 | uint32_t bit_offset_start; |
| 2513 | uint32_t bit_offset_end; | 2510 | uint32_t host_int_bytes; |
| 2514 | PtrLen ptr_len; | 2511 | PtrLen ptr_len; |
| 2515 | bool is_const; | 2512 | bool is_const; |
| 2516 | bool is_volatile; | 2513 | bool is_volatile; |
src/analyze.cpp+39-26| ... | @@ -419,7 +419,7 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { | ... | @@ -419,7 +419,7 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 421 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 422 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count) | 422 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes) |
| 423 | { | 423 | { |
| 424 | assert(!type_is_invalid(child_type)); | 424 | assert(!type_is_invalid(child_type)); |
| 425 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); | 425 | assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); |
| ... | @@ -430,23 +430,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -430,23 +430,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 430 | byte_alignment = 0; | 430 | byte_alignment = 0; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | if (host_int_bytes != 0) { | ||
| 434 | uint32_t child_type_bits = type_size_bits(g, child_type); | ||
| 435 | if (host_int_bytes * 8 == child_type_bits) { | ||
| 436 | assert(bit_offset_in_host == 0); | ||
| 437 | host_int_bytes = 0; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 433 | TypeId type_id = {}; | 441 | TypeId type_id = {}; |
| 434 | ZigType **parent_pointer = nullptr; | 442 | ZigType **parent_pointer = nullptr; |
| 435 | if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { | 443 | if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { |
| 436 | type_id.id = ZigTypeIdPointer; | 444 | type_id.id = ZigTypeIdPointer; |
| 437 | type_id.data.pointer.child_type = child_type; | 445 | type_id.data.pointer.child_type = child_type; |
| 438 | type_id.data.pointer.is_const = is_const; | 446 | type_id.data.pointer.is_const = is_const; |
| 439 | type_id.data.pointer.is_volatile = is_volatile; | 447 | type_id.data.pointer.is_volatile = is_volatile; |
| 440 | type_id.data.pointer.alignment = byte_alignment; | 448 | type_id.data.pointer.alignment = byte_alignment; |
| 441 | type_id.data.pointer.bit_offset = bit_offset; | 449 | type_id.data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 442 | type_id.data.pointer.unaligned_bit_count = unaligned_bit_count; | 450 | type_id.data.pointer.host_int_bytes = host_int_bytes; |
| 443 | type_id.data.pointer.ptr_len = ptr_len; | 451 | type_id.data.pointer.ptr_len = ptr_len; |
| 444 | 452 | ||
| 445 | auto existing_entry = g->type_table.maybe_get(type_id); | 453 | auto existing_entry = g->type_table.maybe_get(type_id); |
| 446 | if (existing_entry) | 454 | if (existing_entry) |
| 447 | return existing_entry->value; | 455 | return existing_entry->value; |
| 448 | } else { | 456 | } else { |
| 449 | assert(bit_offset == 0); | 457 | assert(bit_offset_in_host == 0); |
| 450 | parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; | 458 | parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; |
| 451 | if (*parent_pointer) { | 459 | if (*parent_pointer) { |
| 452 | assert((*parent_pointer)->data.pointer.explicit_alignment == 0); | 460 | assert((*parent_pointer)->data.pointer.explicit_alignment == 0); |
| ... | @@ -463,17 +471,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -463,17 +471,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 463 | const char *const_str = is_const ? "const " : ""; | 471 | const char *const_str = is_const ? "const " : ""; |
| 464 | const char *volatile_str = is_volatile ? "volatile " : ""; | 472 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 465 | buf_resize(&entry->name, 0); | 473 | buf_resize(&entry->name, 0); |
| 466 | if (unaligned_bit_count == 0 && byte_alignment == 0) { | 474 | if (host_int_bytes == 0 && byte_alignment == 0) { |
| 467 | buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); | 475 | buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); |
| 468 | } else if (unaligned_bit_count == 0) { | 476 | } else if (host_int_bytes == 0) { |
| 469 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, | 477 | buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, |
| 470 | const_str, volatile_str, buf_ptr(&child_type->name)); | 478 | const_str, volatile_str, buf_ptr(&child_type->name)); |
| 471 | } else if (byte_alignment == 0) { | 479 | } else if (byte_alignment == 0) { |
| 472 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, | 480 | buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, |
| 473 | bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); | 481 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); |
| 474 | } else { | 482 | } else { |
| 475 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, | 483 | buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, |
| 476 | bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); | 484 | bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); |
| 477 | } | 485 | } |
| 478 | 486 | ||
| 479 | assert(child_type->id != ZigTypeIdInvalid); | 487 | assert(child_type->id != ZigTypeIdInvalid); |
| ... | @@ -481,7 +489,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -481,7 +489,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 481 | entry->zero_bits = !type_has_bits(child_type); | 489 | entry->zero_bits = !type_has_bits(child_type); |
| 482 | 490 | ||
| 483 | if (!entry->zero_bits) { | 491 | if (!entry->zero_bits) { |
| 484 | if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 || | 492 | if (is_const || is_volatile || host_int_bytes != 0 || byte_alignment != 0 || |
| 485 | ptr_len != PtrLenSingle) | 493 | ptr_len != PtrLenSingle) |
| 486 | { | 494 | { |
| 487 | ZigType *peer_type = get_pointer_to_type(g, child_type, false); | 495 | ZigType *peer_type = get_pointer_to_type(g, child_type, false); |
| ... | @@ -506,8 +514,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons | ... | @@ -506,8 +514,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons |
| 506 | entry->data.pointer.is_const = is_const; | 514 | entry->data.pointer.is_const = is_const; |
| 507 | entry->data.pointer.is_volatile = is_volatile; | 515 | entry->data.pointer.is_volatile = is_volatile; |
| 508 | entry->data.pointer.explicit_alignment = byte_alignment; | 516 | entry->data.pointer.explicit_alignment = byte_alignment; |
| 509 | entry->data.pointer.bit_offset = bit_offset; | 517 | entry->data.pointer.bit_offset_in_host = bit_offset_in_host; |
| 510 | entry->data.pointer.unaligned_bit_count = unaligned_bit_count; | 518 | entry->data.pointer.host_int_bytes = host_int_bytes; |
| 511 | 519 | ||
| 512 | if (parent_pointer) { | 520 | if (parent_pointer) { |
| 513 | *parent_pointer = entry; | 521 | *parent_pointer = entry; |
| ... | @@ -2007,12 +2015,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -2007,12 +2015,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2007 | size_t field_size_in_bits = type_size_bits(g, field_type); | 2015 | size_t field_size_in_bits = type_size_bits(g, field_type); |
| 2008 | size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; | 2016 | size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; |
| 2009 | 2017 | ||
| 2010 | type_struct_field->packed_bits_size = field_size_in_bits; | ||
| 2011 | |||
| 2012 | if (first_packed_bits_offset_misalign != SIZE_MAX) { | 2018 | if (first_packed_bits_offset_misalign != SIZE_MAX) { |
| 2013 | // this field is not byte-aligned; it is part of the previous field with a bit offset | 2019 | // this field is not byte-aligned; it is part of the previous field with a bit offset |
| 2014 | type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; | 2020 | type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign; |
| 2015 | type_struct_field->unaligned_bit_count = field_size_in_bits; | ||
| 2016 | 2021 | ||
| 2017 | size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; | 2022 | size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; |
| 2018 | LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count)); | 2023 | LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count)); |
| ... | @@ -2025,13 +2030,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -2025,13 +2030,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2025 | } | 2030 | } |
| 2026 | } else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) { | 2031 | } else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) { |
| 2027 | first_packed_bits_offset_misalign = packed_bits_offset; | 2032 | first_packed_bits_offset_misalign = packed_bits_offset; |
| 2028 | type_struct_field->packed_bits_offset = 0; | 2033 | type_struct_field->bit_offset_in_host = 0; |
| 2029 | type_struct_field->unaligned_bit_count = field_size_in_bits; | ||
| 2030 | } else { | 2034 | } else { |
| 2031 | // This is a byte-aligned field (both start and end) in a packed struct. | 2035 | // This is a byte-aligned field (both start and end) in a packed struct. |
| 2032 | element_types[gen_field_index] = field_type->type_ref; | 2036 | element_types[gen_field_index] = field_type->type_ref; |
| 2033 | type_struct_field->packed_bits_offset = 0; | 2037 | type_struct_field->bit_offset_in_host = 0; |
| 2034 | type_struct_field->unaligned_bit_count = 0; | ||
| 2035 | gen_field_index += 1; | 2038 | gen_field_index += 1; |
| 2036 | } | 2039 | } |
| 2037 | packed_bits_offset = next_packed_bits_offset; | 2040 | packed_bits_offset = next_packed_bits_offset; |
| ... | @@ -2124,10 +2127,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -2124,10 +2127,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2124 | uint64_t debug_align_in_bits; | 2127 | uint64_t debug_align_in_bits; |
| 2125 | uint64_t debug_offset_in_bits; | 2128 | uint64_t debug_offset_in_bits; |
| 2126 | if (packed) { | 2129 | if (packed) { |
| 2127 | debug_size_in_bits = type_struct_field->packed_bits_size; | 2130 | debug_size_in_bits = type_size_bits(g, type_struct_field->type_entry); |
| 2128 | debug_align_in_bits = 1; | 2131 | debug_align_in_bits = 1; |
| 2129 | debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, | 2132 | debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, |
| 2130 | (unsigned)gen_field_index) + type_struct_field->packed_bits_offset; | 2133 | (unsigned)gen_field_index) + type_struct_field->bit_offset_in_host; |
| 2131 | } else { | 2134 | } else { |
| 2132 | debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 2135 | debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 2133 | debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); | 2136 | debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); |
| ... | @@ -6007,8 +6010,8 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -6007,8 +6010,8 @@ uint32_t type_id_hash(TypeId x) { |
| 6007 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + | 6010 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| 6008 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + | 6011 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + |
| 6009 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + | 6012 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + |
| 6010 | (((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) + | 6013 | (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + |
| 6011 | (((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881); | 6014 | (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); |
| 6012 | case ZigTypeIdArray: | 6015 | case ZigTypeIdArray: |
| 6013 | return hash_ptr(x.data.array.child_type) + | 6016 | return hash_ptr(x.data.array.child_type) + |
| 6014 | ((uint32_t)x.data.array.size ^ (uint32_t)2122979968); | 6017 | ((uint32_t)x.data.array.size ^ (uint32_t)2122979968); |
| ... | @@ -6055,8 +6058,8 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -6055,8 +6058,8 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6055 | a.data.pointer.is_const == b.data.pointer.is_const && | 6058 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 6056 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && | 6059 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 6057 | a.data.pointer.alignment == b.data.pointer.alignment && | 6060 | a.data.pointer.alignment == b.data.pointer.alignment && |
| 6058 | a.data.pointer.bit_offset == b.data.pointer.bit_offset && | 6061 | a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && |
| 6059 | a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; | 6062 | a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; |
| 6060 | case ZigTypeIdArray: | 6063 | case ZigTypeIdArray: |
| 6061 | return a.data.array.child_type == b.data.array.child_type && | 6064 | return a.data.array.child_type == b.data.array.child_type && |
| 6062 | a.data.array.size == b.data.array.size; | 6065 | a.data.array.size == b.data.array.size; |
| ... | @@ -6534,3 +6537,13 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { | ... | @@ -6534,3 +6537,13 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { |
| 6534 | ty->id == ZigTypeIdUnreachable || | 6537 | ty->id == ZigTypeIdUnreachable || |
| 6535 | get_codegen_ptr_type(ty) != nullptr); | 6538 | get_codegen_ptr_type(ty) != nullptr); |
| 6536 | } | 6539 | } |
| 6540 | |||
| 6541 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) { | ||
| 6542 | assert(struct_type->id == ZigTypeIdStruct); | ||
| 6543 | if (struct_type->data.structure.layout != ContainerLayoutPacked) { | ||
| 6544 | return 0; | ||
| 6545 | } | ||
| 6546 | LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); | ||
| 6547 | return LLVMStoreSizeOfType(g->target_data_ref, field_type); | ||
| 6548 | } | ||
| 6549 |
src/analyze.hpp+2| ... | @@ -216,4 +216,6 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); | ... | @@ -216,4 +216,6 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); |
| 216 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); | 216 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); |
| 217 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); | 217 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); |
| 218 | 218 | ||
| 219 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); | ||
| 220 | |||
| 219 | #endif | 221 | #endif |
src/ast_render.cpp+2-2| ... | @@ -635,7 +635,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -635,7 +635,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 635 | fprintf(ar->f, "align("); | 635 | fprintf(ar->f, "align("); |
| 636 | render_node_grouped(ar, node->data.pointer_type.align_expr); | 636 | render_node_grouped(ar, node->data.pointer_type.align_expr); |
| 637 | if (node->data.pointer_type.bit_offset_start != nullptr) { | 637 | if (node->data.pointer_type.bit_offset_start != nullptr) { |
| 638 | assert(node->data.pointer_type.bit_offset_end != nullptr); | 638 | assert(node->data.pointer_type.host_int_bytes != nullptr); |
| 639 | 639 | ||
| 640 | Buf offset_start_buf = BUF_INIT; | 640 | Buf offset_start_buf = BUF_INIT; |
| 641 | buf_resize(&offset_start_buf, 0); | 641 | buf_resize(&offset_start_buf, 0); |
| ... | @@ -643,7 +643,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -643,7 +643,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 643 | 643 | ||
| 644 | Buf offset_end_buf = BUF_INIT; | 644 | Buf offset_end_buf = BUF_INIT; |
| 645 | buf_resize(&offset_end_buf, 0); | 645 | buf_resize(&offset_end_buf, 0); |
| 646 | bigint_append_buf(&offset_end_buf, node->data.pointer_type.bit_offset_end, 10); | 646 | bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10); |
| 647 | 647 | ||
| 648 | fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); | 648 | fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); |
| 649 | } | 649 | } |
src/codegen.cpp+30-21| ... | @@ -1795,8 +1795,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty | ... | @@ -1795,8 +1795,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty |
| 1795 | return nullptr; | 1795 | return nullptr; |
| 1796 | } | 1796 | } |
| 1797 | 1797 | ||
| 1798 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; | 1798 | uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; |
| 1799 | if (unaligned_bit_count == 0) { | 1799 | if (host_int_bytes == 0) { |
| 1800 | gen_store(g, value, ptr, ptr_type); | 1800 | gen_store(g, value, ptr, ptr_type); |
| 1801 | return nullptr; | 1801 | return nullptr; |
| 1802 | } | 1802 | } |
| ... | @@ -1804,10 +1804,12 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty | ... | @@ -1804,10 +1804,12 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty |
| 1804 | bool big_endian = g->is_big_endian; | 1804 | bool big_endian = g->is_big_endian; |
| 1805 | 1805 | ||
| 1806 | LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); | 1806 | LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); |
| 1807 | |||
| 1808 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; | ||
| 1809 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); | 1807 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| 1810 | uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset; | 1808 | assert(host_bit_count == host_int_bytes * 8); |
| 1809 | uint32_t size_in_bits = type_size_bits(g, child_type); | ||
| 1810 | |||
| 1811 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host; | ||
| 1812 | uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset; | ||
| 1811 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); | 1813 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| 1812 | 1814 | ||
| 1813 | LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); | 1815 | LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); |
| ... | @@ -3209,18 +3211,20 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3209,18 +3211,20 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3209 | ZigType *ptr_type = instruction->ptr->value.type; | 3211 | ZigType *ptr_type = instruction->ptr->value.type; |
| 3210 | assert(ptr_type->id == ZigTypeIdPointer); | 3212 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3211 | 3213 | ||
| 3212 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; | 3214 | uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; |
| 3213 | if (unaligned_bit_count == 0) | 3215 | if (host_int_bytes == 0) |
| 3214 | return get_handle_value(g, ptr, child_type, ptr_type); | 3216 | return get_handle_value(g, ptr, child_type, ptr_type); |
| 3215 | 3217 | ||
| 3216 | bool big_endian = g->is_big_endian; | 3218 | bool big_endian = g->is_big_endian; |
| 3217 | 3219 | ||
| 3218 | assert(!handle_is_ptr(child_type)); | 3220 | assert(!handle_is_ptr(child_type)); |
| 3219 | LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); | 3221 | LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); |
| 3220 | |||
| 3221 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; | ||
| 3222 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); | 3222 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| 3223 | uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset; | 3223 | assert(host_bit_count == host_int_bytes * 8); |
| 3224 | uint32_t size_in_bits = type_size_bits(g, child_type); | ||
| 3225 | |||
| 3226 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host; | ||
| 3227 | uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset; | ||
| 3224 | 3228 | ||
| 3225 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); | 3229 | LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); |
| 3226 | LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); | 3230 | LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); |
| ... | @@ -3276,20 +3280,22 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3276,20 +3280,22 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3276 | array_type->data.array.len, false); | 3280 | array_type->data.array.len, false); |
| 3277 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); | 3281 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); |
| 3278 | } | 3282 | } |
| 3279 | if (array_ptr_type->data.pointer.unaligned_bit_count != 0) { | 3283 | if (array_ptr_type->data.pointer.host_int_bytes != 0) { |
| 3280 | return array_ptr_ptr; | 3284 | return array_ptr_ptr; |
| 3281 | } | 3285 | } |
| 3282 | ZigType *child_type = array_type->data.array.child_type; | 3286 | ZigType *child_type = array_type->data.array.child_type; |
| 3283 | if (child_type->id == ZigTypeIdStruct && | 3287 | if (child_type->id == ZigTypeIdStruct && |
| 3284 | child_type->data.structure.layout == ContainerLayoutPacked) | 3288 | child_type->data.structure.layout == ContainerLayoutPacked) |
| 3285 | { | 3289 | { |
| 3286 | size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count; | 3290 | ZigType *ptr_type = instruction->base.value.type; |
| 3287 | if (unaligned_bit_count != 0) { | 3291 | size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; |
| 3292 | if (host_int_bytes != 0) { | ||
| 3293 | uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type); | ||
| 3288 | LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); | 3294 | LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); |
| 3289 | LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); | 3295 | LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); |
| 3290 | assert(unaligned_bit_count % 8 == 0); | 3296 | assert(size_in_bits % 8 == 0); |
| 3291 | LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref, | 3297 | LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 3292 | unaligned_bit_count / 8, false); | 3298 | size_in_bits / 8, false); |
| 3293 | LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); | 3299 | LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); |
| 3294 | LLVMValueRef indices[] = { | 3300 | LLVMValueRef indices[] = { |
| 3295 | byte_offset | 3301 | byte_offset |
| ... | @@ -3505,7 +3511,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa | ... | @@ -3505,7 +3511,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 3505 | return nullptr; | 3511 | return nullptr; |
| 3506 | 3512 | ||
| 3507 | if (struct_ptr_type->id == ZigTypeIdPointer && | 3513 | if (struct_ptr_type->id == ZigTypeIdPointer && |
| 3508 | struct_ptr_type->data.pointer.unaligned_bit_count != 0) | 3514 | struct_ptr_type->data.pointer.host_int_bytes != 0) |
| 3509 | { | 3515 | { |
| 3510 | return struct_ptr; | 3516 | return struct_ptr; |
| 3511 | } | 3517 | } |
| ... | @@ -4671,10 +4677,11 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, | ... | @@ -4671,10 +4677,11 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, |
| 4671 | LLVMValueRef value = ir_llvm_value(g, field->value); | 4677 | LLVMValueRef value = ir_llvm_value(g, field->value); |
| 4672 | 4678 | ||
| 4673 | uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry); | 4679 | uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry); |
| 4680 | uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field); | ||
| 4674 | 4681 | ||
| 4675 | ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, | 4682 | ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, |
| 4676 | false, false, PtrLenSingle, field_align_bytes, | 4683 | false, false, PtrLenSingle, field_align_bytes, |
| 4677 | (uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count); | 4684 | (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes); |
| 4678 | 4685 | ||
| 4679 | gen_assign_raw(g, field_ptr, ptr_type, value); | 4686 | gen_assign_raw(g, field_ptr, ptr_type, value); |
| 4680 | } | 4687 | } |
| ... | @@ -5459,15 +5466,16 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -5459,15 +5466,16 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 5459 | continue; | 5466 | continue; |
| 5460 | } | 5467 | } |
| 5461 | LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); | 5468 | LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); |
| 5469 | uint32_t packed_bits_size = type_size_bits(g, field->type_entry); | ||
| 5462 | if (is_big_endian) { | 5470 | if (is_big_endian) { |
| 5463 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, field->packed_bits_size, false); | 5471 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false); |
| 5464 | val = LLVMConstShl(val, shift_amt); | 5472 | val = LLVMConstShl(val, shift_amt); |
| 5465 | val = LLVMConstOr(val, child_val); | 5473 | val = LLVMConstOr(val, child_val); |
| 5466 | } else { | 5474 | } else { |
| 5467 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); | 5475 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); |
| 5468 | LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); | 5476 | LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); |
| 5469 | val = LLVMConstOr(val, child_val_shifted); | 5477 | val = LLVMConstOr(val, child_val_shifted); |
| 5470 | used_bits += field->packed_bits_size; | 5478 | used_bits += packed_bits_size; |
| 5471 | } | 5479 | } |
| 5472 | } | 5480 | } |
| 5473 | return val; | 5481 | return val; |
| ... | @@ -5677,16 +5685,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5677,16 +5685,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5677 | } | 5685 | } |
| 5678 | LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, | 5686 | LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, |
| 5679 | &const_val->data.x_struct.fields[i]); | 5687 | &const_val->data.x_struct.fields[i]); |
| 5688 | uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry); | ||
| 5680 | if (is_big_endian) { | 5689 | if (is_big_endian) { |
| 5681 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, | 5690 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, |
| 5682 | it_field->packed_bits_size, false); | 5691 | packed_bits_size, false); |
| 5683 | val = LLVMConstShl(val, shift_amt); | 5692 | val = LLVMConstShl(val, shift_amt); |
| 5684 | val = LLVMConstOr(val, child_val); | 5693 | val = LLVMConstOr(val, child_val); |
| 5685 | } else { | 5694 | } else { |
| 5686 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); | 5695 | LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); |
| 5687 | LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); | 5696 | LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); |
| 5688 | val = LLVMConstOr(val, child_val_shifted); | 5697 | val = LLVMConstOr(val, child_val_shifted); |
| 5689 | used_bits += it_field->packed_bits_size; | 5698 | used_bits += packed_bits_size; |
| 5690 | } | 5699 | } |
| 5691 | } | 5700 | } |
| 5692 | fields[type_struct_field->gen_index] = val; | 5701 | fields[type_struct_field->gen_index] = val; |
src/ir.cpp+31-31| ... | @@ -1296,7 +1296,7 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru | ... | @@ -1296,7 +1296,7 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru |
| 1296 | 1296 | ||
| 1297 | static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1297 | static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1298 | IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, | 1298 | IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, |
| 1299 | IrInstruction *align_value, uint32_t bit_offset_start, uint32_t bit_offset_end) | 1299 | IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes) |
| 1300 | { | 1300 | { |
| 1301 | IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node); | 1301 | IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node); |
| 1302 | ptr_type_of_instruction->align_value = align_value; | 1302 | ptr_type_of_instruction->align_value = align_value; |
| ... | @@ -1305,7 +1305,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -1305,7 +1305,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 1305 | ptr_type_of_instruction->is_volatile = is_volatile; | 1305 | ptr_type_of_instruction->is_volatile = is_volatile; |
| 1306 | ptr_type_of_instruction->ptr_len = ptr_len; | 1306 | ptr_type_of_instruction->ptr_len = ptr_len; |
| 1307 | ptr_type_of_instruction->bit_offset_start = bit_offset_start; | 1307 | ptr_type_of_instruction->bit_offset_start = bit_offset_start; |
| 1308 | ptr_type_of_instruction->bit_offset_end = bit_offset_end; | 1308 | ptr_type_of_instruction->host_int_bytes = host_int_bytes; |
| 1309 | 1309 | ||
| 1310 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | 1310 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); |
| 1311 | ir_ref_instruction(child_type, irb->current_basic_block); | 1311 | ir_ref_instruction(child_type, irb->current_basic_block); |
| ... | @@ -5154,26 +5154,26 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -5154,26 +5154,26 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 5154 | bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start); | 5154 | bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start); |
| 5155 | } | 5155 | } |
| 5156 | 5156 | ||
| 5157 | uint32_t bit_offset_end = 0; | 5157 | uint32_t host_int_bytes = 0; |
| 5158 | if (node->data.pointer_type.bit_offset_end != nullptr) { | 5158 | if (node->data.pointer_type.host_int_bytes != nullptr) { |
| 5159 | if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_end, 32, false)) { | 5159 | if (!bigint_fits_in_bits(node->data.pointer_type.host_int_bytes, 32, false)) { |
| 5160 | Buf *val_buf = buf_alloc(); | 5160 | Buf *val_buf = buf_alloc(); |
| 5161 | bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_end, 10); | 5161 | bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10); |
| 5162 | exec_add_error_node(irb->codegen, irb->exec, node, | 5162 | exec_add_error_node(irb->codegen, irb->exec, node, |
| 5163 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); | 5163 | buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); |
| 5164 | return irb->codegen->invalid_instruction; | 5164 | return irb->codegen->invalid_instruction; |
| 5165 | } | 5165 | } |
| 5166 | bit_offset_end = bigint_as_unsigned(node->data.pointer_type.bit_offset_end); | 5166 | host_int_bytes = bigint_as_unsigned(node->data.pointer_type.host_int_bytes); |
| 5167 | } | 5167 | } |
| 5168 | 5168 | ||
| 5169 | if ((bit_offset_start != 0 || bit_offset_end != 0) && bit_offset_start >= bit_offset_end) { | 5169 | if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { |
| 5170 | exec_add_error_node(irb->codegen, irb->exec, node, | 5170 | exec_add_error_node(irb->codegen, irb->exec, node, |
| 5171 | buf_sprintf("bit offset start must be less than bit offset end")); | 5171 | buf_sprintf("bit offset starts after end of host integer")); |
| 5172 | return irb->codegen->invalid_instruction; | 5172 | return irb->codegen->invalid_instruction; |
| 5173 | } | 5173 | } |
| 5174 | 5174 | ||
| 5175 | return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, | 5175 | return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, |
| 5176 | ptr_len, align_value, bit_offset_start, bit_offset_end); | 5176 | ptr_len, align_value, bit_offset_start, host_int_bytes); |
| 5177 | } | 5177 | } |
| 5178 | 5178 | ||
| 5179 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, | 5179 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, |
| ... | @@ -8600,8 +8600,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted | ... | @@ -8600,8 +8600,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8600 | if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && | 8600 | if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && |
| 8601 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && | 8601 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && |
| 8602 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && | 8602 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && |
| 8603 | actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset && | 8603 | actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host && |
| 8604 | actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count && | 8604 | actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes && |
| 8605 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) | 8605 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) |
| 8606 | { | 8606 | { |
| 8607 | return result; | 8607 | return result; |
| ... | @@ -8622,8 +8622,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted | ... | @@ -8622,8 +8622,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8622 | } | 8622 | } |
| 8623 | if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && | 8623 | if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && |
| 8624 | (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && | 8624 | (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && |
| 8625 | actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset && | 8625 | actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && |
| 8626 | actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count && | 8626 | actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && |
| 8627 | get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type)) | 8627 | get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type)) |
| 8628 | { | 8628 | { |
| 8629 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, | 8629 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, |
| ... | @@ -11166,8 +11166,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -11166,8 +11166,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11166 | if (dest_ptr_type != nullptr && | 11166 | if (dest_ptr_type != nullptr && |
| 11167 | (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) && | 11167 | (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) && |
| 11168 | (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) && | 11168 | (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) && |
| 11169 | actual_type->data.pointer.bit_offset == dest_ptr_type->data.pointer.bit_offset && | 11169 | actual_type->data.pointer.bit_offset_in_host == dest_ptr_type->data.pointer.bit_offset_in_host && |
| 11170 | actual_type->data.pointer.unaligned_bit_count == dest_ptr_type->data.pointer.unaligned_bit_count && | 11170 | actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && |
| 11171 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) | 11171 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) |
| 11172 | { | 11172 | { |
| 11173 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr); | 11173 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr); |
| ... | @@ -14359,7 +14359,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali | ... | @@ -14359,7 +14359,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali |
| 14359 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 14359 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14360 | ptr_type->data.pointer.ptr_len, | 14360 | ptr_type->data.pointer.ptr_len, |
| 14361 | new_align, | 14361 | new_align, |
| 14362 | ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); | 14362 | ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes); |
| 14363 | } | 14363 | } |
| 14364 | 14364 | ||
| 14365 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { | 14365 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { |
| ... | @@ -14376,7 +14376,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) { | ... | @@ -14376,7 +14376,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) { |
| 14376 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 14376 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14377 | ptr_len, | 14377 | ptr_len, |
| 14378 | ptr_type->data.pointer.explicit_alignment, | 14378 | ptr_type->data.pointer.explicit_alignment, |
| 14379 | ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); | 14379 | ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes); |
| 14380 | } | 14380 | } |
| 14381 | 14381 | ||
| 14382 | static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { | 14382 | static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| ... | @@ -14423,7 +14423,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle | ... | @@ -14423,7 +14423,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle |
| 14423 | return ira->codegen->builtin_types.entry_invalid; | 14423 | return ira->codegen->builtin_types.entry_invalid; |
| 14424 | } | 14424 | } |
| 14425 | ZigType *child_type = array_type->data.array.child_type; | 14425 | ZigType *child_type = array_type->data.array.child_type; |
| 14426 | if (ptr_type->data.pointer.unaligned_bit_count == 0) { | 14426 | if (ptr_type->data.pointer.host_int_bytes == 0) { |
| 14427 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 14427 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 14428 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 14428 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14429 | elem_ptr_instruction->ptr_len, | 14429 | elem_ptr_instruction->ptr_len, |
| ... | @@ -14439,7 +14439,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle | ... | @@ -14439,7 +14439,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle |
| 14439 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 14439 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 14440 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 14440 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14441 | elem_ptr_instruction->ptr_len, | 14441 | elem_ptr_instruction->ptr_len, |
| 14442 | 1, (uint32_t)bit_offset, (uint32_t)bit_width); | 14442 | 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes); |
| 14443 | } | 14443 | } |
| 14444 | } else if (array_type->id == ZigTypeIdPointer) { | 14444 | } else if (array_type->id == ZigTypeIdPointer) { |
| 14445 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { | 14445 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { |
| ... | @@ -14740,10 +14740,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -14740,10 +14740,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14740 | if (field) { | 14740 | if (field) { |
| 14741 | bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); | 14741 | bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); |
| 14742 | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); | 14742 | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); |
| 14743 | size_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset; | 14743 | uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host; |
| 14744 | size_t ptr_unaligned_bit_count = container_ptr->value.type->data.pointer.unaligned_bit_count; | 14744 | uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes; |
| 14745 | size_t unaligned_bit_count_for_result_type = (ptr_unaligned_bit_count == 0) ? | 14745 | uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? |
| 14746 | field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); | 14746 | get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes; |
| 14747 | if (instr_is_comptime(container_ptr)) { | 14747 | if (instr_is_comptime(container_ptr)) { |
| 14748 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); | 14748 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); |
| 14749 | if (!ptr_val) | 14749 | if (!ptr_val) |
| ... | @@ -14758,8 +14758,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -14758,8 +14758,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14758 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; | 14758 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; |
| 14759 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, | 14759 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, |
| 14760 | is_const, is_volatile, PtrLenSingle, align_bytes, | 14760 | is_const, is_volatile, PtrLenSingle, align_bytes, |
| 14761 | (uint32_t)(ptr_bit_offset + field->packed_bits_offset), | 14761 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 14762 | (uint32_t)unaligned_bit_count_for_result_type); | 14762 | (uint32_t)host_int_bytes_for_result_type); |
| 14763 | IrInstruction *result = ir_get_const(ira, source_instr); | 14763 | IrInstruction *result = ir_get_const(ira, source_instr); |
| 14764 | ConstExprValue *const_val = &result->value; | 14764 | ConstExprValue *const_val = &result->value; |
| 14765 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; | 14765 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| ... | @@ -14775,8 +14775,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ | ... | @@ -14775,8 +14775,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ |
| 14775 | result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, | 14775 | result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, |
| 14776 | PtrLenSingle, | 14776 | PtrLenSingle, |
| 14777 | align_bytes, | 14777 | align_bytes, |
| 14778 | (uint32_t)(ptr_bit_offset + field->packed_bits_offset), | 14778 | (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), |
| 14779 | (uint32_t)unaligned_bit_count_for_result_type); | 14779 | host_int_bytes_for_result_type); |
| 14780 | return result; | 14780 | return result; |
| 14781 | } else { | 14781 | } else { |
| 14782 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 14782 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| ... | @@ -17135,7 +17135,7 @@ static ZigType *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira, | ... | @@ -17135,7 +17135,7 @@ static ZigType *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira, |
| 17135 | if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset))) | 17135 | if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset))) |
| 17136 | return ira->codegen->builtin_types.entry_invalid; | 17136 | return ira->codegen->builtin_types.entry_invalid; |
| 17137 | 17137 | ||
| 17138 | size_t bit_offset = byte_offset * 8 + field->packed_bits_offset; | 17138 | size_t bit_offset = byte_offset * 8 + field->bit_offset_in_host; |
| 17139 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 17139 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 17140 | bigint_init_unsigned(&out_val->data.x_bigint, bit_offset); | 17140 | bigint_init_unsigned(&out_val->data.x_bigint, bit_offset); |
| 17141 | return ira->codegen->builtin_types.entry_num_lit_int; | 17141 | return ira->codegen->builtin_types.entry_num_lit_int; |
| ... | @@ -20758,7 +20758,7 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr | ... | @@ -20758,7 +20758,7 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr |
| 20758 | out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, | 20758 | out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 20759 | instruction->is_const, instruction->is_volatile, | 20759 | instruction->is_const, instruction->is_volatile, |
| 20760 | instruction->ptr_len, align_bytes, | 20760 | instruction->ptr_len, align_bytes, |
| 20761 | instruction->bit_offset_start, instruction->bit_offset_end - instruction->bit_offset_start); | 20761 | instruction->bit_offset_start, instruction->host_int_bytes); |
| 20762 | 20762 | ||
| 20763 | return ira->codegen->builtin_types.entry_type; | 20763 | return ira->codegen->builtin_types.entry_type; |
| 20764 | } | 20764 | } |
src/ir_print.cpp+1-1| ... | @@ -1015,7 +1015,7 @@ static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) { | ... | @@ -1015,7 +1015,7 @@ static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) { |
| 1015 | } | 1015 | } |
| 1016 | const char *const_str = instruction->is_const ? "const " : ""; | 1016 | const char *const_str = instruction->is_const ? "const " : ""; |
| 1017 | const char *volatile_str = instruction->is_volatile ? "volatile " : ""; | 1017 | const char *volatile_str = instruction->is_volatile ? "volatile " : ""; |
| 1018 | fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end, | 1018 | fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes, |
| 1019 | const_str, volatile_str); | 1019 | const_str, volatile_str); |
| 1020 | ir_print_other_instruction(irp, instruction->child_type); | 1020 | ir_print_other_instruction(irp, instruction->child_type); |
| 1021 | } | 1021 | } |
src/parser.cpp+2-2| ... | @@ -1161,10 +1161,10 @@ static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, To | ... | @@ -1161,10 +1161,10 @@ static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, To |
| 1161 | *token_index += 1; | 1161 | *token_index += 1; |
| 1162 | Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); | 1162 | Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); |
| 1163 | ast_eat_token(pc, token_index, TokenIdColon); | 1163 | ast_eat_token(pc, token_index, TokenIdColon); |
| 1164 | Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); | 1164 | Token *host_int_bytes_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); |
| 1165 | 1165 | ||
| 1166 | node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok); | 1166 | node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok); |
| 1167 | node->data.pointer_type.bit_offset_end = token_bigint(bit_offset_end_tok); | 1167 | node->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes_tok); |
| 1168 | } | 1168 | } |
| 1169 | ast_eat_token(pc, token_index, TokenIdRParen); | 1169 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 1170 | token = &pc->tokens->at(*token_index); | 1170 | token = &pc->tokens->at(*token_index); |
test/cases/align.zig+1-1| ... | @@ -40,7 +40,7 @@ const blah: packed struct { | ... | @@ -40,7 +40,7 @@ const blah: packed struct { |
| 40 | } = undefined; | 40 | } = undefined; |
| 41 | 41 | ||
| 42 | test "bit field alignment" { | 42 | test "bit field alignment" { |
| 43 | assert(@typeOf(&blah.b) == *align(1:3:6) const u3); | 43 | assert(@typeOf(&blah.b) == *align(1:3:1) const u3); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | test "default alignment allows unspecified in type syntax" { | 46 | test "default alignment allows unspecified in type syntax" { |
test/cases/eval.zig+8| ... | @@ -754,3 +754,11 @@ test "comptime bitwise operators" { | ... | @@ -754,3 +754,11 @@ test "comptime bitwise operators" { |
| 754 | assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); | 754 | assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); |
| 755 | } | 755 | } |
| 756 | } | 756 | } |
| 757 | |||
| 758 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | ||
| 759 | comptime { | ||
| 760 | assert(*align(1:0:2) u16 == *align(1) u16); | ||
| 761 | // TODO add parsing support for this syntax | ||
| 762 | //assert(*align(:0:2) u16 == *u16); | ||
| 763 | } | ||
| 764 | } |
test/compile_errors.zig+1-1| ... | @@ -3536,7 +3536,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3536,7 +3536,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3536 | \\ | 3536 | \\ |
| 3537 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | 3537 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } |
| 3538 | , | 3538 | , |
| 3539 | ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'", | 3539 | ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:1) const u3'", |
| 3540 | ); | 3540 | ); |
| 3541 | 3541 | ||
| 3542 | cases.add( | 3542 | cases.add( |