authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-02-15 22:37:23+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-02-22 15:06:40+01:00
log21eb75749722668632da55499831eedc62120d61
tree9f7bbb1f5cf56763c1e82813f026fc2f1c14e8c8
parent41b179ca09f33a6a667ccdb063ebf8ff4cf076b8
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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.

2 files changed, 65 insertions(+), 9 deletions(-)

src/codegen/llvm.zig+61-7
......@@ -5771,6 +5771,7 @@ pub const FuncGen = struct {
57715771 try o.builder.intValue(.i8, 0xaa),
57725772 len,
57735773 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
5774 self.ng.ownerModule().no_builtin,
57745775 );
57755776 const owner_mod = self.ng.ownerModule();
57765777 if (owner_mod.valgrind) {
......@@ -5821,6 +5822,7 @@ pub const FuncGen = struct {
58215822 try o.builder.intValue(.i8, 0xaa),
58225823 len,
58235824 .normal,
5825 self.ng.ownerModule().no_builtin,
58245826 );
58255827 const owner_mod = self.ng.ownerModule();
58265828 if (owner_mod.valgrind) {
......@@ -9734,6 +9736,7 @@ pub const FuncGen = struct {
97349736 if (safety) try o.builder.intValue(.i8, 0xaa) else try o.builder.undefValue(.i8),
97359737 len,
97369738 if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal,
9739 self.ng.ownerModule().no_builtin,
97379740 );
97389741 if (safety and owner_mod.valgrind) {
97399742 try self.valgrindMarkUndef(dest_ptr, len);
......@@ -10041,9 +10044,22 @@ pub const FuncGen = struct {
1004110044 try o.builder.undefValue(.i8);
1004210045 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
1004310046 if (intrinsic_len0_traps) {
10044 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
10047 try self.safeWasmMemset(
10048 dest_ptr,
10049 fill_byte,
10050 len,
10051 dest_ptr_align,
10052 access_kind,
10053 );
1004510054 } else {
10046 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
10055 _ = try self.wip.callMemSet(
10056 dest_ptr,
10057 dest_ptr_align,
10058 fill_byte,
10059 len,
10060 access_kind,
10061 self.ng.ownerModule().no_builtin,
10062 );
1004710063 }
1004810064 const owner_mod = self.ng.ownerModule();
1004910065 if (safety and owner_mod.valgrind) {
......@@ -10060,9 +10076,22 @@ pub const FuncGen = struct {
1006010076 const fill_byte = try o.builder.intValue(.i8, byte_val);
1006110077 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
1006210078 if (intrinsic_len0_traps) {
10063 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
10079 try self.safeWasmMemset(
10080 dest_ptr,
10081 fill_byte,
10082 len,
10083 dest_ptr_align,
10084 access_kind,
10085 );
1006410086 } else {
10065 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
10087 _ = try self.wip.callMemSet(
10088 dest_ptr,
10089 dest_ptr_align,
10090 fill_byte,
10091 len,
10092 access_kind,
10093 self.ng.ownerModule().no_builtin,
10094 );
1006610095 }
1006710096 return .none;
1006810097 }
......@@ -10077,9 +10106,22 @@ pub const FuncGen = struct {
1007710106 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
1007810107
1007910108 if (intrinsic_len0_traps) {
10080 try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, access_kind);
10109 try self.safeWasmMemset(
10110 dest_ptr,
10111 fill_byte,
10112 len,
10113 dest_ptr_align,
10114 access_kind,
10115 );
1008110116 } else {
10082 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
10117 _ = try self.wip.callMemSet(
10118 dest_ptr,
10119 dest_ptr_align,
10120 fill_byte,
10121 len,
10122 access_kind,
10123 self.ng.ownerModule().no_builtin,
10124 );
1008310125 }
1008410126 return .none;
1008510127 }
......@@ -10131,6 +10173,7 @@ pub const FuncGen = struct {
1013110173 elem_abi_align.toLlvm(),
1013210174 try o.builder.intValue(llvm_usize_ty, elem_abi_size),
1013310175 access_kind,
10176 self.ng.ownerModule().no_builtin,
1013410177 );
1013510178 } else _ = try self.wip.store(access_kind, value, it_ptr.toValue(), it_ptr_align);
1013610179 const next_ptr = try self.wip.gep(.inbounds, elem_llvm_ty, it_ptr.toValue(), &.{
......@@ -10158,7 +10201,14 @@ pub const FuncGen = struct {
1015810201 const end_block = try self.wip.block(2, "MemsetTrapEnd");
1015910202 _ = try self.wip.brCond(cond, memset_block, end_block, .none);
1016010203 self.wip.cursor = .{ .block = memset_block };
10161 _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind);
10204 _ = try self.wip.callMemSet(
10205 dest_ptr,
10206 dest_ptr_align,
10207 fill_byte,
10208 len,
10209 access_kind,
10210 self.ng.ownerModule().no_builtin,
10211 );
1016210212 _ = try self.wip.br(end_block);
1016310213 self.wip.cursor = .{ .block = end_block };
1016410214 }
......@@ -10200,6 +10250,7 @@ pub const FuncGen = struct {
1020010250 src_ptr_ty.ptrAlignment(zcu).toLlvm(),
1020110251 len,
1020210252 access_kind,
10253 self.ng.ownerModule().no_builtin,
1020310254 );
1020410255 _ = try self.wip.br(end_block);
1020510256 self.wip.cursor = .{ .block = end_block };
......@@ -10213,6 +10264,7 @@ pub const FuncGen = struct {
1021310264 src_ptr_ty.ptrAlignment(zcu).toLlvm(),
1021410265 len,
1021510266 access_kind,
10267 self.ng.ownerModule().no_builtin,
1021610268 );
1021710269 return .none;
1021810270 }
......@@ -11346,6 +11398,7 @@ pub const FuncGen = struct {
1134611398 ptr_alignment,
1134711399 try o.builder.intValue(try o.lowerType(Type.usize), size_bytes),
1134811400 access_kind,
11401 fg.ng.ownerModule().no_builtin,
1134911402 );
1135011403 return result_ptr;
1135111404 }
......@@ -11513,6 +11566,7 @@ pub const FuncGen = struct {
1151311566 elem_ty.abiAlignment(zcu).toLlvm(),
1151411567 try o.builder.intValue(try o.lowerType(Type.usize), elem_ty.abiSize(zcu)),
1151511568 access_kind,
11569 self.ng.ownerModule().no_builtin,
1151611570 );
1151711571 }
1151811572
src/codegen/llvm/Builder.zig+4-2
......@@ -6102,6 +6102,7 @@ pub const WipFunction = struct {
61026102 src_align: Alignment,
61036103 len: Value,
61046104 kind: MemoryAccessKind,
6105 @"inline": bool,
61056106 ) Allocator.Error!Instruction.Index {
61066107 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
61076108 var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })};
......@@ -6113,7 +6114,7 @@ pub const WipFunction = struct {
61136114 try self.builder.attrs(&dst_attrs),
61146115 try self.builder.attrs(&src_attrs),
61156116 }),
6116 .memcpy,
6117 if (@"inline") .@"memcpy.inline" else .memcpy,
61176118 &.{ dst.typeOfWip(self), src.typeOfWip(self), len.typeOfWip(self) },
61186119 &.{ dst, src, len, switch (kind) {
61196120 .normal => Value.false,
......@@ -6131,12 +6132,13 @@ pub const WipFunction = struct {
61316132 val: Value,
61326133 len: Value,
61336134 kind: MemoryAccessKind,
6135 @"inline": bool,
61346136 ) Allocator.Error!Instruction.Index {
61356137 var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })};
61366138 const value = try self.callIntrinsic(
61376139 .normal,
61386140 try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }),
6139 .memset,
6141 if (@"inline") .@"memset.inline" else .memset,
61406142 &.{ dst.typeOfWip(self), len.typeOfWip(self) },
61416143 &.{ dst, val, len, switch (kind) {
61426144 .normal => Value.false,