From 21eb75749722668632da55499831eedc62120d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 15 Feb 2025 22:37:23 +0100 Subject: [PATCH] llvm: Use inline variants of memcpy/memset intrinsics when using -fno-builtin. This is a correctness issue: When -fno-builtin is used, we must assume that we could be compiling the memcpy/memset implementations, so generating calls to them is problematic. --- src/codegen/llvm.zig | 68 ++++++++++++++++++++++++++++++++---- src/codegen/llvm/Builder.zig | 6 ++-- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 719c53c630..56cdd38b19 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5771,6 +5771,7 @@ pub const FuncGen = struct { try o.builder.intValue(.i8, 0xaa), len, if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, + self.ng.ownerModule().no_builtin, ); const owner_mod = self.ng.ownerModule(); if (owner_mod.valgrind) { @@ -5821,6 +5822,7 @@ pub const FuncGen = struct { try o.builder.intValue(.i8, 0xaa), len, .normal, + self.ng.ownerModule().no_builtin, ); const owner_mod = self.ng.ownerModule(); if (owner_mod.valgrind) { @@ -9734,6 +9736,7 @@ pub const FuncGen = struct { if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8), len, if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, + self.ng.ownerModule().no_builtin, ); if (safety and owner_mod.valgrind) { try self.valgrindMarkUndef(dest_ptr, len); @@ -10041,9 +10044,22 @@ pub const FuncGen = struct { try o.builder.undefValue(.i8); const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); if (intrinsic_len0_traps) { - try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); + try self.safeWasmMemset( + dest_ptr, + fill_byte, + len, + dest_ptr_align, + access_kind, + ); } else { - _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); + _ = try self.wip.callMemSet( + dest_ptr, + dest_ptr_align, + fill_byte, + len, + access_kind, + self.ng.ownerModule().no_builtin, + ); } const owner_mod = self.ng.ownerModule(); if (safety and owner_mod.valgrind) { @@ -10060,9 +10076,22 @@ pub const FuncGen = struct { const fill_byte = try o.builder.intValue(.i8, byte_val); const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); if (intrinsic_len0_traps) { - try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); + try self.safeWasmMemset( + dest_ptr, + fill_byte, + len, + dest_ptr_align, + access_kind, + ); } else { - _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); + _ = try self.wip.callMemSet( + dest_ptr, + dest_ptr_align, + fill_byte, + len, + access_kind, + self.ng.ownerModule().no_builtin, + ); } return .none; } @@ -10077,9 +10106,22 @@ pub const FuncGen = struct { const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); if (intrinsic_len0_traps) { - try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind); + try self.safeWasmMemset( + dest_ptr, + fill_byte, + len, + dest_ptr_align, + access_kind, + ); } else { - _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); + _ = try self.wip.callMemSet( + dest_ptr, + dest_ptr_align, + fill_byte, + len, + access_kind, + self.ng.ownerModule().no_builtin, + ); } return .none; } @@ -10131,6 +10173,7 @@ pub const FuncGen = struct { elem_abi_align.toLlvm(), try o.builder.intValue(llvm_usize_ty, elem_abi_size), access_kind, + self.ng.ownerModule().no_builtin, ); } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align); const next_ptr = try self.wip.gep(.inbounds, elem_llvm_ty, it_ptr.toValue(), &.{ @@ -10158,7 +10201,14 @@ pub const FuncGen = struct { const end_block = try self.wip.block(2, "MemsetTrapEnd"); _ = try self.wip.brCond(cond, memset_block, end_block, .none); self.wip.cursor = .{ .block = memset_block }; - _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); + _ = try self.wip.callMemSet( + dest_ptr, + dest_ptr_align, + fill_byte, + len, + access_kind, + self.ng.ownerModule().no_builtin, + ); _ = try self.wip.br(end_block); self.wip.cursor = .{ .block = end_block }; } @@ -10200,6 +10250,7 @@ pub const FuncGen = struct { src_ptr_ty.ptrAlignment(zcu).toLlvm(), len, access_kind, + self.ng.ownerModule().no_builtin, ); _ = try self.wip.br(end_block); self.wip.cursor = .{ .block = end_block }; @@ -10213,6 +10264,7 @@ pub const FuncGen = struct { src_ptr_ty.ptrAlignment(zcu).toLlvm(), len, access_kind, + self.ng.ownerModule().no_builtin, ); return .none; } @@ -11346,6 +11398,7 @@ pub const FuncGen = struct { ptr_alignment, try o.builder.intValue(try o.lowerType(Type.usize), size_bytes), access_kind, + fg.ng.ownerModule().no_builtin, ); return result_ptr; } @@ -11513,6 +11566,7 @@ pub const FuncGen = struct { elem_ty.abiAlignment(zcu).toLlvm(), try o.builder.intValue(try o.lowerType(Type.usize), elem_ty.abiSize(zcu)), access_kind, + self.ng.ownerModule().no_builtin, ); } diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 0a8d64fb72..7461854510 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -6102,6 +6102,7 @@ pub const WipFunction = struct { src_align: Alignment, len: Value, kind: MemoryAccessKind, + @"inline": bool, ) Allocator.Error!Instruction.Index { var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; @@ -6113,7 +6114,7 @@ pub const WipFunction = struct { try self.builder.attrs(&dst_attrs), try self.builder.attrs(&src_attrs), }), - .memcpy, + if (@"inline") .@"memcpy.inline" else .memcpy, &.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) }, &.{ dst, src, len, switch (kind) { .normal => Value.false, @@ -6131,12 +6132,13 @@ pub const WipFunction = struct { val: Value, len: Value, kind: MemoryAccessKind, + @"inline": bool, ) Allocator.Error!Instruction.Index { var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; const value = try self.callIntrinsic( .normal, try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }), - .memset, + if (@"inline") .@"memset.inline" else .memset, &.{ dst.typeOfWip(self), len.typeOfWip(self) }, &.{ dst, val, len, switch (kind) { .normal => Value.false,