| author | |
| committer | |
| log | 792bbfa301436fc0ce31bc4072b4765ba1408a55 |
| tree | 4e249d92a5ab600e4ba67893e10ce392b7e506cb |
| parent | 5378fdffdcc60a5273021bc9cfc5be917e87c992 |
Previously it was not multiplying by the element ABI size. Now, it uses
ptr_add instructions which do math based on the element type.4 files changed, 58 insertions(+), 27 deletions(-)
lib/std/os.zig+1-1| ... | ... | @@ -5548,7 +5548,7 @@ pub fn toPosixPath(file_path: []const u8) ![MAX_PATH_BYTES - 1:0]u8 { |
| 5548 | 5548 | var path_with_null: [MAX_PATH_BYTES - 1:0]u8 = undefined; |
| 5549 | 5549 | // >= rather than > to make room for the null byte |
| 5550 | 5550 | if (file_path.len >= MAX_PATH_BYTES) return error.NameTooLong; |
| 5551 | mem.copy(u8, &path_with_null, file_path); | |
| 5551 | @memcpy(path_with_null[0..file_path.len], file_path); | |
| 5552 | 5552 | path_with_null[file_path.len] = 0; |
| 5553 | 5553 | return path_with_null; |
| 5554 | 5554 | } |
src/Air.zig+2| ... | ... | @@ -138,12 +138,14 @@ pub const Inst = struct { |
| 138 | 138 | /// The offset is in element type units, not bytes. |
| 139 | 139 | /// Wrapping is undefined behavior. |
| 140 | 140 | /// The lhs is the pointer, rhs is the offset. Result type is the same as lhs. |
| 141 | /// The pointer may be a slice. | |
| 141 | 142 | /// Uses the `ty_pl` field. Payload is `Bin`. |
| 142 | 143 | ptr_add, |
| 143 | 144 | /// Subtract an offset from a pointer, returning a new pointer. |
| 144 | 145 | /// The offset is in element type units, not bytes. |
| 145 | 146 | /// Wrapping is undefined behavior. |
| 146 | 147 | /// The lhs is the pointer, rhs is the offset. Result type is the same as lhs. |
| 148 | /// The pointer may be a slice. | |
| 147 | 149 | /// Uses the `ty_pl` field. Payload is `Bin`. |
| 148 | 150 | ptr_sub, |
| 149 | 151 | /// Given two operands which can be floats, integers, or vectors, returns the |
src/Sema.zig+21-6| ... | ... | @@ -21950,12 +21950,19 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 21950 | 21950 | new_src_ptr = try upgradeToArrayPtr(sema, block, src_ptr, len); |
| 21951 | 21951 | } |
| 21952 | 21952 | |
| 21953 | if (dest_len != .none) { | |
| 21954 | // Change the src from slice to a many pointer, to avoid multiple ptr | |
| 21955 | // slice extractions in AIR instructions. | |
| 21956 | const new_src_ptr_ty = sema.typeOf(new_src_ptr); | |
| 21957 | if (new_src_ptr_ty.isSlice()) { | |
| 21958 | new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); | |
| 21959 | } | |
| 21960 | } | |
| 21961 | ||
| 21953 | 21962 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 21954 | 21963 | |
| 21955 | 21964 | // Aliasing safety check. |
| 21956 | 21965 | if (block.wantSafety()) { |
| 21957 | const dest_int = try block.addUnOp(.ptrtoint, new_dest_ptr); | |
| 21958 | const src_int = try block.addUnOp(.ptrtoint, new_src_ptr); | |
| 21959 | 21966 | const len = if (len_val) |v| |
| 21960 | 21967 | try sema.addConstant(Type.usize, v) |
| 21961 | 21968 | else if (dest_len != .none) |
| ... | ... | @@ -21963,12 +21970,20 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 21963 | 21970 | else |
| 21964 | 21971 | src_len; |
| 21965 | 21972 | |
| 21973 | // Extract raw pointer from dest slice. The AIR instructions could support them, but | |
| 21974 | // it would cause redundant machine code instructions. | |
| 21975 | const new_dest_ptr_ty = sema.typeOf(new_dest_ptr); | |
| 21976 | const raw_dest_ptr = if (new_dest_ptr_ty.isSlice()) | |
| 21977 | try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty) | |
| 21978 | else | |
| 21979 | new_dest_ptr; | |
| 21980 | ||
| 21966 | 21981 | // ok1: dest >= src + len |
| 21967 | 21982 | // ok2: src >= dest + len |
| 21968 | const src_plus_len = try block.addBinOp(.add, src_int, len); | |
| 21969 | const dest_plus_len = try block.addBinOp(.add, dest_int, len); | |
| 21970 | const ok1 = try block.addBinOp(.cmp_gte, dest_int, src_plus_len); | |
| 21971 | const ok2 = try block.addBinOp(.cmp_gte, src_int, dest_plus_len); | |
| 21983 | const src_plus_len = try sema.analyzePtrArithmetic(block, src, new_src_ptr, len, .ptr_add, src_src, src); | |
| 21984 | const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src); | |
| 21985 | const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len); | |
| 21986 | const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len); | |
| 21972 | 21987 | const ok = try block.addBinOp(.bit_or, ok1, ok2); |
| 21973 | 21988 | try sema.addSafetyCheck(block, ok, .memcpy_alias); |
| 21974 | 21989 | } |
src/codegen/llvm.zig+34-20| ... | ... | @@ -7293,39 +7293,53 @@ pub const FuncGen = struct { |
| 7293 | 7293 | fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7294 | 7294 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 7295 | 7295 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 7296 | const base_ptr = try self.resolveInst(bin_op.lhs); | |
| 7296 | const ptr = try self.resolveInst(bin_op.lhs); | |
| 7297 | 7297 | const offset = try self.resolveInst(bin_op.rhs); |
| 7298 | 7298 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 7299 | 7299 | const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); |
| 7300 | if (ptr_ty.ptrSize() == .One) { | |
| 7301 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | |
| 7302 | const indices: [2]*llvm.Value = .{ | |
| 7303 | self.context.intType(32).constNull(), offset, | |
| 7304 | }; | |
| 7305 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | |
| 7306 | } else { | |
| 7307 | const indices: [1]*llvm.Value = .{offset}; | |
| 7308 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | |
| 7300 | switch (ptr_ty.ptrSize()) { | |
| 7301 | .One => { | |
| 7302 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | |
| 7303 | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset }; | |
| 7304 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | |
| 7305 | }, | |
| 7306 | .C, .Many => { | |
| 7307 | const indices: [1]*llvm.Value = .{offset}; | |
| 7308 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | |
| 7309 | }, | |
| 7310 | .Slice => { | |
| 7311 | const base = self.builder.buildExtractValue(ptr, 0, ""); | |
| 7312 | const indices: [1]*llvm.Value = .{offset}; | |
| 7313 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base, &indices, indices.len, ""); | |
| 7314 | }, | |
| 7309 | 7315 | } |
| 7310 | 7316 | } |
| 7311 | 7317 | |
| 7312 | 7318 | fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7313 | 7319 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 7314 | 7320 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 7315 | const base_ptr = try self.resolveInst(bin_op.lhs); | |
| 7321 | const ptr = try self.resolveInst(bin_op.lhs); | |
| 7316 | 7322 | const offset = try self.resolveInst(bin_op.rhs); |
| 7317 | 7323 | const negative_offset = self.builder.buildNeg(offset, ""); |
| 7318 | 7324 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 7319 | 7325 | const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); |
| 7320 | if (ptr_ty.ptrSize() == .One) { | |
| 7321 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | |
| 7322 | const indices: [2]*llvm.Value = .{ | |
| 7323 | self.context.intType(32).constNull(), negative_offset, | |
| 7324 | }; | |
| 7325 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | |
| 7326 | } else { | |
| 7327 | const indices: [1]*llvm.Value = .{negative_offset}; | |
| 7328 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | |
| 7326 | switch (ptr_ty.ptrSize()) { | |
| 7327 | .One => { | |
| 7328 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | |
| 7329 | const indices: [2]*llvm.Value = .{ | |
| 7330 | self.context.intType(32).constNull(), negative_offset, | |
| 7331 | }; | |
| 7332 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | |
| 7333 | }, | |
| 7334 | .C, .Many => { | |
| 7335 | const indices: [1]*llvm.Value = .{negative_offset}; | |
| 7336 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | |
| 7337 | }, | |
| 7338 | .Slice => { | |
| 7339 | const base = self.builder.buildExtractValue(ptr, 0, ""); | |
| 7340 | const indices: [1]*llvm.Value = .{negative_offset}; | |
| 7341 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base, &indices, indices.len, ""); | |
| 7342 | }, | |
| 7329 | 7343 | } |
| 7330 | 7344 | } |
| 7331 | 7345 |