authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-21 19:50:26-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-11-21 19:50:26-05:00
log670b4c5c02edc8fdfb4a73e72388ac0a140f8856
treec06a30c37804a58cdae9e12df257d17d68744733
parent271cc52a1619a553212192478d96a7c4bd629424
parent78389af55266d58e699a4d982e00afb6cce7ec64
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13292 from mitchellh/valgrind-arm64

std: valgrind client request support for aarch64

3 files changed, 89 insertions(+), 56 deletions(-)

lib/std/valgrind.zig+11-1
......@@ -30,10 +30,20 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
3030 : "cc", "memory"
3131 );
3232 },
33 .aarch64 => {
34 return asm volatile (
35 \\ ror x12, x12, #3 ; ror x12, x12, #13
36 \\ ror x12, x12, #51 ; ror x12, x12, #61
37 \\ orr x10, x10, x10
38 : [_] "={x3}" (-> usize),
39 : [_] "{x4}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
40 [_] "0" (default),
41 : "cc", "memory"
42 );
43 },
3344 // ppc32
3445 // ppc64
3546 // arm
36 // arm64
3747 // s390x
3848 // mips32
3949 // mips64
src/codegen/llvm.zig+72-54
......@@ -9839,62 +9839,80 @@ pub const FuncGen = struct {
98399839 const usize_llvm_ty = fg.context.intType(target.cpu.arch.ptrBitWidth());
98409840 const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target));
98419841
9842 switch (target.cpu.arch) {
9843 .x86_64 => {
9844 const array_llvm_ty = usize_llvm_ty.arrayType(6);
9845 const array_ptr = fg.valgrind_client_request_array orelse a: {
9846 const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment);
9847 fg.valgrind_client_request_array = array_ptr;
9848 break :a array_ptr;
9849 };
9850 const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 };
9851 const zero = usize_llvm_ty.constInt(0, .False);
9852 for (array_elements) |elem, i| {
9853 const indexes = [_]*llvm.Value{
9854 zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False),
9855 };
9856 const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
9857 const store_inst = fg.builder.buildStore(elem, elem_ptr);
9858 store_inst.setAlignment(usize_alignment);
9859 }
9860
9861 const asm_template =
9862 \\rolq $$3, %rdi ; rolq $$13, %rdi
9863 \\rolq $$61, %rdi ; rolq $$51, %rdi
9864 \\xchgq %rbx,%rbx
9865 ;
9866
9867 const asm_constraints = "={rdx},{rax},0,~{cc},~{memory}";
9868
9869 const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, "");
9870 const args = [_]*llvm.Value{ array_ptr_as_usize, default_value };
9871 const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty };
9872 const fn_llvm_ty = llvm.functionType(usize_llvm_ty, &param_types, args.len, .False);
9873 const asm_fn = llvm.getInlineAsm(
9874 fn_llvm_ty,
9875 asm_template,
9876 asm_template.len,
9877 asm_constraints,
9878 asm_constraints.len,
9879 .True, // has side effects
9880 .False, // alignstack
9881 .ATT,
9882 .False,
9883 );
9884
9885 const call = fg.builder.buildCall(
9886 fn_llvm_ty,
9887 asm_fn,
9888 &args,
9889 args.len,
9890 .C,
9891 .Auto,
9892 "",
9893 );
9894 return call;
9842 const array_llvm_ty = usize_llvm_ty.arrayType(6);
9843 const array_ptr = fg.valgrind_client_request_array orelse a: {
9844 const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment);
9845 fg.valgrind_client_request_array = array_ptr;
9846 break :a array_ptr;
9847 };
9848 const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 };
9849 const zero = usize_llvm_ty.constInt(0, .False);
9850 for (array_elements) |elem, i| {
9851 const indexes = [_]*llvm.Value{
9852 zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False),
9853 };
9854 const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
9855 const store_inst = fg.builder.buildStore(elem, elem_ptr);
9856 store_inst.setAlignment(usize_alignment);
9857 }
9858
9859 const arch_specific: struct {
9860 template: [:0]const u8,
9861 constraints: [:0]const u8,
9862 } = switch (target.cpu.arch) {
9863 .x86 => .{
9864 .template =
9865 \\roll $$3, %edi ; roll $$13, %edi
9866 \\roll $$61, %edi ; roll $$51, %edi
9867 \\xchgl %ebx,%ebx
9868 ,
9869 .constraints = "={edx},{eax},0,~{cc},~{memory}",
9870 },
9871 .x86_64 => .{
9872 .template =
9873 \\rolq $$3, %rdi ; rolq $$13, %rdi
9874 \\rolq $$61, %rdi ; rolq $$51, %rdi
9875 \\xchgq %rbx,%rbx
9876 ,
9877 .constraints = "={rdx},{rax},0,~{cc},~{memory}",
9878 },
9879 .aarch64, .aarch64_32, .aarch64_be => .{
9880 .template =
9881 \\ror x12, x12, #3 ; ror x12, x12, #13
9882 \\ror x12, x12, #51 ; ror x12, x12, #61
9883 \\orr x10, x10, x10
9884 ,
9885 .constraints = "={x3},{x4},0,~{cc},~{memory}",
98959886 },
98969887 else => unreachable,
9897 }
9888 };
9889
9890 const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, "");
9891 const args = [_]*llvm.Value{ array_ptr_as_usize, default_value };
9892 const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty };
9893 const fn_llvm_ty = llvm.functionType(usize_llvm_ty, &param_types, args.len, .False);
9894 const asm_fn = llvm.getInlineAsm(
9895 fn_llvm_ty,
9896 arch_specific.template.ptr,
9897 arch_specific.template.len,
9898 arch_specific.constraints.ptr,
9899 arch_specific.constraints.len,
9900 .True, // has side effects
9901 .False, // alignstack
9902 .ATT,
9903 .False, // can throw
9904 );
9905
9906 const call = fg.builder.buildCall(
9907 fn_llvm_ty,
9908 asm_fn,
9909 &args,
9910 args.len,
9911 .C,
9912 .Auto,
9913 "",
9914 );
9915 return call;
98989916 }
98999917};
99009918
src/target.zig+6-1
......@@ -211,7 +211,12 @@ pub fn isSingleThreaded(target: std.Target) bool {
211211/// Valgrind supports more, but Zig does not support them yet.
212212pub fn hasValgrindSupport(target: std.Target) bool {
213213 switch (target.cpu.arch) {
214 .x86_64 => {
214 .x86,
215 .x86_64,
216 .aarch64,
217 .aarch64_32,
218 .aarch64_be,
219 => {
215220 return target.os.tag == .linux or target.os.tag == .solaris or
216221 (target.os.tag == .windows and target.abi != .msvc);
217222 },