Skip to content

Commit 78389af

Browse files
committed
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.
1 parent 95e135a commit 78389af

File tree

3 files changed

+82
-62
lines changed

3 files changed

+82
-62
lines changed

lib/std/valgrind.zig

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,13 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3:
3232
},
3333
.aarch64 => {
3434
return asm volatile (
35-
\\ mov x3, %[default]
36-
\\ mov x4, %[ptr]
3735
\\ ror x12, x12, #3 ; ror x12, x12, #13
3836
\\ ror x12, x12, #51 ; ror x12, x12, #61
3937
\\ orr x10, x10, x10
40-
\\ mov %[ret], x3
41-
: [ret] "=r" (-> usize),
42-
: [default] "r" (default),
43-
[ptr] "r" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
44-
: "cc", "memory", "x3", "x4"
38+
: [_] "={x3}" (-> usize),
39+
: [_] "{x4}" (&[_]usize{ request, a1, a2, a3, a4, a5 }),
40+
[_] "0" (default),
41+
: "cc", "memory"
4542
);
4643
},
4744
// ppc32

src/codegen/llvm.zig

Lines changed: 72 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9832,62 +9832,80 @@ pub const FuncGen = struct {
98329832
const usize_llvm_ty = fg.context.intType(target.cpu.arch.ptrBitWidth());
98339833
const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target));
98349834

9835-
switch (target.cpu.arch) {
9836-
.x86_64 => {
9837-
const array_llvm_ty = usize_llvm_ty.arrayType(6);
9838-
const array_ptr = fg.valgrind_client_request_array orelse a: {
9839-
const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment);
9840-
fg.valgrind_client_request_array = array_ptr;
9841-
break :a array_ptr;
9842-
};
9843-
const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 };
9844-
const zero = usize_llvm_ty.constInt(0, .False);
9845-
for (array_elements) |elem, i| {
9846-
const indexes = [_]*llvm.Value{
9847-
zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False),
9848-
};
9849-
const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
9850-
const store_inst = fg.builder.buildStore(elem, elem_ptr);
9851-
store_inst.setAlignment(usize_alignment);
9852-
}
9853-
9854-
const asm_template =
9855-
\\rolq $$3, %rdi ; rolq $$13, %rdi
9856-
\\rolq $$61, %rdi ; rolq $$51, %rdi
9857-
\\xchgq %rbx,%rbx
9858-
;
9859-
9860-
const asm_constraints = "={rdx},{rax},0,~{cc},~{memory}";
9861-
9862-
const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, "");
9863-
const args = [_]*llvm.Value{ array_ptr_as_usize, default_value };
9864-
const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty };
9865-
const fn_llvm_ty = llvm.functionType(usize_llvm_ty, &param_types, args.len, .False);
9866-
const asm_fn = llvm.getInlineAsm(
9867-
fn_llvm_ty,
9868-
asm_template,
9869-
asm_template.len,
9870-
asm_constraints,
9871-
asm_constraints.len,
9872-
.True, // has side effects
9873-
.False, // alignstack
9874-
.ATT,
9875-
.False,
9876-
);
9877-
9878-
const call = fg.builder.buildCall(
9879-
fn_llvm_ty,
9880-
asm_fn,
9881-
&args,
9882-
args.len,
9883-
.C,
9884-
.Auto,
9885-
"",
9886-
);
9887-
return call;
9835+
const array_llvm_ty = usize_llvm_ty.arrayType(6);
9836+
const array_ptr = fg.valgrind_client_request_array orelse a: {
9837+
const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment);
9838+
fg.valgrind_client_request_array = array_ptr;
9839+
break :a array_ptr;
9840+
};
9841+
const array_elements = [_]*llvm.Value{ request, a1, a2, a3, a4, a5 };
9842+
const zero = usize_llvm_ty.constInt(0, .False);
9843+
for (array_elements) |elem, i| {
9844+
const indexes = [_]*llvm.Value{
9845+
zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False),
9846+
};
9847+
const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, "");
9848+
const store_inst = fg.builder.buildStore(elem, elem_ptr);
9849+
store_inst.setAlignment(usize_alignment);
9850+
}
9851+
9852+
const arch_specific: struct {
9853+
template: [:0]const u8,
9854+
constraints: [:0]const u8,
9855+
} = switch (target.cpu.arch) {
9856+
.x86 => .{
9857+
.template =
9858+
\\roll $$3, %edi ; roll $$13, %edi
9859+
\\roll $$61, %edi ; roll $$51, %edi
9860+
\\xchgl %ebx,%ebx
9861+
,
9862+
.constraints = "={edx},{eax},0,~{cc},~{memory}",
9863+
},
9864+
.x86_64 => .{
9865+
.template =
9866+
\\rolq $$3, %rdi ; rolq $$13, %rdi
9867+
\\rolq $$61, %rdi ; rolq $$51, %rdi
9868+
\\xchgq %rbx,%rbx
9869+
,
9870+
.constraints = "={rdx},{rax},0,~{cc},~{memory}",
9871+
},
9872+
.aarch64, .aarch64_32, .aarch64_be => .{
9873+
.template =
9874+
\\ror x12, x12, #3 ; ror x12, x12, #13
9875+
\\ror x12, x12, #51 ; ror x12, x12, #61
9876+
\\orr x10, x10, x10
9877+
,
9878+
.constraints = "={x3},{x4},0,~{cc},~{memory}",
98889879
},
98899880
else => unreachable,
9890-
}
9881+
};
9882+
9883+
const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, "");
9884+
const args = [_]*llvm.Value{ array_ptr_as_usize, default_value };
9885+
const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty };
9886+
const fn_llvm_ty = llvm.functionType(usize_llvm_ty, &param_types, args.len, .False);
9887+
const asm_fn = llvm.getInlineAsm(
9888+
fn_llvm_ty,
9889+
arch_specific.template.ptr,
9890+
arch_specific.template.len,
9891+
arch_specific.constraints.ptr,
9892+
arch_specific.constraints.len,
9893+
.True, // has side effects
9894+
.False, // alignstack
9895+
.ATT,
9896+
.False, // can throw
9897+
);
9898+
9899+
const call = fg.builder.buildCall(
9900+
fn_llvm_ty,
9901+
asm_fn,
9902+
&args,
9903+
args.len,
9904+
.C,
9905+
.Auto,
9906+
"",
9907+
);
9908+
return call;
98919909
}
98929910
};
98939911

src/target.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,12 @@ pub fn isSingleThreaded(target: std.Target) bool {
211211
/// Valgrind supports more, but Zig does not support them yet.
212212
pub 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
},

0 commit comments

Comments
 (0)