| ... | @@ -3416,19 +3416,12 @@ fn indexablePtrLenOrNone( | ... | @@ -3416,19 +3416,12 @@ fn indexablePtrLenOrNone( |
| 3416 | sema: *Sema, | 3416 | sema: *Sema, |
| 3417 | block: *Block, | 3417 | block: *Block, |
| 3418 | src: LazySrcLoc, | 3418 | src: LazySrcLoc, |
| 3419 | object: Air.Inst.Ref, | 3419 | operand: Air.Inst.Ref, |
| 3420 | ) CompileError!Air.Inst.Ref { | 3420 | ) CompileError!Air.Inst.Ref { |
| 3421 | const object_ty = sema.typeOf(object); | 3421 | const operand_ty = sema.typeOf(operand); |
| 3422 | const indexable_ty = t: { | 3422 | try checkMemOperand(sema, block, src, operand_ty); |
| 3423 | const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty; | 3423 | if (operand_ty.ptrSize() == .Many) return .none; |
| 3424 | break :t switch (ptr_size) { | 3424 | return sema.fieldVal(block, src, operand, "len", src); |
| 3425 | .Many => return .none, | | |
| 3426 | .One => object_ty.childType(), | | |
| 3427 | else => object_ty, | | |
| 3428 | }; | | |
| 3429 | }; | | |
| 3430 | try checkIndexable(sema, block, src, indexable_ty); | | |
| 3431 | return sema.fieldVal(block, src, object, "len", src); | | |
| 3432 | } | 3425 | } |
| 3433 | | 3426 | |
| 3434 | fn zirAllocExtended( | 3427 | fn zirAllocExtended( |
| ... | @@ -22080,19 +22073,25 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22080,19 +22073,25 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22080 | const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 22073 | const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 22081 | const dest_ptr = try sema.resolveInst(extra.lhs); | 22074 | const dest_ptr = try sema.resolveInst(extra.lhs); |
| 22082 | const src_ptr = try sema.resolveInst(extra.rhs); | 22075 | const src_ptr = try sema.resolveInst(extra.rhs); |
| | 22076 | const dest_ty = sema.typeOf(dest_ptr); |
| | 22077 | const src_ty = sema.typeOf(src_ptr); |
| 22083 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); | 22078 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); |
| 22084 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); | 22079 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); |
| 22085 | const target = sema.mod.getTarget(); | 22080 | const target = sema.mod.getTarget(); |
| 22086 | | 22081 | |
| | 22082 | if (dest_ty.isConstPtr()) { |
| | 22083 | return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{}); |
| | 22084 | } |
| | 22085 | |
| 22087 | if (dest_len == .none and src_len == .none) { | 22086 | if (dest_len == .none and src_len == .none) { |
| 22088 | const msg = msg: { | 22087 | const msg = msg: { |
| 22089 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); | 22088 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); |
| 22090 | errdefer msg.destroy(sema.gpa); | 22089 | errdefer msg.destroy(sema.gpa); |
| 22091 | try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ | 22090 | try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ |
| 22092 | sema.typeOf(dest_ptr).fmt(sema.mod), | 22091 | dest_ty.fmt(sema.mod), |
| 22093 | }); | 22092 | }); |
| 22094 | try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ | 22093 | try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ |
| 22095 | sema.typeOf(src_ptr).fmt(sema.mod), | 22094 | src_ty.fmt(sema.mod), |
| 22096 | }); | 22095 | }); |
| 22097 | break :msg msg; | 22096 | break :msg msg; |
| 22098 | }; | 22097 | }; |
| ... | @@ -22130,6 +22129,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22130,6 +22129,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22130 | const ok = try block.addBinOp(.cmp_eq, dest_len, src_len); | 22129 | const ok = try block.addBinOp(.cmp_eq, dest_len, src_len); |
| 22131 | try sema.addSafetyCheck(block, ok, .memcpy_len_mismatch); | 22130 | try sema.addSafetyCheck(block, ok, .memcpy_len_mismatch); |
| 22132 | } | 22131 | } |
| | 22132 | } else if (dest_len != .none) { |
| | 22133 | if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| { |
| | 22134 | len_val = dest_len_val; |
| | 22135 | } |
| | 22136 | } else if (src_len != .none) { |
| | 22137 | if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| { |
| | 22138 | len_val = src_len_val; |
| | 22139 | } |
| 22133 | } | 22140 | } |
| 22134 | | 22141 | |
| 22135 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { | 22142 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { |
| ... | @@ -22139,7 +22146,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22139,7 +22146,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22139 | const len = try sema.usizeCast(block, dest_src, len_u64); | 22146 | const len = try sema.usizeCast(block, dest_src, len_u64); |
| 22140 | for (0..len) |i| { | 22147 | for (0..len) |i| { |
| 22141 | const elem_index = try sema.addIntUnsigned(Type.usize, i); | 22148 | const elem_index = try sema.addIntUnsigned(Type.usize, i); |
| 22142 | const dest_elem_ptr = try sema.elemPtr( | 22149 | const dest_elem_ptr = try sema.elemPtrOneLayerOnly( |
| 22143 | block, | 22150 | block, |
| 22144 | src, | 22151 | src, |
| 22145 | dest_ptr, | 22152 | dest_ptr, |
| ... | @@ -22148,7 +22155,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22148,7 +22155,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22148 | true, // init | 22155 | true, // init |
| 22149 | false, // oob_safety | 22156 | false, // oob_safety |
| 22150 | ); | 22157 | ); |
| 22151 | const src_elem_ptr = try sema.elemPtr( | 22158 | const src_elem_ptr = try sema.elemPtrOneLayerOnly( |
| 22152 | block, | 22159 | block, |
| 22153 | src, | 22160 | src, |
| 22154 | src_ptr, | 22161 | src_ptr, |
| ... | @@ -22172,9 +22179,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22172,9 +22179,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22172 | } else break :rs src_src; | 22179 | } else break :rs src_src; |
| 22173 | } else dest_src; | 22180 | } else dest_src; |
| 22174 | | 22181 | |
| 22175 | const dest_ty = sema.typeOf(dest_ptr); | | |
| 22176 | const src_ty = sema.typeOf(src_ptr); | | |
| 22177 | | | |
| 22178 | // If in-memory coercion is not allowed, explode this memcpy call into a | 22182 | // If in-memory coercion is not allowed, explode this memcpy call into a |
| 22179 | // for loop that copies element-wise. | 22183 | // for loop that copies element-wise. |
| 22180 | // Likewise if this is an iterable rather than a pointer, do the same | 22184 | // Likewise if this is an iterable rather than a pointer, do the same |
| ... | @@ -22213,6 +22217,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22213,6 +22217,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22213 | if (new_src_ptr_ty.isSlice()) { | 22217 | if (new_src_ptr_ty.isSlice()) { |
| 22214 | new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); | 22218 | new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); |
| 22215 | } | 22219 | } |
| | 22220 | } else if (dest_len == .none and len_val == null) { |
| | 22221 | // Change the dest to a slice, since its type must have the length. |
| | 22222 | const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); |
| | 22223 | new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false); |
| 22216 | } | 22224 | } |
| 22217 | | 22225 | |
| 22218 | try sema.requireRuntimeBlock(block, src, runtime_src); | 22226 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| ... | @@ -22262,7 +22270,11 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22262,7 +22270,11 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22262 | const dest_ptr = try sema.resolveInst(extra.lhs); | 22270 | const dest_ptr = try sema.resolveInst(extra.lhs); |
| 22263 | const uncoerced_elem = try sema.resolveInst(extra.rhs); | 22271 | const uncoerced_elem = try sema.resolveInst(extra.rhs); |
| 22264 | const dest_ptr_ty = sema.typeOf(dest_ptr); | 22272 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 22265 | try checkIndexable(sema, block, dest_src, dest_ptr_ty); | 22273 | try checkMemOperand(sema, block, dest_src, dest_ptr_ty); |
| | 22274 | |
| | 22275 | if (dest_ptr_ty.isConstPtr()) { |
| | 22276 | return sema.fail(block, dest_src, "cannot memset constant pointer", .{}); |
| | 22277 | } |
| 22266 | | 22278 | |
| 22267 | const dest_elem_ty = dest_ptr_ty.elemType2(); | 22279 | const dest_elem_ty = dest_ptr_ty.elemType2(); |
| 22268 | const target = sema.mod.getTarget(); | 22280 | const target = sema.mod.getTarget(); |
| ... | @@ -31100,6 +31112,27 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | ... | @@ -31100,6 +31112,27 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 31100 | } | 31112 | } |
| 31101 | } | 31113 | } |
| 31102 | | 31114 | |
| | 31115 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| | 31116 | if (ty.zigTypeTag() == .Pointer) { |
| | 31117 | switch (ty.ptrSize()) { |
| | 31118 | .Slice, .Many, .C => return, |
| | 31119 | .One => { |
| | 31120 | const elem_ty = ty.childType(); |
| | 31121 | if (elem_ty.zigTypeTag() == .Array) return; |
| | 31122 | // TODO https://github.com/ziglang/zig/issues/15479 |
| | 31123 | // if (elem_ty.isTuple()) return; |
| | 31124 | }, |
| | 31125 | } |
| | 31126 | } |
| | 31127 | const msg = msg: { |
| | 31128 | const msg = try sema.errMsg(block, src, "type '{}' is not an indexable pointer", .{ty.fmt(sema.mod)}); |
| | 31129 | errdefer msg.destroy(sema.gpa); |
| | 31130 | try sema.errNote(block, src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); |
| | 31131 | break :msg msg; |
| | 31132 | }; |
| | 31133 | return sema.failWithOwnedErrorMsg(msg); |
| | 31134 | } |
| | 31135 | |
| 31103 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | 31136 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31104 | const resolved_ty = try sema.resolveTypeFields(ty); | 31137 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31105 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | 31138 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |