diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig index 471342ef17cf..099aaf73600a 100644 --- a/lib/std/valgrind.zig +++ b/lib/std/valgrind.zig @@ -30,10 +30,20 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: : "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 - // arm64 // s390x // mips32 // mips64 diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8459920d61e2..d34336701ad5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -9839,62 +9839,80 @@ pub const FuncGen = struct { const usize_llvm_ty = fg.context.intType(target.cpu.arch.ptrBitWidth()); const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target)); - switch (target.cpu.arch) { - .x86_64 => { - const array_llvm_ty = usize_llvm_ty.arrayType(6); - const array_ptr = fg.valgrind_client_request_array orelse a: { - const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment); - fg.valgrind_client_request_array = array_ptr; - break :a array_ptr; - }; - const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 }; - const zero = usize_llvm_ty.constInt(0, .False); - for (array_elements) |elem, i| { - const indexes = [_]*llvm.Value{ - zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False), - }; - const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); - const store_inst = fg.builder.buildStore(elem, elem_ptr); - store_inst.setAlignment(usize_alignment); - } - - const asm_template = - \\rolq $$3, %rdi ; rolq $$13, %rdi - \\rolq $$61, %rdi ; rolq $$51, %rdi - \\xchgq %rbx,%rbx - ; - - const asm_constraints = "={rdx},{rax},0,~{cc},~{memory}"; - - const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); - const args = [_]*llvm.Value{ array_ptr_as_usize, default_value }; - const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty }; - const fn_llvm_ty = llvm.functionType(usize_llvm_ty, ¶m_types, args.len, .False); - const asm_fn = llvm.getInlineAsm( - fn_llvm_ty, - asm_template, - asm_template.len, - asm_constraints, - asm_constraints.len, - .True, // has side effects - .False, // alignstack - .ATT, - .False, - ); - - const call = fg.builder.buildCall( - fn_llvm_ty, - asm_fn, - &args, - args.len, - .C, - .Auto, - "", - ); - return call; + const array_llvm_ty = usize_llvm_ty.arrayType(6); + const array_ptr = fg.valgrind_client_request_array orelse a: { + const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment); + fg.valgrind_client_request_array = array_ptr; + break :a array_ptr; + }; + const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 }; + const zero = usize_llvm_ty.constInt(0, .False); + for (array_elements) |elem, i| { + const indexes = [_]*llvm.Value{ + zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False), + }; + const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); + const store_inst = fg.builder.buildStore(elem, elem_ptr); + store_inst.setAlignment(usize_alignment); + } + + const arch_specific: struct { + template: [:0]const u8, + constraints: [:0]const u8, + } = switch (target.cpu.arch) { + .x86 => .{ + .template = + \\roll $$3, %edi ; roll $$13, %edi + \\roll $$61, %edi ; roll $$51, %edi + \\xchgl %ebx,%ebx + , + .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}", + }, + .aarch64, .aarch64_32, .aarch64_be => .{ + .template = + \\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}", }, else => unreachable, - } + }; + + const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); + const args = [_]*llvm.Value{ array_ptr_as_usize, default_value }; + const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty }; + const fn_llvm_ty = llvm.functionType(usize_llvm_ty, ¶m_types, args.len, .False); + const asm_fn = llvm.getInlineAsm( + fn_llvm_ty, + arch_specific.template.ptr, + arch_specific.template.len, + arch_specific.constraints.ptr, + arch_specific.constraints.len, + .True, // has side effects + .False, // alignstack + .ATT, + .False, // can throw + ); + + const call = fg.builder.buildCall( + fn_llvm_ty, + asm_fn, + &args, + args.len, + .C, + .Auto, + "", + ); + return call; } }; diff --git a/src/target.zig b/src/target.zig index 23aff0f256fb..90cc50db2379 100644 --- a/src/target.zig +++ b/src/target.zig @@ -211,7 +211,12 @@ pub fn isSingleThreaded(target: std.Target) bool { /// Valgrind supports more, but Zig does not support them yet. pub fn hasValgrindSupport(target: std.Target) bool { switch (target.cpu.arch) { - .x86_64 => { + .x86, + .x86_64, + .aarch64, + .aarch64_32, + .aarch64_be, + => { return target.os.tag == .linux or target.os.tag == .solaris or (target.os.tag == .windows and target.abi != .msvc); },