authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-29 20:52:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log66ae42bb72a9ad4b1cd44b32fa5be322b07a5ffb
tree565d5713d56669aa437aeaac56ccbe47444008ff
parent55cda9a592dd5aa030d1134351394e1014fefed1

Sema: fix pointer arithmetic on single array pointers


3 files changed, 59 insertions(+), 35 deletions(-)

src/InternPool.zig+25-23
...@@ -3352,30 +3352,32 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3352,30 +3352,32 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3352 },3352 },
3353 .elem, .field => |base_index| {3353 .elem, .field => |base_index| {
3354 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;3354 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3355 switch (base_ptr_type.size) {3355 switch (ptr.addr) {
3356 .One => switch (ip.indexToKey(base_ptr_type.elem_type)) {3356 .elem => assert(base_ptr_type.size == .Many),
3357 .array_type, .vector_type => assert(ptr.addr == .elem),3357 .field => {
3358 .anon_struct_type => |anon_struct_type| {3358 assert(base_ptr_type.size == .One);
3359 assert(ptr.addr == .field);3359 switch (ip.indexToKey(base_ptr_type.elem_type)) {
3360 assert(base_index.index < anon_struct_type.types.len);3360 .anon_struct_type => |anon_struct_type| {
3361 },3361 assert(ptr.addr == .field);
3362 .struct_type => |struct_type| {3362 assert(base_index.index < anon_struct_type.types.len);
3363 assert(ptr.addr == .field);3363 },
3364 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());3364 .struct_type => |struct_type| {
3365 },3365 assert(ptr.addr == .field);
3366 .union_type => |union_type| {3366 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3367 assert(ptr.addr == .field);3367 },
3368 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());3368 .union_type => |union_type| {
3369 },3369 assert(ptr.addr == .field);
3370 .ptr_type => |slice_type| {3370 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3371 assert(ptr.addr == .field);3371 },
3372 assert(slice_type.size == .Slice);3372 .ptr_type => |slice_type| {
3373 assert(base_index.index < 2);3373 assert(ptr.addr == .field);
3374 },3374 assert(slice_type.size == .Slice);
3375 else => unreachable,3375 assert(base_index.index < 2);
3376 },
3377 else => unreachable,
3378 }
3376 },3379 },
3377 .Many => assert(ptr.addr == .elem),3380 else => unreachable,
3378 .Slice, .C => unreachable,
3379 }3381 }
3380 _ = ip.map.pop();3382 _ = ip.map.pop();
3381 const index_index = try ip.get(gpa, .{ .int = .{3383 const index_index = try ip.get(gpa, .{ .int = .{
src/Sema.zig+30-11
...@@ -15036,10 +15036,7 @@ fn analyzePtrArithmetic(...@@ -15036,10 +15036,7 @@ fn analyzePtrArithmetic(
15036 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);15036 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);
15037 const ptr_ty = sema.typeOf(ptr);15037 const ptr_ty = sema.typeOf(ptr);
15038 const ptr_info = ptr_ty.ptrInfo(mod);15038 const ptr_info = ptr_ty.ptrInfo(mod);
15039 const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Array)15039 assert(ptr_info.size == .Many or ptr_info.size == .C);
15040 ptr_info.pointee_type.childType(mod)
15041 else
15042 ptr_info.pointee_type;
1504315040
15044 const new_ptr_ty = t: {15041 const new_ptr_ty = t: {
15045 // Calculate the new pointer alignment.15042 // Calculate the new pointer alignment.
...@@ -15050,7 +15047,7 @@ fn analyzePtrArithmetic(...@@ -15050,7 +15047,7 @@ fn analyzePtrArithmetic(
15050 }15047 }
15051 // If the addend is not a comptime-known value we can still count on15048 // If the addend is not a comptime-known value we can still count on
15052 // it being a multiple of the type size.15049 // it being a multiple of the type size.
15053 const elem_size = elem_ty.abiSize(mod);15050 const elem_size = ptr_info.pointee_type.abiSize(mod);
15054 const addend = if (opt_off_val) |off_val| a: {15051 const addend = if (opt_off_val) |off_val| a: {
15055 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(mod));15052 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(mod));
15056 break :a elem_size * off_int;15053 break :a elem_size * off_int;
...@@ -15081,7 +15078,7 @@ fn analyzePtrArithmetic(...@@ -15081,7 +15078,7 @@ fn analyzePtrArithmetic(
15081 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(mod));15078 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(mod));
15082 if (offset_int == 0) return ptr;15079 if (offset_int == 0) return ptr;
15083 if (try ptr_val.getUnsignedIntAdvanced(mod, sema)) |addr| {15080 if (try ptr_val.getUnsignedIntAdvanced(mod, sema)) |addr| {
15084 const elem_size = elem_ty.abiSize(mod);15081 const elem_size = ptr_info.pointee_type.abiSize(mod);
15085 const new_addr = switch (air_tag) {15082 const new_addr = switch (air_tag) {
15086 .ptr_add => addr + elem_size * offset_int,15083 .ptr_add => addr + elem_size * offset_int,
15087 .ptr_sub => addr - elem_size * offset_int,15084 .ptr_sub => addr - elem_size * offset_int,
...@@ -22673,12 +22670,28 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -22673,12 +22670,28 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
22673 const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);22670 const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);
22674 const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod))22671 const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod))
22675 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)22672 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
22676 else22673 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {
22677 new_dest_ptr;22674 var dest_manyptr_ty_key = mod.intern_pool.indexToKey(new_dest_ptr_ty.toIntern()).ptr_type;
22675 assert(dest_manyptr_ty_key.size == .One);
22676 dest_manyptr_ty_key.elem_type = dest_elem_ty.toIntern();
22677 dest_manyptr_ty_key.size = .Many;
22678 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);
22679 } else new_dest_ptr;
22680
22681 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
22682 const raw_src_ptr = if (new_src_ptr_ty.isSlice(mod))
22683 try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty)
22684 else if (new_src_ptr_ty.ptrSize(mod) == .One) ptr: {
22685 var src_manyptr_ty_key = mod.intern_pool.indexToKey(new_src_ptr_ty.toIntern()).ptr_type;
22686 assert(src_manyptr_ty_key.size == .One);
22687 src_manyptr_ty_key.elem_type = src_elem_ty.toIntern();
22688 src_manyptr_ty_key.size = .Many;
22689 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);
22690 } else new_src_ptr;
2267822691
22679 // ok1: dest >= src + len22692 // ok1: dest >= src + len
22680 // ok2: src >= dest + len22693 // ok2: src >= dest + len
22681 const src_plus_len = try sema.analyzePtrArithmetic(block, src, new_src_ptr, len, .ptr_add, src_src, src);22694 const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src_src, src);
22682 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);22695 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);
22683 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);22696 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);
22684 const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);22697 const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);
...@@ -29968,8 +29981,14 @@ fn analyzeSlice(...@@ -29968,8 +29981,14 @@ fn analyzeSlice(
2996829981
29969 const ptr = if (slice_ty.isSlice(mod))29982 const ptr = if (slice_ty.isSlice(mod))
29970 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)29983 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
29971 else29984 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
29972 ptr_or_slice;29985 var manyptr_ty_key = mod.intern_pool.indexToKey(slice_ty.toIntern()).ptr_type;
29986 assert(manyptr_ty_key.elem_type == array_ty.toIntern());
29987 assert(manyptr_ty_key.size == .One);
29988 manyptr_ty_key.elem_type = elem_ty.toIntern();
29989 manyptr_ty_key.size = .Many;
29990 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);
29991 } else ptr_or_slice;
2997329992
29974 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);29993 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);
29975 const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);29994 const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);
src/value.zig+4-1
...@@ -2079,10 +2079,13 @@ pub const Value = struct {...@@ -2079,10 +2079,13 @@ pub const Value = struct {
2079 },2079 },
2080 else => val,2080 else => val,
2081 };2081 };
2082 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;
2083 assert(ptr_ty_key.size != .Slice);
2084 ptr_ty_key.size = .Many;
2082 return (try mod.intern(.{ .ptr = .{2085 return (try mod.intern(.{ .ptr = .{
2083 .ty = elem_ptr_ty.toIntern(),2086 .ty = elem_ptr_ty.toIntern(),
2084 .addr = .{ .elem = .{2087 .addr = .{ .elem = .{
2085 .base = ptr_val.toIntern(),2088 .base = (try mod.getCoerced(ptr_val, try mod.ptrType(ptr_ty_key))).toIntern(),
2086 .index = index,2089 .index = index,
2087 } },2090 } },
2088 } })).toValue();2091 } })).toValue();