| author | |
| committer | |
| log | 5e345ff0ee9eb70d7f5f7167227f6a1e8903f428 |
| tree | 34d82c8ef040fc30fe895043d7a84d75552d36cf |
| parent | 5ab5de89c03bf9b3f08dfaa78d3b0fe41a72cdea |
| parent | c51b79c56e32594e4fb119fc760ae38b69fb9bbb |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Pointer arithmetic affects the alignment factor5 files changed, 78 insertions(+), 14 deletions(-)
lib/std/debug.zig+2-2| ... | @@ -1084,7 +1084,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -1084,7 +1084,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 1084 | std.macho.LC_SYMTAB => break @ptrCast(*std.macho.symtab_command, ptr), | 1084 | std.macho.LC_SYMTAB => break @ptrCast(*std.macho.symtab_command, ptr), |
| 1085 | else => {}, | 1085 | else => {}, |
| 1086 | } | 1086 | } |
| 1087 | ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403 | 1087 | ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize); |
| 1088 | } else { | 1088 | } else { |
| 1089 | return error.MissingDebugInfo; | 1089 | return error.MissingDebugInfo; |
| 1090 | }; | 1090 | }; |
| ... | @@ -2129,7 +2129,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u | ... | @@ -2129,7 +2129,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 2129 | std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)), | 2129 | std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)), |
| 2130 | else => {}, | 2130 | else => {}, |
| 2131 | } | 2131 | } |
| 2132 | ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403 | 2132 | ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize); |
| 2133 | } else { | 2133 | } else { |
| 2134 | return error.MissingDebugInfo; | 2134 | return error.MissingDebugInfo; |
| 2135 | }; | 2135 | }; |
lib/std/event/fs.zig+3-1| ... | @@ -1263,7 +1263,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -1263,7 +1263,7 @@ pub fn Watch(comptime V: type) type { |
| 1263 | var ptr = event_buf[0..].ptr; | 1263 | var ptr = event_buf[0..].ptr; |
| 1264 | const end_ptr = ptr + event_buf.len; | 1264 | const end_ptr = ptr + event_buf.len; |
| 1265 | var ev: *os.linux.inotify_event = undefined; | 1265 | var ev: *os.linux.inotify_event = undefined; |
| 1266 | while (@ptrToInt(ptr) < @ptrToInt(end_ptr)) : (ptr += @sizeOf(os.linux.inotify_event) + ev.len) { | 1266 | while (@ptrToInt(ptr) < @ptrToInt(end_ptr)) { |
| 1267 | ev = @ptrCast(*os.linux.inotify_event, ptr); | 1267 | ev = @ptrCast(*os.linux.inotify_event, ptr); |
| 1268 | if (ev.mask & os.linux.IN_CLOSE_WRITE == os.linux.IN_CLOSE_WRITE) { | 1268 | if (ev.mask & os.linux.IN_CLOSE_WRITE == os.linux.IN_CLOSE_WRITE) { |
| 1269 | const basename_ptr = ptr + @sizeOf(os.linux.inotify_event); | 1269 | const basename_ptr = ptr + @sizeOf(os.linux.inotify_event); |
| ... | @@ -1287,6 +1287,8 @@ pub fn Watch(comptime V: type) type { | ... | @@ -1287,6 +1287,8 @@ pub fn Watch(comptime V: type) type { |
| 1287 | }); | 1287 | }); |
| 1288 | } | 1288 | } |
| 1289 | } | 1289 | } |
| 1290 | |||
| 1291 | ptr = @alignCast(@alignOf(os.linux.inotify_event), ptr + @sizeOf(os.linux.inotify_event) + ev.len); | ||
| 1290 | } | 1292 | } |
| 1291 | }, | 1293 | }, |
| 1292 | os.linux.EINTR => continue, | 1294 | os.linux.EINTR => continue, |
lib/std/start.zig+2-2| ... | @@ -142,14 +142,14 @@ fn posixCallMainAndExit() noreturn { | ... | @@ -142,14 +142,14 @@ fn posixCallMainAndExit() noreturn { |
| 142 | const argc = starting_stack_ptr[0]; | 142 | const argc = starting_stack_ptr[0]; |
| 143 | const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1); | 143 | const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1); |
| 144 | 144 | ||
| 145 | const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1); | 145 | const envp_optional = @ptrCast([*:null]?[*:0]u8, @alignCast(@alignOf(usize), argv + argc + 1)); |
| 146 | var envp_count: usize = 0; | 146 | var envp_count: usize = 0; |
| 147 | while (envp_optional[envp_count]) |_| : (envp_count += 1) {} | 147 | while (envp_optional[envp_count]) |_| : (envp_count += 1) {} |
| 148 | const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count]; | 148 | const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count]; |
| 149 | 149 | ||
| 150 | if (builtin.os == .linux) { | 150 | if (builtin.os == .linux) { |
| 151 | // Find the beginning of the auxiliary vector | 151 | // Find the beginning of the auxiliary vector |
| 152 | const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); | 152 | const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1)); |
| 153 | std.os.linux.elf_aux_maybe = auxv; | 153 | std.os.linux.elf_aux_maybe = auxv; |
| 154 | // Initialize the TLS area | 154 | // Initialize the TLS area |
| 155 | const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size"); | 155 | const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size"); |
src/ir.cpp+41-9| ... | @@ -15783,19 +15783,51 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15783,19 +15783,51 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15783 | return ir_const_undef(ira, &instruction->base, op1->value->type); | 15783 | return ir_const_undef(ira, &instruction->base, op1->value->type); |
| 15784 | } | 15784 | } |
| 15785 | 15785 | ||
| 15786 | ZigType *elem_type = op1->value->type->data.pointer.child_type; | ||
| 15787 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) | ||
| 15788 | return ira->codegen->invalid_instruction; | ||
| 15789 | |||
| 15790 | // NOTE: this variable is meaningful iff op2_val is not null! | ||
| 15791 | uint64_t byte_offset; | ||
| 15792 | if (op2_val != nullptr) { | ||
| 15793 | uint64_t elem_offset; | ||
| 15794 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) | ||
| 15795 | return ira->codegen->invalid_instruction; | ||
| 15796 | |||
| 15797 | byte_offset = type_size(ira->codegen, elem_type) * elem_offset; | ||
| 15798 | } | ||
| 15799 | |||
| 15800 | // Fast path for cases where the RHS is zero | ||
| 15801 | if (op2_val != nullptr && byte_offset == 0) { | ||
| 15802 | return op1; | ||
| 15803 | } | ||
| 15804 | |||
| 15805 | ZigType *result_type = op1->value->type; | ||
| 15806 | // Calculate the new alignment of the pointer | ||
| 15807 | { | ||
| 15808 | uint32_t align_bytes; | ||
| 15809 | if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes))) | ||
| 15810 | return ira->codegen->invalid_instruction; | ||
| 15811 | |||
| 15812 | // If the addend is not a comptime-known value we can still count on | ||
| 15813 | // it being a multiple of the type size | ||
| 15814 | uint32_t addend = op2_val ? byte_offset : type_size(ira->codegen, elem_type); | ||
| 15815 | |||
| 15816 | // The resulting pointer is aligned to the lcd between the | ||
| 15817 | // offset (an arbitrary number) and the alignment factor (always | ||
| 15818 | // a power of two, non zero) | ||
| 15819 | uint32_t new_align = 1 << ctzll(addend | align_bytes); | ||
| 15820 | // Rough guard to prevent overflows | ||
| 15821 | assert(new_align); | ||
| 15822 | result_type = adjust_ptr_align(ira->codegen, result_type, new_align); | ||
| 15823 | } | ||
| 15824 | |||
| 15786 | if (op2_val != nullptr && op1_val != nullptr && | 15825 | if (op2_val != nullptr && op1_val != nullptr && |
| 15787 | (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | 15826 | (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| 15788 | op1->value->data.x_ptr.special == ConstPtrSpecialNull)) | 15827 | op1->value->data.x_ptr.special == ConstPtrSpecialNull)) |
| 15789 | { | 15828 | { |
| 15790 | uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ? | 15829 | uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ? |
| 15791 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; | 15830 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; |
| 15792 | uint64_t elem_offset; | ||
| 15793 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) | ||
| 15794 | return ira->codegen->invalid_instruction; | ||
| 15795 | ZigType *elem_type = op1_val->type->data.pointer.child_type; | ||
| 15796 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) | ||
| 15797 | return ira->codegen->invalid_instruction; | ||
| 15798 | uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; | ||
| 15799 | uint64_t new_addr; | 15831 | uint64_t new_addr; |
| 15800 | if (op_id == IrBinOpAdd) { | 15832 | if (op_id == IrBinOpAdd) { |
| 15801 | new_addr = start_addr + byte_offset; | 15833 | new_addr = start_addr + byte_offset; |
| ... | @@ -15804,7 +15836,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15804,7 +15836,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15804 | } else { | 15836 | } else { |
| 15805 | zig_unreachable(); | 15837 | zig_unreachable(); |
| 15806 | } | 15838 | } |
| 15807 | IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type); | 15839 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); |
| 15808 | result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 15840 | result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 15809 | result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; | 15841 | result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; |
| 15810 | result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr; | 15842 | result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr; |
| ... | @@ -15813,7 +15845,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15813,7 +15845,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15813 | 15845 | ||
| 15814 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 15846 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| 15815 | instruction->base.source_node, op_id, op1, casted_op2, true); | 15847 | instruction->base.source_node, op_id, op1, casted_op2, true); |
| 15816 | result->value->type = op1->value->type; | 15848 | result->value->type = result_type; |
| 15817 | return result; | 15849 | return result; |
| 15818 | } | 15850 | } |
| 15819 | 15851 |
test/stage1/behavior/pointers.zig+30| ... | @@ -288,3 +288,33 @@ test "pointer to array at fixed address" { | ... | @@ -288,3 +288,33 @@ test "pointer to array at fixed address" { |
| 288 | // Silly check just to reference `array` | 288 | // Silly check just to reference `array` |
| 289 | expect(@ptrToInt(&array[0]) == 0x10); | 289 | expect(@ptrToInt(&array[0]) == 0x10); |
| 290 | } | 290 | } |
| 291 | |||
| 292 | test "pointer arithmetic affects the alignment" { | ||
| 293 | { | ||
| 294 | var ptr: [*]align(8) u32 = undefined; | ||
| 295 | var x: usize = 1; | ||
| 296 | |||
| 297 | expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8); | ||
| 298 | const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4 | ||
| 299 | expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4); | ||
| 300 | const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8 | ||
| 301 | expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8); | ||
| 302 | const ptr3 = ptr + 0; // no-op | ||
| 303 | expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8); | ||
| 304 | const ptr4 = ptr + x; // runtime-known addend | ||
| 305 | expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4); | ||
| 306 | } | ||
| 307 | { | ||
| 308 | var ptr: [*]align(8) [3]u8 = undefined; | ||
| 309 | var x: usize = 1; | ||
| 310 | |||
| 311 | const ptr1 = ptr + 17; // 3 * 17 = 51 | ||
| 312 | expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1); | ||
| 313 | const ptr2 = ptr + x; // runtime-known addend | ||
| 314 | expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1); | ||
| 315 | const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8 | ||
| 316 | expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8); | ||
| 317 | const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4 | ||
| 318 | expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4); | ||
| 319 | } | ||
| 320 | } |