Commit 792bbfa301
lib/std/os.zig
@@ -5548,7 +5548,7 @@ pub fn toPosixPath(file_path: []const u8) ![MAX_PATH_BYTES - 1:0]u8 {
var path_with_null: [MAX_PATH_BYTES - 1:0]u8 = undefined;
// >= rather than > to make room for the null byte
if (file_path.len >= MAX_PATH_BYTES) return error.NameTooLong;
- mem.copy(u8, &path_with_null, file_path);
+ @memcpy(path_with_null[0..file_path.len], file_path);
path_with_null[file_path.len] = 0;
return path_with_null;
}
src/codegen/llvm.zig
@@ -7293,39 +7293,53 @@ pub const FuncGen = struct {
fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
- const base_ptr = try self.resolveInst(bin_op.lhs);
+ const ptr = try self.resolveInst(bin_op.lhs);
const offset = try self.resolveInst(bin_op.rhs);
const ptr_ty = self.air.typeOf(bin_op.lhs);
const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());
- if (ptr_ty.ptrSize() == .One) {
- // It's a pointer to an array, so according to LLVM we need an extra GEP index.
- const indices: [2]*llvm.Value = .{
- self.context.intType(32).constNull(), offset,
- };
- return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
- } else {
- const indices: [1]*llvm.Value = .{offset};
- return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
+ switch (ptr_ty.ptrSize()) {
+ .One => {
+ // It's a pointer to an array, so according to LLVM we need an extra GEP index.
+ const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset };
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, "");
+ },
+ .C, .Many => {
+ const indices: [1]*llvm.Value = .{offset};
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, "");
+ },
+ .Slice => {
+ const base = self.builder.buildExtractValue(ptr, 0, "");
+ const indices: [1]*llvm.Value = .{offset};
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, base, &indices, indices.len, "");
+ },
}
}
fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
- const base_ptr = try self.resolveInst(bin_op.lhs);
+ const ptr = try self.resolveInst(bin_op.lhs);
const offset = try self.resolveInst(bin_op.rhs);
const negative_offset = self.builder.buildNeg(offset, "");
const ptr_ty = self.air.typeOf(bin_op.lhs);
const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());
- if (ptr_ty.ptrSize() == .One) {
- // It's a pointer to an array, so according to LLVM we need an extra GEP index.
- const indices: [2]*llvm.Value = .{
- self.context.intType(32).constNull(), negative_offset,
- };
- return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
- } else {
- const indices: [1]*llvm.Value = .{negative_offset};
- return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
+ switch (ptr_ty.ptrSize()) {
+ .One => {
+ // It's a pointer to an array, so according to LLVM we need an extra GEP index.
+ const indices: [2]*llvm.Value = .{
+ self.context.intType(32).constNull(), negative_offset,
+ };
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, "");
+ },
+ .C, .Many => {
+ const indices: [1]*llvm.Value = .{negative_offset};
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, "");
+ },
+ .Slice => {
+ const base = self.builder.buildExtractValue(ptr, 0, "");
+ const indices: [1]*llvm.Value = .{negative_offset};
+ return self.builder.buildInBoundsGEP(llvm_elem_ty, base, &indices, indices.len, "");
+ },
}
}
src/Air.zig
@@ -138,12 +138,14 @@ pub const Inst = struct {
/// The offset is in element type units, not bytes.
/// Wrapping is undefined behavior.
/// The lhs is the pointer, rhs is the offset. Result type is the same as lhs.
+ /// The pointer may be a slice.
/// Uses the `ty_pl` field. Payload is `Bin`.
ptr_add,
/// Subtract an offset from a pointer, returning a new pointer.
/// The offset is in element type units, not bytes.
/// Wrapping is undefined behavior.
/// The lhs is the pointer, rhs is the offset. Result type is the same as lhs.
+ /// The pointer may be a slice.
/// Uses the `ty_pl` field. Payload is `Bin`.
ptr_sub,
/// Given two operands which can be floats, integers, or vectors, returns the
src/Sema.zig
@@ -21950,12 +21950,19 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
new_src_ptr = try upgradeToArrayPtr(sema, block, src_ptr, len);
}
+ if (dest_len != .none) {
+ // Change the src from slice to a many pointer, to avoid multiple ptr
+ // slice extractions in AIR instructions.
+ const new_src_ptr_ty = sema.typeOf(new_src_ptr);
+ if (new_src_ptr_ty.isSlice()) {
+ new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
+ }
+ }
+
try sema.requireRuntimeBlock(block, src, runtime_src);
// Aliasing safety check.
if (block.wantSafety()) {
- const dest_int = try block.addUnOp(.ptrtoint, new_dest_ptr);
- const src_int = try block.addUnOp(.ptrtoint, new_src_ptr);
const len = if (len_val) |v|
try sema.addConstant(Type.usize, v)
else if (dest_len != .none)
@@ -21963,12 +21970,20 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
else
src_len;
+ // Extract raw pointer from dest slice. The AIR instructions could support them, but
+ // it would cause redundant machine code instructions.
+ const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);
+ const raw_dest_ptr = if (new_dest_ptr_ty.isSlice())
+ try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
+ else
+ new_dest_ptr;
+
// ok1: dest >= src + len
// ok2: src >= dest + len
- const src_plus_len = try block.addBinOp(.add, src_int, len);
- const dest_plus_len = try block.addBinOp(.add, dest_int, len);
- const ok1 = try block.addBinOp(.cmp_gte, dest_int, src_plus_len);
- const ok2 = try block.addBinOp(.cmp_gte, src_int, dest_plus_len);
+ const src_plus_len = try sema.analyzePtrArithmetic(block, src, new_src_ptr, len, .ptr_add, src_src, src);
+ const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);
+ const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);
+ const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);
const ok = try block.addBinOp(.bit_or, ok1, ok2);
try sema.addSafetyCheck(block, ok, .memcpy_alias);
}