Skip to content

Commit

Permalink
Merge pull request #13292 from mitchellh/valgrind-arm64
Browse files Browse the repository at this point in the history
std: valgrind client request support for aarch64
  • Loading branch information
andrewrk authored Nov 22, 2022
2 parents 271cc52 + 78389af commit 670b4c5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 56 deletions.
12 changes: 11 additions & 1 deletion lib/std/valgrind.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
126 changes: 72 additions & 54 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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, &param_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, &param_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;
}
};

Expand Down
7 changes: 6 additions & 1 deletion src/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},
Expand Down

0 comments on commit 670b4c5

Please sign in to comment.