authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-09 13:53:56-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-09 13:53:56-05:00
log5e345ff0ee9eb70d7f5f7167227f6a1e8903f428
tree34d82c8ef040fc30fe895043d7a84d75552d36cf
parent5ab5de89c03bf9b3f08dfaa78d3b0fe41a72cdea
parentc51b79c56e32594e4fb119fc760ae38b69fb9bbb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3955 from LemonBoy/fix-1528

Pointer arithmetic affects the alignment factor

5 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/14031087 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/14032132 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);
144144
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];
149149
150 if (builtin.os == .linux) {150 if (builtin.os == .linux) {
151 // Find the beginning of the auxiliary vector151 // 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 area154 // 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 }
1578515785
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
1581315845
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 }
1581915851
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
292test "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}