From 4050d9bbf918dee0195e88d57b653e89d5e25372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 4 Nov 2024 10:56:32 +0100 Subject: [PATCH 1/3] std.valgrind: Fix some compile errors. --- lib/std/valgrind.zig | 4 ++-- lib/std/valgrind/memcheck.zig | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig index 241f4c732a..7b7dc4deef 100644 --- a/lib/std/valgrind.zig +++ b/lib/std/valgrind.zig @@ -121,7 +121,7 @@ pub fn discardTranslations(qzz: []const u8) void { } pub fn innerThreads(qzz: [*]u8) void { - doClientRequestStmt(.InnerThreads, qzz, 0, 0, 0, 0); + doClientRequestStmt(.InnerThreads, @intFromPtr(qzz), 0, 0, 0, 0); } pub fn nonSimdCall0(func: fn (usize) usize) usize { @@ -273,7 +273,7 @@ pub fn enableErrorReporting() void { /// If no connection is opened, output will go to the log output. /// Returns 1 if command not recognised, 0 otherwise. pub fn monitorCommand(command: [*]u8) bool { - return doClientRequestExpr(0, .GdbMonitorCommand, @intFromPtr(command.ptr), 0, 0, 0, 0) != 0; + return doClientRequestExpr(0, .GdbMonitorCommand, @intFromPtr(command), 0, 0, 0, 0) != 0; } pub const memcheck = @import("valgrind/memcheck.zig"); diff --git a/lib/std/valgrind/memcheck.zig b/lib/std/valgrind/memcheck.zig index 950026afc5..d0e0f0bd8c 100644 --- a/lib/std/valgrind/memcheck.zig +++ b/lib/std/valgrind/memcheck.zig @@ -90,26 +90,26 @@ pub fn checkMemIsDefined(qzz: []const u8) usize { /// Do a full memory leak check (like --leak-check=full) mid-execution. pub fn doLeakCheck() void { - doClientRequestStmt(.DO_LEAK_CHECK, 0, 0, 0, 0, 0); + doClientRequestStmt(.DoLeakCheck, 0, 0, 0, 0, 0); } /// Same as doLeakCheck() but only showing the entries for /// which there was an increase in leaked bytes or leaked nr of blocks /// since the previous leak search. pub fn doAddedLeakCheck() void { - doClientRequestStmt(.DO_LEAK_CHECK, 0, 1, 0, 0, 0); + doClientRequestStmt(.DoLeakCheck, 0, 1, 0, 0, 0); } /// Same as doAddedLeakCheck() but showing entries with /// increased or decreased leaked bytes/blocks since previous leak /// search. pub fn doChangedLeakCheck() void { - doClientRequestStmt(.DO_LEAK_CHECK, 0, 2, 0, 0, 0); + doClientRequestStmt(.DoLeakCheck, 0, 2, 0, 0, 0); } /// Do a summary memory leak check (like --leak-check=summary) mid-execution. pub fn doQuickLeakCheck() void { - doClientRequestStmt(.DO_LEAK_CHECK, 1, 0, 0, 0, 0); + doClientRequestStmt(.DoLeakCheck, 1, 0, 0, 0, 0); } /// Return number of leaked, dubious, reachable and suppressed bytes found by @@ -191,7 +191,7 @@ test countLeakBlocks { /// impossible to segfault your system by using this call. pub fn getVbits(zza: []u8, zzvbits: []u8) u2 { std.debug.assert(zzvbits.len >= zza.len / 8); - return @as(u2, @intCast(doClientRequestExpr(0, .GetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits), zza.len, 0, 0))); + return @as(u2, @intCast(doClientRequestExpr(0, .GetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits.ptr), zza.len, 0, 0))); } /// Set the validity data for addresses zza, copying it @@ -204,7 +204,7 @@ pub fn getVbits(zza: []u8, zzvbits: []u8) u2 { /// impossible to segfault your system by using this call. pub fn setVbits(zzvbits: []u8, zza: []u8) u2 { std.debug.assert(zzvbits.len >= zza.len / 8); - return @as(u2, @intCast(doClientRequestExpr(0, .SetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits), zza.len, 0, 0))); + return @as(u2, @intCast(doClientRequestExpr(0, .SetVbits, @intFromPtr(zza.ptr), @intFromPtr(zzvbits.ptr), zza.len, 0, 0))); } /// Disable and re-enable reporting of addressing errors in the From 2307cf73b044527464e63aa315e3af343d6584ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 4 Nov 2024 12:39:48 +0100 Subject: [PATCH 2/3] std.valgrind: Port doClientRequest() to all archs supported by Valgrind. --- lib/std/valgrind.zig | 134 +++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 44 deletions(-) diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig index 7b7dc4deef..30170aa6ed 100644 --- a/lib/std/valgrind.zig +++ b/lib/std/valgrind.zig @@ -7,50 +7,96 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: return default; } - switch (builtin.target.cpu.arch) { - .x86 => { - return asm volatile ( - \\ roll $3, %%edi ; roll $13, %%edi - \\ roll $29, %%edi ; roll $19, %%edi - \\ xchgl %%ebx,%%ebx - : [_] "={edx}" (-> usize), - : [_] "{eax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }), - [_] "0" (default), - : "cc", "memory" - ); - }, - .x86_64 => { - return asm volatile ( - \\ rolq $3, %%rdi ; rolq $13, %%rdi - \\ rolq $61, %%rdi ; rolq $51, %%rdi - \\ xchgq %%rbx,%%rbx - : [_] "={rdx}" (-> usize), - : [_] "{rax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }), - [_] "0" (default), - : "cc", "memory" - ); - }, - .aarch64 => { - return asm volatile ( - \\ ror x12, x12, #3 ; ror x12, x12, #13 - \\ ror x12, x12, #51 ; ror x12, x12, #61 - \\ orr x10, x10, x10 - : [_] "={x3}" (-> usize), - : [_] "{x4}" (&[_]usize{ request, a1, a2, a3, a4, a5 }), - [_] "0" (default), - : "cc", "memory" - ); - }, - // ppc32 - // ppc64 - // arm - // s390x - // mips32 - // mips64 - else => { - return default; - }, - } + const args = &[_]usize{ request, a1, a2, a3, a4, a5 }; + + return switch (builtin.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => asm volatile ( + \\ mov r12, r12, ror #3 ; mov r12, r12, ror #13 + \\ mov r12, r12, ror #29 ; mov r12, r12, ror #19 + \\ orr r10, r10, r10 + : [_] "={r3}" (-> usize), + : [_] "{r4}" (args), + [_] "{r3}" (default), + : "cc", "memory" + ), + .aarch64, .aarch64_be => asm volatile ( + \\ ror x12, x12, #3 ; ror x12, x12, #13 + \\ ror x12, x12, #51 ; ror x12, x12, #61 + \\ orr x10, x10, x10 + : [_] "={x3}" (-> usize), + : [_] "{x4}" (args), + [_] "{x3}" (default), + : "cc", "memory" + ), + .mips, .mipsel => asm volatile ( + \\ srl $0, $0, 13 + \\ srl $0, $0, 29 + \\ srl $0, $0, 3 + \\ srl $0, $0, 19 + \\ or $13, $13, $13 + : [_] "={$11}" (-> usize), + : [_] "{$12}" (args), + [_] "{$11}" (default), + : "memory" + ), + .mips64, .mips64el => asm volatile ( + \\ dsll $0, $0, 3 ; dsll $0, $0, 13 + \\ dsll $0, $0, 29 ; dsll $0, $0, 19 + \\ or $13, $13, $13 + : [_] "={$11}" (-> usize), + : [_] "{$12}" (args), + [_] "{$11}" (default), + : "memory" + ), + .powerpc, .powerpcle => asm volatile ( + \\ rlwinm 0, 0, 3, 0, 31 ; rlwinm 0, 0, 13, 0, 31 + \\ rlwinm 0, 0, 29, 0, 31 ; rlwinm 0, 0, 19, 0, 31 + \\ or 1, 1, 1 + : [_] "={r3}" (-> usize), + : [_] "{r4}" (args), + [_] "{r3}" (default), + : "cc", "memory" + ), + .powerpc64, .powerpc64le => asm volatile ( + \\ rotldi 0, 0, 3 ; rotldi 0, 0, 13 + \\ rotldi 0, 0, 61 ; rotldi 0, 0, 51 + \\ or 1, 1, 1 + : [_] "={r3}" (-> usize), + : [_] "{r4}" (args), + [_] "{r3}" (default), + : "cc", "memory" + ), + .s390x => asm volatile ( + \\ lr %%r15, %%r15 + \\ lr %%r1, %%r1 + \\ lr %%r2, %%r2 + \\ lr %%r3, %%r3 + \\ lr %%r2, %%r2 + : [_] "={r3}" (-> usize), + : [_] "{r2}" (args), + [_] "{r3}" (default), + : "cc", "memory" + ), + .x86 => asm volatile ( + \\ roll $3, %%edi ; roll $13, %%edi + \\ roll $29, %%edi ; roll $19, %%edi + \\ xchgl %%ebx, %%ebx + : [_] "={edx}" (-> usize), + : [_] "{eax}" (args), + [_] "{edx}" (default), + : "cc", "memory" + ), + .x86_64 => asm volatile ( + \\ rolq $3, %%rdi ; rolq $13, %%rdi + \\ rolq $61, %%rdi ; rolq $51, %%rdi + \\ xchgq %%rbx, %%rbx + : [_] "={rdx}" (-> usize), + : [_] "{rax}" (args), + [_] "{rdx}" (default), + : "cc", "memory" + ), + else => default, + }; } pub const ClientRequest = enum(u32) { From 8a73a965d3185cadee2bd819daa12b5b3f1daafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 4 Nov 2024 12:40:27 +0100 Subject: [PATCH 3/3] llvm: Add client request support for all archs supported by Valgrind. --- src/codegen/llvm.zig | 86 +++++++++++++++++++++++++++++++++++--------- src/target.zig | 48 +++++++++++++++++++------ 2 files changed, 106 insertions(+), 28 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b709403256..514a360a66 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -11595,29 +11595,81 @@ pub const FuncGen = struct { template: [:0]const u8, constraints: [:0]const u8, } = switch (target.cpu.arch) { - .x86 => .{ + .arm, .armeb, .thumb, .thumbeb => .{ .template = - \\roll $$3, %edi ; roll $$13, %edi - \\roll $$61, %edi ; roll $$51, %edi - \\xchgl %ebx,%ebx + \\ mov r12, r12, ror #3 ; mov r12, r12, ror #13 + \\ mov r12, r12, ror #29 ; mov r12, r12, ror #19 + \\ orr r10, r10, r10 , - .constraints = "={edx},{eax},0,~{cc},~{memory}", - }, - .x86_64 => .{ - .template = - \\rolq $$3, %rdi ; rolq $$13, %rdi - \\rolq $$61, %rdi ; rolq $$51, %rdi - \\xchgq %rbx,%rbx - , - .constraints = "={rdx},{rax},0,~{cc},~{memory}", + .constraints = "={r3},{r4},{r3},~{cc},~{memory}", }, .aarch64, .aarch64_be => .{ .template = - \\ror x12, x12, #3 ; ror x12, x12, #13 - \\ror x12, x12, #51 ; ror x12, x12, #61 - \\orr x10, x10, x10 + \\ ror x12, x12, #3 ; ror x12, x12, #13 + \\ ror x12, x12, #51 ; ror x12, x12, #61 + \\ orr x10, x10, x10 , - .constraints = "={x3},{x4},0,~{cc},~{memory}", + .constraints = "={x3},{x4},{x3},~{cc},~{memory}", + }, + .mips, .mipsel => .{ + .template = + \\ srl $$0, $$0, 13 + \\ srl $$0, $$0, 29 + \\ srl $$0, $$0, 3 + \\ srl $$0, $$0, 19 + \\ or $$13, $$13, $$13 + , + .constraints = "={$11},{$12},{$11},~{memory}", + }, + .mips64, .mips64el => .{ + .template = + \\ dsll $$0, $$0, 3 ; dsll $$0, $$0, 13 + \\ dsll $$0, $$0, 29 ; dsll $$0, $$0, 19 + \\ or $$13, $$13, $$13 + , + .constraints = "={$11},{$12},{$11},~{memory}", + }, + .powerpc, .powerpcle => .{ + .template = + \\ rlwinm 0, 0, 3, 0, 31 ; rlwinm 0, 0, 13, 0, 31 + \\ rlwinm 0, 0, 29, 0, 31 ; rlwinm 0, 0, 19, 0, 31 + \\ or 1, 1, 1 + , + .constraints = "={r3},{r4},{r3},~{cc},~{memory}", + }, + .powerpc64, .powerpc64le => .{ + .template = + \\ rotldi 0, 0, 3 ; rotldi 0, 0, 13 + \\ rotldi 0, 0, 61 ; rotldi 0, 0, 51 + \\ or 1, 1, 1 + , + .constraints = "={r3},{r4},{r3},~{cc},~{memory}", + }, + .s390x => .{ + .template = + \\ lr %r15, %r15 + \\ lr %r1, %r1 + \\ lr %r2, %r2 + \\ lr %r3, %r3 + \\ lr %r2, %r2 + , + .constraints = "={r3},{r2},{r3},~{cc},~{memory}", + }, + .x86 => .{ + .template = + \\ roll $$3, %edi ; roll $$13, %edi + \\ roll $$61, %edi ; roll $$51, %edi + \\ xchgl %ebx, %ebx + , + .constraints = "={edx},{eax},{edx},~{cc},~{memory}", + }, + .x86_64 => .{ + .template = + \\ rolq $$3, %rdi ; rolq $$13, %rdi + \\ rolq $$61, %rdi ; rolq $$51, %rdi + \\ xchgq %rbx, %rbx + , + .constraints = "={rdx},{rax},{edx},~{cc},~{memory}", }, else => unreachable, }; diff --git a/src/target.zig b/src/target.zig index 2327ff0c4a..aba1fffcbc 100644 --- a/src/target.zig +++ b/src/target.zig @@ -79,19 +79,45 @@ pub fn defaultSingleThreaded(target: std.Target) bool { return false; } -/// Valgrind supports more, but Zig does not support them yet. pub fn hasValgrindSupport(target: std.Target) bool { - switch (target.cpu.arch) { - .x86, - .x86_64, - .aarch64, - .aarch64_be, - => { - return target.os.tag == .linux or target.os.tag == .solaris or target.os.tag == .illumos or - (target.os.tag == .windows and target.abi.isGnu()); + // We can't currently output the necessary Valgrind client request assembly when using the C + // backend and compiling with an MSVC-like compiler. + const ofmt_c_msvc = (target.abi == .msvc or target.abi == .itanium) and target.ofmt == .c; + + return switch (target.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) { + .linux => true, + else => false, }, - else => return false, - } + .aarch64, .aarch64_be => switch (target.os.tag) { + .linux, .freebsd => true, + else => false, + }, + .mips, .mipsel, .mips64, .mips64el => switch (target.os.tag) { + .linux => true, + else => false, + }, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (target.os.tag) { + .linux => true, + else => false, + }, + .s390x => switch (target.os.tag) { + .linux => true, + else => false, + }, + .x86 => switch (target.os.tag) { + .linux, .freebsd, .solaris, .illumos => true, + .windows => !ofmt_c_msvc, + else => false, + }, + .x86_64 => switch (target.os.tag) { + .linux => target.abi != .gnux32 and target.abi != .muslx32, + .freebsd, .solaris, .illumos => true, + .windows => !ofmt_c_msvc, + else => false, + }, + else => false, + }; } /// The set of targets that LLVM has non-experimental support for.