| ... | ... | @@ -9839,62 +9839,80 @@ pub const FuncGen = struct { |
| 9839 | 9839 | const usize_llvm_ty = fg.context.intType(target.cpu.arch.ptrBitWidth()); |
| 9840 | 9840 | const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target)); |
| 9841 | 9841 | |
| 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}", |
| 9895 | 9886 | }, |
| 9896 | 9887 | 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; |
| 9898 | 9916 | } |
| 9899 | 9917 | }; |
| 9900 | 9918 | |