LLVM: add valgrind integration for x86 and aarch64

This also modifies the inline assembly to be more optimizable - instead of
doing explicit movs, we instead communicate to LLVM which registers we
would like to, somehow, have the correct values. This is how the x86_64
code already worked and thus allows the code to be unified across the
two architectures.

As a bonus, I threw in x86 support.
This commit is contained in:
Andrew Kelley 2022-11-19 19:32:26 -07:00
parent 95e135a8cb
commit 78389af552
3 changed files with 81 additions and 61 deletions

View file

@ -32,16 +32,13 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
},
.aarch64 => {
return asm volatile (
\\ mov x3, %[default]
\\ mov x4, %[ptr]
\\ ror x12, x12, #3 ; ror x12, x12, #13
\\ ror x12, x12, #51 ; ror x12, x12, #61
\\ orr x10, x10, x10
\\ mov %[ret], x3
: [ret] "=r" (-> usize),
: [default] "r" (default),
[ptr] "r" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
: "cc", "memory", "x3", "x4"
: [_] "={x3}" (-> usize),
: [_] "{x4}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
[_] "0" (default),
: "cc", "memory"
);
},
// ppc32

View file

@ -9832,8 +9832,6 @@ 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);
@ -9851,13 +9849,36 @@ pub const FuncGen = struct {
store_inst.setAlignment(usize_alignment);
}
const asm_template =
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
;
const asm_constraints = "={rdx},{rax},0,~{cc},~{memory}";
,
.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 };
@ -9865,14 +9886,14 @@ pub const FuncGen = struct {
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,
arch_specific.template.ptr,
arch_specific.template.len,
arch_specific.constraints.ptr,
arch_specific.constraints.len,
.True, // has side effects
.False, // alignstack
.ATT,
.False,
.False, // can throw
);
const call = fg.builder.buildCall(
@ -9885,9 +9906,6 @@ pub const FuncGen = struct {
"",
);
return call;
},
else => unreachable,
}
}
};

View file

@ -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);
},