| ... | ... | @@ -9832,62 +9832,80 @@ pub const FuncGen = struct { |
| 9832 | 9832 | const usize_llvm_ty = fg.context.intType(target.cpu.arch.ptrBitWidth()); |
| 9833 | 9833 | const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target)); |
| 9834 | 9834 | |
| 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}", |
| 9888 | 9879 | }, |
| 9889 | 9880 | 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; |
| 9891 | 9909 | } |
| 9892 | 9910 | }; |
| 9893 | 9911 | |