diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-04-21 18:03:33 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-04-25 11:23:40 -0700 |
| commit | edb5e493e6d9a4478b3d9c06aa590694757d8c03 (patch) | |
| tree | 5d5ccca94129e3a0e177845dbb5a9b251271cd07 /src/codegen | |
| parent | a5c910adb610ae530db99f10aa77aaed3e85e830 (diff) | |
| download | zig-edb5e493e6d9a4478b3d9c06aa590694757d8c03.tar.gz zig-edb5e493e6d9a4478b3d9c06aa590694757d8c03.zip | |
update `@memcpy` to require equal src and dest lens
* Sema: upgrade operands to array pointers if possible when emitting
AIR.
* Implement safety checks for length mismatch and aliasing.
* AIR: make ptrtoint support slice operands. Implement in LLVM backend.
* C backend: implement new `@memset` semantics. `@memcpy` is not done
yet.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 98 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 12 |
2 files changed, 81 insertions, 29 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 903d2449fd..9dac87f11b 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -6177,18 +6177,43 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa } fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue { - const pl_op = f.air.instructions.items(.data)[inst].pl_op; - const extra = f.air.extraData(Air.Bin, pl_op.payload).data; - const dest_ty = f.air.typeOf(pl_op.operand); - const dest_ptr = try f.resolveInst(pl_op.operand); - const value = try f.resolveInst(extra.lhs); - const len = try f.resolveInst(extra.rhs); - + const bin_op = f.air.instructions.items(.data)[inst].bin_op; + const dest_ty = f.air.typeOf(bin_op.lhs); + const dest_slice = try f.resolveInst(bin_op.lhs); + const value = try f.resolveInst(bin_op.rhs); + const elem_ty = f.air.typeOf(bin_op.rhs); + const target = f.object.dg.module.getTarget(); + const elem_abi_size = elem_ty.abiSize(target); + const val_is_undef = if (f.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false; const writer = f.object.writer(); - if (dest_ty.isVolatilePtr()) { - var u8_ptr_pl = dest_ty.ptrInfo(); - u8_ptr_pl.data.pointee_type = Type.u8; - const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); + + if (val_is_undef) { + try writer.writeAll("memset("); + switch (dest_ty.ptrSize()) { + .Slice => { + try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); + try writer.writeAll(", 0xaa, "); + try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); + if (elem_abi_size > 1) { + try writer.print(" * {d});\n", .{elem_abi_size}); + } else { + try writer.writeAll(");\n"); + } + }, + .One => { + const array_ty = dest_ty.childType(); + const len = array_ty.arrayLen() * elem_abi_size; + + try f.writeCValue(writer, dest_slice, .FunctionArgument); + try writer.print(", 0xaa, {d});\n", .{len}); + }, + .Many, .C => unreachable, + } + try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + return .none; + } + + if (elem_abi_size > 1 or dest_ty.isVolatilePtr()) { const index = try f.allocLocal(inst, Type.usize); try writer.writeAll("for ("); @@ -6198,36 +6223,61 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("; "); try f.writeCValue(writer, index, .Other); try writer.writeAll(" != "); - try f.writeCValue(writer, len, .Other); + switch (dest_ty.ptrSize()) { + .Slice => { + try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); + }, + .One => { + const array_ty = dest_ty.childType(); + const len = array_ty.arrayLen() * elem_abi_size; + try writer.print("{d}", .{len}); + }, + .Many, .C => unreachable, + } try writer.writeAll("; "); try f.writeCValue(writer, index, .Other); try writer.writeAll(" += "); try f.object.dg.renderValue(writer, Type.usize, Value.one, .Other); - try writer.writeAll(") (("); - try f.renderType(writer, u8_ptr_ty); - try writer.writeByte(')'); - try f.writeCValue(writer, dest_ptr, .FunctionArgument); + try writer.writeAll(") ("); + switch (dest_ty.ptrSize()) { + .Slice => try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }), + .One => try f.writeCValue(writer, dest_slice, .FunctionArgument), + .Many, .C => unreachable, + } try writer.writeAll(")["); try f.writeCValue(writer, index, .Other); try writer.writeAll("] = "); try f.writeCValue(writer, value, .FunctionArgument); try writer.writeAll(";\n"); - try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); + try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); try freeLocal(f, inst, index.new_local, 0); return .none; } - try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); try writer.writeAll("memset("); - try f.writeCValue(writer, dest_ptr, .FunctionArgument); - try writer.writeAll(", "); - try f.writeCValue(writer, value, .FunctionArgument); - try writer.writeAll(", "); - try f.writeCValue(writer, len, .FunctionArgument); - try writer.writeAll(");\n"); + switch (dest_ty.ptrSize()) { + .Slice => { + try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); + try writer.writeAll(", "); + try f.writeCValue(writer, value, .FunctionArgument); + try writer.writeAll(", "); + try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); + try writer.writeAll(");\n"); + }, + .One => { + const array_ty = dest_ty.childType(); + const len = array_ty.arrayLen() * elem_abi_size; + try f.writeCValue(writer, dest_slice, .FunctionArgument); + try writer.writeAll(", "); + try f.writeCValue(writer, value, .FunctionArgument); + try writer.print(", {d});\n", .{len}); + }, + .Many, .C => unreachable, + } + try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d80fb62969..50db9c76f8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5777,10 +5777,10 @@ pub const FuncGen = struct { } fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { - switch (ty.ptrSize()) { - .Slice => return fg.builder.buildExtractValue(ptr, 0, ""), - .One => return ptr, - .Many, .C => unreachable, + if (ty.isSlice()) { + return fg.builder.buildExtractValue(ptr, 0, ""); + } else { + return ptr; } } @@ -7917,8 +7917,10 @@ pub const FuncGen = struct { fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); + const ptr_ty = self.air.typeOf(un_op); + const operand_ptr = self.sliceOrArrayPtr(operand, ptr_ty); const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); - return self.builder.buildPtrToInt(operand, dest_llvm_ty, ""); + return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, ""); } fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
