From 41b179ca09f33a6a667ccdb063ebf8ff4cf076b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 22 Feb 2025 08:20:10 +0100 Subject: [PATCH 1/2] llvm.Builder: Update some intrinsic definitions for LLVM 19. --- src/codegen/llvm.zig | 6 +++--- src/codegen/llvm/Builder.zig | 21 +++++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 97ed00c98d84..719c53c63067 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5902,7 +5902,7 @@ pub const FuncGen = struct { const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); const dest_list = try self.buildAllocaWorkaround(va_list_ty, result_alignment); - _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{}, &.{ dest_list, src_list }, ""); + _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{dest_list.typeOfWip(&self.wip)}, &.{ dest_list, src_list }, ""); return if (isByRef(va_list_ty, zcu)) dest_list else @@ -5913,7 +5913,7 @@ pub const FuncGen = struct { const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const src_list = try self.resolveInst(un_op); - _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{}, &.{src_list}, ""); + _ = try self.wip.callIntrinsic(.normal, .none, .va_end, &.{src_list.typeOfWip(&self.wip)}, &.{src_list}, ""); return .none; } @@ -5927,7 +5927,7 @@ pub const FuncGen = struct { const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); const dest_list = try self.buildAllocaWorkaround(va_list_ty, result_alignment); - _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{}, &.{dest_list}, ""); + _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{dest_list.typeOfWip(&self.wip)}, &.{dest_list}, ""); return if (isByRef(va_list_ty, zcu)) dest_list else diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index f79b5700a8f8..0a8d64fb7277 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -2634,6 +2634,7 @@ pub const Intrinsic = enum { cos, pow, exp, + exp10, exp2, ldexp, frexp, @@ -2801,22 +2802,22 @@ pub const Intrinsic = enum { .va_start = .{ .ret_len = 0, .params = &.{ - .{ .kind = .{ .type = .ptr } }, + .{ .kind = .overloaded }, }, .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, }, .va_end = .{ .ret_len = 0, .params = &.{ - .{ .kind = .{ .type = .ptr } }, + .{ .kind = .overloaded }, }, .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, }, .va_copy = .{ .ret_len = 0, .params = &.{ - .{ .kind = .{ .type = .ptr } }, - .{ .kind = .{ .type = .ptr } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, }, .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, }, @@ -2929,7 +2930,7 @@ pub const Intrinsic = enum { .params = &.{ .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .writeonly } }, .{ .kind = .overloaded, .attrs = &.{ .@"noalias", .nocapture, .readonly } }, - .{ .kind = .overloaded, .attrs = &.{.immarg} }, + .{ .kind = .overloaded }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .readwrite } } }, @@ -2959,7 +2960,7 @@ pub const Intrinsic = enum { .params = &.{ .{ .kind = .overloaded, .attrs = &.{ .nocapture, .writeonly } }, .{ .kind = .{ .type = .i8 } }, - .{ .kind = .overloaded, .attrs = &.{.immarg} }, + .{ .kind = .overloaded }, .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, }, .attrs = &.{ .nocallback, .nofree, .nounwind, .willreturn, .{ .memory = .{ .argmem = .write } } }, @@ -3022,6 +3023,14 @@ pub const Intrinsic = enum { }, .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, }, + .exp10 = .{ + .ret_len = 1, + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, .ldexp = .{ .ret_len = 1, .params = &.{ 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 2/2] 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 719c53c63067..56cdd38b19d7 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 0a8d64fb7277..74618545106b 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,