From dcfd15a7f0ed5159afad47915a11d1dd8315cbe8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 26 Sep 2018 14:24:55 -0400 Subject: [PATCH] the last number in a packed ptr is host int bytes See #1121 --- src/all_types.hpp | 17 +++++------ src/analyze.cpp | 65 ++++++++++++++++++++++++----------------- src/analyze.hpp | 2 ++ src/ast_render.cpp | 4 +-- src/codegen.cpp | 51 +++++++++++++++++++------------- src/ir.cpp | 62 +++++++++++++++++++-------------------- src/ir_print.cpp | 2 +- src/parser.cpp | 4 +-- test/cases/align.zig | 2 +- test/cases/eval.zig | 8 +++++ test/compile_errors.zig | 2 +- 11 files changed, 124 insertions(+), 95 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 0eaf69ed64..89c117ce82 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -664,7 +664,7 @@ struct AstNodePointerType { Token *star_token; AstNode *align_expr; BigInt *bit_offset_start; - BigInt *bit_offset_end; + BigInt *host_int_bytes; bool is_const; bool is_volatile; AstNode *op_expr; @@ -1020,8 +1020,8 @@ struct ZigTypePointer { ZigType *slice_parent; PtrLen ptr_len; uint32_t explicit_alignment; // 0 means use ABI alignment - uint32_t bit_offset; - uint32_t unaligned_bit_count; + uint32_t bit_offset_in_host; + uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned bool is_const; bool is_volatile; }; @@ -1045,10 +1045,7 @@ struct TypeStructField { ZigType *type_entry; size_t src_index; size_t gen_index; - // offset from the memory at gen_index - size_t packed_bits_offset; - size_t packed_bits_size; - size_t unaligned_bit_count; + uint32_t bit_offset_in_host; // offset from the memory at gen_index AstNode *decl_node; }; @@ -1470,8 +1467,8 @@ struct TypeId { bool is_const; bool is_volatile; uint32_t alignment; - uint32_t bit_offset; - uint32_t unaligned_bit_count; + uint32_t bit_offset_in_host; + uint32_t host_int_bytes; } pointer; struct { ZigType *child_type; @@ -2510,7 +2507,7 @@ struct IrInstructionPtrType { IrInstruction *align_value; IrInstruction *child_type; uint32_t bit_offset_start; - uint32_t bit_offset_end; + uint32_t host_int_bytes; PtrLen ptr_len; bool is_const; bool is_volatile; diff --git a/src/analyze.cpp b/src/analyze.cpp index 650f5b6b11..e0aa6224e8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -419,7 +419,7 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { } ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, - bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count) + bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes) { assert(!type_is_invalid(child_type)); 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 byte_alignment = 0; } + if (host_int_bytes != 0) { + uint32_t child_type_bits = type_size_bits(g, child_type); + if (host_int_bytes * 8 == child_type_bits) { + assert(bit_offset_in_host == 0); + host_int_bytes = 0; + } + } + TypeId type_id = {}; ZigType **parent_pointer = nullptr; - if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { + if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { type_id.id = ZigTypeIdPointer; type_id.data.pointer.child_type = child_type; type_id.data.pointer.is_const = is_const; type_id.data.pointer.is_volatile = is_volatile; type_id.data.pointer.alignment = byte_alignment; - type_id.data.pointer.bit_offset = bit_offset; - type_id.data.pointer.unaligned_bit_count = unaligned_bit_count; + type_id.data.pointer.bit_offset_in_host = bit_offset_in_host; + type_id.data.pointer.host_int_bytes = host_int_bytes; type_id.data.pointer.ptr_len = ptr_len; auto existing_entry = g->type_table.maybe_get(type_id); if (existing_entry) return existing_entry->value; } else { - assert(bit_offset == 0); + assert(bit_offset_in_host == 0); parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; if (*parent_pointer) { 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 const char *const_str = is_const ? "const " : ""; const char *volatile_str = is_volatile ? "volatile " : ""; buf_resize(&entry->name, 0); - if (unaligned_bit_count == 0 && byte_alignment == 0) { + if (host_int_bytes == 0 && byte_alignment == 0) { buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); - } else if (unaligned_bit_count == 0) { + } else if (host_int_bytes == 0) { buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, const_str, volatile_str, buf_ptr(&child_type->name)); } else if (byte_alignment == 0) { buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, - bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); + bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); } else { buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, - bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); + bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name)); } assert(child_type->id != ZigTypeIdInvalid); @@ -481,7 +489,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons entry->zero_bits = !type_has_bits(child_type); if (!entry->zero_bits) { - if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 || + if (is_const || is_volatile || host_int_bytes != 0 || byte_alignment != 0 || ptr_len != PtrLenSingle) { 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 entry->data.pointer.is_const = is_const; entry->data.pointer.is_volatile = is_volatile; entry->data.pointer.explicit_alignment = byte_alignment; - entry->data.pointer.bit_offset = bit_offset; - entry->data.pointer.unaligned_bit_count = unaligned_bit_count; + entry->data.pointer.bit_offset_in_host = bit_offset_in_host; + entry->data.pointer.host_int_bytes = host_int_bytes; if (parent_pointer) { *parent_pointer = entry; @@ -2007,12 +2015,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { size_t field_size_in_bits = type_size_bits(g, field_type); size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; - type_struct_field->packed_bits_size = field_size_in_bits; - if (first_packed_bits_offset_misalign != SIZE_MAX) { // this field is not byte-aligned; it is part of the previous field with a bit offset - type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign; - type_struct_field->unaligned_bit_count = field_size_in_bits; + type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign; size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count)); @@ -2025,13 +2030,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { } } else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) { first_packed_bits_offset_misalign = packed_bits_offset; - type_struct_field->packed_bits_offset = 0; - type_struct_field->unaligned_bit_count = field_size_in_bits; + type_struct_field->bit_offset_in_host = 0; } else { // This is a byte-aligned field (both start and end) in a packed struct. element_types[gen_field_index] = field_type->type_ref; - type_struct_field->packed_bits_offset = 0; - type_struct_field->unaligned_bit_count = 0; + type_struct_field->bit_offset_in_host = 0; gen_field_index += 1; } packed_bits_offset = next_packed_bits_offset; @@ -2124,10 +2127,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { uint64_t debug_align_in_bits; uint64_t debug_offset_in_bits; if (packed) { - debug_size_in_bits = type_struct_field->packed_bits_size; + debug_size_in_bits = type_size_bits(g, type_struct_field->type_entry); debug_align_in_bits = 1; debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, - (unsigned)gen_field_index) + type_struct_field->packed_bits_offset; + (unsigned)gen_field_index) + type_struct_field->bit_offset_in_host; } else { debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); 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) { (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + - (((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) + - (((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881); + (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) + + (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881); case ZigTypeIdArray: return hash_ptr(x.data.array.child_type) + ((uint32_t)x.data.array.size ^ (uint32_t)2122979968); @@ -6055,8 +6058,8 @@ bool type_id_eql(TypeId a, TypeId b) { a.data.pointer.is_const == b.data.pointer.is_const && a.data.pointer.is_volatile == b.data.pointer.is_volatile && a.data.pointer.alignment == b.data.pointer.alignment && - a.data.pointer.bit_offset == b.data.pointer.bit_offset && - a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; + a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && + a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; case ZigTypeIdArray: return a.data.array.child_type == b.data.array.child_type && a.data.array.size == b.data.array.size; @@ -6534,3 +6537,13 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { ty->id == ZigTypeIdUnreachable || get_codegen_ptr_type(ty) != nullptr); } + +uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) { + assert(struct_type->id == ZigTypeIdStruct); + if (struct_type->data.structure.layout != ContainerLayoutPacked) { + return 0; + } + LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); + return LLVMStoreSizeOfType(g->target_data_ref, field_type); +} + diff --git a/src/analyze.hpp b/src/analyze.hpp index b04cf6fdfd..fdc979ec9a 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -216,4 +216,6 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); bool type_is_c_abi_int(CodeGen *g, ZigType *ty); bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); +uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); + #endif diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 37d4221eef..82c245d03a 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -635,7 +635,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { fprintf(ar->f, "align("); render_node_grouped(ar, node->data.pointer_type.align_expr); if (node->data.pointer_type.bit_offset_start != nullptr) { - assert(node->data.pointer_type.bit_offset_end != nullptr); + assert(node->data.pointer_type.host_int_bytes != nullptr); Buf offset_start_buf = BUF_INIT; buf_resize(&offset_start_buf, 0); @@ -643,7 +643,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { Buf offset_end_buf = BUF_INIT; buf_resize(&offset_end_buf, 0); - bigint_append_buf(&offset_end_buf, node->data.pointer_type.bit_offset_end, 10); + bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10); fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); } diff --git a/src/codegen.cpp b/src/codegen.cpp index d4d57d541c..176b7bb08b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1795,8 +1795,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty return nullptr; } - uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; - if (unaligned_bit_count == 0) { + uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; + if (host_int_bytes == 0) { gen_store(g, value, ptr, ptr_type); return nullptr; } @@ -1804,10 +1804,12 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty bool big_endian = g->is_big_endian; LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); - - uint32_t bit_offset = ptr_type->data.pointer.bit_offset; uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); - uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset; + assert(host_bit_count == host_int_bytes * 8); + uint32_t size_in_bits = type_size_bits(g, child_type); + + uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host; + uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset; LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); @@ -3209,18 +3211,20 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI ZigType *ptr_type = instruction->ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); - uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; - if (unaligned_bit_count == 0) + uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; + if (host_int_bytes == 0) return get_handle_value(g, ptr, child_type, ptr_type); bool big_endian = g->is_big_endian; assert(!handle_is_ptr(child_type)); LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, ""); - - uint32_t bit_offset = ptr_type->data.pointer.bit_offset; uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); - uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset; + assert(host_bit_count == host_int_bytes * 8); + uint32_t size_in_bits = type_size_bits(g, child_type); + + uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host; + uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset; LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); 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 array_type->data.array.len, false); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); } - if (array_ptr_type->data.pointer.unaligned_bit_count != 0) { + if (array_ptr_type->data.pointer.host_int_bytes != 0) { return array_ptr_ptr; } ZigType *child_type = array_type->data.array.child_type; if (child_type->id == ZigTypeIdStruct && child_type->data.structure.layout == ContainerLayoutPacked) { - size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count; - if (unaligned_bit_count != 0) { + ZigType *ptr_type = instruction->base.value.type; + size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; + if (host_int_bytes != 0) { + uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type); LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); - assert(unaligned_bit_count % 8 == 0); + assert(size_in_bits % 8 == 0); LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref, - unaligned_bit_count / 8, false); + size_in_bits / 8, false); LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); LLVMValueRef indices[] = { byte_offset @@ -3505,7 +3511,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa return nullptr; if (struct_ptr_type->id == ZigTypeIdPointer && - struct_ptr_type->data.pointer.unaligned_bit_count != 0) + struct_ptr_type->data.pointer.host_int_bytes != 0) { return struct_ptr; } @@ -4671,10 +4677,11 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, LLVMValueRef value = ir_llvm_value(g, field->value); uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry); + uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field); ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, false, false, PtrLenSingle, field_align_bytes, - (uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count); + (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes); gen_assign_raw(g, field_ptr, ptr_type, value); } @@ -5459,15 +5466,16 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con continue; } LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); + uint32_t packed_bits_size = type_size_bits(g, field->type_entry); if (is_big_endian) { - LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, field->packed_bits_size, false); + LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false); val = LLVMConstShl(val, shift_amt); val = LLVMConstOr(val, child_val); } else { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); val = LLVMConstOr(val, child_val_shifted); - used_bits += field->packed_bits_size; + used_bits += packed_bits_size; } } return val; @@ -5677,16 +5685,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c } LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); + uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry); if (is_big_endian) { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, - it_field->packed_bits_size, false); + packed_bits_size, false); val = LLVMConstShl(val, shift_amt); val = LLVMConstOr(val, child_val); } else { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false); LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt); val = LLVMConstOr(val, child_val_shifted); - used_bits += it_field->packed_bits_size; + used_bits += packed_bits_size; } } fields[type_struct_field->gen_index] = val; diff --git a/src/ir.cpp b/src/ir.cpp index 022909d184..79b809349c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1296,7 +1296,7 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, - IrInstruction *align_value, uint32_t bit_offset_start, uint32_t bit_offset_end) + IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes) { IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction(irb, scope, source_node); ptr_type_of_instruction->align_value = align_value; @@ -1305,7 +1305,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s ptr_type_of_instruction->is_volatile = is_volatile; ptr_type_of_instruction->ptr_len = ptr_len; ptr_type_of_instruction->bit_offset_start = bit_offset_start; - ptr_type_of_instruction->bit_offset_end = bit_offset_end; + ptr_type_of_instruction->host_int_bytes = host_int_bytes; if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(child_type, irb->current_basic_block); @@ -5154,26 +5154,26 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start); } - uint32_t bit_offset_end = 0; - if (node->data.pointer_type.bit_offset_end != nullptr) { - if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_end, 32, false)) { + uint32_t host_int_bytes = 0; + if (node->data.pointer_type.host_int_bytes != nullptr) { + if (!bigint_fits_in_bits(node->data.pointer_type.host_int_bytes, 32, false)) { Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_end, 10); + bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10); exec_add_error_node(irb->codegen, irb->exec, node, - buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); + buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); return irb->codegen->invalid_instruction; } - bit_offset_end = bigint_as_unsigned(node->data.pointer_type.bit_offset_end); + host_int_bytes = bigint_as_unsigned(node->data.pointer_type.host_int_bytes); } - if ((bit_offset_start != 0 || bit_offset_end != 0) && bit_offset_start >= bit_offset_end) { + if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { exec_add_error_node(irb->codegen, irb->exec, node, - buf_sprintf("bit offset start must be less than bit offset end")); + buf_sprintf("bit offset starts after end of host integer")); return irb->codegen->invalid_instruction; } return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, - ptr_len, align_value, bit_offset_start, bit_offset_end); + ptr_len, align_value, bit_offset_start, host_int_bytes); } 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 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && - actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset && - actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count && + actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host && + actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes && get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) { return result; @@ -8622,8 +8622,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && - actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset && - actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count && + actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && + actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type)) { 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 if (dest_ptr_type != nullptr && (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) && (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) && - actual_type->data.pointer.bit_offset == dest_ptr_type->data.pointer.bit_offset && - actual_type->data.pointer.unaligned_bit_count == dest_ptr_type->data.pointer.unaligned_bit_count && + actual_type->data.pointer.bit_offset_in_host == dest_ptr_type->data.pointer.bit_offset_in_host && + actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes && get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) { 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 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, ptr_type->data.pointer.ptr_len, new_align, - ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); + ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes); } 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) { ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, ptr_len, ptr_type->data.pointer.explicit_alignment, - ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); + ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes); } 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 return ira->codegen->builtin_types.entry_invalid; } ZigType *child_type = array_type->data.array.child_type; - if (ptr_type->data.pointer.unaligned_bit_count == 0) { + if (ptr_type->data.pointer.host_int_bytes == 0) { return_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, @@ -14439,7 +14439,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle return_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - 1, (uint32_t)bit_offset, (uint32_t)bit_width); + 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes); } } else if (array_type->id == ZigTypeIdPointer) { if (array_type->data.pointer.ptr_len == PtrLenSingle) { @@ -14740,10 +14740,10 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ if (field) { bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); - size_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset; - size_t ptr_unaligned_bit_count = container_ptr->value.type->data.pointer.unaligned_bit_count; - size_t unaligned_bit_count_for_result_type = (ptr_unaligned_bit_count == 0) ? - field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); + uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host; + uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes; + uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? + get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes; if (instr_is_comptime(container_ptr)) { ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); if (!ptr_val) @@ -14758,8 +14758,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, is_const, is_volatile, PtrLenSingle, align_bytes, - (uint32_t)(ptr_bit_offset + field->packed_bits_offset), - (uint32_t)unaligned_bit_count_for_result_type); + (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), + (uint32_t)host_int_bytes_for_result_type); IrInstruction *result = ir_get_const(ira, source_instr); ConstExprValue *const_val = &result->value; const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; @@ -14775,8 +14775,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, PtrLenSingle, align_bytes, - (uint32_t)(ptr_bit_offset + field->packed_bits_offset), - (uint32_t)unaligned_bit_count_for_result_type); + (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), + host_int_bytes_for_result_type); return result; } else { 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, if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset))) return ira->codegen->builtin_types.entry_invalid; - size_t bit_offset = byte_offset * 8 + field->packed_bits_offset; + size_t bit_offset = byte_offset * 8 + field->bit_offset_in_host; ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); bigint_init_unsigned(&out_val->data.x_bigint, bit_offset); return ira->codegen->builtin_types.entry_num_lit_int; @@ -20758,7 +20758,7 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, instruction->is_const, instruction->is_volatile, instruction->ptr_len, align_bytes, - instruction->bit_offset_start, instruction->bit_offset_end - instruction->bit_offset_start); + instruction->bit_offset_start, instruction->host_int_bytes); return ira->codegen->builtin_types.entry_type; } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index dc756cf492..3bed716756 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1015,7 +1015,7 @@ static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) { } const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; - fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end, + fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes, const_str, volatile_str); ir_print_other_instruction(irp, instruction->child_type); } diff --git a/src/parser.cpp b/src/parser.cpp index 8e6076c5e5..c57b1303e7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1161,10 +1161,10 @@ static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, To *token_index += 1; Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); ast_eat_token(pc, token_index, TokenIdColon); - Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); + Token *host_int_bytes_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok); - node->data.pointer_type.bit_offset_end = token_bigint(bit_offset_end_tok); + node->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes_tok); } ast_eat_token(pc, token_index, TokenIdRParen); token = &pc->tokens->at(*token_index); diff --git a/test/cases/align.zig b/test/cases/align.zig index 838935f53c..3dff57feb8 100644 --- a/test/cases/align.zig +++ b/test/cases/align.zig @@ -40,7 +40,7 @@ const blah: packed struct { } = undefined; test "bit field alignment" { - assert(@typeOf(&blah.b) == *align(1:3:6) const u3); + assert(@typeOf(&blah.b) == *align(1:3:1) const u3); } test "default alignment allows unspecified in type syntax" { diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 2cd7f695e7..408e9b04af 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -754,3 +754,11 @@ test "comptime bitwise operators" { assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); } } + +test "*align(1) u16 is the same as *align(1:0:2) u16" { + comptime { + assert(*align(1:0:2) u16 == *align(1) u16); + // TODO add parsing support for this syntax + //assert(*align(:0:2) u16 == *u16); + } +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 19bb630fb7..96d35e4de9 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3536,7 +3536,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'", + ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:1) const u3'", ); cases.add(