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 {
33523352 },
33533353 .elem, .field => |base_index| {
33543354 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3355 switch (base_ptr_type.size) {
3356 .One => switch (ip.indexToKey(base_ptr_type.elem_type)) {
3357 .array_type, .vector_type => assert(ptr.addr == .elem),
3358 .anon_struct_type => |anon_struct_type| {
3359 assert(ptr.addr == .field);
3360 assert(base_index.index < anon_struct_type.types.len);
3361 },
3362 .struct_type => |struct_type| {
3363 assert(ptr.addr == .field);
3364 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3365 },
3366 .union_type => |union_type| {
3367 assert(ptr.addr == .field);
3368 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3369 },
3370 .ptr_type => |slice_type| {
3371 assert(ptr.addr == .field);
3372 assert(slice_type.size == .Slice);
3373 assert(base_index.index < 2);
3374 },
3375 else => unreachable,
3355 switch (ptr.addr) {
3356 .elem => assert(base_ptr_type.size == .Many),
3357 .field => {
3358 assert(base_ptr_type.size == .One);
3359 switch (ip.indexToKey(base_ptr_type.elem_type)) {
3360 .anon_struct_type => |anon_struct_type| {
3361 assert(ptr.addr == .field);
3362 assert(base_index.index < anon_struct_type.types.len);
3363 },
3364 .struct_type => |struct_type| {
3365 assert(ptr.addr == .field);
3366 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3367 },
3368 .union_type => |union_type| {
3369 assert(ptr.addr == .field);
3370 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3371 },
3372 .ptr_type => |slice_type| {
3373 assert(ptr.addr == .field);
3374 assert(slice_type.size == .Slice);
3375 assert(base_index.index < 2);
3376 },
3377 else => unreachable,
3378 }
33763379 },
3377 .Many => assert(ptr.addr == .elem),
3378 .Slice, .C => unreachable,
3380 else => unreachable,
33793381 }
33803382 _ = ip.map.pop();
33813383 const index_index = try ip.get(gpa, .{ .int = .{
src/Sema.zig+30-11
......@@ -15036,10 +15036,7 @@ fn analyzePtrArithmetic(
1503615036 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);
1503715037 const ptr_ty = sema.typeOf(ptr);
1503815038 const ptr_info = ptr_ty.ptrInfo(mod);
15039 const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Array)
15040 ptr_info.pointee_type.childType(mod)
15041 else
15042 ptr_info.pointee_type;
15039 assert(ptr_info.size == .Many or ptr_info.size == .C);
1504315040
1504415041 const new_ptr_ty = t: {
1504515042 // Calculate the new pointer alignment.
......@@ -15050,7 +15047,7 @@ fn analyzePtrArithmetic(
1505015047 }
1505115048 // If the addend is not a comptime-known value we can still count on
1505215049 // 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);
1505415051 const addend = if (opt_off_val) |off_val| a: {
1505515052 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(mod));
1505615053 break :a elem_size * off_int;
......@@ -15081,7 +15078,7 @@ fn analyzePtrArithmetic(
1508115078 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(mod));
1508215079 if (offset_int == 0) return ptr;
1508315080 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);
1508515082 const new_addr = switch (air_tag) {
1508615083 .ptr_add => addr + elem_size * offset_int,
1508715084 .ptr_sub => addr - elem_size * offset_int,
......@@ -22673,12 +22670,28 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2267322670 const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);
2267422671 const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod))
2267522672 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
22676 else
22677 new_dest_ptr;
22673 else if (new_dest_ptr_ty.ptrSize(mod) == .One) 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
2267922692 // ok1: dest >= src + len
2268022693 // 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);
2268222695 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);
2268322696 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);
2268422697 const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);
......@@ -29968,8 +29981,14 @@ fn analyzeSlice(
2996829981
2996929982 const ptr = if (slice_ty.isSlice(mod))
2997029983 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
29971 else
29972 ptr_or_slice;
29984 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
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
2997429993 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);
2997529994 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 {
20792079 },
20802080 else => val,
20812081 };
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;
20822085 return (try mod.intern(.{ .ptr = .{
20832086 .ty = elem_ptr_ty.toIntern(),
20842087 .addr = .{ .elem = .{
2085 .base = ptr_val.toIntern(),
2088 .base = (try mod.getCoerced(ptr_val, try mod.ptrType(ptr_ty_key))).toIntern(),
20862089 .index = index,
20872090 } },
20882091 } })).toValue();