From 0e0753baf33bfa0f504006917fb20f455ca796e4 Mon Sep 17 00:00:00 2001 From: nevermoe Date: Sat, 20 Mar 2021 22:19:32 +0900 Subject: [PATCH] swift5.4 support --- .gitignore | 16 + AntiHackOSS/LICENSE-DeClang | 202 +++ AntiHackOSS/LICENSE-ollvm | 44 + AntiHackOSS/clang/DeClangExtraProcess.cpp | 10 + AntiHackOSS/include/AntiHack.h | 36 + AntiHackOSS/include/CryptoUtils.h | 283 +++++ AntiHackOSS/include/DynamicBranch.h | 37 + AntiHackOSS/include/Flattening.h | 34 + AntiHackOSS/include/Obfuscation.h | 35 + AntiHackOSS/include/SplitBasicBlock.h | 33 + AntiHackOSS/include/Utils.h | 26 + AntiHackOSS/src/AntiHack.cpp | 179 +++ AntiHackOSS/src/CMakeLists.txt | 9 + AntiHackOSS/src/CryptoUtils.cpp | 1089 +++++++++++++++++ AntiHackOSS/src/DynamicBranch.cpp | 198 +++ AntiHackOSS/src/Flattening.cpp | 401 ++++++ AntiHackOSS/src/LLVMBuild.txt | 5 + AntiHackOSS/src/Obfuscation.cpp | 113 ++ AntiHackOSS/src/SplitBasicBlock.cpp | 183 +++ AntiHackOSS/src/Utils.cpp | 151 +++ AntiHackOSS/tools/build_tools.sh | 9 + AntiHackOSS/tools/config/GenConfig.go | 184 +++ AntiHackOSS/tools/config/Makefile | 24 + AntiHackOSS/tools/config/build.sh | 7 + AntiHackOSS/tools/config/config.pre.json | 9 + AntiHackOSS/tools/config/copy.sh | 5 + AntiHackOSS/tools/config/gen_config.sh | 14 + AntiHackOSS/tools/release.sh | 56 + AntiHackOSS/tools/tests/flatten/Makefile | 22 + .../tools/tests/flatten/config.pre.json | 11 + AntiHackOSS/tools/tests/flatten/test.cpp | 54 + clang/lib/Driver/CMakeLists.txt | 2 + clang/lib/Driver/Driver.cpp | 42 + .../Driver/Inputs/CUDA-symlinks/usr/bin/ptxas | 1 - .../usr/bin/i386-unknown-linux-gnu-ld | 2 +- .../usr/bin/x86_64-unknown-linux-gnu-ld | 2 +- .../usr/i386-unknown-linux-gnu/bin/ld | 2 +- .../usr/x86_64-unknown-linux-gnu/bin/ld | 2 +- .../multilib_32bit_linux_tree/usr/bin/as | 2 +- .../multilib_32bit_linux_tree/usr/bin/ld | 2 +- .../usr/i386-unknown-linux/bin/as | 2 +- .../usr/i386-unknown-linux/bin/ld | 2 +- .../multilib_64bit_linux_tree/usr/bin/as | 2 +- .../multilib_64bit_linux_tree/usr/bin/ld | 2 +- .../usr/x86_64-unknown-linux/bin/as | 2 +- .../usr/x86_64-unknown-linux/bin/ld | 2 +- libclc/amdgcn-mesa3d | 1 - libclc/amdgcn-mesa3d/lib/SOURCES | 3 + .../lib/workitem/get_global_size.cl | 24 + .../lib/workitem/get_local_size.cl | 30 + .../lib/workitem/get_num_groups.cl | 12 + libcxx/test/std/pstl | 1 - .../alg.merge/inplace_merge.pass.cpp | 159 +++ .../pstl/algorithms/alg.merge/merge.pass.cpp | 113 ++ .../alg.copy/copy_if.pass.cpp | 147 +++ .../alg.partitions/is_partitioned.pass.cpp | 101 ++ .../alg.partitions/partition.pass.cpp | 178 +++ .../alg.partitions/partition_copy.pass.cpp | 116 ++ .../alg.reverse/reverse.pass.cpp | 104 ++ .../alg.reverse/reverse_copy.pass.cpp | 132 ++ .../copy_move.pass.cpp | 197 +++ .../alg.modifying.operations/fill.pass.cpp | 100 ++ .../generate.pass.cpp | 104 ++ .../alg.modifying.operations/remove.pass.cpp | 161 +++ .../remove_copy.pass.cpp | 91 ++ .../alg.modifying.operations/replace.pass.cpp | 159 +++ .../replace_copy.pass.cpp | 105 ++ .../alg.modifying.operations/rotate.pass.cpp | 176 +++ .../rotate_copy.pass.cpp | 146 +++ .../swap_ranges.pass.cpp | 133 ++ .../transform_binary.pass.cpp | 122 ++ .../transform_unary.pass.cpp | 91 ++ .../alg.modifying.operations/unique.pass.cpp | 163 +++ .../unique_copy_equal.pass.cpp | 135 ++ .../alg.nonmodifying/adjacent_find.pass.cpp | 114 ++ .../alg.nonmodifying/all_of.pass.cpp | 117 ++ .../alg.nonmodifying/any_of.pass.cpp | 103 ++ .../alg.nonmodifying/count.pass.cpp | 108 ++ .../alg.nonmodifying/equal.pass.cpp | 168 +++ .../algorithms/alg.nonmodifying/find.pass.cpp | 96 ++ .../alg.nonmodifying/find_end.pass.cpp | 123 ++ .../alg.nonmodifying/find_first_of.pass.cpp | 112 ++ .../alg.nonmodifying/find_if.pass.cpp | 109 ++ .../alg.nonmodifying/for_each.pass.cpp | 102 ++ .../alg.nonmodifying/mismatch.pass.cpp | 132 ++ .../alg.nonmodifying/none_of.pass.cpp | 101 ++ .../alg.nonmodifying/nth_element.pass.cpp | 175 +++ .../alg.nonmodifying/search_n.pass.cpp | 109 ++ .../alg.heap.operations/is_heap.pass.cpp | 146 +++ .../lexicographical_compare.pass.cpp | 175 +++ .../alg.min.max/minmax_element.pass.cpp | 193 +++ .../alg.set.operations/includes.pass.cpp | 106 ++ .../alg.set.operations/set.pass.cpp | 280 +++++ .../algorithms/alg.sorting/is_sorted.pass.cpp | 100 ++ .../alg.sorting/partial_sort.pass.cpp | 149 +++ .../alg.sorting/partial_sort_copy.pass.cpp | 196 +++ .../pstl/algorithms/alg.sorting/sort.pass.cpp | 247 ++++ libcxx/test/std/pstl/lit.local.cfg | 2 + .../numeric.ops/adjacent_difference.pass.cpp | 170 +++ .../pstl/numerics/numeric.ops/reduce.pass.cpp | 114 ++ .../pstl/numerics/numeric.ops/scan.fail.cpp | 38 + .../pstl/numerics/numeric.ops/scan.pass.cpp | 201 +++ .../numeric.ops/transform_reduce.pass.cpp | 129 ++ .../numeric.ops/transform_scan.pass.cpp | 177 +++ .../uninitialized_construct.pass.cpp | 123 ++ .../uninitialized_copy_move.pass.cpp | 143 +++ .../uninitialized_fill_destroy.pass.cpp | 93 ++ llvm/lib/Transforms/CMakeLists.txt | 1 + llvm/lib/Transforms/IPO/LLVMBuild.txt | 2 +- .../lib/Transforms/IPO/PassManagerBuilder.cpp | 16 + llvm/lib/Transforms/LLVMBuild.txt | 2 +- script/build.sh | 65 + script/build_tools.sh | 8 + script/ndk_setup.sh | 50 + script/ndk_unset.sh | 39 + script/release.sh | 8 + script/xcode_setup.sh | 79 ++ script/xcode_unset.sh | 18 + 118 files changed, 11274 insertions(+), 17 deletions(-) create mode 100644 AntiHackOSS/LICENSE-DeClang create mode 100644 AntiHackOSS/LICENSE-ollvm create mode 100644 AntiHackOSS/clang/DeClangExtraProcess.cpp create mode 100644 AntiHackOSS/include/AntiHack.h create mode 100644 AntiHackOSS/include/CryptoUtils.h create mode 100644 AntiHackOSS/include/DynamicBranch.h create mode 100644 AntiHackOSS/include/Flattening.h create mode 100644 AntiHackOSS/include/Obfuscation.h create mode 100644 AntiHackOSS/include/SplitBasicBlock.h create mode 100644 AntiHackOSS/include/Utils.h create mode 100644 AntiHackOSS/src/AntiHack.cpp create mode 100644 AntiHackOSS/src/CMakeLists.txt create mode 100644 AntiHackOSS/src/CryptoUtils.cpp create mode 100644 AntiHackOSS/src/DynamicBranch.cpp create mode 100644 AntiHackOSS/src/Flattening.cpp create mode 100644 AntiHackOSS/src/LLVMBuild.txt create mode 100644 AntiHackOSS/src/Obfuscation.cpp create mode 100644 AntiHackOSS/src/SplitBasicBlock.cpp create mode 100644 AntiHackOSS/src/Utils.cpp create mode 100644 AntiHackOSS/tools/build_tools.sh create mode 100644 AntiHackOSS/tools/config/GenConfig.go create mode 100644 AntiHackOSS/tools/config/Makefile create mode 100644 AntiHackOSS/tools/config/build.sh create mode 100644 AntiHackOSS/tools/config/config.pre.json create mode 100644 AntiHackOSS/tools/config/copy.sh create mode 100755 AntiHackOSS/tools/config/gen_config.sh create mode 100644 AntiHackOSS/tools/release.sh create mode 100644 AntiHackOSS/tools/tests/flatten/Makefile create mode 100644 AntiHackOSS/tools/tests/flatten/config.pre.json create mode 100644 AntiHackOSS/tools/tests/flatten/test.cpp mode change 120000 => 100755 clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas mode change 120000 => 100755 clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld mode change 120000 => 100755 clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld mode change 120000 => 100755 clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld mode change 120000 => 100755 clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as mode change 120000 => 100755 clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld delete mode 120000 libclc/amdgcn-mesa3d create mode 100644 libclc/amdgcn-mesa3d/lib/SOURCES create mode 100644 libclc/amdgcn-mesa3d/lib/workitem/get_global_size.cl create mode 100644 libclc/amdgcn-mesa3d/lib/workitem/get_local_size.cl create mode 100644 libclc/amdgcn-mesa3d/lib/workitem/get_num_groups.cl delete mode 120000 libcxx/test/std/pstl create mode 100644 libcxx/test/std/pstl/algorithms/alg.merge/inplace_merge.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.merge/merge.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/copy_move.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/fill.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/generate.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/swap_ranges.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_binary.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_unary.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/adjacent_find.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/all_of.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/any_of.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/count.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/equal.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/find.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_end.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_first_of.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_if.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/for_each.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/mismatch.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/none_of.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/nth_element.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.nonmodifying/search_n.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/set.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/is_sorted.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort_copy.pass.cpp create mode 100644 libcxx/test/std/pstl/algorithms/alg.sorting/sort.pass.cpp create mode 100644 libcxx/test/std/pstl/lit.local.cfg create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/adjacent_difference.pass.cpp create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/reduce.pass.cpp create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/scan.fail.cpp create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/scan.pass.cpp create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/transform_reduce.pass.cpp create mode 100644 libcxx/test/std/pstl/numerics/numeric.ops/transform_scan.pass.cpp create mode 100644 libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp create mode 100644 libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp create mode 100644 libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp create mode 100644 script/build.sh create mode 100644 script/build_tools.sh create mode 100644 script/ndk_setup.sh create mode 100644 script/ndk_unset.sh create mode 100644 script/release.sh create mode 100644 script/xcode_setup.sh create mode 100644 script/xcode_unset.sh diff --git a/.gitignore b/.gitignore index 1c8d4b15925d..21dd5df17bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,19 @@ autoconf/autom4te.cache /clang/utils/analyzer/projects/*/PatchedSource /clang/utils/analyzer/projects/*/ScanBuildResults /clang/utils/analyzer/projects/*/RefScanBuildResults + + +/.vscode/ +/build/ +/Release*/ +/**/config.json +/AntiHackDeNA*/ +/clang/lib/Driver/DeClangExtraProcess.cpp +/llvm/lib/Transforms/AntiHack +/llvm/include/llvm/Transforms/AntiHack +/AntiHackOSS/tools/config/gen_config_* +/tools +.DS_Store +/Release* +.python-version + diff --git a/AntiHackOSS/LICENSE-DeClang b/AntiHackOSS/LICENSE-DeClang new file mode 100644 index 000000000000..1e1c8cfa08b5 --- /dev/null +++ b/AntiHackOSS/LICENSE-DeClang @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 DeNA Co., Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/AntiHackOSS/LICENSE-ollvm b/AntiHackOSS/LICENSE-ollvm new file mode 100644 index 000000000000..ea86a85bf6f2 --- /dev/null +++ b/AntiHackOSS/LICENSE-ollvm @@ -0,0 +1,44 @@ +============================================================================== +Obfuscator-LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2014 Haute Ecole d'Ingénierie et de Gestion du Canton de Vaud (HEIG-VD). All rights reserved. + +Developed by: + + Obfuscator-LLVM Team + + Haute-Ecole d'Ingénierie et de Gestion du Canton de Vaud (HEIG-VD), a part + of the University of Applied Sciences and Arts Western Switzerland (HES-SO) + + http://o-llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the Obfuscator-LLVM Team, the Haute Ecole d'Ingénierie + et de Gestion du Canton de Vaud (HEIG-VD), the University of Applied Sciences + and Arts Western Switzerland (HES-SO) nor the names of its contributors + may be used to endorse or promote products derived from this Software + without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/AntiHackOSS/clang/DeClangExtraProcess.cpp b/AntiHackOSS/clang/DeClangExtraProcess.cpp new file mode 100644 index 000000000000..bc79bb804e0e --- /dev/null +++ b/AntiHackOSS/clang/DeClangExtraProcess.cpp @@ -0,0 +1,10 @@ +#include "clang/Driver/Compilation.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang::driver; +using namespace clang; +using namespace llvm::opt; + +void DeClangExtraProcess(const Compilation &C, const std::string& homeDir, llvm::raw_fd_ostream *logFile) { + // do nothing +} diff --git a/AntiHackOSS/include/AntiHack.h b/AntiHackOSS/include/AntiHack.h new file mode 100644 index 000000000000..fdb37000644a --- /dev/null +++ b/AntiHackOSS/include/AntiHack.h @@ -0,0 +1,36 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANTI_CHEAT_INCLUDES_ +#define _ANTI_CHEAT_INCLUDES_ + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/JSON.h" + +using namespace std; + +namespace llvm { + void initializeAntiHackPass(PassRegistry &Registry); + Pass *createAntiHack(std::string configPath); +} + +#endif diff --git a/AntiHackOSS/include/CryptoUtils.h b/AntiHackOSS/include/CryptoUtils.h new file mode 100644 index 000000000000..48f04337765f --- /dev/null +++ b/AntiHackOSS/include/CryptoUtils.h @@ -0,0 +1,283 @@ +//===- CryptoUtils.h - Cryptographically Secure Pseudo-Random Generator ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains includes and defines for the AES CTR PRNG +// The AES implementation has been derived and adapted +// from libtomcrypt (see http://libtom.org) +// Created on: 22 juin 2012 +// Author(s): jrinaldini, pjunod +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CryptoUtils_H +#define LLVM_CryptoUtils_H + +#include "llvm/Support/ManagedStatic.h" + +#include +#include +#include + +namespace llvm { + +class CryptoUtils; +extern ManagedStatic cryptoutils; + +#define BYTE(x, n) (((x) >> (8 * (n))) & 0xFF) + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(INTEL_CC) + +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif + +#define ENDIAN_32BITWORD +#define UNALIGNED + +#elif defined(__alpha) + +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif +#define ENDIAN_64BITWORD + +#elif defined(__x86_64__) + +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif +#define ENDIAN_64BITWORD +#define UNALIGNED + +#elif (defined(__R5900) || defined(R5900) || defined(__R5900__)) && \ + (defined(_mips) || defined(__mips__) || defined(mips)) + +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif + +#define ENDIAN_64BITWORD + +#elif defined(__sparc) + +#ifndef ENDIAN_BIG +#define ENDIAN_BIG + +#endif + +#if defined(__arch64__) +#define ENDIAN_64BITWORD +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif +#else + +#define ENDIAN_32BITWORD +#ifndef ENDIAN_LITTLE +#define ENDIAN_LITTLE +#endif + +#endif + +#endif + +#if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) +#define ENDIAN_BIG +#endif + +//fixme: always assume windows is little endian +#if _WIN32 || _WIN64 +#define ENDIAN_LITTLE +#endif + +#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) +//default little endian +#define ENDIAN_LITTLE +// #error \ +// "Unknown endianness of the compilation platform, check this header aes_encrypt.h" +#endif + +#ifdef ENDIAN_LITTLE + +#define STORE32H(y, x) \ + { \ + (y)[0] = (uint8_t)(((x) >> 24) & 0xFF); \ + (y)[1] = (uint8_t)(((x) >> 16) & 0xFF); \ + (y)[2] = (uint8_t)(((x) >> 8) & 0xFF); \ + (y)[3] = (uint8_t)(((x) >> 0) & 0xFF); \ + } +#define LOAD32H(x, y) \ + { \ + (x) = ((uint32_t)((y)[0] & 0xFF) << 24) | \ + ((uint32_t)((y)[1] & 0xFF) << 16) | \ + ((uint32_t)((y)[2] & 0xFF) << 8) | ((uint32_t)((y)[3] & 0xFF) << 0); \ + } + +#define LOAD64H(x, y) \ + { \ + (x) = ((uint64_t)((y)[0] & 0xFF) << 56) | \ + ((uint64_t)((y)[1] & 0xFF) << 48) | \ + ((uint64_t)((y)[2] & 0xFF) << 40) | \ + ((uint64_t)((y)[3] & 0xFF) << 32) | \ + ((uint64_t)((y)[4] & 0xFF) << 24) | \ + ((uint64_t)((y)[5] & 0xFF) << 16) | \ + ((uint64_t)((y)[6] & 0xFF) << 8) | ((uint64_t)((y)[7] & 0xFF) << 0); \ + } + +#define STORE64H(y, x) \ + { \ + (y)[0] = (uint8_t)(((x) >> 56) & 0xFF); \ + (y)[1] = (uint8_t)(((x) >> 48) & 0xFF); \ + (y)[2] = (uint8_t)(((x) >> 40) & 0xFF); \ + (y)[3] = (uint8_t)(((x) >> 32) & 0xFF); \ + (y)[4] = (uint8_t)(((x) >> 24) & 0xFF); \ + (y)[5] = (uint8_t)(((x) >> 16) & 0xFF); \ + (y)[6] = (uint8_t)(((x) >> 8) & 0xFF); \ + (y)[7] = (uint8_t)(((x) >> 0) & 0xFF); \ + } + +#endif /* ENDIAN_LITTLE */ + +#ifdef ENDIAN_BIG + +#define STORE32H(y, x) \ + { \ + (y)[3] = (uint8_t)(((x) >> 24) & 0xFF); \ + (y)[2] = (uint8_t)(((x) >> 16) & 0xFF); \ + (y)[1] = (uint8_t)(((x) >> 8) & 0xFF); \ + (y)[0] = (uint8_t)(((x) >> 0) & 0xFF); \ + } +#define STORE64H(y, x) \ + { \ + (y)[7] = (uint8_t)(((x) >> 56) & 0xFF); \ + (y)[6] = (uint8_t)(((x) >> 48) & 0xFF); \ + (y)[5] = (uint8_t)(((x) >> 40) & 0xFF); \ + (y)[4] = (uint8_t)(((x) >> 32) & 0xFF); \ + (y)[3] = (uint8_t)(((x) >> 24) & 0xFF); \ + (y)[2] = (uint8_t)(((x) >> 16) & 0xFF); \ + (y)[1] = (uint8_t)(((x) >> 8) & 0xFF); \ + (y)[0] = (uint8_t)(((x) >> 0) & 0xFF); \ + } +#define LOAD32H(x, y) \ + { \ + (x) = ((uint32_t)((y)[3] & 0xFF) << 24) | \ + ((uint32_t)((y)[2] & 0xFF) << 16) | \ + ((uint32_t)((y)[1] & 0xFF) << 8) | ((uint32_t)((y)[0] & 0xFF) << 0); \ + } + +#define LOAD64H(x, y) \ + { \ + (x) = ((uint64_t)((y)[7] & 0xFF) << 56) | \ + ((uint64_t)((y)[6] & 0xFF) << 48) | \ + ((uint64_t)((y)[5] & 0xFF) << 40) | \ + ((uint64_t)((y)[4] & 0xFF) << 32) | \ + ((uint64_t)((y)[3] & 0xFF) << 24) | \ + ((uint64_t)((y)[2] & 0xFF) << 16) | \ + ((uint64_t)((y)[1] & 0xFF) << 8) | ((uint64_t)((y)[0] & 0xFF) << 0); \ + } + +#endif /* ENDIAN_BIG */ + +#define AES_TE0(x) AES_PRECOMP_TE0[(x)] +#define AES_TE1(x) AES_PRECOMP_TE1[(x)] +#define AES_TE2(x) AES_PRECOMP_TE2[(x)] +#define AES_TE3(x) AES_PRECOMP_TE3[(x)] + +#define AES_TE4_0(x) AES_PRECOMP_TE4_0[(x)] +#define AES_TE4_1(x) AES_PRECOMP_TE4_1[(x)] +#define AES_TE4_2(x) AES_PRECOMP_TE4_2[(x)] +#define AES_TE4_3(x) AES_PRECOMP_TE4_3[(x)] + +#define CryptoUtils_POOL_SIZE (0x1 << 17) // 2^17 + +#define DUMP(x, l, s) \ + fprintf(stderr, "%s :", (s)); \ + for (int ii = 0; ii < (l); ii++) { \ + fprintf(stderr, "%02hhX", *((x) + ii)); \ + } \ + fprintf(stderr, "\n"); + +// SHA256 +/* Various logical functions */ +#define Ch(x, y, z) (z ^ (x & (y ^ z))) +#define Maj(x, y, z) (((x | y) & z) | (x & y)) +#define CRYPTOUTILS_S(x, n) RORc((x), (n)) +#define R1(x, n) (((x)&0xFFFFFFFFUL) >> (n)) +#define Sigma0(x) \ + (CRYPTOUTILS_S(x, 2) ^ CRYPTOUTILS_S(x, 13) ^ CRYPTOUTILS_S(x, 22)) +#define Sigma1(x) \ + (CRYPTOUTILS_S(x, 6) ^ CRYPTOUTILS_S(x, 11) ^ CRYPTOUTILS_S(x, 25)) +#define Gamma0(x) (CRYPTOUTILS_S(x, 7) ^ CRYPTOUTILS_S(x, 18) ^ R1(x, 3)) +#define Gamma1(x) (CRYPTOUTILS_S(x, 17) ^ CRYPTOUTILS_S(x, 19) ^ R1(x, 10)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +#define RND(a, b, c, d, e, f, g, h, i, ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + +#define RORc(x, y) \ + (((((unsigned long)(x)&0xFFFFFFFFUL) >> (unsigned long)((y)&31)) | \ + ((unsigned long)(x) << (unsigned long)(32 - ((y)&31)))) & \ + 0xFFFFFFFFUL) + +class CryptoUtils { +public: + CryptoUtils(); + ~CryptoUtils(); + + char *get_seed(); + void get_bytes(char *buffer, const int len); + char get_char(); + bool prng_seed(const std::string seed); + + // Returns a uniformly distributed 8-bit value + uint8_t get_uint8_t(); + // Returns a uniformly distributed 32-bit value + uint32_t get_uint32_t(); + // Returns an integer uniformly distributed on [0, max[ + uint32_t get_range(const uint32_t max); + // Returns a uniformly distributed 64-bit value + uint64_t get_uint64_t(); + + // Scramble a 32-bit value depending on a 128-bit value + unsigned scramble32(const unsigned in, const char key[16]); + + int sha256(const char *msg, unsigned char *hash); + +private: + uint32_t ks[44]; + char key[16]; + char ctr[16]; + char pool[CryptoUtils_POOL_SIZE]; + uint32_t idx; + std::string seed; + bool seeded; + + typedef struct { + uint64_t length; + uint32_t state[8], curlen; + unsigned char buf[64]; + } sha256_state; + + void aes_compute_ks(uint32_t *ks, const char *k); + void aes_encrypt(char *out, const char *in, const uint32_t *ks); + bool prng_seed(); + void inc_ctr(); + void populate_pool(); + int sha256_done(sha256_state *md, unsigned char *out); + int sha256_init(sha256_state *md); + static int sha256_compress(sha256_state *md, unsigned char *buf); + int sha256_process(sha256_state *md, const unsigned char *in, + unsigned long inlen); +}; +} // namespace llvm + +#endif // LLVM_CryptoUtils_H diff --git a/AntiHackOSS/include/DynamicBranch.h b/AntiHackOSS/include/DynamicBranch.h new file mode 100644 index 000000000000..d5d6c5c769ca --- /dev/null +++ b/AntiHackOSS/include/DynamicBranch.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DYNAMICBRANCH_INCLUDES_ +#define _DYNAMICBRANCH_INCLUDES_ + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/JSON.h" + +using namespace std; + +namespace llvm { + void initializeDynamicBranchPass(PassRegistry &Registry); + Pass *createDynamicBranch(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir); +} + +#endif diff --git a/AntiHackOSS/include/Flattening.h b/AntiHackOSS/include/Flattening.h new file mode 100644 index 000000000000..e3a1dee06d09 --- /dev/null +++ b/AntiHackOSS/include/Flattening.h @@ -0,0 +1,34 @@ +//===- FlatteningIncludes.h - Flattening Obfuscation pass------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains includes and defines for the flattening pass +// +//===----------------------------------------------------------------------===// + +#ifndef _FLATTENING_INCLUDES_ +#define _FLATTENING_INCLUDES_ + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/JSON.h" + +using namespace std; + +namespace llvm { + void initializeFlatteningPass(PassRegistry &Registry); + Pass *createFlattening(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir); +} + +#endif diff --git a/AntiHackOSS/include/Obfuscation.h b/AntiHackOSS/include/Obfuscation.h new file mode 100644 index 000000000000..b705f70ebf6a --- /dev/null +++ b/AntiHackOSS/include/Obfuscation.h @@ -0,0 +1,35 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OBFUSCATION_INCLUDES_ +#define _OBFUSCATION_INCLUDES_ + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/JSON.h" + +using namespace std; + +namespace llvm { + void initializeObfuscationPass(PassRegistry &Registry); + Pass *createObfuscation(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir); +} + +#endif diff --git a/AntiHackOSS/include/SplitBasicBlock.h b/AntiHackOSS/include/SplitBasicBlock.h new file mode 100644 index 000000000000..cd4b9bfb4219 --- /dev/null +++ b/AntiHackOSS/include/SplitBasicBlock.h @@ -0,0 +1,33 @@ +//===- SplitBasicBlock.h - Split basicblock pass --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains includes and defines for the split basicblock pass +// +//===----------------------------------------------------------------------===// + +#ifndef _SPLITBASICBLOCK_INCLUDES_ +#define _SPLITBASICBLOCK_INCLUDES_ + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/JSON.h" + +using namespace std; + +namespace llvm { + void initializeSplitBasicBlockPass(PassRegistry &Registry); + Pass *createSplitBasicBlock(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir); +} + +#endif diff --git a/AntiHackOSS/include/Utils.h b/AntiHackOSS/include/Utils.h new file mode 100644 index 000000000000..1d5a268d42a3 --- /dev/null +++ b/AntiHackOSS/include/Utils.h @@ -0,0 +1,26 @@ +//===- Utils.h ------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef __UTILS_OBF__ +#define __UTILS_OBF__ + +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Transforms/Utils/Local.h" // For DemoteRegToStack and DemotePHIToStack +#include + +using namespace llvm; + +void fixStack(Function *f); +std::string readAnnotate(Function *f); +bool toObfuscate(bool flag, Function *f, std::string attribute); +bool isCompilingForAndroid(const llvm::Module &m); +bool isCompilingForIOS(const llvm::Module &m); + +#endif diff --git a/AntiHackOSS/src/AntiHack.cpp b/AntiHackOSS/src/AntiHack.cpp new file mode 100644 index 000000000000..5ba8c5564fd9 --- /dev/null +++ b/AntiHackOSS/src/AntiHack.cpp @@ -0,0 +1,179 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "llvm/InitializePasses.h" +#include "llvm-c/Initialization.h" +#include "llvm/PassRegistry.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Transforms/AntiHack/AntiHack.h" +#include "llvm/Transforms/AntiHack/Obfuscation.h" +#include + +using namespace llvm; + +namespace { + struct AntiHack: ModulePass { + static char ID; // Pass identification, replacement for typeid + + std::vector functionPasses; + std::vector modulePasses; + + llvm::json::Value configJson; + llvm::raw_fd_ostream *logFile; + std::string homeDir; + + bool doAntiHack; + + AntiHack(): ModulePass(ID), configJson(0) {}; + AntiHack(std::string configPath); + ~AntiHack(); + + virtual bool doInitialization(Module &m); + bool runOnModule(Module &M); + }; + + bool AntiHack::doInitialization(Module &m) + { + if (!doAntiHack) { + return false; + } + + ModulePass *mp = static_cast(createObfuscation(&configJson, logFile, homeDir)); + mp->doInitialization(m); + modulePasses.push_back(mp); + + return true; + } + + bool AntiHack::runOnModule(Module& m) + { + bool modified = false; + + if (doAntiHack) { + + for (ModulePass *p : modulePasses) { + modified |= p->runOnModule(m); + } + + for (FunctionPass *p : functionPasses) { + for (Module::iterator iter = m.begin(); iter != m.end(); iter++) { + Function &F = *iter; + if (!F.isDeclaration()) { + modified |= p->runOnFunction(F); + } + } + } + } + return modified; + } + + AntiHack::AntiHack(std::string configPath) + : ModulePass(ID), configJson(0) + { + doAntiHack = true; + char* home_dir = getenv("DECLANG_HOME"); + if (home_dir == nullptr) { + home_dir = getenv("HOME"); + } + if (home_dir == nullptr) { + home_dir = getenv("USERPROFILE"); + } + if (home_dir == nullptr) { + llvm::errs() << "[Frontend]: (Warning) Cannot find $DECLANG_HOME, $HOME or %USERPROFILE%\n"; + llvm::errs().flush(); + std::exit(EXIT_FAILURE); + } + homeDir.assign(home_dir); + homeDir = llvm::sys::path::convert_to_slash(homeDir); + + llvm::sys::fs::create_directory(homeDir+"/.DeClang/"); + + if (configPath == "") { + configPath = homeDir + "/.DeClang/config.json"; + } + std::string logPath = homeDir + "/.DeClang/log.txt"; + std::error_code EC; + logFile = new llvm::raw_fd_ostream(logPath, EC, sys::fs::F_Append); + if (EC) { + errs() << "[Frontend]: Open logFile Failed. Check DECLANG_HOME maybe?: " << EC.message() << "\n"; + } + + ifstream configFile(configPath); + if (!configFile) { + doAntiHack = false; + (*logFile) << "[Frontend]: (Warning) Config file "<< configPath << " not found! Pass won't work'\n"; + logFile->flush(); + return; + } + + std::string content( + (std::istreambuf_iterator(configFile) ), + (std::istreambuf_iterator() ) ); + + // if content length is zero (which means no config file in ~/.DeClang/) + // abort the rest handling + if (content.length() == 0) { + doAntiHack = false; + (*logFile) << "[Frontend]: (Warning) Config "<< configPath << "'s JSON content length is 0, Pass won't work'!\n"; + logFile->flush(); + return; + } + + llvm::Expected expectedConfig = llvm::json::parse(content.c_str()); + //configJson = llvm::json::parse(content.c_str()); + if (llvm::Error EC = expectedConfig.takeError()) { + doAntiHack = false; + (*logFile) << "[Frontend]: (Error) (AntiHack.cpp) Config Error: llvm::json::parse error \n"; + logFile->flush(); + return; + } + configJson = expectedConfig.get(); + if (!configJson.getAsObject()) { + doAntiHack = false; + (*logFile) << "[Frontend]: (Error) (AntiHack.cpp) Config Error: JSON is broken\n"; + logFile->flush(); + return; + } + + } + + AntiHack::~AntiHack() + { + for (Pass* p : modulePasses) { + delete p; + } + for (Pass* p : functionPasses) { + delete p; + } + + logFile->close(); + delete logFile; + } + +} + +char AntiHack::ID = 0; +INITIALIZE_PASS(AntiHack, "AntiHack", "AntiHack Pass", false, false) + +Pass* llvm::createAntiHack(std::string configPath) { + return new AntiHack(configPath); +} diff --git a/AntiHackOSS/src/CMakeLists.txt b/AntiHackOSS/src/CMakeLists.txt new file mode 100644 index 000000000000..41f0cc618519 --- /dev/null +++ b/AntiHackOSS/src/CMakeLists.txt @@ -0,0 +1,9 @@ +add_llvm_library( LLVMAntiHack + AntiHack.cpp + Obfuscation.cpp + Flattening.cpp + DynamicBranch.cpp + SplitBasicBlock.cpp + CryptoUtils.cpp + Utils.cpp +) \ No newline at end of file diff --git a/AntiHackOSS/src/CryptoUtils.cpp b/AntiHackOSS/src/CryptoUtils.cpp new file mode 100644 index 000000000000..b0bc5019ab10 --- /dev/null +++ b/AntiHackOSS/src/CryptoUtils.cpp @@ -0,0 +1,1089 @@ +//===- CryptoUtils.cpp - AES-based Pseudo-Random Generator +//------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an AES-CTR-based cryptographically secure +// pseudo-random generator. +// +// Created on: June 22, 2012 +// Last modification: November 15, 2013 +// Author(s): jrinaldini, pjunod +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Transforms/AntiHack/CryptoUtils.h" + +#include +#include +#include +#include +#include +#include + +// Stats +#define DEBUG_TYPE "CryptoUtils" +STATISTIC(statsGetBytes, "a. Number of calls to get_bytes ()"); +STATISTIC(statsGetChar, "b. Number of calls to get_char ()"); +STATISTIC(statsGetUint8, "c. Number of calls to get_uint8_t ()"); +STATISTIC(statsGetUint32, "d. Number of calls to get_uint32_t ()"); +STATISTIC(statsGetUint64, "e. Number of calls to get_uint64_t ()"); +STATISTIC(statsGetRange, "f. Number of calls to get_range ()"); +STATISTIC(statsPopulate, "g. Number of calls to populate ()"); +STATISTIC(statsAESEncrypt, "h. Number of calls to aes_encrypt ()"); + +using namespace llvm; + +namespace llvm { +ManagedStatic cryptoutils; +} + +const uint32_t AES_RCON[10] = { 0x01000000UL, 0x02000000UL, 0x04000000UL, + 0x08000000UL, 0x10000000UL, 0x20000000UL, + 0x40000000UL, 0x80000000UL, 0x1b000000UL, + 0x36000000UL }; + +const uint32_t AES_PRECOMP_TE0[256] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, 0xfff2f20dUL, + 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, 0x60303050UL, 0x02010103UL, + 0xce6767a9UL, 0x562b2b7dUL, 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, + 0xec76769aUL, 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, 0x41adadecUL, + 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, 0x239c9cbfUL, 0x53a4a4f7UL, + 0xe4727296UL, 0x9bc0c05bUL, 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, + 0x4c26266aUL, 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, 0xe2717193UL, + 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, 0x0804040cUL, 0x95c7c752UL, + 0x46232365UL, 0x9dc3c35eUL, 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, + 0x2f9a9ab5UL, 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, 0x1209091bUL, + 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, 0x361b1b2dUL, 0xdc6e6eb2UL, + 0xb45a5aeeUL, 0x5ba0a0fbUL, 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, + 0x7db3b3ceUL, 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, 0x40202060UL, + 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, 0xd46a6abeUL, 0x8dcbcb46UL, + 0x67bebed9UL, 0x7239394bUL, 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, + 0x85cfcf4aUL, 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, 0x8a4545cfUL, + 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, 0xa05050f0UL, 0x783c3c44UL, + 0x259f9fbaUL, 0x4ba8a8e3UL, 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, + 0x058f8f8aUL, 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, 0x20101030UL, + 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, 0x81cdcd4cUL, 0x180c0c14UL, + 0x26131335UL, 0xc3ecec2fUL, 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, + 0x2e171739UL, 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, 0xc06060a0UL, + 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, 0x44222266UL, 0x542a2a7eUL, + 0x3b9090abUL, 0x0b888883UL, 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, + 0x2814143cUL, 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, 0x924949dbUL, + 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, 0x9fc2c25dUL, 0xbdd3d36eUL, + 0x43acacefUL, 0xc46262a6UL, 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, + 0xf279798bUL, 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, 0xd86c6cb4UL, + 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, 0xca6565afUL, 0xf47a7a8eUL, + 0x47aeaee9UL, 0x10080818UL, 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, + 0x5c2e2e72UL, 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, 0x964b4bddUL, + 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, 0xe0707090UL, 0x7c3e3e42UL, + 0x71b5b5c4UL, 0xcc6666aaUL, 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, + 0x1c0e0e12UL, 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, 0xd9e1e138UL, + 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, 0xd26969bbUL, 0xa9d9d970UL, + 0x078e8e89UL, 0x339494a7UL, 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, + 0xc9e9e920UL, 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, 0x65bfbfdaUL, + 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, 0x824141c3UL, 0x299999b0UL, + 0x5a2d2d77UL, 0x1e0f0f11UL, 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, + 0x2c16163aUL +}; + +const uint32_t AES_PRECOMP_TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, 0x0dfff2f2UL, + 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, 0x50603030UL, 0x03020101UL, + 0xa9ce6767UL, 0x7d562b2bUL, 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, + 0x9aec7676UL, 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, 0xec41adadUL, + 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, 0xbf239c9cUL, 0xf753a4a4UL, + 0x96e47272UL, 0x5b9bc0c0UL, 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, + 0x6a4c2626UL, 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, 0x93e27171UL, + 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, 0x0c080404UL, 0x5295c7c7UL, + 0x65462323UL, 0x5e9dc3c3UL, 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, + 0xb52f9a9aUL, 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, 0x1b120909UL, + 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, 0x2d361b1bUL, 0xb2dc6e6eUL, + 0xeeb45a5aUL, 0xfb5ba0a0UL, 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, + 0xce7db3b3UL, 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, 0x60402020UL, + 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, 0xbed46a6aUL, 0x468dcbcbUL, + 0xd967bebeUL, 0x4b723939UL, 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, + 0x4a85cfcfUL, 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, 0xcf8a4545UL, + 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, 0xf0a05050UL, 0x44783c3cUL, + 0xba259f9fUL, 0xe34ba8a8UL, 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, + 0x8a058f8fUL, 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, 0x30201010UL, + 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, 0x4c81cdcdUL, 0x14180c0cUL, + 0x35261313UL, 0x2fc3ececUL, 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, + 0x392e1717UL, 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, 0xa0c06060UL, + 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, 0x66442222UL, 0x7e542a2aUL, + 0xab3b9090UL, 0x830b8888UL, 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, + 0x3c281414UL, 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, 0xdb924949UL, + 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, 0x5d9fc2c2UL, 0x6ebdd3d3UL, + 0xef43acacUL, 0xa6c46262UL, 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, + 0x8bf27979UL, 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, 0xb4d86c6cUL, + 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, 0xafca6565UL, 0x8ef47a7aUL, + 0xe947aeaeUL, 0x18100808UL, 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, + 0x725c2e2eUL, 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, 0xdd964b4bUL, + 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, 0x90e07070UL, 0x427c3e3eUL, + 0xc471b5b5UL, 0xaacc6666UL, 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, + 0x121c0e0eUL, 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, 0x38d9e1e1UL, + 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, 0xbbd26969UL, 0x70a9d9d9UL, + 0x89078e8eUL, 0xa7339494UL, 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, + 0x20c9e9e9UL, 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, 0xda65bfbfUL, + 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, 0xc3824141UL, 0xb0299999UL, + 0x775a2d2dUL, 0x111e0f0fUL, 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, + 0x3a2c1616UL +}; + +const uint32_t AES_PRECOMP_TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, 0xf20dfff2UL, + 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, 0x30506030UL, 0x01030201UL, + 0x67a9ce67UL, 0x2b7d562bUL, 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, + 0x769aec76UL, 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, 0xadec41adUL, + 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, 0x9cbf239cUL, 0xa4f753a4UL, + 0x7296e472UL, 0xc05b9bc0UL, 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, + 0x266a4c26UL, 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, 0x7193e271UL, + 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, 0x040c0804UL, 0xc75295c7UL, + 0x23654623UL, 0xc35e9dc3UL, 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, + 0x9ab52f9aUL, 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, 0x091b1209UL, + 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, 0x1b2d361bUL, 0x6eb2dc6eUL, + 0x5aeeb45aUL, 0xa0fb5ba0UL, 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, + 0xb3ce7db3UL, 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, 0x20604020UL, + 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, 0x6abed46aUL, 0xcb468dcbUL, + 0xbed967beUL, 0x394b7239UL, 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, + 0xcf4a85cfUL, 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, 0x45cf8a45UL, + 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, 0x50f0a050UL, 0x3c44783cUL, + 0x9fba259fUL, 0xa8e34ba8UL, 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, + 0x8f8a058fUL, 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, 0x10302010UL, + 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, 0xcd4c81cdUL, 0x0c14180cUL, + 0x13352613UL, 0xec2fc3ecUL, 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, + 0x17392e17UL, 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, 0x60a0c060UL, + 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, 0x22664422UL, 0x2a7e542aUL, + 0x90ab3b90UL, 0x88830b88UL, 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, + 0x143c2814UL, 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, 0x49db9249UL, + 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, 0xc25d9fc2UL, 0xd36ebdd3UL, + 0xacef43acUL, 0x62a6c462UL, 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, + 0x798bf279UL, 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, 0x6cb4d86cUL, + 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, 0x65afca65UL, 0x7a8ef47aUL, + 0xaee947aeUL, 0x08181008UL, 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, + 0x2e725c2eUL, 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, 0x4bdd964bUL, + 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, 0x7090e070UL, 0x3e427c3eUL, + 0xb5c471b5UL, 0x66aacc66UL, 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, + 0x0e121c0eUL, 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, 0xe138d9e1UL, + 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, 0x69bbd269UL, 0xd970a9d9UL, + 0x8e89078eUL, 0x94a73394UL, 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, + 0xe920c9e9UL, 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, 0xbfda65bfUL, + 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, 0x41c38241UL, 0x99b02999UL, + 0x2d775a2dUL, 0x0f111e0fUL, 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, + 0x163a2c16UL +}; + +const uint32_t AES_PRECOMP_TE3[256] = { + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, 0xf2f20dffUL, + 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, 0x30305060UL, 0x01010302UL, + 0x6767a9ceUL, 0x2b2b7d56UL, 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, + 0x76769aecUL, 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, 0xadadec41UL, + 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, 0x9c9cbf23UL, 0xa4a4f753UL, + 0x727296e4UL, 0xc0c05b9bUL, 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, + 0x26266a4cUL, 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, 0x717193e2UL, + 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, 0x04040c08UL, 0xc7c75295UL, + 0x23236546UL, 0xc3c35e9dUL, 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, + 0x9a9ab52fUL, 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, 0x09091b12UL, + 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, 0x1b1b2d36UL, 0x6e6eb2dcUL, + 0x5a5aeeb4UL, 0xa0a0fb5bUL, 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, + 0xb3b3ce7dUL, 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, 0x20206040UL, + 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, 0x6a6abed4UL, 0xcbcb468dUL, + 0xbebed967UL, 0x39394b72UL, 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, + 0xcfcf4a85UL, 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, 0x4545cf8aUL, + 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, 0x5050f0a0UL, 0x3c3c4478UL, + 0x9f9fba25UL, 0xa8a8e34bUL, 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, + 0x8f8f8a05UL, 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, 0x10103020UL, + 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, 0xcdcd4c81UL, 0x0c0c1418UL, + 0x13133526UL, 0xecec2fc3UL, 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, + 0x1717392eUL, 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, 0x6060a0c0UL, + 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, 0x22226644UL, 0x2a2a7e54UL, + 0x9090ab3bUL, 0x8888830bUL, 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, + 0x14143c28UL, 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, 0x4949db92UL, + 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, 0xc2c25d9fUL, 0xd3d36ebdUL, + 0xacacef43UL, 0x6262a6c4UL, 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, + 0x79798bf2UL, 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, 0x6c6cb4d8UL, + 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, 0x6565afcaUL, 0x7a7a8ef4UL, + 0xaeaee947UL, 0x08081810UL, 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, + 0x2e2e725cUL, 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, 0x4b4bdd96UL, + 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, 0x707090e0UL, 0x3e3e427cUL, + 0xb5b5c471UL, 0x6666aaccUL, 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, + 0x0e0e121cUL, 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, 0xe1e138d9UL, + 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, 0x6969bbd2UL, 0xd9d970a9UL, + 0x8e8e8907UL, 0x9494a733UL, 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, + 0xe9e920c9UL, 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, 0xbfbfda65UL, + 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, 0x4141c382UL, 0x9999b029UL, + 0x2d2d775aUL, 0x0f0f111eUL, 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, + 0x16163a2cUL +}; + +const uint32_t AES_PRECOMP_TE4_0[256] = { + 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, + 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 0x00000030UL, 0x00000001UL, + 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, + 0x00000076UL, 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, + 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 0x000000adUL, + 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, + 0x00000072UL, 0x000000c0UL, 0x000000b7UL, 0x000000fdUL, 0x00000093UL, + 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, + 0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, + 0x000000d8UL, 0x00000031UL, 0x00000015UL, 0x00000004UL, 0x000000c7UL, + 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, + 0x0000009aUL, 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, + 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 0x00000009UL, + 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, + 0x0000005aUL, 0x000000a0UL, 0x00000052UL, 0x0000003bUL, 0x000000d6UL, + 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, + 0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, + 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 0x0000006aUL, 0x000000cbUL, + 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, + 0x000000cfUL, 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, + 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 0x00000045UL, + 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, + 0x0000009fUL, 0x000000a8UL, 0x00000051UL, 0x000000a3UL, 0x00000040UL, + 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, + 0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, + 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 0x000000cdUL, 0x0000000cUL, + 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, + 0x00000017UL, 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, + 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 0x00000060UL, + 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, + 0x00000090UL, 0x00000088UL, 0x00000046UL, 0x000000eeUL, 0x000000b8UL, + 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, + 0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, + 0x00000006UL, 0x00000024UL, 0x0000005cUL, 0x000000c2UL, 0x000000d3UL, + 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, + 0x00000079UL, 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, + 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 0x0000006cUL, + 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, + 0x000000aeUL, 0x00000008UL, 0x000000baUL, 0x00000078UL, 0x00000025UL, + 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, + 0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, + 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 0x00000070UL, 0x0000003eUL, + 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, + 0x0000000eUL, 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, + 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 0x000000e1UL, + 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, + 0x0000008eUL, 0x00000094UL, 0x0000009bUL, 0x0000001eUL, 0x00000087UL, + 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, + 0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, + 0x000000e6UL, 0x00000042UL, 0x00000068UL, 0x00000041UL, 0x00000099UL, + 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, + 0x00000016UL +}; + +const uint32_t AES_PRECOMP_TE4_1[256] = { + 0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, + 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 0x00003000UL, 0x00000100UL, + 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, + 0x00007600UL, 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, + 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 0x0000ad00UL, + 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, + 0x00007200UL, 0x0000c000UL, 0x0000b700UL, 0x0000fd00UL, 0x00009300UL, + 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, + 0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, + 0x0000d800UL, 0x00003100UL, 0x00001500UL, 0x00000400UL, 0x0000c700UL, + 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, + 0x00009a00UL, 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, + 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 0x00000900UL, + 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, + 0x00005a00UL, 0x0000a000UL, 0x00005200UL, 0x00003b00UL, 0x0000d600UL, + 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, + 0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, + 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 0x00006a00UL, 0x0000cb00UL, + 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, + 0x0000cf00UL, 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, + 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 0x00004500UL, + 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, + 0x00009f00UL, 0x0000a800UL, 0x00005100UL, 0x0000a300UL, 0x00004000UL, + 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, + 0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, + 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 0x0000cd00UL, 0x00000c00UL, + 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, + 0x00001700UL, 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, + 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 0x00006000UL, + 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, + 0x00009000UL, 0x00008800UL, 0x00004600UL, 0x0000ee00UL, 0x0000b800UL, + 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, + 0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, + 0x00000600UL, 0x00002400UL, 0x00005c00UL, 0x0000c200UL, 0x0000d300UL, + 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, + 0x00007900UL, 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, + 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 0x00006c00UL, + 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, + 0x0000ae00UL, 0x00000800UL, 0x0000ba00UL, 0x00007800UL, 0x00002500UL, + 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, + 0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, + 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 0x00007000UL, 0x00003e00UL, + 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, + 0x00000e00UL, 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, + 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 0x0000e100UL, + 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, + 0x00008e00UL, 0x00009400UL, 0x00009b00UL, 0x00001e00UL, 0x00008700UL, + 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, + 0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, + 0x0000e600UL, 0x00004200UL, 0x00006800UL, 0x00004100UL, 0x00009900UL, + 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, + 0x00001600UL +}; + +const uint32_t AES_PRECOMP_TE4_2[256] = { + 0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, + 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 0x00300000UL, 0x00010000UL, + 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, + 0x00760000UL, 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, + 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 0x00ad0000UL, + 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, + 0x00720000UL, 0x00c00000UL, 0x00b70000UL, 0x00fd0000UL, 0x00930000UL, + 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, + 0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, + 0x00d80000UL, 0x00310000UL, 0x00150000UL, 0x00040000UL, 0x00c70000UL, + 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, + 0x009a0000UL, 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, + 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 0x00090000UL, + 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, + 0x005a0000UL, 0x00a00000UL, 0x00520000UL, 0x003b0000UL, 0x00d60000UL, + 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, + 0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, + 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 0x006a0000UL, 0x00cb0000UL, + 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, + 0x00cf0000UL, 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, + 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 0x00450000UL, + 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, + 0x009f0000UL, 0x00a80000UL, 0x00510000UL, 0x00a30000UL, 0x00400000UL, + 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, + 0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, + 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 0x00cd0000UL, 0x000c0000UL, + 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, + 0x00170000UL, 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, + 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 0x00600000UL, + 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, + 0x00900000UL, 0x00880000UL, 0x00460000UL, 0x00ee0000UL, 0x00b80000UL, + 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, + 0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, + 0x00060000UL, 0x00240000UL, 0x005c0000UL, 0x00c20000UL, 0x00d30000UL, + 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, + 0x00790000UL, 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, + 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 0x006c0000UL, + 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, + 0x00ae0000UL, 0x00080000UL, 0x00ba0000UL, 0x00780000UL, 0x00250000UL, + 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, + 0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, + 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 0x00700000UL, 0x003e0000UL, + 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, + 0x000e0000UL, 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, + 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 0x00e10000UL, + 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, + 0x008e0000UL, 0x00940000UL, 0x009b0000UL, 0x001e0000UL, 0x00870000UL, + 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, + 0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, + 0x00e60000UL, 0x00420000UL, 0x00680000UL, 0x00410000UL, 0x00990000UL, + 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, + 0x00160000UL +}; + +const uint32_t AES_PRECOMP_TE4_3[256] = { + 0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, + 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 0x30000000UL, 0x01000000UL, + 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, + 0x76000000UL, 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, + 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 0xad000000UL, + 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, + 0x72000000UL, 0xc0000000UL, 0xb7000000UL, 0xfd000000UL, 0x93000000UL, + 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, + 0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, + 0xd8000000UL, 0x31000000UL, 0x15000000UL, 0x04000000UL, 0xc7000000UL, + 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, + 0x9a000000UL, 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, + 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 0x09000000UL, + 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, + 0x5a000000UL, 0xa0000000UL, 0x52000000UL, 0x3b000000UL, 0xd6000000UL, + 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, + 0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, + 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 0x6a000000UL, 0xcb000000UL, + 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, + 0xcf000000UL, 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, + 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 0x45000000UL, + 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, + 0x9f000000UL, 0xa8000000UL, 0x51000000UL, 0xa3000000UL, 0x40000000UL, + 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, + 0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, + 0xff000000UL, 0xf3000000UL, 0xd2000000UL, 0xcd000000UL, 0x0c000000UL, + 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, + 0x17000000UL, 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, + 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 0x60000000UL, + 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, + 0x90000000UL, 0x88000000UL, 0x46000000UL, 0xee000000UL, 0xb8000000UL, + 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, + 0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, + 0x06000000UL, 0x24000000UL, 0x5c000000UL, 0xc2000000UL, 0xd3000000UL, + 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, + 0x79000000UL, 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, + 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 0x6c000000UL, + 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, + 0xae000000UL, 0x08000000UL, 0xba000000UL, 0x78000000UL, 0x25000000UL, + 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, + 0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, + 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 0x70000000UL, 0x3e000000UL, + 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, + 0x0e000000UL, 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, + 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 0xe1000000UL, + 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, + 0x8e000000UL, 0x94000000UL, 0x9b000000UL, 0x1e000000UL, 0x87000000UL, + 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, + 0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, + 0xe6000000UL, 0x42000000UL, 0x68000000UL, 0x41000000UL, 0x99000000UL, + 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, + 0x16000000UL +}; + +const uint32_t masks[32] = { + 0x80000000UL, 0x40000000UL, 0x20000000UL, 0x10000000UL, 0x08000000UL, + 0x04000000UL, 0x02000000UL, 0x01000000UL, 0x00800000UL, 0x00400000UL, + 0x00200000UL, 0x00100000UL, 0x00080000UL, 0x00040000UL, 0x00020000UL, + 0x00010000UL, 0x00008000UL, 0x00004000UL, 0x00002000UL, 0x00001000UL, + 0x00000800UL, 0x00000400UL, 0x00000200UL, 0x00000100UL, 0x00000080UL, + 0x00000040UL, 0x00000020UL, 0x00000010UL, 0x00000008UL, 0x00000004UL, + 0x00000002UL, 0x00000001UL +}; + +CryptoUtils::CryptoUtils() { seeded = false; } + +unsigned CryptoUtils::scramble32(const unsigned in, const char key[16]) { + assert(key != NULL && "CryptoUtils::scramble key=NULL"); + + unsigned tmpA, tmpB; + + // AES中で行うRoundを4回だけやって疑似乱数ということにしている + // TODO: OSSのものと全く同じなので、今後変える + // https://github.com/obfuscator-llvm/obfuscator/blob/llvm-4.0/lib/Transforms/Obfuscation/CryptoUtils.cpp#L515 + + // Round 1 + tmpA = 0x0; + tmpA ^= AES_PRECOMP_TE0[((in >> 24) ^ key[0]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE1[((in >> 16) ^ key[1]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE2[((in >> 8) ^ key[2]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE3[((in >> 0) ^ key[3]) & 0xFF]; + + // Round 2 + tmpB = 0x0; + tmpB ^= AES_PRECOMP_TE0[((tmpA >> 24) ^ key[4]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE1[((tmpA >> 16) ^ key[5]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE2[((tmpA >> 8) ^ key[6]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE3[((tmpA >> 0) ^ key[7]) & 0xFF]; + + // Round 3 + tmpA = 0x0; + tmpA ^= AES_PRECOMP_TE0[((tmpB >> 24) ^ key[8]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE1[((tmpB >> 16) ^ key[9]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE2[((tmpB >> 8) ^ key[10]) & 0xFF]; + tmpA ^= AES_PRECOMP_TE3[((tmpB >> 0) ^ key[11]) & 0xFF]; + + // Round 4 + tmpB = 0x0; + tmpB ^= AES_PRECOMP_TE0[((tmpA >> 24) ^ key[12]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE1[((tmpA >> 16) ^ key[13]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE2[((tmpA >> 8) ^ key[14]) & 0xFF]; + tmpB ^= AES_PRECOMP_TE3[((tmpA >> 0) ^ key[15]) & 0xFF]; + + LOAD32H(tmpA, key); + + return tmpA ^ tmpB; +} + +bool CryptoUtils::prng_seed(const std::string _seed) { + unsigned char s[16]; + unsigned int i = 0; + + /* We accept a prefix "0x" */ + if (!(_seed.size() == 32 || _seed.size() == 34)) { + errs()<<"The AES-CTR PRNG seeding mechanism is expecting a 16-byte value " + "expressed in hexadecimal, like DEAD....BEEF\n"; + return false; + } + + seed = _seed; + + if (_seed.size() == 34) { + // Assuming that the two first characters are "0x" + i = 2; + } + + + for (unsigned int j=0; i < _seed.size(); i += 2, j++) { + std::string byte = _seed.substr(i, 2); + s[j] = (unsigned char)(int)strtol(byte.c_str(), NULL, 16); + } + + // _seed is defined to be the + // key initial value + memcpy(key, s, 16); + DEBUG_WITH_TYPE("cryptoutils", dbgs() << "CPNRG seeded with " << _seed << "\n"); + + // ctr is initialized to all-zeroes + memset(ctr, 0, 16); + + // Once the seed is there, we compute the + // AES128 key-schedule + aes_compute_ks(ks, key); + + seeded = true; + + // We are now ready to fill the pool with + // cryptographically secure pseudo-random + // values. + populate_pool(); + return true; +} + +CryptoUtils::~CryptoUtils() { + // Some wiping work here + memset(key, 0, 16); + memset(ks, 0, 44 * sizeof(uint32_t)); + memset(ctr, 0, 16); + memset(pool, 0, CryptoUtils_POOL_SIZE); + + idx = 0; +} + +void CryptoUtils::populate_pool() { + + statsPopulate++; + + for (int i = 0; i < CryptoUtils_POOL_SIZE; i += 16) { + + // ctr += 1 + inc_ctr(); + + // We then encrypt the counter + aes_encrypt(pool + i, ctr, ks); + } + + // Reinitializing the index of the first + // available pseudo-random byte + idx = 0; +} + +bool CryptoUtils::prng_seed() { + +#if defined(__linux__) + std::ifstream devrandom("/dev/urandom"); +#else + std::ifstream devrandom("/dev/random"); +#endif + + if (devrandom) { + + devrandom.read(key, 16); + + if (devrandom.gcount() != 16) { + errs()<<"Cannot read enough bytes in /dev/random\n"; + return false; + } + + devrandom.close(); + DEBUG_WITH_TYPE("cryptoutils", dbgs() << "cryptoutils seeded with /dev/random\n"); + + memset(ctr, 0, 16); + + // Once the seed is there, we compute the + // AES128 key-schedule + aes_compute_ks(ks, key); + + seeded = true; + } else { + errs()<<"Cannot open /dev/random\n"; + return false; + } + return true; +} + +void CryptoUtils::inc_ctr() { + uint64_t iseed; + + LOAD64H(iseed, ctr + 8); + ++iseed; + STORE64H(ctr + 8, iseed); +} + +char *CryptoUtils::get_seed() { + + if (seeded) { + return key; + } else { + return NULL; + } +} + +void CryptoUtils::get_bytes(char *buffer, const int len) { + + int sofar = 0, available = 0; + + assert(buffer != NULL && "CryptoUtils::get_bytes buffer=NULL"); + assert(len > 0 && "CryptoUtils::get_bytes len <= 0"); + + statsGetBytes++; + + if (len > 0) { + + // If the PRNG is not seeded, it the very last time to do it ! + if (!seeded) { + prng_seed(); + populate_pool(); + } + + do { + if (idx + (len - sofar) >= CryptoUtils_POOL_SIZE) { + // We don't have enough bytes ready in the pool, + // so let's use the available ones and repopulate ! + available = CryptoUtils_POOL_SIZE - idx; + memcpy(buffer + sofar, pool + idx, available); + sofar += available; + populate_pool(); + } else { + memcpy(buffer + sofar, pool + idx, len - sofar); + idx += len - sofar; + // This will trigger a loop exit + sofar = len; + } + } while (sofar < (len - 1)); + } +} + +uint8_t CryptoUtils::get_uint8_t() { + char ret; + + statsGetUint8++; + + get_bytes(&ret, 1); + + return (uint8_t)ret; +} + +char CryptoUtils::get_char() { + char ret; + + statsGetChar++; + + get_bytes(&ret, 1); + + return ret; +} + +uint32_t CryptoUtils::get_uint32_t() { + char tmp[4]; + uint32_t ret = 0; + + statsGetUint32++; + + get_bytes(tmp, 4); + + LOAD32H(ret, tmp); + + return ret; +} + +uint64_t CryptoUtils::get_uint64_t() { + char tmp[8]; + uint64_t ret = 0; + + statsGetUint64++; + + get_bytes(tmp, 8); + + LOAD64H(ret, tmp); + + return ret; +} + +uint32_t CryptoUtils::get_range(const uint32_t max) { + uint32_t log, r, mask; + + statsGetRange++; + + if (max == 0) { + return 0; + } else { + // Computing the above power of two + log = 32; + int i = 0; + // This loop will terminate, as there is at least one + // bit set somewhere in max + while (!(max & masks[i++])) { + log -= 1; + } + mask = (0x1UL << log) - 1; + + // This should loop two times in average + do { + r = get_uint32_t() & mask; + } while (r >= max); + + return r; + } +} + +void CryptoUtils::aes_compute_ks(uint32_t *ks, const char *k) { + int i; + uint32_t *p, tmp; + + assert(ks != NULL); + assert(k != NULL); + + LOAD32H(ks[0], k); + LOAD32H(ks[1], k + 4); + LOAD32H(ks[2], k + 8); + LOAD32H(ks[3], k + 12); + + p = ks; + i = 0; + while (1) { + tmp = p[3]; + tmp = ((AES_TE4_3(BYTE(tmp, 2))) ^ (AES_TE4_2(BYTE(tmp, 1))) ^ + (AES_TE4_1(BYTE(tmp, 0))) ^ (AES_TE4_0(BYTE(tmp, 3)))); + + p[4] = p[0] ^ tmp ^ AES_RCON[i]; + p[5] = p[1] ^ p[4]; + p[6] = p[2] ^ p[5]; + p[7] = p[3] ^ p[6]; + if (++i == 10) { + break; + } + p += 4; + } +} + +void CryptoUtils::aes_encrypt(char *out, const char *in, const uint32_t *ks) { + uint32_t state0 = 0, state1 = 0, state2 = 0, state3 = 0; + uint32_t tmp0, tmp1, tmp2, tmp3; + int i; + uint32_t r; + + statsAESEncrypt++; + + r = 0; + LOAD32H(state0, in + 0); + LOAD32H(state1, in + 4); + LOAD32H(state2, in + 8); + LOAD32H(state3, in + 12); + + state0 ^= ks[r + 0]; + state1 ^= ks[r + 1]; + state2 ^= ks[r + 2]; + state3 ^= ks[r + 3]; + + i = 0; + while (1) { + r += 4; + + tmp0 = AES_TE0(BYTE(state0, 3)) ^ AES_TE1(BYTE(state1, 2)) ^ + AES_TE2(BYTE(state2, 1)) ^ AES_TE3(BYTE(state3, 0)) ^ ks[r + 0]; + + tmp1 = AES_TE0(BYTE(state1, 3)) ^ AES_TE1(BYTE(state2, 2)) ^ + AES_TE2(BYTE(state3, 1)) ^ AES_TE3(BYTE(state0, 0)) ^ ks[r + 1]; + + tmp2 = AES_TE0(BYTE(state2, 3)) ^ AES_TE1(BYTE(state3, 2)) ^ + AES_TE2(BYTE(state0, 1)) ^ AES_TE3(BYTE(state1, 0)) ^ ks[r + 2]; + + tmp3 = AES_TE0(BYTE(state3, 3)) ^ AES_TE1(BYTE(state0, 2)) ^ + AES_TE2(BYTE(state1, 1)) ^ AES_TE3(BYTE(state2, 0)) ^ ks[r + 3]; + + if (i == 8) { + break; + } + i++; + state0 = tmp0; + state1 = tmp1; + state2 = tmp2; + state3 = tmp3; + } + + r += 4; + state0 = (AES_TE4_3(BYTE(tmp0, 3))) ^ (AES_TE4_2(BYTE(tmp1, 2))) ^ + (AES_TE4_1(BYTE(tmp2, 1))) ^ (AES_TE4_0(BYTE(tmp3, 0))) ^ ks[r + 0]; + + state1 = (AES_TE4_3(BYTE(tmp1, 3))) ^ (AES_TE4_2(BYTE(tmp2, 2))) ^ + (AES_TE4_1(BYTE(tmp3, 1))) ^ (AES_TE4_0(BYTE(tmp0, 0))) ^ ks[r + 1]; + + state2 = (AES_TE4_3(BYTE(tmp2, 3))) ^ (AES_TE4_2(BYTE(tmp3, 2))) ^ + (AES_TE4_1(BYTE(tmp0, 1))) ^ (AES_TE4_0(BYTE(tmp1, 0))) ^ ks[r + 2]; + + state3 = (AES_TE4_3(BYTE(tmp3, 3))) ^ (AES_TE4_2(BYTE(tmp0, 2))) ^ + (AES_TE4_1(BYTE(tmp1, 1))) ^ (AES_TE4_0(BYTE(tmp2, 0))) ^ ks[r + 3]; + + STORE32H(out + 0, state0); + STORE32H(out + 4, state1); + STORE32H(out + 8, state2); + STORE32H(out + 12, state3); +} + +int CryptoUtils::sha256_process(sha256_state *md, const unsigned char *in, + unsigned long inlen) { + unsigned long n; + int err; + assert(md != NULL && "CryptoUtils::sha256_process md=NULL"); + assert(in != NULL && "CryptoUtils::sha256_process in=NULL"); + + if (md->curlen > sizeof(md->buf)) { + return 1; + } + while (inlen > 0) { + if (md->curlen == 0 && inlen >= 64) { + if ((err = sha256_compress(md, (unsigned char *)in)) != 0) { + return err; + } + md->length += 64 * 8; + in += 64; + inlen -= 64; + } else { + n = MIN(inlen, (64 - md->curlen)); + memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == 64) { + if ((err = sha256_compress(md, md->buf)) != 0) { + return err; + } + md->length += 8 * 64; + md->curlen = 0; + } + } + } + return 0; +} + +int CryptoUtils::sha256_compress(sha256_state *md, unsigned char *buf) { + uint32_t S[8], W[64], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4 * i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ + + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 0, 0x428a2f98); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 1, 0x71374491); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 2, 0xb5c0fbcf); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 3, 0xe9b5dba5); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 4, 0x3956c25b); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 5, 0x59f111f1); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 6, 0x923f82a4); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 7, 0xab1c5ed5); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 8, 0xd807aa98); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 9, 0x12835b01); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 10, 0x243185be); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 11, 0x550c7dc3); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 12, 0x72be5d74); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 13, 0x80deb1fe); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 14, 0x9bdc06a7); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 15, 0xc19bf174); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 16, 0xe49b69c1); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 17, 0xefbe4786); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 18, 0x0fc19dc6); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 19, 0x240ca1cc); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 20, 0x2de92c6f); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 21, 0x4a7484aa); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 22, 0x5cb0a9dc); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 23, 0x76f988da); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 24, 0x983e5152); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 25, 0xa831c66d); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 26, 0xb00327c8); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 27, 0xbf597fc7); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 28, 0xc6e00bf3); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 29, 0xd5a79147); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 30, 0x06ca6351); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 31, 0x14292967); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 32, 0x27b70a85); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 33, 0x2e1b2138); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 34, 0x4d2c6dfc); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 35, 0x53380d13); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 36, 0x650a7354); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 37, 0x766a0abb); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 38, 0x81c2c92e); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 39, 0x92722c85); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 40, 0xa2bfe8a1); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 41, 0xa81a664b); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 42, 0xc24b8b70); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 43, 0xc76c51a3); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 44, 0xd192e819); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 45, 0xd6990624); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 46, 0xf40e3585); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 47, 0x106aa070); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 48, 0x19a4c116); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 49, 0x1e376c08); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 50, 0x2748774c); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 51, 0x34b0bcb5); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 52, 0x391c0cb3); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 53, 0x4ed8aa4a); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 54, 0x5b9cca4f); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 55, 0x682e6ff3); + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 56, 0x748f82ee); + RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 57, 0x78a5636f); + RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 58, 0x84c87814); + RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 59, 0x8cc70208); + RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 60, 0x90befffa); + RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 61, 0xa4506ceb); + RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 62, 0xbef9a3f7); + RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 63, 0xc67178f2); + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int CryptoUtils::sha256_init(sha256_state *md) { + assert(md != NULL && "CryptoUtils::sha256_init md=NULL"); + + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; + return 0; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int CryptoUtils::sha256_done(sha256_state *md, unsigned char *out) { + int i; + + assert(md != NULL && "CryptoUtils::sha256_done md=NULL"); + assert(out != NULL && "CryptoUtils::sha256_done out=NULL"); + + if (md->curlen >= sizeof(md->buf)) { + return 1; + } + + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->buf + 56, md->length); + sha256_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(out + (4 * i), md->state[i]); + } + return 0; +} + +int CryptoUtils::sha256(const char *msg, unsigned char *hash) { + unsigned char tmp[32]; + sha256_state md; + + sha256_init(&md); + sha256_process(&md, (const unsigned char *)msg, + (unsigned long)strlen((const char *)msg)); + sha256_done(&md, tmp); + + memcpy(hash, tmp, 32); + return 0; +} diff --git a/AntiHackOSS/src/DynamicBranch.cpp b/AntiHackOSS/src/DynamicBranch.cpp new file mode 100644 index 000000000000..1844cd1f7566 --- /dev/null +++ b/AntiHackOSS/src/DynamicBranch.cpp @@ -0,0 +1,198 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "llvm/Transforms/AntiHack/DynamicBranch.h" +#include "llvm/Transforms/AntiHack/Obfuscation.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Transforms/Utils.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Regex.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/LineIterator.h" + +#include +#include +#include +#include +#include + + +#include "llvm/IR/GlobalValue.h" + +#define DEBUG_TYPE "dynamicbranch" + +using namespace llvm; + +namespace { + struct DynamicBranch: public FunctionPass { + static char ID; // Pass identification, replacement for typeid + bool doDynamicBranch; + int overallObf; + + std::string homeDir; + llvm::json::Value* configJson; + + llvm::raw_fd_ostream *logFile; + + DynamicBranch() : FunctionPass(ID), configJson(0) {} + DynamicBranch(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile); + ~DynamicBranch(); + + bool runOnFunction(Function &F); + + + virtual StringRef getPassName() const { + return "DynamicBranch Pass"; + } + + }; +} + +char DynamicBranch::ID = 0; +INITIALIZE_PASS(DynamicBranch, "DynamicBranch", "obfuscate branch instruction", false, false) + +Pass *llvm::createDynamicBranch(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir) { + return new DynamicBranch(configJson, logFile); +} + +DynamicBranch::~DynamicBranch() +{ +} + +DynamicBranch::DynamicBranch(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile) + : FunctionPass(ID), configJson(0) +{ + this->doDynamicBranch = true; + this->logFile = logFile; + this->configJson = configJson; + + llvm::json::Object *jsonObj = configJson->getAsObject(); + + overallObf = jsonObj->getInteger("overall_obfuscation").getValueOr(0); + if (overallObf == 0) { + this->doDynamicBranch = false; + } + + if (overallObf < 0 || overallObf > 100) { + (*logFile) << "[Frontend]: Config Error: overall_obfuscation should be within 0 to 100.\n"; + this->doDynamicBranch = false; + } + else { + (*logFile) << "[Frontend]: Doing overallObf: " << overallObf << "%\n"; + } + +} + + +bool DynamicBranch::runOnFunction(Function &Func) +{ + + Module *m = Func.getParent(); + +#if 0 + IntrinsicLowering *IL = new IntrinsicLowering(m->getDataLayout()); + errs() << "lowering " << Func.getName() << "\n"; + for (inst_iterator I = inst_begin(Func); I != inst_end(Func); I++) { + Instruction *Inst = &(*I); + if (IntrinsicInst *II = dyn_cast(Inst)) { + errs() << "lowering 1\n"; + IL->LowerIntrinsicCall(II); + } + } + errs() << "lowering 2\n"; + delete IL; +#endif + + if (!this->doDynamicBranch) { + return false; + } + + //Module *m = Func.getParent(); + std::string triple = m->getTargetTriple(); + bool is64bit = false; + if (triple.find("arm64") != std::string::npos || + triple.find("aarch64") != std::string::npos || + triple.find("x86_64") != std::string::npos) { + is64bit = true; + } + + std::vector condBrIns; + for (inst_iterator I = inst_begin(Func); I != inst_end(Func); I++) { + Instruction *Inst = &(*I); + if (BranchInst *BI = dyn_cast(Inst)) { + if (BI->isConditional()) { + condBrIns.push_back(BI); + } + } + } + int obfNum = (int)(((double)overallObf / 100) * condBrIns.size()); + + //alloc an variable in advance instead of every time + AllocaInst* ai; + if (is64bit) { + ai = new AllocaInst(Type::getInt64Ty(m->getContext()), 0, "jumpdest", &Func.front().front()); + } + else { + ai = new AllocaInst(Type::getInt32Ty(m->getContext()), 0, "jumpdest", &Func.front().front()); + } + + for (BranchInst* BI: condBrIns) { + obfNum--; + if (obfNum < 0) { + break; + } + BasicBlock *TrueDest = BI->getSuccessor(0);//BI is a conditional branch + BasicBlock *FalseDest = BI->getSuccessor(1); + BlockAddress * TrueDestAddr = BlockAddress::get(TrueDest); + BlockAddress * FalseDestAddr = BlockAddress::get(FalseDest); + Value * ConditionValue = BI->getCondition(); + SelectInst * SI = SelectInst::Create(ConditionValue, TrueDestAddr, FalseDestAddr, "", BI); +#if 1 + //StoreInst *si = new StoreInst(SI, ai, BI); + //LoadInst *li = new LoadInst(Type::getInt32Ty(m->getContext()), ai, "tmpload", BI); + //IndirectBrInst *indirBr = IndirectBrInst::Create(li, 2, BI); + IndirectBrInst *indirBr = IndirectBrInst::Create(SI, 2, BI); + indirBr->addDestination(TrueDest); + indirBr->addDestination(FalseDest); +#else + IndirectBrInst *indirBr = IndirectBrInst::Create(SI, 2, BI); + indirBr->addDestination(TrueDest); + indirBr->addDestination(FalseDest); +#endif + BI->eraseFromParent(); + + } + + //if (Func.getName().find("run") != std::string::npos) { + // Func.dump(); + // errs() << "===================\n"; + //} + + return true; +} + diff --git a/AntiHackOSS/src/Flattening.cpp b/AntiHackOSS/src/Flattening.cpp new file mode 100644 index 000000000000..a489e6f943b6 --- /dev/null +++ b/AntiHackOSS/src/Flattening.cpp @@ -0,0 +1,401 @@ +//===- Flattening.cpp - Flattening Obfuscation pass------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the flattening pass +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/AntiHack/Flattening.h" +#include "llvm/Transforms/AntiHack/Obfuscation.h" +#include "llvm/Transforms/AntiHack/CryptoUtils.h" +#include "llvm/Transforms/AntiHack/Utils.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Regex.h" +#include "llvm/Transforms/Utils.h" +#include +#include + +#define DEBUG_TYPE "flattening" + +using namespace llvm; + +// Stats +//STATISTIC(Flattened, "Functions flattened"); + +namespace { +struct Flattening : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + llvm::json::Value* configJson; + + std::string homeDir; + bool doFlattening; + llvm::raw_fd_ostream *logFile; + std::set flattenedFuncs; + + Flattening() : FunctionPass(ID), configJson(0) {} + Flattening(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile); + ~Flattening(); + bool runOnFunction(Function &F); + bool flatten(Function *f, std::string seed); + + void split(Function *f, int SplitNum, const std::string seed); + bool containsPHI(BasicBlock *b); + void shuffle(std::vector &vec); +}; +} + +char Flattening::ID = 0; +INITIALIZE_PASS(Flattening, "flattening", "Call graph Flattening", false, false) + +Pass *llvm::createFlattening(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir) { + return new Flattening(configJson, logFile); +} + +Flattening::Flattening(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile) : FunctionPass(ID), configJson(0) +{ + this->doFlattening = true; + this->configJson = configJson; + this->logFile = logFile; + +} + +Flattening::~Flattening() +{ +} + +bool Flattening::runOnFunction(Function &F) { + if (!this->doFlattening) { + return false; + } + + llvm::json::Object *jsonObj = configJson->getAsObject(); + if (jsonObj->getArray("flatten")) { + llvm::json::Array *flattenArray = jsonObj->getArray("flatten"); + + for (auto &obj : *flattenArray) { + if (!obj.getAsObject()->getString("name")) { + (*logFile) << "[Frontend]: Config Error: missing 'name' string object in flatten array\n"; + std::exit(EXIT_FAILURE); + } + + std::string funcName = obj.getAsObject()->getString("name")->str(); + //(*logFile) << "[Frontend]: flattening, try match " << F.getName() << " with " << funcName << "\n"; + //logFile->flush(); + + llvm::Regex reFuncName(funcName); + + std::string seed = obj.getAsObject()->getString("seed")->str(); + if (reFuncName.match(F.getName()) && flattenedFuncs.find(F.getName().str()) == flattenedFuncs.end() ) { + flattenedFuncs.insert(F.getName().str()); + (*logFile) << "[Frontend]: Flattening func " << F.getName() << "\n"; + //F.print(*logFile); + if (flatten(&F, seed) ) { + (*logFile) << "[Frontend]: Successfully flattened func " << F.getName() << "\n"; + //F.print(*logFile); + logFile->flush(); + } + } + } + } + + return false; +} + +bool Flattening::flatten(Function *f, std::string seed) { + vector origBB; + BasicBlock *loopEntry; + BasicBlock *loopEnd; + LoadInst *load; + SwitchInst *switchI; + AllocaInst *switchVar; + + // SCRAMBLER + if (seed.size() == 0) { + (*logFile) << "[Frontend]: Config Error: missing 'seed' in flatten array\n"; + } + llvm::cryptoutils->prng_seed(seed); + char scrambling_key[16]; + llvm::cryptoutils->get_bytes(scrambling_key, 16); + // END OF SCRAMBLER + + //FIXME: when llvm vesion >= 9, call LowerSwtichPass will crash +#if LLVM_VERSION_MAJOR < 9 + // Lower switch + FunctionPass *lower = createLowerSwitchPass(); + lower->runOnFunction(*f); +#else +#endif + + // Save all original BB + for (Function::iterator i = f->begin(); i != f->end(); ++i) { + BasicBlock *tmp = &*i; + //tmp->print(*logFile); + if (tmp->isEHPad() || tmp->isLandingPad() || isa(tmp->getTerminator()) ) { + (*logFile) << f->getName() << "[Frontend]: (Warning) Exception handing instructions is unsupported for flattening " + "in DeClang OSS version. Contact us if you really need to flatten functions with exception handling.\n"; + return false; + } + origBB.push_back(tmp); + + BasicBlock *bb = &*i; + if (!isa(bb->getTerminator()) && !isa(bb->getTerminator()) && + !isa(bb->getTerminator()) ) { + (*logFile) << "[Frontend]: (Warning) " << f->getName() << " Terminator Error. Not Flattening.\n"; + (*logFile) << "terminator: "; + bb->getTerminator()->print(*logFile); + return false; + } + } + + // Nothing to flatten + if (origBB.size() <= 1) { + (*logFile) << f->getName() << "[Frontend]: (Warning) Function too small. Not Flattening.\n"; + return false; + } + + // Remove first BB + origBB.erase(origBB.begin()); + + // Get a pointer on the first BB + Function::iterator tmp = f->begin(); //++tmp; + BasicBlock *insert = &*tmp; + + BranchInst *br = NULL; + if (isa(insert->getTerminator())) { + br = cast(insert->getTerminator()); + } + + // always split first BB + if ((br != NULL/* && br->isConditional()*/) || + insert->getTerminator()->getNumSuccessors() > 1) { + BasicBlock::iterator i = insert->end(); + --i; + + if (insert->size() > 1) { + --i; + } + + BasicBlock *tmpBB = insert->splitBasicBlock(i, "first"); + origBB.insert(origBB.begin(), tmpBB); + } + + // Remove jump + Instruction* oldTerm=insert->getTerminator(); + + // Create switch variable and set as it + switchVar = + new AllocaInst(Type::getInt32Ty(f->getContext()), 0, "switchVar",oldTerm); + oldTerm->eraseFromParent(); + new StoreInst( + ConstantInt::get(Type::getInt32Ty(f->getContext()), + llvm::cryptoutils->scramble32(0, scrambling_key)), + switchVar, insert); + + // Create main loop + loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert); + loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert); + + load = new LoadInst(Type::getInt32Ty(f->getContext()), switchVar, "switchVar", loopEntry); + + // Move first BB on top + insert->moveBefore(loopEntry); + BranchInst::Create(loopEntry, insert); + + // loopEnd jump to loopEntry + BranchInst::Create(loopEntry, loopEnd); + + BasicBlock *swDefault = + BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd); + BranchInst::Create(loopEnd, swDefault); + + // Create switch instruction itself and set condition + switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry); + switchI->setCondition(load); + + // Remove branch jump from 1st BB and make a jump to the while + f->begin()->getTerminator()->eraseFromParent(); + + BranchInst::Create(loopEntry, &*f->begin()); + + // Put all BB in the switch + for (vector::iterator b = origBB.begin(); b != origBB.end(); + ++b) { + BasicBlock *i = *b; + ConstantInt *numCase = NULL; + + // Move the BB inside the switch (only visual, no code logic) + i->moveBefore(loopEnd); + + // Add case to switch + numCase = cast(ConstantInt::get( + switchI->getCondition()->getType(), + llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key))); + switchI->addCase(numCase, i); + } + + // Recalculate switchVar + for (vector::iterator b = origBB.begin(); b != origBB.end(); + ++b) { + BasicBlock *i = *b; + ConstantInt *numCase = NULL; + + // Ret BB + if (i->getTerminator()->getNumSuccessors() == 0) { + continue; + } + + // If it's a non-conditional jump + if (i->getTerminator()->getNumSuccessors() == 1) { + // Get successor and delete terminator + BasicBlock *succ = i->getTerminator()->getSuccessor(0); + i->getTerminator()->eraseFromParent(); + + // Get next case + numCase = switchI->findCaseDest(succ); + + // If next case == default case (switchDefault) + if (numCase == NULL) { + numCase = cast( + ConstantInt::get(switchI->getCondition()->getType(), + llvm::cryptoutils->scramble32( + switchI->getNumCases() - 1, scrambling_key))); + } + + // Update switchVar and jump to the end of loop + new StoreInst(numCase, load->getPointerOperand(), i); + BranchInst::Create(loopEnd, i); + continue; + } + + // If it's a conditional jump + if (i->getTerminator()->getNumSuccessors() == 2) { + // Get next cases + ConstantInt *numCaseTrue = + switchI->findCaseDest(i->getTerminator()->getSuccessor(0)); + ConstantInt *numCaseFalse = + switchI->findCaseDest(i->getTerminator()->getSuccessor(1)); + + // Check if next case == default case (switchDefault) + if (numCaseTrue == NULL) { + numCaseTrue = cast( + ConstantInt::get(switchI->getCondition()->getType(), + llvm::cryptoutils->scramble32( + switchI->getNumCases() - 1, scrambling_key))); + } + + if (numCaseFalse == NULL) { + numCaseFalse = cast( + ConstantInt::get(switchI->getCondition()->getType(), + llvm::cryptoutils->scramble32( + switchI->getNumCases() - 1, scrambling_key))); + } + + // Create a SelectInst + BranchInst *br = cast(i->getTerminator()); + SelectInst *sel = + SelectInst::Create(br->getCondition(), numCaseTrue, numCaseFalse, "", + i->getTerminator()); + + // Erase terminator + i->getTerminator()->eraseFromParent(); + // Update switchVar and jump to the end of loop + new StoreInst(sel, load->getPointerOperand(), i); + BranchInst::Create(loopEnd, i); + continue; + } + } + //f->dump(); + fixStack(f); + return true; +} + +void Flattening::split(Function *f, int SplitNum, string seed) { + + if (seed.size() == 0) { + (*logFile) << "[Frontend]: Config Error: missing 'seed' in flatten array\n"; + } + llvm::cryptoutils->prng_seed(seed); + + + std::vector origBB; + int splitN = SplitNum; + + // Save all basic blocks + for (Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) { + origBB.push_back(&*I); + } + + for (std::vector::iterator I = origBB.begin(), + IE = origBB.end(); + I != IE; ++I) { + BasicBlock *curr = *I; + + // No need to split a 1 inst bb + // Or ones containing a PHI node + if (curr->size() < 2 || containsPHI(curr)) { + continue; + } + + // Check splitN and current BB size + if ((size_t)splitN > curr->size()) { + splitN = curr->size() - 1; + } + + // Generate splits point + std::vector test; + for (unsigned i = 1; i < curr->size(); ++i) { + test.push_back(i); + } + + // Shuffle + if (test.size() != 1) { + shuffle(test); + std::sort(test.begin(), test.begin() + splitN); + } + + // Split + BasicBlock::iterator it = curr->begin(); + BasicBlock *toSplit = curr; + int last = 0; + for (int i = 0; i < splitN; ++i) { + for (int j = 0; j < test[i] - last; ++j) { + ++it; + } + last = test[i]; + if(toSplit->size() < 2) + continue; + toSplit = toSplit->splitBasicBlock(it, toSplit->getName() + ".split"); + } + + } +} + +bool Flattening::containsPHI(BasicBlock *b) { + for (BasicBlock::iterator I = b->begin(), IE = b->end(); I != IE; ++I) { + if (isa(I)) { + return true; + } + } + return false; +} + +void Flattening::shuffle(std::vector &vec) { + int n = vec.size(); + for (int i = n - 1; i > 0; --i) { + std::swap(vec[i], vec[cryptoutils->get_uint32_t() % (i + 1)]); + } +} diff --git a/AntiHackOSS/src/LLVMBuild.txt b/AntiHackOSS/src/LLVMBuild.txt new file mode 100644 index 000000000000..1c573a08ba85 --- /dev/null +++ b/AntiHackOSS/src/LLVMBuild.txt @@ -0,0 +1,5 @@ +[component_0] +type = Library +name = AntiHack +parent = Transforms +required_libraries = Linker \ No newline at end of file diff --git a/AntiHackOSS/src/Obfuscation.cpp b/AntiHackOSS/src/Obfuscation.cpp new file mode 100644 index 000000000000..a2a04f42e659 --- /dev/null +++ b/AntiHackOSS/src/Obfuscation.cpp @@ -0,0 +1,113 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "llvm/InitializePasses.h" +#include "llvm-c/Initialization.h" +#include "llvm/PassRegistry.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Transforms/AntiHack/Obfuscation.h" +#include "llvm/Transforms/AntiHack/Flattening.h" +#include "llvm/Transforms/AntiHack/SplitBasicBlock.h" +#include "llvm/Transforms/AntiHack/DynamicBranch.h" +#include + +using namespace llvm; + +namespace { + struct Obfuscation: ModulePass { + static char ID; // Pass identification, replacement for typeid + + std::vector functionPasses; + + llvm::json::Value *configJson; + llvm::raw_fd_ostream *logFile; + std::string homeDir; + bool doObfuscation; + + Obfuscation(): ModulePass(ID), logFile(nullptr), configJson(nullptr), doObfuscation(false) {}; + Obfuscation(llvm::json::Value *configJson, llvm::raw_fd_ostream *logFile, std::string homeDir); + ~Obfuscation(); + + virtual bool doInitialization(Module &m); + bool runOnModule(Module &M); + }; + + bool Obfuscation::doInitialization(Module &m) + { + if (!doObfuscation) { + return false; + } + FunctionPass *fp = static_cast(createSplitBasicBlock(configJson, logFile, homeDir)); + functionPasses.push_back(fp); + + fp = static_cast(createFlattening(configJson, logFile, homeDir)); + functionPasses.push_back(fp); + + fp = static_cast(createDynamicBranch(configJson, logFile, homeDir)); + functionPasses.push_back(fp); + return true; + } + + bool Obfuscation::runOnModule(Module& m) + { + bool modified = false; + + if (doObfuscation) { + for (FunctionPass* p : functionPasses) { + for (Module::iterator iter = m.begin(); iter != m.end(); iter++) { + Function &F = *iter; + if (!F.isDeclaration()) { + modified |= p->runOnFunction(F); + } + } + } + } + return modified; + } + + Obfuscation::Obfuscation(llvm::json::Value *configJson, llvm::raw_fd_ostream *logFile, std::string homeDir) + : ModulePass(ID), configJson(configJson), logFile(logFile), homeDir(homeDir) + { + doObfuscation = true; + llvm::json::Object *jsonObj = configJson->getAsObject(); + int enable_obf = jsonObj->getInteger("enable_obfuscation").getValueOr(1); + if (!enable_obf) { + doObfuscation = false; + (*logFile) << "[Frontend]: (Info) enable_obf is 0, all obfuscations will be disabled.\n"; + } + } + + Obfuscation::~Obfuscation() + { + for (Pass* p : functionPasses) { + delete p; + } + } + +} // namespace + +char Obfuscation::ID = 0; +INITIALIZE_PASS(Obfuscation, "Obfuscation", "Obfuscation Pass", false, false) + +Pass *llvm::createObfuscation(llvm::json::Value *configJson, llvm::raw_fd_ostream *logFile, std::string homeDir) { + return new Obfuscation(configJson, logFile, homeDir); +} \ No newline at end of file diff --git a/AntiHackOSS/src/SplitBasicBlock.cpp b/AntiHackOSS/src/SplitBasicBlock.cpp new file mode 100644 index 000000000000..45b4fbb637e1 --- /dev/null +++ b/AntiHackOSS/src/SplitBasicBlock.cpp @@ -0,0 +1,183 @@ +//===- SplitBasicBlock.cpp - SplitBasicBlokc Obfuscation pass--------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the split basic block pass +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/AntiHack/Obfuscation.h" +#include "llvm/Transforms/AntiHack/SplitBasicBlock.h" +#include "llvm/Transforms/AntiHack/Utils.h" +#include "llvm/Transforms/AntiHack/CryptoUtils.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Regex.h" +#include + +#define DEBUG_TYPE "split" + +using namespace llvm; +using namespace std; + +// Stats +//STATISTIC(Split, "Basicblock splitted"); + +namespace { +struct SplitBasicBlock : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + bool flag; + std::set splittedFuncs; + + llvm::json::Value* configJson; + + std::string homeDir; + bool doSplit; + llvm::raw_fd_ostream *logFile; + + SplitBasicBlock() : FunctionPass(ID), configJson(0) {} + SplitBasicBlock(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile); + + bool runOnFunction(Function &F); + void split(Function *f, int SplitNum, std::string seed); + + bool containsPHI(BasicBlock *b); + void shuffle(std::vector &vec); +}; +} + +char SplitBasicBlock::ID = 0; +INITIALIZE_PASS(SplitBasicBlock, "split_basic_block", "Split Basic Block", false, false) + +Pass *llvm::createSplitBasicBlock(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile, std::string homeDir) { + return new SplitBasicBlock(configJson, logFile); +} + +SplitBasicBlock::SplitBasicBlock(llvm::json::Value* configJson, llvm::raw_fd_ostream *logFile) : FunctionPass(ID), configJson(0) +{ + this->doSplit = true; + this->configJson = configJson; + this->logFile = logFile; + +} + +bool SplitBasicBlock::runOnFunction(Function &F) { + // Check if the number of applications is correct + if (!this->doSplit) { + return false; + } + + llvm::json::Object *jsonObj = configJson->getAsObject(); + if (jsonObj->getArray("flatten")) { + llvm::json::Array *flattenArray = jsonObj->getArray("flatten"); + + for (auto &obj : *flattenArray) { + if (!obj.getAsObject()->getString("name")) { + (*logFile) << "[Frontend]: Config Error: missing 'name' string object in flatten array\n"; + std::exit(EXIT_FAILURE); + } + + std::string funcName = obj.getAsObject()->getString("name")->str(); + llvm::Regex reFuncName(funcName); + + std::string seed = obj.getAsObject()->getString("seed")->str(); + int SplitNum = obj.getAsObject()->getInteger("split_level").getValueOr(0); + if (!((SplitNum >= 0) && (SplitNum <= 10))) { + (*logFile) << "[Frontend]: Config Error: split_level should be 0 to 10.\n"; + return false; + } + //only split function once + if (reFuncName.match(F.getName()) && splittedFuncs.find(F.getName().str()) == splittedFuncs.end() ) { + splittedFuncs.insert(F.getName().str()); + Function *tmp = &F; + (*logFile) << "[Frontend]: Spliting " << F.getName() << " by " << SplitNum << "\n"; + split(tmp, SplitNum, seed); + } + + } + } + + return true; +} + +void SplitBasicBlock::split(Function *f, int SplitNum, std::string seed) { + + if (seed.size() == 0) { + (*logFile) << "[Frontend]: Split Warning: missing 'seed' in flatten array\n"; + } + llvm::cryptoutils->prng_seed(seed); + + + std::vector origBB; + int splitN = SplitNum; + + // Save all basic blocks + for (Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) { + origBB.push_back(&*I); + } + + for (std::vector::iterator I = origBB.begin(), + IE = origBB.end(); + I != IE; ++I) { + BasicBlock *curr = *I; + + // No need to split a 1 inst bb + // Or ones containing a PHI node + if (curr->size() < 2 || containsPHI(curr)) { + continue; + } + + // Check splitN and current BB size + if ((size_t)splitN > curr->size()) { + splitN = curr->size() - 1; + } + + // Generate splits point + std::vector test; + for (unsigned i = 1; i < curr->size(); ++i) { + test.push_back(i); + } + + // Shuffle + if (test.size() != 1) { + shuffle(test); + std::sort(test.begin(), test.begin() + splitN); + } + + // Split + BasicBlock::iterator it = curr->begin(); + BasicBlock *toSplit = curr; + int last = 0; + for (int i = 0; i < splitN; ++i) { + for (int j = 0; j < test[i] - last; ++j) { + ++it; + } + last = test[i]; + if(toSplit->size() < 2) + continue; + toSplit = toSplit->splitBasicBlock(it, toSplit->getName() + ".split"); + } + + } +} + +bool SplitBasicBlock::containsPHI(BasicBlock *b) { + for (BasicBlock::iterator I = b->begin(), IE = b->end(); I != IE; ++I) { + if (isa(I)) { + return true; + } + } + return false; +} + +void SplitBasicBlock::shuffle(std::vector &vec) { + int n = vec.size(); + for (int i = n - 1; i > 0; --i) { + std::swap(vec[i], vec[cryptoutils->get_uint32_t() % (i + 1)]); + } +} + diff --git a/AntiHackOSS/src/Utils.cpp b/AntiHackOSS/src/Utils.cpp new file mode 100644 index 000000000000..dd60b86b7545 --- /dev/null +++ b/AntiHackOSS/src/Utils.cpp @@ -0,0 +1,151 @@ +//===- Utils.cpp ---------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/AntiHack/Utils.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/raw_ostream.h" +#include +#include "llvm/IR/Module.h" + +// Shamefully borrowed from ../Scalar/RegToMem.cpp :( +bool valueEscapes(Instruction *Inst) { + BasicBlock *BB = Inst->getParent(); + for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; + ++UI) { + Instruction *I = cast(*UI); + if (I->getParent() != BB || isa(I)) { + return true; + } + } + return false; +} + +void fixStack(Function *f) { + // Try to remove phi node and demote reg to stack + std::vector tmpPhi; + std::vector tmpReg; + BasicBlock *bbEntry = &*f->begin(); + + do { + tmpPhi.clear(); + tmpReg.clear(); + + for (Function::iterator i = f->begin(); i != f->end(); ++i) { + + for (BasicBlock::iterator j = i->begin(); j != i->end(); ++j) { + + if (isa(j)) { + PHINode *phi = cast(j); + tmpPhi.push_back(phi); + continue; + } + if (!(isa(j) && j->getParent() == bbEntry) && + (valueEscapes(&*j) || j->isUsedOutsideOfBlock(&*i))) { + tmpReg.push_back(&*j); + continue; + } + } + } + for (unsigned int i = 0; i != tmpReg.size(); ++i) { + DemoteRegToStack(*tmpReg.at(i), f->begin()->getTerminator()); + } + + for (unsigned int i = 0; i != tmpPhi.size(); ++i) { + DemotePHIToStack(tmpPhi.at(i), f->begin()->getTerminator()); + } + + } while (tmpReg.size() != 0 || tmpPhi.size() != 0); +} + +std::string readAnnotate(Function *f) { + std::string annotation = ""; + + // Get annotation variable + GlobalVariable *glob = + f->getParent()->getGlobalVariable("llvm.global.annotations"); + + if (glob != NULL) { + // Get the array + if (ConstantArray *ca = dyn_cast(glob->getInitializer())) { + for (unsigned i = 0; i < ca->getNumOperands(); ++i) { + // Get the struct + if (ConstantStruct *structAn = + dyn_cast(ca->getOperand(i))) { + if (ConstantExpr *expr = + dyn_cast(structAn->getOperand(0))) { + // If it's a bitcast we can check if the annotation is concerning + // the current function + if (expr->getOpcode() == Instruction::BitCast && + expr->getOperand(0) == f) { + ConstantExpr *note = cast(structAn->getOperand(1)); + // If it's a GetElementPtr, that means we found the variable + // containing the annotations + if (note->getOpcode() == Instruction::GetElementPtr) { + if (GlobalVariable *annoteStr = + dyn_cast(note->getOperand(0))) { + if (ConstantDataSequential *data = + dyn_cast( + annoteStr->getInitializer())) { + if (data->isString()) { + annotation += data->getAsString().lower() + " "; + } + } + } + } + } + } + } + } + } + } + return annotation; +} + +bool toObfuscate(bool flag, Function *f, std::string attribute) { + std::string attr = attribute; + std::string attrNo = "no" + attr; + + // Check if declaration + if (f->isDeclaration()) { + return false; + } + + // Check external linkage + if(f->hasAvailableExternallyLinkage() != 0) { + return false; + } + + // We have to check the nofla flag first + // Because .find("fla") is true for a string like "fla" or + // "nofla" + if (readAnnotate(f).find(attrNo) != std::string::npos) { + return false; + } + + // If fla annotations + if (readAnnotate(f).find(attr) != std::string::npos) { + return true; + } + + return false; +} + +bool isCompilingForAndroid(const llvm::Module &m) { + // android target sample: aarch64-none-linux-android + llvm::Regex reAndroid(".*android.*"); + std::string target(m.getTargetTriple()); + return reAndroid.match(target) ? true : false; +} + +bool isCompilingForIOS(const llvm::Module &m) { + // iOS target sample: arm64-apple-ios12.4 + llvm::Regex reAndroid(".*ios.*"); + std::string target(m.getTargetTriple()); + return reAndroid.match(target) ? true : false; +} diff --git a/AntiHackOSS/tools/build_tools.sh b/AntiHackOSS/tools/build_tools.sh new file mode 100644 index 000000000000..f2c3e764ea07 --- /dev/null +++ b/AntiHackOSS/tools/build_tools.sh @@ -0,0 +1,9 @@ +set -e + +#build gen_config +pushd $(dirname $0) > /dev/null + +cd config/ +bash build.sh $1 +popd > /dev/null + diff --git a/AntiHackOSS/tools/config/GenConfig.go b/AntiHackOSS/tools/config/GenConfig.go new file mode 100644 index 000000000000..8e4c3b1229ea --- /dev/null +++ b/AntiHackOSS/tools/config/GenConfig.go @@ -0,0 +1,184 @@ +/* + * Copyright 2020 DeNA Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "fmt" + "os" + "log" + "encoding/json" + "flag" + "io" + "bytes" +) + +var DEFAULT_SPLIT_LEVEL int = 1 + +type Flatten struct { + Name string `json:"name"` + Seed string `json:"seed"` + SplitLevel int `json:"split_level"` + SearchType string `json:"search_type"` +} + +type Config struct { + Build_seed string `json:"build_seed"` + Overall_obfuscation int `json:"overall_obfuscation"` + Enable_obfuscation int `json:"enable_obfuscation"` + Flattens []Flatten `json:"flatten"` +} + +func GetConfig(path string) Config { + jsonPath := path + jsonFile, err := os.Open(jsonPath) + if err != nil { + check(fmt.Sprintf("%v のファイルが開けませんでした。", path), err) + } + defer jsonFile.Close() + + var config Config + decoder := json.NewDecoder(jsonFile) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&config); err != nil && err != io.EOF { + check(fmt.Sprintf("%v のJSONのパースに失敗しました。", path), err) + } + return config +} + +func CalcHash(data []byte, start uint64, size uint64) uint64{ + const BLOCK_SIZE uint64 = 4 + const BASE uint64 = 617365819018153 + var hash uint64 = 0 + i := start + var j uint64 = 0 + + for ; i+BLOCK_SIZE < start+size; i += BLOCK_SIZE { + hash *= BASE + var tmp uint64 = 1 + for j = 0; j < BLOCK_SIZE; j++ { + hash += uint64(data[i+j]) * tmp + tmp <<= 8 + } + } + for ; i < start+size; i++ { + hash = hash*BASE + uint64(data[i]) + } + return hash +} + + + +func (config *Config) UnmarshalJSON(data []byte) error { + type xConfig Config + defaultConfig := &xConfig{Overall_obfuscation: 0, Enable_obfuscation: 1} + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(defaultConfig); err != nil && err != io.EOF { + return err + } + *config = Config(*defaultConfig) + return nil +} + +func (flatten *Flatten) UnmarshalJSON(data []byte) error { + type xFlatten Flatten + xf := &xFlatten{Seed: "", SplitLevel: DEFAULT_SPLIT_LEVEL} + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(xf); err != nil && err != io.EOF { + return err + } + *flatten = Flatten(*xf) + if flatten.Name == "" { + log.Fatalf("flattenでnameが定義されていません。") + } + return nil +} + +func check(message string, e error) { + if e != nil { + log.Print(message) + log.Fatalf("Error: %v\n", e) + } +} + +func flattenContainsName(f []Flatten, name string) bool { + for _, v := range f { + if name == v.Name { + return true + } + } + return false +} + +func contains(s []string, e string) bool { + for _, v := range s { + if e == v { + return true + } + } + return false +} + +func main() { + homeDir := os.Getenv("DECLANG_HOME") + if len(homeDir) == 0 { + homeDir = os.Getenv("HOME") + } + + pathPtr := flag.String("path", homeDir+"/.DeClang/", "config file path") + seedPtr := flag.String("seed", "", "a seed") + flag.Parse() + + //if len(os.Args) != 1 && len(os.Args) != 2 && len(os.Args) != 3 { + // fmt.Println("usage: gen_config_{linux,mac,windows} [seed] [path_to_config.pre.json]") + // os.Exit(1) + //} + fmt.Printf("[GenConfig]: Generate config.json\n") + + var config Config + var jsonOutPath string + jsonOutPath = *pathPtr + "/config.json" + config = GetConfig(*pathPtr+"/config.pre.json") + + if len(*seedPtr) > 0 { + config.Build_seed = *seedPtr + } + buildSeed := config.Build_seed + + //generate seed for flattening + for i := 0; i < len(config.Flattens); i++ { + funcName := config.Flattens[i].Name + seed := config.Flattens[i].Seed + if seed == "" { + str := []byte(buildSeed + funcName) + hash := CalcHash(str, 0, uint64(len(str)) ) + seed = fmt.Sprintf("%016x%016x", hash, hash) + config.Flattens[i].Seed = seed + } + fmt.Printf("[GenConfig]: Flatten %s using %s\n", funcName, seed) + } + + configStr, err := json.MarshalIndent(config, "", " ") + check("JSON形式への変換に失敗しました。", err) + + jsonOutFile, err := os.Create(jsonOutPath) + check(fmt.Sprintf("%v のファイルが開けませんでした。", jsonOutPath), err) + defer jsonOutFile.Close() + + jsonOutFile.Write(configStr) +} diff --git a/AntiHackOSS/tools/config/Makefile b/AntiHackOSS/tools/config/Makefile new file mode 100644 index 000000000000..a0348fc0b975 --- /dev/null +++ b/AntiHackOSS/tools/config/Makefile @@ -0,0 +1,24 @@ +.PHONY: all + +NAME := gen_config + +ALL: $(NAME)_mac $(NAME)_linux $(NAME)_windows.exe + +clean: + rm -f $(NAME)_mac + rm -f $(NAME)_windows.exe + rm -f $(NAME)_linux + rm -f $(NAME)_android + rm -f config.json + +SRCS := GenConfig.go + +$(NAME)_mac: $(SRCS) + GOOS=darwin GOARCH=amd64 go build -o $@ +$(NAME)_windows.exe: $(SRCS) + GOOS=windows GOARCH=386 go build -o $@ +$(NAME)_linux: $(SRCS) + GOOS=linux GOARCH=amd64 go build -o $@ +$(NAME)_android: $(SRCS) + GOOS=linux GOARCH=arm go build -o $@ + diff --git a/AntiHackOSS/tools/config/build.sh b/AntiHackOSS/tools/config/build.sh new file mode 100644 index 000000000000..1e9f1c826655 --- /dev/null +++ b/AntiHackOSS/tools/config/build.sh @@ -0,0 +1,7 @@ +set -e + +pushd $(dirname $0) > /dev/null + +make $1 + +popd > /dev/null diff --git a/AntiHackOSS/tools/config/config.pre.json b/AntiHackOSS/tools/config/config.pre.json new file mode 100644 index 000000000000..a93db9888f35 --- /dev/null +++ b/AntiHackOSS/tools/config/config.pre.json @@ -0,0 +1,9 @@ +{ + "build_seed":"hello, i am seed", + "flatten": + [ + { + "name": ".*main.*" + } + ] +} diff --git a/AntiHackOSS/tools/config/copy.sh b/AntiHackOSS/tools/config/copy.sh new file mode 100644 index 000000000000..3e9fd6ad5c08 --- /dev/null +++ b/AntiHackOSS/tools/config/copy.sh @@ -0,0 +1,5 @@ +pushd $(dirname $0) > /dev/null + +cp -v gen_config_mac ~/.DeClang/ + +popd > /dev/null diff --git a/AntiHackOSS/tools/config/gen_config.sh b/AntiHackOSS/tools/config/gen_config.sh new file mode 100755 index 000000000000..1aa8c34f47b4 --- /dev/null +++ b/AntiHackOSS/tools/config/gen_config.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +BASE=$(dirname "$0") +SCRIPT_DIR=$(cd "$BASE"; pwd) +os=$(uname -s) +if [ $os = "Darwin" ]; then + "${SCRIPT_DIR}/gen_config_mac" "$@" +elif [[ "_$OS" = "_Windows_NT" ]]; then + "${SCRIPT_DIR}/gen_config_windows" "$@" +else + "${SCRIPT_DIR}/gen_config_linux" "$@" +fi diff --git a/AntiHackOSS/tools/release.sh b/AntiHackOSS/tools/release.sh new file mode 100644 index 000000000000..9795a772bc00 --- /dev/null +++ b/AntiHackOSS/tools/release.sh @@ -0,0 +1,56 @@ +set -e + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 {version_num}" >&2 + exit 1 +fi + +#copy declang +pushd $(dirname $0) > /dev/null +cd ../ + +rm -rf ./Release/ +mkdir -p ./Release/compiler/bin/ +mkdir -p ./Release/compiler/lib/ + +cp -v build/bin/clang++ ./Release/compiler/bin/ +cp -v build/bin/clang ./Release/compiler/bin/ +cp -r build/lib/clang/ ./Release/compiler/lib/clang/ +popd > /dev/null + + +#copy include files +pushd $(dirname $0) > /dev/null +cd ../ +mkdir -p ./Release/compiler/include/llvm/ +mkdir -p ./Release/compiler/include/c++/v1/ + +cp -r build/include/llvm/* ./Release/compiler/include/llvm/ +cp -r libcxx/include/* ./Release/compiler/include/c++/v1/ +popd > /dev/null + +pushd $(dirname $0) > /dev/null +cd ../ + +# cp -v tools/config/config.pre.json ./Release/ +cp -v tools/config/gen_config_* ./Release/ +cp -v tools/config/gen_config.sh ./Release/ + +mkdir -p ./Release/script/ +cp -v script/*setup.sh ./Release/script/ +cp -v script/*unset.sh ./Release/script/ +popd > /dev/null + +# copy license +pushd $(dirname $0) > /dev/null +cd .. +cp ./AntiHackOSS/LICENSE-DeClang ./Release/ +cp ./AntiHackOSS/LICENSE-ollvm ./Release/ +cp ./LICENSE ./Release/ +popd > /dev/null + +pushd $(dirname $0) > /dev/null +cd ../ + +mv Release Release-$1 +popd > /dev/null diff --git a/AntiHackOSS/tools/tests/flatten/Makefile b/AntiHackOSS/tools/tests/flatten/Makefile new file mode 100644 index 000000000000..02f97d6f6c04 --- /dev/null +++ b/AntiHackOSS/tools/tests/flatten/Makefile @@ -0,0 +1,22 @@ +CXX=../../../../build/bin/clang++ +INC=/Applications/Xcode.app/Contents//Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ +x64:test.cpp config.json + DECLANG_HOME=. $(CXX) -Os -mmacosx-version-min=10.14.6 -std=c++03 -I$(INC) -lc++ -lstdc++ -lSystem -g test.cpp -mllvm -antihack=./config.json -o test +x64_ir:test.cpp config.json + DECLANG_HOME=. $(CXX) -Os -mmacosx-version-min=10.14.6 -std=c++03 -I$(INC) -lc++ -lstdc++ -lSystem test.cpp -mllvm -antihack=./config.json -emit-llvm -S -o test.ll +aarch64:test.cpp config.json + DECLANG_HOME=. $(CXX) -std=c++03 -I$(INC) -c -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/ -lclang_rt.ios -Os -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk test.cpp -mllvm -antihack=./config.json -mllvm --loop-unswitch-threshold=1 -o test +aarch64_ir:test.cpp config.json + DECLANG_HOME=. $(CXX) -std=c++03 -I$(INC) -c -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/lib/darwin/ -lclang_rt.ios -Os -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk test.cpp -mllvm -antihack=./config.json -mllvm --loop-unswitch-threshold=1 -emit-llvm -S -o test.ll + +config.json:config.pre.json + mkdir -p ./.DeClang/ + ../../config/gen_config_mac -path . + +clean: + rm -f *.o + rm -f test + rm -f test.ll + rm -f config.json + rm -rf *.dSYM + rm -rf ./.DeClang/ diff --git a/AntiHackOSS/tools/tests/flatten/config.pre.json b/AntiHackOSS/tools/tests/flatten/config.pre.json new file mode 100644 index 000000000000..e45e9e490e2e --- /dev/null +++ b/AntiHackOSS/tools/tests/flatten/config.pre.json @@ -0,0 +1,11 @@ +{ + "flatten": + [ + { + "name": "foo" + }, + { + "name": "bar" + } + ] +} diff --git a/AntiHackOSS/tools/tests/flatten/test.cpp b/AntiHackOSS/tools/tests/flatten/test.cpp new file mode 100644 index 000000000000..1c1ce0d54ed4 --- /dev/null +++ b/AntiHackOSS/tools/tests/flatten/test.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +__attribute__((optnone)) uint32_t getNum() +{ + static uint32_t count = 2; + count--; + return count; +} + +uint32_t foo() +{ + uint32_t V_0 = 0; + goto LBL3; + +LBL1: + if (V_0 == 1) { + printf("2\n"); + goto LBL2; + } + else + goto LBL3; + +LBL2: + printf("3\n"); + goto LBL3; + +LBL3: + printf("1\n"); + V_0 = getNum(); + if (V_0) + goto LBL1; + else { + printf("4\n"); + return V_0; + } +} + +void bar(int a) +{ + if (a == 1) { + printf("a==1\n"); + } + else { + printf("a!=1\n"); + } +} + +int main(int argc, char **argv) +{ + foo(); + return 0; +} diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 9463ca5c109d..ca4d4da01fdd 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -75,6 +75,8 @@ add_clang_library(clangDriver ToolChains/InterfaceStubs.cpp Types.cpp XRayArgs.cpp + DeClangExtraProcess.cpp + DEPENDS ClangDriverOptions diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 5557be0e2be0..6fc377d56afb 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -93,6 +93,8 @@ using namespace clang::driver; using namespace clang; using namespace llvm::opt; +extern void DeClangExtraProcess(const Compilation &C, const std::string& homeDir, llvm::raw_fd_ostream *logFile); + // static std::string Driver::GetResourcesPath(StringRef BinaryPath, StringRef CustomResourceDir) { @@ -989,6 +991,15 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { } } + //DECLANG CODES BEGIN + //add -DDECLANG + std::vector modArgs = ArgList.vec(); + modArgs.push_back("-DDECLANG"); + + ArgList = ArrayRef(modArgs); + + //DECLANG CODES END + // We look for the driver mode option early, because the mode can affect // how other options are parsed. ParseDriverMode(ClangExecutable, ArgList.slice(1)); @@ -1568,6 +1579,37 @@ int Driver::ExecuteCompilation( for (auto &Job : C.getJobs()) setUpResponseFiles(C, Job); + //DECLANG CODES BEGIN + char* home_dir = getenv("DECLANG_HOME"); + if (home_dir == nullptr) { + home_dir = getenv("HOME"); + } + if (home_dir == nullptr) { + home_dir = getenv("USERPROFILE"); + } + if (home_dir == nullptr) { + llvm::errs() << "[Linker]: (Warning) Cannot find $DECLANG_HOME, $HOME or %USERPROFILE%\n"; + llvm::errs().flush(); + std::exit(EXIT_FAILURE); + } + std::string homeDir(home_dir); + homeDir = llvm::sys::path::convert_to_slash(homeDir); + + //log path + std::string logPath = homeDir + "/.DeClang/log.txt"; + llvm::raw_fd_ostream *logFile; + std::error_code EC; + logFile = new llvm::raw_fd_ostream(logPath, EC, llvm::sys::fs::F_Append); + if (EC) { + llvm::errs() << "[Linker]: Open logFile Failed. Check DECLANG_HOME maybe?: " << EC.message() << " " << logPath << "\n"; + llvm::errs().flush(); + } + + for (Command& cmd : C.getJobs() ) { + cmd.Print(*logFile, "\n", /*Quote=*/true); + } + //DECLANG CODES END + C.ExecuteJobs(C.getJobs(), FailingCommands); // If the command succeeded, we are done. diff --git a/clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas b/clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas deleted file mode 120000 index 59eefd95a902..000000000000 --- a/clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas +++ /dev/null @@ -1 +0,0 @@ -../../opt/cuda/bin/ptxas \ No newline at end of file diff --git a/clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas b/clang/test/Driver/Inputs/CUDA-symlinks/usr/bin/ptxas new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld deleted file mode 120000 index 7e0a9cfe2ddb..000000000000 --- a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld +++ /dev/null @@ -1 +0,0 @@ -i386-unknown-linux-gnu-ld.gold \ No newline at end of file diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/i386-unknown-linux-gnu-ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld deleted file mode 120000 index ce36ac093b61..000000000000 --- a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld +++ /dev/null @@ -1 +0,0 @@ -x86_64-unknown-linux-gnu-ld.gold \ No newline at end of file diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/bin/x86_64-unknown-linux-gnu-ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld deleted file mode 120000 index 6cd03701cdda..000000000000 --- a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld +++ /dev/null @@ -1 +0,0 @@ -ld.gold \ No newline at end of file diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/i386-unknown-linux-gnu/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld deleted file mode 120000 index 6cd03701cdda..000000000000 --- a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld +++ /dev/null @@ -1 +0,0 @@ -ld.gold \ No newline at end of file diff --git a/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/basic_cross_linux_tree/usr/x86_64-unknown-linux-gnu/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as deleted file mode 120000 index 0065315cfd1d..000000000000 --- a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as +++ /dev/null @@ -1 +0,0 @@ -i386-unknown-linux-gnu-as \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/as @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld deleted file mode 120000 index 9e5574285c70..000000000000 --- a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld +++ /dev/null @@ -1 +0,0 @@ -i386-unknown-linux-gnu-ld \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as deleted file mode 120000 index 2aa12fdef916..000000000000 --- a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as +++ /dev/null @@ -1 +0,0 @@ -../../bin/i386-unknown-linux-gnu-as \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/as @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld deleted file mode 120000 index 5aeaff619662..000000000000 --- a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld +++ /dev/null @@ -1 +0,0 @@ -../../bin/i386-unknown-linux-gnu-ld \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_32bit_linux_tree/usr/i386-unknown-linux/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as deleted file mode 120000 index 477cbc9635fc..000000000000 --- a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as +++ /dev/null @@ -1 +0,0 @@ -x86_64-unknown-linux-gnu-as \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/as @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld deleted file mode 120000 index 5343caf34d8f..000000000000 --- a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld +++ /dev/null @@ -1 +0,0 @@ -x86_64-unknown-linux-gnu-ld \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as deleted file mode 120000 index 84a9113f2671..000000000000 --- a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as +++ /dev/null @@ -1 +0,0 @@ -../../bin/x86_64-unknown-linux-gnu-as \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/as @@ -0,0 +1 @@ +#!/bin/true diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld deleted file mode 120000 index c417e3afaa49..000000000000 --- a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld +++ /dev/null @@ -1 +0,0 @@ -../../bin/x86_64-unknown-linux-gnu-ld \ No newline at end of file diff --git a/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld new file mode 100755 index 000000000000..b23e55619b2f --- /dev/null +++ b/clang/test/Driver/Inputs/multilib_64bit_linux_tree/usr/x86_64-unknown-linux/bin/ld @@ -0,0 +1 @@ +#!/bin/true diff --git a/libclc/amdgcn-mesa3d b/libclc/amdgcn-mesa3d deleted file mode 120000 index 400782833efe..000000000000 --- a/libclc/amdgcn-mesa3d +++ /dev/null @@ -1 +0,0 @@ -amdgcn-amdhsa \ No newline at end of file diff --git a/libclc/amdgcn-mesa3d/lib/SOURCES b/libclc/amdgcn-mesa3d/lib/SOURCES new file mode 100644 index 000000000000..8224b7721b2c --- /dev/null +++ b/libclc/amdgcn-mesa3d/lib/SOURCES @@ -0,0 +1,3 @@ +workitem/get_global_size.cl +workitem/get_local_size.cl +workitem/get_num_groups.cl diff --git a/libclc/amdgcn-mesa3d/lib/workitem/get_global_size.cl b/libclc/amdgcn-mesa3d/lib/workitem/get_global_size.cl new file mode 100644 index 000000000000..2f95f9916b2c --- /dev/null +++ b/libclc/amdgcn-mesa3d/lib/workitem/get_global_size.cl @@ -0,0 +1,24 @@ +#include + +#if __clang_major__ >= 8 +#define CONST_AS __constant +#elif __clang_major__ >= 7 +#define CONST_AS __attribute__((address_space(4))) +#else +#define CONST_AS __attribute__((address_space(2))) +#endif + +#if __clang_major__ >= 6 +#define __dispatch_ptr __builtin_amdgcn_dispatch_ptr +#else +#define __dispatch_ptr __clc_amdgcn_dispatch_ptr +CONST_AS uchar * __clc_amdgcn_dispatch_ptr(void) __asm("llvm.amdgcn.dispatch.ptr"); +#endif + +_CLC_DEF size_t get_global_size(uint dim) +{ + CONST_AS uint * ptr = (CONST_AS uint *) __dispatch_ptr(); + if (dim < 3) + return ptr[3 + dim]; + return 1; +} diff --git a/libclc/amdgcn-mesa3d/lib/workitem/get_local_size.cl b/libclc/amdgcn-mesa3d/lib/workitem/get_local_size.cl new file mode 100644 index 000000000000..9f208d8aea77 --- /dev/null +++ b/libclc/amdgcn-mesa3d/lib/workitem/get_local_size.cl @@ -0,0 +1,30 @@ +#include + +#if __clang_major__ >= 8 +#define CONST_AS __constant +#elif __clang_major__ >= 7 +#define CONST_AS __attribute__((address_space(4))) +#else +#define CONST_AS __attribute__((address_space(2))) +#endif + +#if __clang_major__ >= 6 +#define __dispatch_ptr __builtin_amdgcn_dispatch_ptr +#else +#define __dispatch_ptr __clc_amdgcn_dispatch_ptr +CONST_AS char * __clc_amdgcn_dispatch_ptr(void) __asm("llvm.amdgcn.dispatch.ptr"); +#endif + +_CLC_DEF size_t get_local_size(uint dim) +{ + CONST_AS uint * ptr = (CONST_AS uint *) __dispatch_ptr(); + switch (dim) { + case 0: + return ptr[1] & 0xffffu; + case 1: + return ptr[1] >> 16; + case 2: + return ptr[2] & 0xffffu; + } + return 1; +} diff --git a/libclc/amdgcn-mesa3d/lib/workitem/get_num_groups.cl b/libclc/amdgcn-mesa3d/lib/workitem/get_num_groups.cl new file mode 100644 index 000000000000..946b526fdb68 --- /dev/null +++ b/libclc/amdgcn-mesa3d/lib/workitem/get_num_groups.cl @@ -0,0 +1,12 @@ + +#include + +_CLC_DEF size_t get_num_groups(uint dim) { + size_t global_size = get_global_size(dim); + size_t local_size = get_local_size(dim); + size_t num_groups = global_size / local_size; + if (global_size % local_size != 0) { + num_groups++; + } + return num_groups; +} diff --git a/libcxx/test/std/pstl b/libcxx/test/std/pstl deleted file mode 120000 index 27a2822d9566..000000000000 --- a/libcxx/test/std/pstl +++ /dev/null @@ -1 +0,0 @@ -../../../pstl/test/std \ No newline at end of file diff --git a/libcxx/test/std/pstl/algorithms/alg.merge/inplace_merge.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.merge/inplace_merge.pass.cpp new file mode 100644 index 000000000000..f2cc4040bb1e --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.merge/inplace_merge.pass.cpp @@ -0,0 +1,159 @@ +// -*- C++ -*- +//===-- inplace_merge.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, + Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, + BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } +#endif + + // inplace_merge works with bidirectional iterators at least + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + const BiDirIt1 mid1 = std::next(first1, m); + fill_data(first1, mid1, generator1); + fill_data(mid1, last1, generator2); + + const BiDirIt1 mid2 = std::next(first2, m); + fill_data(first2, mid2, generator1); + fill_data(mid2, last2, generator2); + + std::inplace_merge(first1, mid1, last1, comp); + std::inplace_merge(exec, first2, mid2, last2, comp); + EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, BiDirIt1, BiDirIt1, BiDirIt1, BiDirIt1, Size, Size, Generator1, Generator2, Compare) + { + } +}; + +template +void +test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) +{ + using namespace std; + size_t max_size = 100000; + Sequence in1(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + size_t m; + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + m = 0; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + + m = n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + + m = 2 * n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + } +} + +template +struct LocalWrapper +{ + explicit LocalWrapper(int32_t k) : my_val(k) {} + LocalWrapper(LocalWrapper&& input) { my_val = std::move(input.my_val); } + LocalWrapper& + operator=(LocalWrapper&& input) + { + my_val = std::move(input.my_val); + return *this; + } + bool + operator<(const LocalWrapper& w) const + { + return my_val < w.my_val; + } + friend bool + operator==(const LocalWrapper& x, const LocalWrapper& y) + { + return x.my_val == y.my_val; + } + friend std::ostream& + operator<<(std::ostream& stream, const LocalWrapper& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { inplace_merge(exec, iter, iter, iter, non_const(std::less())); }); + } +}; + +int +main() +{ + test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, + [](const float64_t x, const float64_t y) { return x > y; }); + + test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); + + test_by_type>([](int32_t i) { return LocalWrapper(2 * i + 1); }, + [](int32_t i) { return LocalWrapper(2 * i); }, + std::less>()); + + test_algo_basic_single(run_for_rnd_bi>()); + + test_by_type( + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2)}; }, + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2 + 1)}; }, + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from inplace_merge: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from inplace_merge: number of ctors calls > num of dtors calls"); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.merge/merge.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.merge/merge.pass.cpp new file mode 100644 index 000000000000..d2381036cda0 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.merge/merge.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===-- merge.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_merge +{ + template + void + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + OutputIterator out_first, OutputIterator out_last, Compare comp) + { + using namespace std; + { + const auto res = merge(exec, first1, last1, first2, last2, out_first, comp); + EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); + EXPECT_TRUE(is_sorted(out_first, res, comp), "wrong result from merge with predicate"); + EXPECT_TRUE(includes(out_first, res, first1, last1, comp), "first sequence is not a part of result"); + EXPECT_TRUE(includes(out_first, res, first2, last2, comp), "second sequence is not a part of result"); + } + { + const auto res = merge(exec, first1, last1, first2, last2, out_first); + EXPECT_TRUE(res == out_last, "wrong return result from merge"); + EXPECT_TRUE(is_sorted(out_first, res), "wrong result from merge"); + } + } + + // for reverse iterators + template + void + operator()(Policy&& exec, std::reverse_iterator first1, std::reverse_iterator last1, + std::reverse_iterator first2, std::reverse_iterator last2, + std::reverse_iterator out_first, std::reverse_iterator out_last, Compare) + { + using namespace std; + typedef typename std::iterator_traits>::value_type T; + const auto res = merge(exec, first1, last1, first2, last2, out_first, std::greater()); + + EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); + EXPECT_TRUE(is_sorted(out_first, res, std::greater()), "wrong result from merge with predicate"); + EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater()), + "first sequence is not a part of result"); + EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater()), + "second sequence is not a part of result"); + } +}; + +template +void +test_merge_by_type(Generator1 generator1, Generator2 generator2) +{ + using namespace std; + size_t max_size = 100000; + Sequence in1(max_size, generator1); + Sequence in2(max_size / 2, generator2); + Sequence out(in1.size() + in2.size()); + std::sort(in1.begin(), in1.end()); + std::sort(in2.begin(), in2.end()); + + for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) + { + invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2, + out.begin(), out.begin() + 1.5 * size, std::less()); + invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2, + out.begin(), out.begin() + 3 * size / 2, std::less()); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) + { + merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +int +main() +{ + test_merge_by_type([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; }); + test_merge_by_type([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); }); + +#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT + test_merge_by_type>([](size_t v) { return Wrapper(v % 100); }, + [](size_t v) { return Wrapper(v % 10); }); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp new file mode 100644 index 000000000000..aeafb020f65f --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp @@ -0,0 +1,147 @@ +// -*- C++ -*- +//===-- copy_if.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for copy_if and remove_copy_if +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_copy_if +{ +#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n, + Predicate pred, T trash) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, Size n, Predicate pred, T trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred, + T trash) + { + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + + // Run copy_if + auto i = copy_if(first, last, expected_first, pred); + auto k = copy_if(exec, first, last, out_first, pred); + EXPECT_EQ_N(expected_first, out_first, n, "wrong copy_if effect"); + for (size_t j = 0; j < GuardSize; ++j) + { + ++k; + } + EXPECT_TRUE(out_last == k, "wrong return value from copy_if"); + + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + // Run remove_copy_if + i = remove_copy_if(first, last, expected_first, [=](const T& x) { return !pred(x); }); + k = remove_copy_if(exec, first, last, out_first, [=](const T& x) { return !pred(x); }); + EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy_if effect"); + for (size_t j = 0; j < GuardSize; ++j) + { + ++k; + } + EXPECT_TRUE(out_last == k, "wrong return value from remove_copy_if"); + } +}; + +template +void +test(T trash, Predicate pred, Convert convert, bool check_weakness = true) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + // count is number of output elements, plus a handful + // more for sake of detecting buffer overruns. + size_t count = GuardSize; + Sequence in(n, [&](size_t k) -> T { + T val = convert(n ^ k); + count += pred(val) ? 1 : 0; + return val; + }); + + Sequence out(count, [=](size_t) { return trash; }); + Sequence expected(count, [=](size_t) { return trash; }); + if (check_weakness) + { + auto expected_result = copy_if(in.cfbegin(), in.cfend(), expected.begin(), pred); + size_t m = expected_result - expected.begin(); + EXPECT_TRUE(n / 4 <= m && m <= 3 * (n + 1) / 4, "weak test for copy_if"); + } + invoke_on_all_policies(run_copy_if(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), count, pred, trash); + invoke_on_all_policies(run_copy_if(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), count, pred, trash); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even)); + + invoke_if(exec, [&]() { remove_copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even)); }); + } +}; + +int +main() +{ + test(-666.0, [](const float64_t& x) { return x * x <= 1024; }, + [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? float64_t(j % 32) : float64_t(j % 33 + 34); }); + + test(-666, [](const int32_t& x) { return x != 42; }, + [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? int32_t(j + 1) : 42; }); + +#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + test(Number(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); +#endif + +#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(-666, [](const int32_t&) { return true; }, [](size_t j) { return j; }, false); +#endif + + test_algo_basic_double(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp new file mode 100644 index 000000000000..e5856a13b07b --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp @@ -0,0 +1,101 @@ +// -*- C++ -*- +//===-- is_partitioned.pass.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ + //dummy specialization by policy type, in case of broken configuration +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN + + template + void + operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Predicate pred) + { + const bool expected = std::is_partitioned(begin1, end1, pred); + const bool actual = std::is_partitioned(exec, begin1, end1, pred); + EXPECT_TRUE(actual == expected, "wrong return result from is_partitioned"); + } +}; + +template +void +test(Predicate pred) +{ + + const std::size_t max_n = 1000000; + Sequence in(max_n, [](std::size_t k) { return T(k); }); + + for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) + { + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, pred); + std::partition(in.begin(), in.begin() + n1, pred); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, pred); + } +} + +template +struct LocalWrapper +{ + explicit LocalWrapper(std::size_t k) : my_val(k) {} + + private: + T my_val; +}; + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + invoke_if(exec, [&]() { is_partitioned(exec, iter, iter, non_const(is_even)); }); + } +}; + +int +main() +{ + test([](const float64_t x) { return x < 0; }); + test([](const int32_t x) { return x > 1000; }); + test([](const uint16_t x) { return x % 5 < 3; }); +#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN && !_PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN + test>([](const LocalWrapper&) { return true; }); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp new file mode 100644 index 000000000000..c376f895664b --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp @@ -0,0 +1,178 @@ +// -*- C++ -*- +//===-- partition.pass.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for stable_partition and partition +#include "support/pstl_test_config.h" + +#include +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct DataType +{ + explicit DataType(int32_t k) : my_val(k) {} + DataType(DataType&& input) { my_val = std::move(input.my_val); } + DataType& + operator=(DataType&& input) + { + my_val = std::move(input.my_val); + return *this; + } + T + get_val() const + { + return my_val; + } + + friend std::ostream& + operator<<(std::ostream& stream, const DataType& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +typename std::enable_if::value_type>::value, bool>::type +is_equal(Iterator first, Iterator last, Iterator d_first) +{ + return std::equal(first, last, d_first); +} + +template +typename std::enable_if::value_type>::value, bool>::type + is_equal(Iterator, Iterator, Iterator) +{ + return true; +} + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, + Size n, UnaryOp unary_op, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, + BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) + { + } +#elif _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, + Size n, UnaryOp unary_op, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, + BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) + { + } +#endif + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size, UnaryOp unary_op, + Generator generator) + { + // partition + { + fill_data(first, last, generator); + BiDirIt actual_ret = std::partition(exec, first, last, unary_op); + EXPECT_TRUE(std::all_of(first, actual_ret, unary_op) && !std::any_of(actual_ret, last, unary_op), + "wrong effect from partition"); + } + // stable_partition + { + fill_data(exp_first, exp_last, generator); + BiDirIt exp_ret = std::stable_partition(exp_first, exp_last, unary_op); + fill_data(first, last, generator); + BiDirIt actual_ret = std::stable_partition(exec, first, last, unary_op); + + EXPECT_TRUE(std::distance(first, actual_ret) == std::distance(exp_first, exp_ret), + "wrong result from stable_partition"); + EXPECT_TRUE((is_equal(exp_first, exp_last, first)), "wrong effect from stable_partition"); + } + } + template + typename std::enable_if::value, void>::type + operator()(Policy&&, BiDirIt, BiDirIt, BiDirIt, BiDirIt, Size, UnaryOp, Generator) + { + } +}; + +template +void +test_by_type(Generator generator, UnaryPred pred) +{ + + using namespace std; + size_t max_size = 100000; + Sequence in(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, n, pred, + generator); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + invoke_if(exec, [&]() { + partition(exec, iter, iter, non_const(is_even)); + stable_partition(exec, iter, iter, non_const(is_even)); + }); + } +}; + +int +main() +{ +#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test_by_type([](int32_t i) { return i; }, [](int32_t) { return true; }); +#endif + test_by_type([](int32_t i) { return -i; }, [](const float64_t x) { return x < 0; }); + test_by_type([](int32_t i) { return i + 1; }, [](int64_t x) { return x % 3 == 0; }); + test_by_type>([](int32_t i) { return DataType(2 * i + 1); }, + [](const DataType& x) { return x.get_val() < 0; }); + + test_algo_basic_single(run_for_rnd_bi()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp new file mode 100644 index 000000000000..1a06c55d3566 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp @@ -0,0 +1,116 @@ +// -*- C++ -*- +//===-- partition_copy.pass.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for stable_partition and partition_copy +#include "support/pstl_test_config.h" + +#include +#include +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_partition_copy +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator true_first, OutputIterator, + OutputIterator2 false_first, OutputIterator2, UnaryOp unary_op) + { + + auto actual_ret = std::partition_copy(exec, first, last, true_first, false_first, unary_op); + + EXPECT_TRUE(std::distance(true_first, actual_ret.first) == std::count_if(first, last, unary_op), + "partition_copy has wrong effect from true sequence"); + EXPECT_TRUE(std::distance(false_first, actual_ret.second) == std::count_if(first, last, std::not_fn(unary_op)), + "partition_copy has wrong effect from false sequence"); + } + + //dummy specialization by iterator type and policy type, in case of broken configuration +#if _PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN + template + void + operator()(pstl::execution::unsequenced_policy, std::reverse_iterator first, + std::reverse_iterator last, std::reverse_iterator true_first, + std::reverse_iterator true_last, std::reverse_iterator false_first, + OutputIterator2 false_last, UnaryOp unary_op) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, std::reverse_iterator first, + std::reverse_iterator last, std::reverse_iterator true_first, + std::reverse_iterator true_last, std::reverse_iterator false_first, + OutputIterator2 false_last, UnaryOp unary_op) + { + } +#endif +}; + +template +void +test(UnaryPred pred) +{ + + const std::size_t max_size = 100000; + Sequence in(max_size, [](std::size_t v) -> T { return T(v); }); + Sequence actual_true(max_size); + Sequence actual_false(max_size); + for (std::size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : std::size_t(3.1415 * n)) + { + + // for non-const input iterators + invoke_on_all_policies(test_partition_copy(), in.begin(), in.begin() + n, actual_true.begin(), + actual_true.begin() + n, actual_false.begin(), actual_false.begin() + n, pred); + + // for const input iterators + invoke_on_all_policies(test_partition_copy(), in.cbegin(), in.cbegin() + n, actual_true.begin(), + actual_true.begin() + n, actual_false.begin(), actual_false.begin() + n, pred); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + + partition_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(is_even)); + } +}; + +int +main() +{ + test([](const int32_t value) { return value % 2; }); + +#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test([](const int32_t) { return true; }); +#endif + + test([](const float64_t value) { return value > 2 << 6; }); + test>([](const Wrapper& value) -> bool { return value.get_my_field() != nullptr; }); + + test_algo_basic_double(run_for_rnd_bi()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp new file mode 100644 index 000000000000..ab51504dd3c9 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===-- reverse.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if _PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN || _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e) + { + } +#endif + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) + { + using namespace std; + + copy(data_b, data_e, actual_b); + + reverse(exec, actual_b, actual_e); + + bool check = equal(data_b, data_e, reverse_iterator(actual_e)); + + EXPECT_TRUE(check, "wrong result of reverse"); + } + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&&, Iterator1, Iterator1, Iterator2, Iterator2) + { + } +}; + +template +void +test() +{ + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { return T(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len); + } +} + +template +struct wrapper +{ + T t; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + bool + operator==(const wrapper& a) const + { + return t == a.t; + } +}; + +int +main() +{ + test(); + test(); + test(); +#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + test>(); +#endif + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp new file mode 100644 index 000000000000..8c79de782441 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp @@ -0,0 +1,132 @@ +// -*- C++ -*- +//===-- reverse_copy.pass.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + wrapper& + operator=(const T& t_) + { + t = t_; + return *this; + } + bool + operator==(const wrapper& t_) const + { + return t == t_.t; + } +}; + +template +bool +eq(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +bool +eq(const T1& a, const T2& b) +{ + return a == b; +} + +// we need to save state here, because we need to test with different types of iterators +// due to the caller invoke_on_all_policies does forcing modification passed iterator type to cover additional usage cases. +template +struct test_one_policy +{ + Iterator data_b; + Iterator data_e; + test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {} + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e) + { + using namespace std; + using T = typename iterator_traits::value_type; + + fill(actual_b, actual_e, T(-123)); + Iterator1 actual_return = reverse_copy(exec, data_b, data_e, actual_b); + + EXPECT_TRUE(actual_return == actual_e, "wrong result of reverse_copy"); + + const auto n = std::distance(data_b, data_e); + Sequence res(n); + std::copy(std::reverse_iterator(data_e), std::reverse_iterator(data_b), res.begin()); + + EXPECT_EQ_N(res.begin(), actual_b, n, "wrong effect of reverse_copy"); + } +}; + +template +void +test() +{ + typedef typename Sequence::iterator iterator_type; + typedef typename Sequence::const_bidirectional_iterator cbi_iterator_type; + + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { return T1(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(data.begin(), data.begin() + len), actual.begin(), + actual.begin() + len); + invoke_on_all_policies(test_one_policy(data.cbibegin(), std::next(data.cbibegin(), len)), + actual.begin(), actual.begin() + len); + } +} + +int +main() +{ + // clang-3.8 fails to correctly auto vectorize the loop in some cases of different types of container's elements, + // for example: int32_t and int8_t. This issue isn't detected for clang-3.9 and newer versions. + test(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/copy_move.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/copy_move.pass.cpp new file mode 100644 index 000000000000..5bef48e625bb --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/copy_move.pass.cpp @@ -0,0 +1,197 @@ +// -*- C++ -*- +//===-- copy_move.pass.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for copy, move and copy_n +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_copy +{ + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, + Size n, T trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, Size size, Size n, T trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size n, T trash) + { + // Cleaning + std::fill_n(expected_first, size, trash); + std::fill_n(out_first, size, trash); + + // Run copy + copy(first, last, expected_first); + auto k = copy(exec, first, last, out_first); + for (size_t j = 0; j < GuardSize; ++j) + ++k; + EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy"); + EXPECT_TRUE(out_last == k, "wrong return value from copy"); + + // Cleaning + std::fill_n(out_first, size, trash); + // Run copy_n + k = copy_n(exec, first, n, out_first); + for (size_t j = 0; j < GuardSize; ++j) + ++k; + EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy_n"); + EXPECT_TRUE(out_last == k, "wrong return value from copy_n"); + } +}; + +template +struct run_move +{ + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, + Size n, T trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, Size size, Size n, T trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size, T trash) + { + // Cleaning + std::fill_n(expected_first, size, trash); + std::fill_n(out_first, size, trash); + + // Run move + move(first, last, expected_first); + auto k = move(exec, first, last, out_first); + for (size_t j = 0; j < GuardSize; ++j) + ++k; + EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from move"); + EXPECT_TRUE(out_last == k, "wrong return value from move"); + } +}; + +template +struct run_move> +{ + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, + Size n, Wrapper trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, Size size, Size n, Wrapper trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2, OutputIterator2, Size size, Size, Wrapper trash) + { + // Cleaning + std::fill_n(out_first, size, trash); + Wrapper::SetMoveCount(0); + + // Run move + auto k = move(exec, first, last, out_first); + for (size_t j = 0; j < GuardSize; ++j) + ++k; + EXPECT_TRUE(Wrapper::MoveCount() == size, "wrong effect from move"); + EXPECT_TRUE(out_last == k, "wrong return value from move"); + } +}; + +template +void +test(T trash, Convert convert) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + // count is number of output elements, plus a handful + // more for sake of detecting buffer overruns. + Sequence in(n, [&](size_t k) -> T { + T val = convert(n ^ k); + return val; + }); + + const size_t outN = n + GuardSize; + Sequence out(outN, [=](size_t) { return trash; }); + Sequence expected(outN, [=](size_t) { return trash; }); + invoke_on_all_policies(run_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), outN, n, trash); + invoke_on_all_policies(run_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), outN, n, trash); + invoke_on_all_policies(run_move(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), n, n, trash); + + // For this test const iterator isn't suitable + // because const rvalue-reference call copy assignment operator + } +} + +int +main() +{ + test(-666, [](size_t j) { return int32_t(j); }); + test>(Wrapper(-666.0), [](int32_t j) { return Wrapper(j); }); + +#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT + test(-666.0, [](size_t j) { return float64_t(j); }); + test(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); +#endif + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/fill.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/fill.pass.cpp new file mode 100644 index 000000000000..5d1715705c60 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/fill.pass.cpp @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===-- fill.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_fill +{ + template + bool + check(It first, It last, const T& value) + { + for (; first != last; ++first) + if (*first != value) + return false; + return true; + } + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, const T& value) + { + fill(first, last, T(value + 1)); // initialize memory with different value + + fill(exec, first, last, value); + EXPECT_TRUE(check(first, last, value), "fill wrong result"); + } +}; + +struct test_fill_n +{ + template + bool + check(It first, Size n, const T& value) + { + for (Size i = 0; i < n; ++i, ++first) + if (*first != value) + return false; + return true; + } + + template + void + operator()(Policy&& exec, Iterator first, Size n, const T& value) + { + fill_n(first, n, T(value + 1)); // initialize memory with different value + + const Iterator one_past_last = fill_n(exec, first, n, value); + const Iterator expected_return = std::next(first, n); + + EXPECT_TRUE(expected_return == one_past_last, "fill_n should return Iterator to one past the element assigned"); + EXPECT_TRUE(check(first, n, value), "fill_n wrong result"); + + //n == -1 + const Iterator res = fill_n(exec, first, -1, value); + EXPECT_TRUE(res == first, "fill_n wrong result for n == -1"); + } +}; + +template +void +test_fill_by_type(std::size_t n) +{ + Sequence in(n, [](std::size_t) -> T { return T(0); }); //fill with zeros + T value = -1; + + invoke_on_all_policies(test_fill(), in.begin(), in.end(), value); + invoke_on_all_policies(test_fill_n(), in.begin(), n, value); +} + +int +main() +{ + + const std::size_t N = 100000; + + for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.1415 * n)) + { + test_fill_by_type(n); + test_fill_by_type(n); + } + + std::cout << done() << std::endl; + + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/generate.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/generate.pass.cpp new file mode 100644 index 000000000000..4561f3c6dcef --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/generate.pass.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===-- generate.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Generator_count +{ + const T def_val = T(-1); + T + operator()() + { + return def_val; + } + T + default_value() const + { + return def_val; + } +}; + +struct test_generate +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Size n) + { + using namespace std; + typedef typename std::iterator_traits::value_type T; + + // Try random-access iterator + { + Generator_count g; + generate(exec, first, last, g); + Size count = std::count(first, last, g.default_value()); + EXPECT_TRUE(count == n, "generate wrong result for generate"); + std::fill(first, last, T(0)); + } + + { + Generator_count g; + const auto m = n / 2; + auto actual_last = generate_n(exec, first, m, g); + Size count = std::count(first, actual_last, g.default_value()); + EXPECT_TRUE(count == m && actual_last == std::next(first, m), "generate_n wrong result for generate_n"); + std::fill(first, actual_last, T(0)); + } + } +}; + +template +void +test_generate_by_type() +{ + for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t) -> T { return T(0); }); //fill by zero + + invoke_on_all_policies(test_generate(), in.begin(), in.end(), in.size()); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto gen = []() { return T(0); }; + + generate(exec, iter, iter, non_const(gen)); + generate_n(exec, iter, 0, non_const(gen)); + } +}; + +int +main() +{ + + test_generate_by_type(); + test_generate_by_type(); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove.pass.cpp new file mode 100644 index 000000000000..c41a31d7310d --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove.pass.cpp @@ -0,0 +1,161 @@ +// -*- C++ -*- +//===-- remove.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Test for remove, remove_if +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_remove +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, + const T& value) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, + OutputIterator expected_last, Size n, const T& value) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size, + const T& value) + { + // Cleaning + std::copy(first, last, expected_first); + std::copy(first, last, out_first); + + // Run remove + OutputIterator i = remove(expected_first, expected_last, value); + OutputIterator k = remove(exec, out_first, out_last, value); + EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k), "wrong return value from remove"); + EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove effect"); + } +}; + +struct run_remove_if +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, + Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, + OutputIterator expected_last, Size n, Predicate pred) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size, + Predicate pred) + { + // Cleaning + std::copy(first, last, expected_first); + std::copy(first, last, out_first); + + // Run remove_if + OutputIterator i = remove_if(expected_first, expected_last, pred); + OutputIterator k = remove_if(exec, out_first, out_last, pred); + EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k), + "wrong return value from remove_if"); + EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove_if effect"); + } +}; + +template +void +test(T trash, const T& value, Predicate pred, Convert convert) +{ + const std::size_t max_size = 100000; + Sequence out(max_size, [trash](size_t) { return trash; }); + Sequence expected(max_size, [trash](size_t) { return trash; }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence data(n, [&](size_t k) -> T { return convert(k); }); + + invoke_on_all_policies(run_remove(), data.begin(), data.end(), out.begin(), out.begin() + n, expected.begin(), + expected.begin() + n, n, value); + invoke_on_all_policies(run_remove_if(), data.begin(), data.end(), out.begin(), out.begin() + n, + expected.begin(), expected.begin() + n, n, pred); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + + invoke_if(exec, [&]() { remove_if(exec, iter, iter, non_const(is_even)); }); + } +}; + +int +main() +{ +#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN + test(666, 42, [](int32_t) { return true; }, [](size_t j) { return j; }); +#endif + + test(666, 2001, [](const int32_t& val) { return val != 2001; }, + [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 2001 : -1 - int32_t(j); }); + test(-666.0, 8.5, [](const float64_t& val) { return val != 8.5; }, + [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); + +#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + test(Number(-666, OddTag()), Number(42, OddTag()), IsMultiple(3, OddTag()), + [](int32_t j) { return Number(j, OddTag()); }); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + test(MemoryChecker{0}, MemoryChecker{1}, + [](const MemoryChecker& val){ return val.value() == 1; }, + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx % 3 == 0)}; } + ); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from remove,remove_if: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from remove,remove_if: number of ctors calls > num of dtors calls"); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove_copy.pass.cpp new file mode 100644 index 000000000000..969343b3764c --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/remove_copy.pass.cpp @@ -0,0 +1,91 @@ +// -*- C++ -*- +//===-- remove_copy.pass.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_remove_copy +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, const T& value, + T trash) + { + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + + // Run copy_if + auto i = std::remove_copy(first, last, expected_first, value); + (void)i; + auto k = std::remove_copy(exec, first, last, out_first, value); + EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy effect"); + for (size_t j = 0; j < GuardSize; ++j) + { + ++k; + } + EXPECT_TRUE(out_last == k, "wrong return value from remove_copy"); + } +}; + +template +void +test(T trash, const T& value, Convert convert, bool check_weakness = true) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + // count is number of output elements, plus a handful + // more for sake of detecting buffer overruns. + size_t count = GuardSize; + Sequence in(n, [&](size_t k) -> T { + T x = convert(n ^ k); + count += !(x == value) ? 1 : 0; + return x; + }); + using namespace std; + + Sequence out(count, [=](size_t) { return trash; }); + Sequence expected(count, [=](size_t) { return trash; }); + if (check_weakness) + { + auto expected_result = remove_copy(in.cfbegin(), in.cfend(), expected.begin(), value); + size_t m = expected_result - expected.begin(); + EXPECT_TRUE(n / 4 <= m && m <= 3 * (n + 1) / 4, "weak test for remove_copy"); + } + invoke_on_all_policies(run_remove_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), count, value, trash); + invoke_on_all_policies(run_remove_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), count, value, trash); + } +} + +int +main() +{ + + test(-666.0, 8.5, [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); + + test(-666, 42, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); }); + + test(Number(42, OddTag()), Number(2001, OddTag()), + [](int32_t j) { return ((j + 1) % 3 & 2) != 0 ? Number(2001, OddTag()) : Number(j, OddTag()); }); + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace.pass.cpp new file mode 100644 index 000000000000..d42dae76ebd1 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace.pass.cpp @@ -0,0 +1,159 @@ +// -*- C++ -*- +//===-- replace.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// This class is needed to check the self-copying +struct copy_int +{ + int32_t value; + int32_t copied_times = 0; + constexpr explicit copy_int(int32_t val = 0) : value(val) {} + + constexpr copy_int& + operator=(const copy_int& other) + { + if (&other == this) + copied_times++; + else + { + value = other.value; + copied_times = other.copied_times; + } + return *this; + } + + constexpr bool + operator==(const copy_int& other) const + { + return (value == other.value); + } +}; + +template +struct test_one_policy +{ + std::size_t len; + Iterator data_b; + Iterator data_e; + test_one_policy(Iterator data_, std::size_t len_) + { + len = len_; + data_b = data_; + data_e = std::next(data_b, len); + } + template + void + operator()(ExecutionPolicy&& exec, Iterator1 expected_b, Iterator1 expected_e, Iterator2 actual_b, + Iterator2 actual_e, Predicate pred, const T& value, const T& old_value) + { + using namespace std; + + copy(data_b, data_e, expected_b); + copy(data_b, data_e, actual_b); + + replace(expected_b, expected_e, old_value, value); + replace(exec, actual_b, actual_e, old_value, value); + + EXPECT_TRUE((check(actual_b, actual_e)), "wrong result of self assignment check"); + EXPECT_TRUE(equal(expected_b, expected_e, actual_b), "wrong result of replace"); + + copy(data_b, data_e, expected_b); + copy(data_b, data_e, actual_b); + + replace_if(expected_b, expected_e, pred, value); + replace_if(exec, actual_b, actual_e, pred, value); + EXPECT_TRUE(equal(expected_b, expected_e, actual_b), "wrong result of replace_if"); + } + + template + bool check(Iterator1, Iterator1) + { + return true; + } + + template + typename std::enable_if::value, bool>::type_t + check(Iterator1 b, Iterator1 e) + { + return std::all_of(b, e, [](const copy_int& elem) { return elem.copied_times == 0; }); + } +}; + +template +void +test(Pred pred) +{ + typedef typename Sequence::iterator iterator_type; + + const std::size_t max_len = 100000; + + static constexpr T1 value = T1(0); + static constexpr T1 new_value = T1(666); + + Sequence expected(max_len); + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { + if (i % 3 == 2) + { + return T1(i); + } + else + { + return value; + } + }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + test_one_policy temp(data.begin(), len); + + invoke_on_all_policies(temp, expected.begin(), expected.begin() + len, actual.begin(), actual.begin() + len, + pred, new_value, value); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + invoke_if(exec, [&]() { replace_if(exec, iter, iter, non_const(is_even), T(0)); }); + } +}; + +int +main() +{ + test(__pstl::__internal::__equal_value(666)); + test([](const uint16_t& elem) { return elem % 3 < 2; }); + test([](const float64_t& elem) { return elem * elem - 3.5 * elem > 10; }); + test([](const copy_int& val) { return val.value / 5 > 2; }); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace_copy.pass.cpp new file mode 100644 index 000000000000..4414d1cbd353 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/replace_copy.pass.cpp @@ -0,0 +1,105 @@ +// -*- C++ -*- +//===-- replace_copy.pass.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for replace_copy and replace_copy_if + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_replace_copy +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred, + const T& old_value, const T& new_value, T trash) + { + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + // Run replace_copy + auto i = std::replace_copy(first, last, expected_first, old_value, new_value); + auto k = std::replace_copy(exec, first, last, out_first, old_value, new_value); + EXPECT_EQ_N(expected_first, out_first, n, "wrong replace_copy effect"); + EXPECT_TRUE(out_last == k, "wrong return value from replace_copy"); + + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + // Run replace_copy_if + i = replace_copy_if(first, last, expected_first, pred, new_value); + k = replace_copy_if(exec, first, last, out_first, pred, new_value); + EXPECT_EQ_N(expected_first, out_first, n, "wrong replace_copy_if effect"); + EXPECT_TRUE(out_last == k, "wrong return value from replace_copy_if"); + } +}; + +template +void +test(T trash, const T& old_value, const T& new_value, Predicate pred, Convert convert) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [&](size_t k) -> T { return convert(n ^ k); }); + Sequence out(n, [=](size_t) { return trash; }); + Sequence expected(n, [=](size_t) { return trash; }); + + invoke_on_all_policies(test_replace_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), out.size(), pred, old_value, new_value, trash); + invoke_on_all_policies(test_replace_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), out.size(), pred, old_value, new_value, trash); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + + invoke_if(exec, [&]() { replace_copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even), T(0)); }); + } +}; + +int +main() +{ + + test(-666.0, 8.5, 0.33, [](const float64_t& x) { return x * x <= 1024; }, + [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); + + test(-666, 42, 99, [](const int32_t& x) { return x != 42; }, + [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); }); + +#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + test(Number(42, OddTag()), Number(2001, OddTag()), Number(2017, OddTag()), IsMultiple(3, OddTag()), + [](int32_t j) { return ((j + 1) % 3 & 2) != 0 ? Number(2001, OddTag()) : Number(j, OddTag()); }); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate.pass.cpp new file mode 100644 index 000000000000..03f2b3cb2e87 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate.pass.cpp @@ -0,0 +1,176 @@ +// -*- C++ -*- +//===-- rotate.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + int move_count; + explicit wrapper(T t_) : t(t_), move_count(0) {} + wrapper& + operator=(const T& t_) + { + t = t_; + return *this; + } + + wrapper(const wrapper& a) : move_count(0) { t = a.t; } + + wrapper& + operator=(wrapper& a) + { + t = a.t; + return *this; + } + + wrapper& + operator=(wrapper&& a) + { + t = a.t; + move_count += 1; + return *this; + } +}; + +template +struct compare +{ + bool + operator()(const T& a, const T& b) + { + return a == b; + } +}; + +template +struct compare> +{ + bool + operator()(const wrapper& a, const wrapper& b) + { + return a.t == b.t; + } +}; +#include + +struct test_one_policy +{ + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, + Iterator actual_e, Size shift) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, + Iterator actual_e, Size shift) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator data_b, Iterator data_e, Iterator actual_b, Iterator actual_e, + Size shift) + { + using namespace std; + using T = typename iterator_traits::value_type; + Iterator actual_m = std::next(actual_b, shift); + + copy(data_b, data_e, actual_b); + Iterator actual_return = rotate(exec, actual_b, actual_m, actual_e); + + EXPECT_TRUE(actual_return == std::next(actual_b, std::distance(actual_m, actual_e)), "wrong result of rotate"); + auto comparator = compare(); + bool check = std::equal(actual_return, actual_e, data_b, comparator); + check = check && std::equal(actual_b, actual_return, std::next(data_b, shift), comparator); + + EXPECT_TRUE(check, "wrong effect of rotate"); + EXPECT_TRUE(check_move(exec, actual_b, actual_e, shift), "wrong move test of rotate"); + } + + template + typename std::enable_if< + is_same_iterator_category::value && + !std::is_same::value && + std::is_same::value_type, wrapper>::value, + bool>::type + check_move(ExecutionPolicy&&, Iterator b, Iterator e, Size shift) + { + bool result = all_of(b, e, [](wrapper& a) { + bool temp = a.move_count > 0; + a.move_count = 0; + return temp; + }); + return shift == 0 || result; + } + + template + typename std::enable_if< + !(is_same_iterator_category::value && + !std::is_same::value && + std::is_same::value_type, wrapper>::value), + bool>::type + check_move(ExecutionPolicy&&, Iterator, Iterator, Size) + { + return true; + } +}; + +template +void +test() +{ + const int32_t max_len = 100000; + + Sequence actual(max_len, [](std::size_t i) { return T(i); }); + Sequence data(max_len, [](std::size_t i) { return T(i); }); + + for (int32_t len = 0; len < max_len; len = len <= 16 ? len + 1 : int32_t(3.1415 * len)) + { + int32_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; + for (auto shift : shifts) + { + if (shift >= 0 && shift < len) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len, shift); + } + } + } +} + +int +main() +{ + test(); + test>(); + test(); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from rotate: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from rotate: number of ctors calls > num of dtors calls"); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate_copy.pass.cpp new file mode 100644 index 000000000000..3749492e2a28 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/rotate_copy.pass.cpp @@ -0,0 +1,146 @@ +// -*- C++ -*- +//===-- rotate_copy.pass.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper; + +template +bool +compare(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +bool +compare(const T& a, const T& b) +{ + return a == b; +} + +template +struct wrapper +{ + explicit wrapper(T t_) : t(t_) {} + wrapper& + operator=(const T& t_) + { + t = t_; + return *this; + } + friend bool + compare(const wrapper& a, const wrapper& b); + + private: + T t; +}; + +template +struct comparator +{ + using T1 = typename std::iterator_traits::value_type; + using T2 = typename std::iterator_traits::value_type; + bool + operator()(T1 a, T2 b) + { + T temp = a; + return compare(temp, b); + } +}; + +struct test_one_policy +{ + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, std::size_t shift) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, std::size_t shift) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, + std::size_t shift) + { + using namespace std; + using T = typename iterator_traits::value_type; + Iterator1 data_m = std::next(data_b, shift); + + fill(actual_b, actual_e, T(-123)); + Iterator2 actual_return = rotate_copy(exec, data_b, data_m, data_e, actual_b); + + EXPECT_TRUE(actual_return == actual_e, "wrong result of rotate_copy"); + auto comparer = comparator(); + bool check = std::equal(data_m, data_e, actual_b, comparer); + check = check && std::equal(data_b, data_m, std::next(actual_b, std::distance(data_m, data_e)), comparer); + + EXPECT_TRUE(check, "wrong effect of rotate_copy"); + } +}; + +template +void +test() +{ + + const std::size_t max_len = 100000; + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [](std::size_t i) { return T1(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + std::size_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; + for (std::size_t shift : shifts) + { + if (shift > 0 && shift < len) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len, shift); + invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), + actual.begin() + len, shift); + } + } + } +} + +int +main() +{ + test(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/swap_ranges.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/swap_ranges.pass.cpp new file mode 100644 index 000000000000..2c8f652fdefd --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/swap_ranges.pass.cpp @@ -0,0 +1,133 @@ +// -*- C++ -*- +//===-- swap_ranges.pass.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + std::size_t number_of_swaps = 0; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + template + void + operator=(const U& b) + { + t = b; + } + bool + operator==(const wrapper& a) const + { + return t == a.t; + } +}; + +template +void +swap(wrapper& a, wrapper& b) +{ + std::swap(a.t, b.t); + a.number_of_swaps++; + b.number_of_swaps++; +} + +template +struct check_swap +{ + bool + operator()(T&) + { + return true; + } +}; + +template +struct check_swap> +{ + bool + operator()(wrapper& a) + { + bool temp = (a.number_of_swaps == 1); + a.number_of_swaps = 0; + return temp; + } +}; + +struct test_one_policy +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) + { + using namespace std; + using T_ref = typename iterator_traits::reference; + using T = typename iterator_traits::value_type; + + iota(data_b, data_e, 0); + iota(actual_b, actual_e, std::distance(data_b, data_e)); + + Iterator2 actual_return = swap_ranges(exec, data_b, data_e, actual_b); + bool check_return = (actual_return == actual_e); + EXPECT_TRUE(check_return, "wrong result of swap_ranges"); + if (check_return) + { + std::size_t i = 0; + bool check = all_of(actual_b, actual_e, [&i](T_ref a) { return a == T(i++); }) && + all_of(data_b, data_e, [&i](T_ref a) { return a == T(i++); }); + + EXPECT_TRUE(check, "wrong effect of swap_ranges"); + + if (check) + { + bool swap_check = + all_of(data_b, data_e, check_swap()) && all_of(actual_b, actual_e, check_swap()); + EXPECT_TRUE(swap_check, "wrong effect of swap_ranges swap check"); + } + } + } +}; + +template +void +test() +{ + const std::size_t max_len = 100000; + + Sequence data(max_len); + Sequence actual(max_len); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len); + } +} + +int +main() +{ + test>(); + test>(); + test(); + test(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_binary.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_binary.pass.cpp new file mode 100644 index 000000000000..d0f8c68afa72 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_binary.pass.cpp @@ -0,0 +1,122 @@ +// -*- C++ -*- +//===-- transform_binary.pass.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +class TheOperation +{ + Out val; + + public: + TheOperation(Out v) : val(v) {} + Out + operator()(const In1& x, const In2& y) const + { + return Out(val + x - y); + } +}; + +template +void +check_and_reset(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator out_first) +{ + typedef typename std::iterator_traits::value_type Out; + typename std::iterator_traits::difference_type k = 0; + for (; first1 != last1; ++first1, ++first2, ++out_first, ++k) + { + // check + Out expected = Out(1.5) + *first1 - *first2; + Out actual = *out_first; + if (std::is_floating_point::value) + { + EXPECT_TRUE((expected > actual ? expected - actual : actual - expected) < 1e7, + "wrong value in output sequence"); + } + else + { + EXPECT_EQ(expected, actual, "wrong value in output sequence"); + } + // reset + *out_first = k % 7 != 4 ? 7 * k - 5 : 0; + } +} + +struct test_one_policy +{ + template + void + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2, + OutputIterator out_first, OutputIterator, BinaryOp op) + { + auto result = std::transform(exec, first1, last1, first2, out_first, op); + (void)result; + check_and_reset(first1, last1, first2, out_first); + } +}; + +template +void +test(Predicate pred) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in1(n, [](size_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); + Sequence in2(n, [](size_t k) { return k % 7 != 2 ? 5 * k - 5 : 0; }); + + Sequence out(n, [](size_t) { return -1; }); + + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.begin(), in2.end(), out.begin(), + out.end(), pred); + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cend(), in2.cbegin(), in2.cend(), out.begin(), + out.end(), pred); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + invoke_if(exec, [&]() { + InputIterator input_iter2 = input_iter; + transform(exec, input_iter, input_iter, input_iter2, out_iter, non_const(std::plus())); + }); + } +}; + +int +main() +{ + //const operator() + test(TheOperation(1)); + test(TheOperation(1.5)); + //non-const operator() + test(non_const(TheOperation(1.5))); + test(non_const(TheOperation(1.5))); + //lambda + test([](const int8_t& x, const float64_t& y) { return int8_t(int8_t(1.5) + x - y); }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_unary.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_unary.pass.cpp new file mode 100644 index 000000000000..55726db0c276 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/transform_unary.pass.cpp @@ -0,0 +1,91 @@ +// -*- C++ -*- +//===-- transform_unary.pass.cpp ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +void +check_and_reset(InputIterator first, InputIterator last, OutputIterator out_first) +{ + typedef typename std::iterator_traits::value_type Out; + typename std::iterator_traits::difference_type k = 0; + for (; first != last; ++first, ++out_first, ++k) + { + // check + Out expected = 1 - *first; + Out actual = *out_first; + EXPECT_EQ(expected, actual, "wrong value in output sequence"); + // reset + *out_first = k % 7 != 4 ? 7 * k - 5 : 0; + } +} + +struct test_one_policy +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, UnaryOp op) + { + auto orr = std::transform(exec, first, last, out_first, op); + EXPECT_TRUE(out_last == orr, "transform returned wrong iterator"); + check_and_reset(first, last, out_first); + } +}; + +template +void +test() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](int32_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); + + Sequence out(n); + + const auto flip = Complement(1); + invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), out.begin(), out.end(), flip); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), out.begin(), out.end(), flip); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + invoke_if(exec, [&]() { transform(exec, input_iter, input_iter, out_iter, non_const(std::negate())); }); + } +}; + +int +main() +{ + test(); + test(); + test(); + test(); + test(); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique.pass.cpp new file mode 100644 index 000000000000..2f68c00401fe --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique.pass.cpp @@ -0,0 +1,163 @@ +// -*- C++ -*- +//===-- unique.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Test for unique +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_unique +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, Generator generator) + { + } + + template + void + operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, BinaryPred pred, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, BinaryPred pred, Generator generator) + { + } +#endif + + template + void + operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, Generator generator) + { + using namespace std; + + // Preparation + fill_data(first1, last1, generator); + fill_data(first2, last2, generator); + + ForwardIt i = unique(first1, last1); + ForwardIt k = unique(exec, first2, last2); + + auto n = std::distance(first1, i); + EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique without predicate"); + EXPECT_EQ_N(first1, first2, n, "wrong effect from unique without predicate"); + } + + template + void + operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, BinaryPred pred, + Generator generator) + { + using namespace std; + + // Preparation + fill_data(first1, last1, generator); + fill_data(first2, last2, generator); + + ForwardIt i = unique(first1, last1, pred); + ForwardIt k = unique(exec, first2, last2, pred); + + auto n = std::distance(first1, i); + EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique with predicate"); + EXPECT_EQ_N(first1, first2, n, "wrong effect from unique with predicate"); + } +}; + +template +void +test(Generator generator, Predicate pred) +{ + const std::size_t max_size = 1000000; + Sequence in(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, generator); + invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, pred, generator); + } +} + +template +struct LocalWrapper +{ + T my_val; + + explicit LocalWrapper(T k) : my_val(k) {} + LocalWrapper(LocalWrapper&& input) : my_val(std::move(input.my_val)) {} + LocalWrapper& + operator=(LocalWrapper&& input) + { + my_val = std::move(input.my_val); + return *this; + } + friend bool + operator==(const LocalWrapper& x, const LocalWrapper& y) + { + return x.my_val == y.my_val; + } +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { unique(exec, iter, iter, non_const(std::equal_to())); }); + } +}; + +int +main() +{ +#if !_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN + test([](size_t j) { return j / 3; }, + [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; }); + test([](size_t) { return float64_t(1); }, + [](const float64_t& val1, const float64_t& val2) { return val1 != val2; }); +#endif + test>([](size_t j) { return LocalWrapper(j); }, + [](const LocalWrapper& val1, const LocalWrapper& val2) { + return val1.my_val != val2.my_val; + }); + + test_algo_basic_single(run_for_rnd_fw>()); + + test( + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx / 3)}; }, + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from unique: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from unique: number of ctors calls > num of dtors calls"); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp new file mode 100644 index 000000000000..b1590ef0b14c --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp @@ -0,0 +1,135 @@ +// -*- C++ -*- +//===-- unique_copy_equal.pass.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for unique_copy +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_unique_copy +{ +#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n, + Predicate pred, T trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, Size n, Predicate pred, T trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred, + T trash) + { + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + + // Run unique_copy + auto i = unique_copy(first, last, expected_first); + auto k = unique_copy(exec, first, last, out_first); + EXPECT_EQ_N(expected_first, out_first, n, "wrong unique_copy effect"); + for (size_t j = 0; j < GuardSize; ++j) + { + ++k; + } + EXPECT_TRUE(out_last == k, "wrong return value from unique_copy"); + + // Cleaning + std::fill_n(expected_first, n, trash); + std::fill_n(out_first, n, trash); + // Run unique_copy with predicate + i = unique_copy(first, last, expected_first, pred); + k = unique_copy(exec, first, last, out_first, pred); + EXPECT_EQ_N(expected_first, out_first, n, "wrong unique_copy with predicate effect"); + for (size_t j = 0; j < GuardSize; ++j) + { + ++k; + } + EXPECT_TRUE(out_last == k, "wrong return value from unique_copy with predicate"); + } +}; + +template +void +test(T trash, BinaryPredicate pred, Convert convert, bool check_weakness = true) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + // count is number of output elements, plus a handful + // more for sake of detecting buffer overruns. + Sequence in(n, [&](size_t k) -> T { return convert(k ^ n); }); + using namespace std; + size_t count = GuardSize; + for (size_t k = 0; k < in.size(); ++k) + count += k == 0 || !pred(in[k], in[k - 1]) ? 1 : 0; + Sequence out(count, [=](size_t) { return trash; }); + Sequence expected(count, [=](size_t) { return trash; }); + if (check_weakness) + { + auto expected_result = unique_copy(in.begin(), in.end(), expected.begin(), pred); + size_t m = expected_result - expected.begin(); + EXPECT_TRUE(n / (n < 10000 ? 4 : 6) <= m && m <= (3 * n + 1) / 4, "weak test for unique_copy"); + } + invoke_on_all_policies(run_unique_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), count, pred, trash); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + unique_copy(exec, input_iter, input_iter, out_iter, non_const(std::equal_to())); + } +}; + +int +main() +{ + test(Number(42, OddTag()), std::equal_to(), + [](int32_t j) { return Number(3 * j / 13 ^ (j & 8), OddTag()); }); + + test(float32_t(42), std::equal_to(), + [](int32_t j) { return float32_t(5 * j / 23 ^ (j / 7)); }); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(float32_t(42), [](float32_t, float32_t) { return false; }, [](int32_t j) { return float32_t(j); }, + false); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/adjacent_find.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/adjacent_find.pass.cpp new file mode 100644 index 000000000000..8f00351dcd07 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/adjacent_find.pass.cpp @@ -0,0 +1,114 @@ +// -*- C++ -*- +//===-- adjacent_find.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_adjacent_find +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Pred pred) + { + using namespace std; + + auto k = std::adjacent_find(first, last, pred); + auto i = adjacent_find(exec, first, last, pred); + EXPECT_TRUE(i == k, "wrong return value from adjacent_find with predicate"); + + i = adjacent_find(exec, first, last); + EXPECT_TRUE(i == k, "wrong return value from adjacent_find without predicate"); + } +}; + +template +void +test_adjacent_find_by_type() +{ + + size_t counts[] = {2, 3, 500}; + for (size_t c = 0; c < const_size(counts); ++c) + { + + for (size_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e) + { + Sequence in(counts[c], [](size_t v) -> T { return T(v); }); //fill 0...n + in[e] = in[e + 1] = -1; //make an adjacent pair + + auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); + EXPECT_TRUE(i == in.cbegin() + e, "std::adjacent_find returned wrong result"); + + invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); + } + } + + //special cases: size=0, size=1; + for (size_t expect = 0; expect < 1; ++expect) + { + Sequence in(expect, [](size_t v) -> T { return T(v); }); //fill 0...n + auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); + EXPECT_TRUE(i == in.cbegin() + expect, "std::adjacent_find returned wrong result"); + + invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); + } + + //special cases: + Sequence a1 = {5, 5, 5, 6, 7, 8, 9}; + invoke_on_all_policies(test_adjacent_find(), a1.begin(), a1.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a1.begin() + 1, a1.end(), std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a1.cbegin(), a1.cend(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a1.cbegin() + 1, a1.cend(), std::equal_to()); + + Sequence a2 = {5, 6, 7, 8, 9, 9}; + invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end() - 1, std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend() - 1, std::equal_to()); + + Sequence a3 = {5, 6, 6, 6, 7, 9, 9, 9, 9}; + invoke_on_all_policies(test_adjacent_find(), a3.begin(), a3.end(), std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a3.cbegin(), a3.cend(), std::equal_to()); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + adjacent_find(exec, iter, iter, non_const(std::equal_to())); + } +}; + +int +main() +{ + + test_adjacent_find_by_type(); + test_adjacent_find_by_type(); + + test_algo_basic_single(run_for_rnd_bi>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/all_of.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/all_of.pass.cpp new file mode 100644 index 000000000000..97e41441ac4f --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/all_of.pass.cpp @@ -0,0 +1,117 @@ +// -*- C++ -*- +//===-- all_of.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_all_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::all_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for all_of"); + } +}; + +template +struct Parity +{ + bool parity; + + public: + Parity(bool parity_) : parity(parity_) {} + bool + operator()(T value) const + { + return (size_t(value) ^ parity) % 2 == 0; + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + Sequence inCopy(in); + + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), true); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), true); + EXPECT_EQ(in, inCopy, "all_of modified input sequence"); + if (n > 0) + { + // Sprinkle in a miss + in[2 * n / 3] = spike; + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); + + // Sprinkle in a few more misses + in[n / 2] = spike; + in[n / 3] = spike; + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + all_of(exec, iter, iter, non_const(is_even)); + } +}; + +int +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/any_of.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/any_of.pass.cpp new file mode 100644 index 000000000000..1430de9b63db --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/any_of.pass.cpp @@ -0,0 +1,103 @@ +// -*- C++ -*- +//===-- any_of.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_any_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::any_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for any_of"); + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + Sequence inCopy(in); + + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + EXPECT_EQ(in, inCopy, "any_of modified input sequence"); + if (n > 0) + { + // Sprinkle in a hit + in[2 * n / 3] = spike; + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + + // Sprinkle in a few more hits + in[n / 2] = spike; + in[n / 3] = spike; + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + any_of(exec, iter, iter, non_const(is_even)); + } +}; + +int +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/count.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/count.pass.cpp new file mode 100644 index 000000000000..7ec77f376048 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/count.pass.cpp @@ -0,0 +1,108 @@ +// -*- C++ -*- +//===-- count.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for count and count_if +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_count +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, T needle) + { + auto expected = std::count(first, last, needle); + auto result = std::count(exec, first, last, needle); + EXPECT_EQ(expected, result, "wrong count result"); + } +}; + +struct test_count_if +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + { + auto expected = std::count_if(first, last, pred); + auto result = std::count_if(exec, first, last, pred); + EXPECT_EQ(expected, result, "wrong count_if result"); + } +}; + +template +class IsEqual +{ + T value; + + public: + IsEqual(T value_, OddTag) : value(value_) {} + bool + operator()(const T& x) const + { + return x == value; + } +}; + +template +void +test(T needle, Predicate pred, Convert convert) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [=](size_t k) -> In { + // Sprinkle "42" and "50" early, so that short sequences have non-zero count. + return convert((n - k - 1) % 3 == 0 ? 42 : (n - k - 2) % 5 == 0 ? 50 : 3 * (int(k) % 1000 - 500)); + }); + invoke_on_all_policies(test_count(), in.begin(), in.end(), needle); + invoke_on_all_policies(test_count_if(), in.begin(), in.end(), pred); + + invoke_on_all_policies(test_count(), in.cbegin(), in.cend(), needle); + invoke_on_all_policies(test_count_if(), in.cbegin(), in.cend(), pred); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + count_if(exec, iter, iter, non_const(is_even)); + } +}; + +int +main() +{ + test(42, IsEqual(50, OddTag()), [](int32_t j) { return j; }); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(42, [](const int32_t&) { return true; }, [](int32_t j) { return j; }); +#endif + test(42, IsEqual(50, OddTag()), [](int32_t j) { return float64_t(j); }); + test(Number(42, OddTag()), IsEqual(Number(50, OddTag()), OddTag()), + [](int32_t j) { return Number(j, OddTag()); }); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/equal.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/equal.pass.cpp new file mode 100644 index 000000000000..45ec237a4b2c --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/equal.pass.cpp @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===-- equal.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +#define CPP14_ENABLED 0 + +struct UserType +{ + size_t key; + float32_t f; + float64_t d; + int32_t i; + + bool + operator()(UserType a, UserType b) + { + return a.key < b.key; + } + bool + operator<(UserType a) + { + return a.key < key; + } + bool + operator>=(UserType a) + { + return a.key <= key; + } + bool + operator<=(UserType a) + { + return a.key >= key; + } + bool + operator==(UserType a) + { + return a.key == key; + } + bool + operator==(UserType a) const + { + return a.key == key; + } + bool + operator!=(UserType a) + { + return a.key != key; + } + UserType operator!() + { + UserType tmp; + tmp.key = !key; + return tmp; + } + friend std::ostream& + operator<<(std::ostream& stream, const UserType a) + { + stream << a.key; + return stream; + } + + UserType() : key(-1), f(0.0f), d(0.0), i(0) {} + UserType(size_t Number) : key(Number), f(0.0f), d(0.0), i(0) {} + UserType& + operator=(const UserType& other) + { + key = other.key; + return *this; + } + UserType(const UserType& other) : key(other.key), f(other.f), d(other.d), i(other.i) {} + UserType(UserType&& other) : key(other.key), f(other.f), d(other.d), i(other.i) + { + other.key = -1; + other.f = 0.0f; + other.d = 0.0; + other.i = 0; + } +}; + +struct test_one_policy +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, bool is_true_equal) + { + using namespace std; + + auto expected = equal(first1, last1, first2); + auto actual = equal(exec, first1, last1, first2); + EXPECT_EQ(expected, actual, "result for equal for random-access iterator, checking against std::equal()"); + + // testing bool + EXPECT_TRUE(is_true_equal == actual, "result for equal for random-access iterator, bool"); + +//add C++14 equal symantics tests +//add more cases for inCopy size less than in +#if CPP14_ENABLED + auto actualr14 = std::equal(in.cbegin(), in.cend(), inCopy.cbegin(), inCopy.cend()); + EXPECT_EQ(expected, actualr14, "result for equal for random-access iterator"); +#endif + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 1; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [bits](size_t k) { return T(2 * HashBits(k, bits - 1) ^ 1); }); + Sequence inCopy(in); + + invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), true); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), true); + + // testing bool !equal() + inCopy[0] = !inCopy[0]; + invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), false); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), false); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + equal(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + } +}; + +int +main() +{ + + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + test(256); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find.pass.cpp new file mode 100644 index 000000000000..f5a5d94f5e41 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find.pass.cpp @@ -0,0 +1,96 @@ +// -*- C++ -*- +//===-- find.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for find +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_find +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Value value) + { + auto i = std::find(first, last, value); + auto j = find(exec, first, last, value); + EXPECT_TRUE(i == j, "wrong return value from find"); + } +}; + +template +void +test(Value value, Hit hit, Miss miss) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); + // Try different find positions, including not found. + // By going backwards, we can add extra matches that are *not* supposed to be found. + // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. + for (size_t m = n; m > 0; m *= 0.6) + { + if (m < n) + in[m] = hit(n ^ m); + invoke_on_all_policies(test_find(), in.begin(), in.end(), value); + invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value); + } + } +} + +// Type defined for sake of checking that std::find works with asymmetric ==. +class Weird +{ + Number value; + + public: + friend bool + operator==(Number x, Weird y) + { + return x == y.value; + } + Weird(int32_t val, OddTag) : value(val, OddTag()) {} +}; + +int +main() +{ + // Note that the "hit" and "miss" functions here avoid overflow issues. + test(Weird(42, OddTag()), [](int32_t) { return Number(42, OddTag()); }, // hit + [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss + + // Test with value that is equal to two different bit patterns (-0.0 and 0.0) + test(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit + [](int32_t j) { return j == 0 ? ~j : j; }); // miss + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_end.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_end.pass.cpp new file mode 100644 index 000000000000..20826ae064e2 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_end.pass.cpp @@ -0,0 +1,123 @@ +// -*- C++ -*- +//===-- find_end.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) + { + using namespace std; + // For find_end + { + auto expected = find_end(b, e, bsub, esub, pred); + auto actual = find_end(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from find_end"); + + actual = find_end(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from find_end with a predicate"); + } + + // For search + { + auto expected = search(b, e, bsub, esub, pred); + auto actual = search(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from search"); + + actual = search(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from search with a predicate"); + } + } +}; + +template +void +test(const std::size_t bits) +{ + + const std::size_t max_n1 = 1000; + const std::size_t max_n2 = (max_n1 * 10) / 8; + Sequence in(max_n1, [bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); }); + Sequence sub(max_n2, [bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1)); }); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; + std::size_t res[] = {0, 1, n1 / 2, n1}; + for (auto n2 : sub_n) + { + for (auto r : res) + { + std::size_t i = r, isub = 0; + for (; i < n1 & isub < n2; ++i, ++isub) + in[i] = sub[isub]; + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2, + std::equal_to()); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(), + sub.cbegin() + n2, std::equal_to()); + } + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + }); + } +}; + +int +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_first_of.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_first_of.pass.cpp new file mode 100644 index 000000000000..84c35e95cfc5 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_first_of.pass.cpp @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===-- find_first_of.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) + { + using namespace std; + Iterator1 expected = find_first_of(b, e, bsub, esub, pred); + Iterator1 actual = find_first_of(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from find_first_of with a predicate"); + + expected = find_first_of(b, e, bsub, esub); + actual = find_first_of(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from find_first_of"); + } +}; + +template +void +test(Predicate pred) +{ + + const std::size_t max_n1 = 1000; + const std::size_t max_n2 = (max_n1 * 10) / 8; + Sequence in1(max_n1, [](std::size_t) { return T(1); }); + Sequence in2(max_n2, [](std::size_t) { return T(0); }); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8}; + for (const auto n2 : sub_n) + { + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.data(), in2.data() + n2, pred); + + in2[n2 / 2] = T(1); + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2, + pred); + + if (n2 >= 3) + { + in2[2 * n2 / 3] = T(1); + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(), + in2.begin() + n2, pred); + in2[2 * n2 / 3] = T(0); + } + in2[n2 / 2] = T(0); + } + } + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(), + in1.data() + max_n1 / 10, pred); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + find_first_of(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + }); + } +}; + +int +main() +{ + test(std::equal_to()); + test(std::not_equal_to()); + test([](const float64_t x, const float64_t y) { return x * x == y * y; }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_if.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_if.pass.cpp new file mode 100644 index 000000000000..3dd41c07288e --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/find_if.pass.cpp @@ -0,0 +1,109 @@ +// -*- C++ -*- +//===-- find_if.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for find_if and find_if_not +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_find_if +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, + NotPredicate not_pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, + NotPredicate not_pred) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) + { + auto i = std::find_if(first, last, pred); + auto j = find_if(exec, first, last, pred); + EXPECT_TRUE(i == j, "wrong return value from find_if"); + auto i_not = find_if_not(exec, first, last, not_pred); + EXPECT_TRUE(i_not == i, "wrong return value from find_if_not"); + } +}; + +template +void +test(Predicate pred, Hit hit, Miss miss) +{ + auto not_pred = [pred](T x) { return !pred(x); }; + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); + // Try different find positions, including not found. + // By going backwards, we can add extra matches that are *not* supposed to be found. + // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. + for (size_t m = n; m > 0; m *= 0.6) + { + if (m < n) + in[m] = hit(n ^ m); + invoke_on_all_policies(test_find_if(), in.begin(), in.end(), pred, not_pred); + invoke_on_all_policies(test_find_if(), in.cbegin(), in.cend(), pred, not_pred); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + + invoke_if(exec, [&]() { + find_if(exec, iter, iter, non_const(is_even)); + find_if_not(exec, iter, iter, non_const(is_even)); + }); + } +}; + +int +main() +{ +#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + // Note that the "hit" and "miss" functions here avoid overflow issues. + test(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit + [](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); }); // miss +#endif + + // Try type for which algorithm can really be vectorized. + test([](float32_t x) { return x >= 0; }, [](float32_t j) { return j * j; }, + [](float32_t j) { return -1 - j * j; }); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/for_each.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/for_each.pass.cpp new file mode 100644 index 000000000000..3aae4a4aaefc --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/for_each.pass.cpp @@ -0,0 +1,102 @@ +// -*- C++ -*- +//===-- for_each.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Gen +{ + Type + operator()(std::size_t k) + { + return Type(k % 5 != 1 ? 3 * k - 7 : 0); + }; +}; + +template +struct Flip +{ + int32_t val; + Flip(int32_t y) : val(y) {} + T + operator()(T& x) const + { + return x = val - x; + } +}; + +struct test_one_policy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n) + { + typedef typename std::iterator_traits::value_type T; + + // Try for_each + std::for_each(expected_first, expected_last, Flip(1)); + for_each(exec, first, last, Flip(1)); + EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each"); + + // Try for_each_n + std::for_each_n(std::execution::seq, expected_first, n, Flip(1)); + for_each_n(exec, first, n, Flip(1)); + EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n"); + } +}; + +template +void +test() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence inout(n, Gen()); + Sequence expected(n, Gen()); + invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(), + inout.size()); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { + auto f = [](typename std::iterator_traits::reference x) { x = x + 1; }; + + for_each(exec, iter, iter, non_const(f)); + for_each_n(exec, iter, 0, non_const(f)); + }); + } +}; + +int +main() +{ + test(); + test(); + test(); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/mismatch.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/mismatch.pass.cpp new file mode 100644 index 000000000000..109ac4b82567 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/mismatch.pass.cpp @@ -0,0 +1,132 @@ +// -*- C++ -*- +//===-- mismatch.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_mismatch +{ + template + void + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2) + { + using namespace std; + typedef typename iterator_traits::value_type T; + { + const auto expected = std::mismatch(first1, last1, first2, std::equal_to()); + const auto res3 = mismatch(exec, first1, last1, first2, std::equal_to()); + EXPECT_TRUE(expected == res3, "wrong return result from mismatch"); + const auto res4 = mismatch(exec, first1, last1, first2); + EXPECT_TRUE(expected == res4, "wrong return result from mismatch"); + } + } + template + void + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) + { + using namespace std; + typedef typename iterator_traits::value_type T; + { + const auto expected = mismatch(std::execution::seq, first1, last1, first2, last2, std::equal_to()); + const auto res1 = mismatch(exec, first1, last1, first2, last2, std::equal_to()); + EXPECT_TRUE(expected == res1, "wrong return result from mismatch"); + const auto res2 = mismatch(exec, first1, last1, first2, last2); + EXPECT_TRUE(expected == res2, "wrong return result from mismatch"); + } + } +}; + +template +void +test_mismatch_by_type() +{ + using namespace std; + for (size_t size = 0; size <= 100000; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) + { + const T val = T(-1); + Sequence in(size, [](size_t v) -> T { return T(v % 100); }); + { + Sequence in2(in); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); + + const size_t min_size = 3; + if (size > min_size) + { + const size_t idx_for_1 = size / min_size; + in[idx_for_1] = val, in[idx_for_1 + 1] = val, in[idx_for_1 + 2] = val; + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); + } + + const size_t idx_for_2 = 500; + if (size >= idx_for_2 - 1) + { + in2[size / idx_for_2] = val; + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + } + { + Sequence in2(100, [](size_t v) -> T { return T(v); }); + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); + // We can't call std::mismatch with semantic below when size of second sequence less than size of first sequence + if (in2.size() <= in.size()) + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin()); + + const size_t idx = 97; + in2[idx] = val; + in2[idx + 1] = val; + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + if (in.size() <= in2.size()) + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + { + Sequence in2({}); + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); + + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + if (in.size() == 0) + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + mismatch(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); + } +}; + +int +main() +{ + + test_mismatch_by_type(); + test_mismatch_by_type(); + test_mismatch_by_type>(); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/none_of.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/none_of.pass.cpp new file mode 100644 index 000000000000..e84de3cbaf08 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/none_of.pass.cpp @@ -0,0 +1,101 @@ +// -*- C++ -*- +//===-- none_of.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_none_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::none_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for none_of"); + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + if (n > 0) + { + // Sprinkle in a hit + in[2 * n / 3] = spike; + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + + // Sprinkle in a few more hits + in[n / 3] = spike; + in[n / 2] = spike; + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + none_of(exec, iter, iter, non_const(is_even)); + } +}; + +int +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/nth_element.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/nth_element.pass.cpp new file mode 100644 index 000000000000..71009ac285ad --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/nth_element.pass.cpp @@ -0,0 +1,175 @@ +// -*- C++ -*- +//===-- nth_element.pass.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// User defined type with minimal requirements +template +struct DataType +{ + explicit DataType(int32_t k) : my_val(k) {} + DataType(DataType&& input) + { + my_val = std::move(input.my_val); + input.my_val = T(0); + } + DataType& + operator=(DataType&& input) + { + my_val = std::move(input.my_val); + input.my_val = T(0); + return *this; + } + T + get_val() const + { + return my_val; + } + + friend std::ostream& + operator<<(std::ostream& stream, const DataType& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +bool +is_equal(const DataType& x, const DataType& y) +{ + return x.get_val() == y.get_val(); +} + +template +bool +is_equal(const T& x, const T& y) +{ + return x == y; +} + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } +#endif + + // nth_element works only with random access iterators + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + + using T = typename std::iterator_traits::value_type; + const Iterator1 mid1 = std::next(first1, m); + const Iterator1 mid2 = std::next(first2, m); + + fill_data(first1, mid1, generator1); + fill_data(mid1, last1, generator2); + fill_data(first2, mid2, generator1); + fill_data(mid2, last2, generator2); + std::nth_element(first1, mid1, last1, comp); + std::nth_element(exec, first2, mid2, last2, comp); + if (m > 0 && m < n) + { + EXPECT_TRUE(is_equal(*mid1, *mid2), "wrong result from nth_element with predicate"); + } + EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2, [comp](T& x, T& y) { return comp(y, x); }) == mid2, + "wrong effect from nth_element with predicate"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, Iterator1, Iterator1, Iterator1, Iterator1, Size, Size, Generator1, Generator2, Compare) + { + } +}; + +template +void +test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) +{ + using namespace std; + size_t max_size = 10000; + Sequence in1(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + size_t m; + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + m = 0; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + m = n / 7; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + m = 3 * n / 5; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + } + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + max_size, in1.begin(), in1.begin() + max_size, + max_size, max_size, generator1, generator2, comp); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { nth_element(exec, iter, iter, iter, non_const(std::less())); }); + } +}; + +int +main() +{ + test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); + test_by_type([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less()); + + test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, + [](const float64_t x, const float64_t y) { return x > y; }); + + test_by_type>( + [](int32_t i) { return DataType(2 * i + 1); }, [](int32_t i) { return DataType(2 * i); }, + [](const DataType& x, const DataType& y) { return x.get_val() < y.get_val(); }); + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.nonmodifying/search_n.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/search_n.pass.cpp new file mode 100644 index 000000000000..9bcea249a2ea --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.nonmodifying/search_n.pass.cpp @@ -0,0 +1,109 @@ +// -*- C++ -*- +//===-- search_n.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator b, Iterator e, Size count, const T& value, Predicate pred) + { + using namespace std; + auto expected = search_n(b, e, count, value, pred); + auto actual = search_n(exec, b, e, count, value); + EXPECT_TRUE(actual == expected, "wrong return result from search_n"); + + actual = search_n(exec, b, e, count, value, pred); + EXPECT_TRUE(actual == expected, "wrong return result from search_n with a predicate"); + } +}; + +template +void +test() +{ + + const std::size_t max_n1 = 100000; + const T value = T(1); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; + std::size_t res[] = {0, 1, n1 / 2, n1}; + for (auto n2 : sub_n) + { + // Some of standard libraries return "first" in this case. We return "last" according to the standard + if (n2 == 0) + { + continue; + } + for (auto r : res) + { + Sequence in(n1, [](std::size_t) { return T(0); }); + std::size_t i = r, isub = 0; + for (; i < n1 & isub < n2; ++i, ++isub) + in[i] = value; + + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, n2, value, std::equal_to()); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, n2, value, std::equal_to()); + } + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { search_n(exec, iter, iter, 0, T(0), non_const(std::equal_to())); }); + } +}; + +int +main() +{ + test(); + test(); + test(); +#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(); +#endif + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp new file mode 100644 index 000000000000..78e7a3079dc4 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp @@ -0,0 +1,146 @@ +// -*- C++ -*- +//===-- is_heap.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for is_heap, is_heap_until +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" +#include + +using namespace TestUtils; + +struct WithCmpOp +{ + int32_t _first; + int32_t _second; + WithCmpOp() : _first(0), _second(0){}; + explicit WithCmpOp(int32_t x) : _first(x), _second(x){}; + bool + operator<(const WithCmpOp& rhs) const + { + return this->_first < rhs._first; + } +}; + +struct test_is_heap +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) + { + } +#endif + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + { + using namespace std; + // is_heap + { + bool expected = is_heap(first, last); + bool actual = is_heap(exec, first, last); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap"); + } + // is_heap with predicate + { + bool expected = is_heap(first, last, pred); + bool actual = is_heap(exec, first, last, pred); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap with predicate"); + } + // is_heap_until + { + Iterator expected = is_heap_until(first, last); + Iterator actual = is_heap_until(exec, first, last); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until"); + } + // is_heap_until with predicate + { + const Iterator expected = is_heap_until(first, last, pred); + const auto y = std::distance(first, expected); + const Iterator actual = is_heap_until(exec, first, last, pred); + const auto x = std::distance(first, actual); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate"); + EXPECT_EQ(x, y, "both iterators should be the same distance away from 'first'"); + } + } + + // is_heap, is_heap_until works only with random access iterators + template + typename std::enable_if::value, void>::type + operator()(Policy&&, Iterator, Iterator, Predicate) + { + } +}; + +template +void +test_is_heap_by_type(Comp comp) +{ + using namespace std; + + const size_t max_size = 100000; + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t v) -> T { return T(v); }); + + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); + + std::make_heap(in.begin(), in.begin() + n / 4, comp); + invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); + + std::make_heap(in.begin(), in.begin() + n / 3, comp); + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); + + std::make_heap(in.begin(), in.end(), comp); + invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); + } + + Sequence in(max_size / 10, [](size_t) -> T { return T(1); }); + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { + is_heap(exec, iter, iter, non_const(std::less())); + is_heap_until(exec, iter, iter, non_const(std::less())); + }); + } +}; + +int +main() +{ + test_is_heap_by_type(std::greater()); + test_is_heap_by_type(std::less()); + test_is_heap_by_type([](uint64_t x, uint64_t y) { return x % 100 < y % 100; }); + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp new file mode 100644 index 000000000000..abd10667cad4 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp @@ -0,0 +1,175 @@ +// -*- C++ -*- +//===-- lexicographical_compare.pass.cpp ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2, + Predicate pred) + { + const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2, pred); + const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2, pred); + EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare with predicate"); + } + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) + { + const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2); + const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2); + EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare without predicate"); + } +}; + +template +void +test(Predicate pred) +{ + + const std::size_t max_n = 1000000; + Sequence in1(max_n, [](std::size_t k) { return T1(k); }); + Sequence in2(2 * max_n, [](std::size_t k) { return T2(k); }); + + std::size_t n2; + + // Test case: Call algorithm's version without predicate. + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, + in2.cbegin() + 5 * max_n / 10); + + // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. + std::size_t max_n2 = max_n / 10; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2, + pred); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2, + in2.begin() + 3 * max_n2, pred); + + // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. + max_n2 = 2 * max_n; + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2, + pred); + + for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) + { + // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. + n2 = n1; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + n2 = n1; + // Test case: two ranges have different elements and are of the same length (second sequence less than first) + std::size_t ind = n1 / 2; + in2[ind] = T2(-1); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + in2[ind] = T2(ind); + + // Test case: two ranges have different elements and are of the same length (first sequence less than second) + ind = n1 / 5; + in1[ind] = T1(-1); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); + in1[ind] = T1(ind); + } +} + +template +void +test_string(Predicate pred) +{ + + const std::size_t max_n = 1000000; + std::string in1 = ""; + std::string in2 = ""; + for (std::size_t n1 = 0; n1 <= max_n; ++n1) + { + in1 += n1; + } + + for (std::size_t n1 = 0; n1 <= 2 * max_n; ++n1) + { + in2 += n1; + } + + std::size_t n2; + + for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) + { + // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. + n2 = n1; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + n2 = n1; + // Test case: two ranges have different elements and are of the same length (second sequence less than first) + in2[n1 / 2] = 'a'; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + // Test case: two ranges have different elements and are of the same length (first sequence less than second) + in1[n1 / 5] = 'a'; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); + } + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, + in2.cbegin() + 5 * max_n / 10); +} + +template +struct LocalWrapper +{ + explicit LocalWrapper(std::size_t k) : my_val(k) {} + bool + operator<(const LocalWrapper& w) const + { + return my_val < w.my_val; + } + + private: + T my_val; +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); + }); + } +}; + +int +main() +{ + test(std::less()); + test(std::greater()); +#if !_PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN + test([](const float64_t x, const int32_t y) { return x * x < y * y; }); +#endif + test, LocalWrapper>( + [](const LocalWrapper& x, const LocalWrapper& y) { return x < y; }); + test_string([](const char x, const char y) { return x < y; }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp new file mode 100644 index 000000000000..a1a29b7b646a --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp @@ -0,0 +1,193 @@ +// -*- C++ -*- +//===-- minmax_element.pass.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct check_minelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const Iterator expect = std::min_element(begin, end); + const Iterator result = std::min_element(exec, begin, end); + const Iterator result_pred = std::min_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect == result, "wrong return result from min_element"); + EXPECT_TRUE(expect == result_pred, "wrong return result from min_element"); + } +}; + +struct check_maxelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const Iterator expect = std::max_element(begin, end); + const Iterator result = std::max_element(exec, begin, end); + const Iterator result_pred = std::max_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect == result, "wrong return result from max_element"); + EXPECT_TRUE(expect == result_pred, "wrong return result from max_element"); + } +}; + +struct check_minmaxelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const std::pair expect = std::minmax_element(begin, end); + const std::pair got = std::minmax_element(exec, begin, end); + const std::pair got_pred = std::minmax_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect.first == got.first, "wrong return result from minmax_element (min part)"); + EXPECT_TRUE(expect.second == got.second, "wrong return result from minmax_element (max part)"); + EXPECT_TRUE(expect == got_pred, "wrong return result from minmax_element"); + } +}; + +template +struct sequence_wrapper +{ + TestUtils::Sequence seq; + const T min_value; + const T max_value; + static const std::size_t bits = 30; // We assume that T can handle signed 2^bits+1 value + + // TestUtils::HashBits returns value between 0 and (1< T { return T(TestUtils::HashBits(i, bits)); }); + } + + // sets first one at position `at` and bunch of them farther + void + set_desired_value(std::size_t at, T value) + { + if (seq.size() == 0) + return; + seq[at] = value; + + //Producing serveral red herrings + for (std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5)) + seq[i] = value; + } +}; + +template +void +test_by_type(std::size_t n) +{ + sequence_wrapper wseq(n); + + // to avoid overtesing we use std::set to leave only unique indexes + std::set targets{0}; + if (n > 1) + { + targets.insert(1); + targets.insert(2.718282 * n / 3); + targets.insert(n / 2); + targets.insert(n / 7.389056); + targets.insert(n - 1); // last + } + + for (std::set::iterator it = targets.begin(); it != targets.end(); ++it) + { + wseq.pattern_fill(); + wseq.set_desired_value(*it, wseq.min_value); + TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.begin(), wseq.seq.end()); + + wseq.set_desired_value(*it, wseq.max_value); + TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.begin(), wseq.seq.end()); + + if (targets.size() > 1) + { + for (std::set::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit) + { + if (*rit == *it) // we requires at least 2 unique indexes in targets + break; + wseq.pattern_fill(); + wseq.set_desired_value(*it, wseq.min_value); // setting minimum element + wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); + } + } + else + { // we must check this corner case; it can not be tested in loop above + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); + } + } +} + +// should provide minimal requirements only +struct OnlyLessCompare +{ + int32_t val; + OnlyLessCompare() : val(0) {} + OnlyLessCompare(int32_t val_) : val(val_) {} + bool + operator<(const OnlyLessCompare& other) const + { + return val < other.val; + } +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + max_element(exec, iter, iter, non_const(std::less())); + min_element(exec, iter, iter, non_const(std::less())); + minmax_element(exec, iter, iter, non_const(std::less())); + } +}; + +int +main() +{ + using TestUtils::float64_t; + const std::size_t N = 100000; + + for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n)) + { + test_by_type(n); + test_by_type(n); + } + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << TestUtils::done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp new file mode 100644 index 000000000000..8712f173f10d --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===-- includes.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + explicit Num(const T& v) : val(v) {} + + //for "includes" checks + template + bool + operator<(const Num& v1) const + { + return val < v1.val; + } + + //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them + template + operator Num() const + { + return Num((T1)val); + } +}; + +struct test_one_policy +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + + auto expect_res = std::includes(first1, last1, first2, last2, comp); + auto res = std::includes(exec, first1, last1, first2, last2, comp); + + EXPECT_TRUE(expect_res == res, "wrong result for includes"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template +void +test_includes(Compare compare) +{ + + const std::size_t n_max = 1000000; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) + { + //prepare the input ranges + Sequence in1(n, [](std::size_t k) { return rand() % (2 * k + 1); }); + Sequence in2(m, [](std::size_t k) { return rand() % (k + 1); }); + + std::sort(in1.begin(), in1.end(), compare); + std::sort(in2.begin(), in2.end(), compare); + + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); + + //test w/ non constant predicate + if (n < 5 && m < 5) + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + non_const(compare)); + } + } +} + +int +main() +{ + + test_includes(std::less<>()); + test_includes, Num>([](const Num& x, const Num& y) { return x < y; }); + std::cout << done() << std::endl; + + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/set.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/set.pass.cpp new file mode 100644 index 000000000000..4b2b93dc8e30 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/alg.set.operations/set.pass.cpp @@ -0,0 +1,280 @@ +// -*- C++ -*- +//===-- set.pass.cpp ------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + + Num() : val{} {} + Num(const T& v) : val(v) {} + + //for "includes" checks + template + bool + operator<(const Num& v1) const + { + return val < v1.val; + } + + //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them + template + operator Num() const + { + return Num((T1)val); + } + + friend bool + operator==(const Num& v1, const Num& v2) + { + return v1.val == v2.val; + } +}; + +template +struct test_set_union +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence expect(n); + Sequence out(n); + + auto expect_res = std::set_union(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_union(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_union"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_union effect"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template +struct test_set_intersection +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence expect(n); + Sequence out(n); + + auto expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_intersection"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_intersection effect"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template +struct test_set_difference +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence expect(n); + Sequence out(n); + + auto expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_difference"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_difference effect"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template +struct test_set_symmetric_difference +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence expect(n); + Sequence out(n); + + auto expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_symmetric_difference"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), + "wrong set_symmetric_difference effect"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template +void +test_set(Compare compare) +{ + + const std::size_t n_max = 100000; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(4200); + + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) + { + //prepare the input ranges + Sequence in1(n, [](std::size_t k) { return rand() % (2 * k + 1); }); + Sequence in2(m, [m](std::size_t k) { return (m % 2) * rand() + rand() % (k + 1); }); + + std::sort(in1.begin(), in1.end(), compare); + std::sort(in2.begin(), in2.end(), compare); + + invoke_on_all_policies(test_set_union(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_intersection(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_difference(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_symmetric_difference(), in1.begin(), in1.end(), in2.cbegin(), + in2.cend(), compare); + } + } +} + +template +struct test_non_const_set_difference +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + set_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +template +struct test_non_const_set_intersection +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +template +struct test_non_const_set_symmetric_difference +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, + non_const(std::less())); + } +}; + +template +struct test_non_const_set_union +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +int +main() +{ + + test_set(std::less<>()); + test_set, Num>([](const Num& x, const Num& y) { return x < y; }); + + test_set([](const MemoryChecker& val1, const MemoryChecker& val2) -> bool { + return val1.value() < val2.value(); + }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from set algorithms: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from set algorithms: number of ctors calls > num of dtors calls"); + + test_algo_basic_double(run_for_rnd_fw>()); + + test_algo_basic_double(run_for_rnd_fw>()); + + test_algo_basic_double(run_for_rnd_fw>()); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/is_sorted.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/is_sorted.pass.cpp new file mode 100644 index 000000000000..3a48160fc17b --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/is_sorted.pass.cpp @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===-- is_sorted.pass.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_is_sorted +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, bool exam) + { + using namespace std; + typedef typename std::iterator_traits::value_type T; + + //try random-access iterator + bool res = is_sorted(exec, first, last); + EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); + auto iexam = is_sorted_until(first, last); + auto ires = is_sorted_until(exec, first, last); + EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); + + //try random-access iterator with a predicate + res = is_sorted(exec, first, last, std::less()); + EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); + iexam = is_sorted_until(first, last, std::less()); + ires = is_sorted_until(exec, first, last, std::less()); + EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); + } +}; + +template +void +test_is_sorted_by_type() +{ + + Sequence in(99999, [](size_t v) -> T { return T(v); }); //fill 0..n + + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + in[in.size() / 2] = -1; + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + in[1] = -1; + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + //an empty container + Sequence in0(0); + invoke_on_all_policies(test_is_sorted(), in0.begin(), in0.end(), std::is_sorted(in0.begin(), in0.end())); + invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end())); + + //non-descending order + Sequence in1(9, [](size_t) -> T { return T(0); }); + invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end())); + invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end())); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + is_sorted(exec, iter, iter, std::less()); + is_sorted_until(exec, iter, iter, std::less()); + } +}; + +int +main() +{ + + test_is_sorted_by_type(); + test_is_sorted_by_type(); + + test_is_sorted_by_type>(); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort.pass.cpp new file mode 100644 index 000000000000..e378cb491ab6 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort.pass.cpp @@ -0,0 +1,149 @@ +// -*- C++ -*- +//===-- partial_sort.pass.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +static std::atomic count_val; +static std::atomic count_comp; + +template +struct Num +{ + T val; + + Num() { ++count_val; } + Num(T v) : val(v) { ++count_val; } + Num(const Num& v) : val(v.val) { ++count_val; } + Num(Num&& v) : val(v.val) { ++count_val; } + ~Num() { --count_val; } + Num& + operator=(const Num& v) + { + val = v.val; + return *this; + } + operator T() const { return val; } + bool + operator<(const Num& v) const + { + ++count_comp; + return val < v.val; + } +}; + +struct test_brick_partial_sort +{ + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, + Compare compare) + { + + typedef typename std::iterator_traits::value_type T; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + const std::size_t n = last - first; + for (std::size_t k = 0; k < n; ++k) + { + first[k] = T(rand() % (2 * n + 1)); + } + std::copy(first, last, exp_first); + + for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p)) + { + auto m1 = first + p; + auto m2 = exp_first + p; + + std::partial_sort(exp_first, m2, exp_last, compare); + count_comp = 0; + std::partial_sort(exec, first, m1, last, compare); + EXPECT_EQ_N(exp_first, first, p, "wrong effect from partial_sort"); + + //checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads; + if (m1 - first > 1) + { +#ifdef _DEBUG +# if defined(_PSTL_PAR_BACKEND_TBB) + auto p = tbb::this_task_arena::max_concurrency(); +# else + auto p = 1; +# endif + auto complex = std::ceil(n * std::log(float32_t(m1 - first))); + if (count_comp > complex * p) + { + std::cout << "complexity exceeded" << std::endl; + } +#endif // _DEBUG + } + } + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&&, InputIterator, InputIterator, InputIterator, InputIterator, Compare) + { + } +}; + +template +void +test_partial_sort(Compare compare) +{ + + const std::size_t n_max = 100000; + Sequence in(n_max); + Sequence exp(n_max); + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, + compare); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + partial_sort(exec, iter, iter, iter, non_const(std::less())); + } +}; + +int +main() +{ + count_val = 0; + + test_partial_sort>([](Num x, Num y) { return x < y; }); + + EXPECT_TRUE(count_val == 0, "cleanup error"); + + test_partial_sort( + [](int32_t x, int32_t y) { return x > y; }); // Reversed so accidental use of < will be detected. + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort_copy.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort_copy.pass.cpp new file mode 100644 index 000000000000..ad0f0d6ef9b0 --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/partial_sort_copy.pass.cpp @@ -0,0 +1,196 @@ +// -*- C++ -*- +//===-- partial_sort_copy.pass.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for partial_sort_copy +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + + Num() : val(0) {} + Num(T v) : val(v) {} + Num(const Num& v) : val(v.val) {} + Num(Num&& v) : val(v.val) {} + Num& + operator=(const Num& v) + { + val = v.val; + return *this; + } + operator T() const { return val; } + bool + operator<(const Num& v) const + { + return val < v.val; + } +}; + +template +struct test_one_policy +{ + RandomAccessIterator d_first; + RandomAccessIterator d_last; + RandomAccessIterator exp_first; + RandomAccessIterator exp_last; + // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed) + test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2) + : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2) + { + } +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash, Compare compare) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash, Compare compare) + { + } + + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, + Compare compare) + { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate"); + } + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) + { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate"); + } + + private: + template + void + prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash) + { + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); }); + + std::fill(exp_first, exp_last, trash); + std::fill(d_first, d_last, trash); + } +}; + +template +void +test_partial_sort_copy(Compare compare) +{ + + typedef typename Sequence::iterator iterator_type; + const std::size_t n_max = 100000; + Sequence in(n_max); + Sequence out(2 * n_max); + Sequence exp(2 * n_max); + std::size_t n1 = 0; + std::size_t n2; + T trash = T(-666); + for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + // If both sequences are equal + n2 = n1; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is greater than second + n2 = n1 / 3; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is less than second + n2 = 2 * n1; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + } + // Test partial_sort_copy without predicate + n1 = n_max; + n2 = 2 * n1; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + invoke_if(exec, [&]() { + partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less())); + }); + } +}; + +int +main() +{ + test_partial_sort_copy>([](Num x, Num y) { return x < y; }); + test_partial_sort_copy([](int32_t x, int32_t y) { return x > y; }); + + test_algo_basic_double(run_for_rnd>()); + + test_partial_sort_copy( + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() < val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from partial_sort_copy: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from partial_sort_copy: number of ctors calls > num of dtors calls"); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/algorithms/alg.sorting/sort.pass.cpp b/libcxx/test/std/pstl/algorithms/alg.sorting/sort.pass.cpp new file mode 100644 index 000000000000..add69d66bc2d --- /dev/null +++ b/libcxx/test/std/pstl/algorithms/alg.sorting/sort.pass.cpp @@ -0,0 +1,247 @@ +// -*- C++ -*- +//===-- sort.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; +#define _CRT_SECURE_NO_WARNINGS + +#include + +static bool Stable; + +//! Number of extant keys +static std::atomic KeyCount; + +//! One more than highest index in array to be sorted. +static uint32_t LastIndex; + +//! Keeping Equal() static and a friend of ParanoidKey class (C++, paragraphs 3.5/7.1.1) +class ParanoidKey; +static bool +Equal(const ParanoidKey& x, const ParanoidKey& y); + +//! A key to be sorted, with lots of checking. +class ParanoidKey +{ + //! Value used by comparator + int32_t value; + //! Original position or special value (Empty or Dead) + int32_t index; + //! Special value used to mark object without a comparable value, e.g. after being moved from. + static const int32_t Empty = -1; + //! Special value used to mark destroyed objects. + static const int32_t Dead = -2; + // True if key object has comparable value + bool + isLive() const + { + return (uint32_t)(index) < LastIndex; + } + // True if key object has been constructed. + bool + isConstructed() const + { + return isLive() || index == Empty; + } + + public: + ParanoidKey() + { + ++KeyCount; + index = Empty; + value = Empty; + } + ParanoidKey(const ParanoidKey& k) : value(k.value), index(k.index) + { + EXPECT_TRUE(k.isLive(), "source for copy-constructor is dead"); + ++KeyCount; + } + ~ParanoidKey() + { + EXPECT_TRUE(isConstructed(), "double destruction"); + index = Dead; + --KeyCount; + } + ParanoidKey& + operator=(const ParanoidKey& k) + { + EXPECT_TRUE(k.isLive(), "source for copy-assignment is dead"); + EXPECT_TRUE(isConstructed(), "destination for copy-assignment is dead"); + value = k.value; + index = k.index; + return *this; + } + ParanoidKey(int32_t index, int32_t value, OddTag) : value(value), index(index) {} + ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index) + { + EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead"); +// std::stable_sort() fails in move semantics on paranoid test before VS2015 +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + k.index = Empty; +#endif + ++KeyCount; + } + ParanoidKey& + operator=(ParanoidKey&& k) + { + EXPECT_TRUE(k.isConstructed(), "source for move-assignment is dead"); + EXPECT_TRUE(isConstructed(), "destination for move-assignment is dead"); + value = k.value; + index = k.index; +// std::stable_sort() fails in move semantics on paranoid test before VS2015 +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + k.index = Empty; +#endif + return *this; + } + friend class KeyCompare; + friend bool + Equal(const ParanoidKey& x, const ParanoidKey& y); +}; + +class KeyCompare +{ + enum statusType + { + //! Special value used to mark defined object. + Live = 0xabcd, + //! Special value used to mark destroyed objects. + Dead = -1 + } status; + + public: + KeyCompare(OddTag) : status(Live) {} + ~KeyCompare() { status = Dead; } + bool + operator()(const ParanoidKey& j, const ParanoidKey& k) const + { + EXPECT_TRUE(status == Live, "key comparison object not defined"); + EXPECT_TRUE(j.isLive(), "first key to operator() is not live"); + EXPECT_TRUE(k.isLive(), "second key to operator() is not live"); + return j.value < k.value; + } +}; + +// Equal is equality comparison used for checking result of sort against expected result. +static bool +Equal(const ParanoidKey& x, const ParanoidKey& y) +{ + return (x.value == y.value && !Stable) || (x.index == y.index); +} + +static bool +Equal(float32_t x, float32_t y) +{ + return x == y; +} + +static bool +Equal(int32_t x, int32_t y) +{ + return x == y; +} + +struct test_sort_with_compare +{ + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, InputIterator first, InputIterator, Size n, Compare compare) + { + using namespace std; + copy_n(first, n, expected_first); + copy_n(first, n, tmp_first); + if (Stable) + std::stable_sort(expected_first + 1, expected_last - 1, compare); + else + std::sort(expected_first + 1, expected_last - 1, compare); + int32_t count0 = KeyCount; + if (Stable) + stable_sort(exec, tmp_first + 1, tmp_last - 1, compare); + else + sort(exec, tmp_first + 1, tmp_last - 1, compare); + + for (size_t i = 0; i < n; ++i, ++expected_first, ++tmp_first) + { + // Check that expected[i] is equal to tmp[i] + EXPECT_TRUE(Equal(*expected_first, *tmp_first), "bad sort"); + } + int32_t count1 = KeyCount; + EXPECT_EQ(count0, count1, "key cleanup error"); + } + template + typename std::enable_if::value, + void>::type + operator()(Policy&&, OutputIterator, OutputIterator, OutputIterator2, OutputIterator2, InputIterator, InputIterator, + Size, Compare) + { + } +}; + +template +void +test_sort(Compare compare, Convert convert) +{ + for (size_t n = 0; n < 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + LastIndex = n + 2; + // The rand()%(2*n+1) encourages generation of some duplicates. + // Sequence is padded with an extra element at front and back, to detect overwrite bugs. + Sequence in(n + 2, [=](size_t k) { return convert(k, rand() % (2 * n + 1)); }); + Sequence expected(in); + Sequence tmp(in); + invoke_on_all_policies(test_sort_with_compare(), tmp.begin(), tmp.end(), expected.begin(), expected.end(), + in.begin(), in.end(), in.size(), compare); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + sort(exec, iter, iter, non_const(std::less())); + stable_sort(exec, iter, iter, non_const(std::less())); + } +}; + +int +main() +{ + std::srand(42); + for (int32_t kind = 0; kind < 2; ++kind) + { + Stable = kind != 0; + test_sort(KeyCompare(OddTag()), + [](size_t k, size_t val) { return ParanoidKey(k, val, OddTag()); }); + test_sort([](float32_t x, float32_t y) { return x < y; }, + [](size_t, size_t val) { return float32_t(val); }); + test_sort( + [](int32_t x, int32_t y) { return x > y; }, // Reversed so accidental use of < will be detected. + [](size_t, size_t val) { return int32_t(val); }); + } + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/lit.local.cfg b/libcxx/test/std/pstl/lit.local.cfg new file mode 100644 index 000000000000..6b1e2c657906 --- /dev/null +++ b/libcxx/test/std/pstl/lit.local.cfg @@ -0,0 +1,2 @@ +if 'parallel-algorithms' not in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/adjacent_difference.pass.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/adjacent_difference.pass.cpp new file mode 100644 index 000000000000..65251550381f --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/adjacent_difference.pass.cpp @@ -0,0 +1,170 @@ +// -*- C++ -*- +//===-- adjacent_difference.pass.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + constexpr explicit wrapper(T t_) : t(t_) {} + template + constexpr wrapper(const wrapper& a) + { + t = a.t; + } + template + constexpr void + operator=(const wrapper& a) + { + t = a.t; + } + constexpr wrapper + operator-(const wrapper& a) const + { + return wrapper(t - a.t); + } +}; + +template +bool +compare(const T& a, const T& b) +{ + return a == b; +} + +template +bool +compare(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +typename std::enable_if::value, bool>::type +compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function f) +{ + using T2 = typename std::iterator_traits::value_type; + + if (first == last) + return true; + + { + T2 temp(*first); + if (!compare(temp, *d_first)) + return false; + } + Iterator1 second = std::next(first); + + ++d_first; + for (; second != last; ++first, ++second, ++d_first) + { + T2 temp(f(*second, *first)); + if (!compare(temp, *d_first)) + return false; + } + + return true; +} + +// we don't want to check equality here +// because we can't be sure it will be strictly equal for floating point types +template +typename std::enable_if::value, bool>::type compute_and_check(Iterator1, Iterator1, Iterator2, + T, Function) +{ + return true; +} + +struct test_one_policy +{ +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, T trash, Function f) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, T trash, Function f) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, + T trash, Function f) + { + using namespace std; + using T2 = typename std::iterator_traits::value_type; + + fill(actual_b, actual_e, trash); + + Iterator2 actual_return = adjacent_difference(exec, data_b, data_e, actual_b); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), std::minus()), + "wrong effect of adjacent_difference"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference"); + + fill(actual_b, actual_e, trash); + + actual_return = adjacent_difference(exec, data_b, data_e, actual_b, f); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), f), + "wrong effect of adjacent_difference with functor"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference with functor"); + } +}; + +template +void +test(Pred pred) +{ + const std::size_t max_len = 100000; + + static constexpr T2 value = T2(77); + static constexpr T1 trash = T1(31); + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len, trash, pred); + invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), + actual.begin() + len, trash, pred); + } +} + +int +main() +{ + test([](uint32_t a, uint32_t b) { return a - b; }); + test([](int64_t a, int64_t b) { return a / (b + 1); }); + test([](float32_t a, float32_t b) { return (a + b) / 2; }); + test, wrapper>( + [](const wrapper& a, const wrapper& b) { return a - b; }); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/reduce.pass.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/reduce.pass.cpp new file mode 100644 index 000000000000..743208fd19c4 --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/reduce.pass.cpp @@ -0,0 +1,114 @@ +// -*- C++ -*- +//===-- reduce.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_long_forms_for_one_policy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, T init, BinaryOp binary, T expected) + { + T result_r = std::reduce(exec, first, last, init, binary); + EXPECT_EQ(expected, result_r, "bad result from reduce(exec, first, last, init, binary_op)"); + } +}; + +template +void +test_long_form(T init, BinaryOp binary_op, F f) +{ + // Try sequences of various lengths + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + T expected(init); + Sequence in(n, [n, f](size_t k) { return f((int32_t(k ^ n) % 1000 - 500)); }); + for (size_t k = 0; k < n; ++k) + expected = binary_op(expected, in[k]); + + using namespace std; + + T result = transform_reduce_serial(in.cfbegin(), in.cfend(), init, binary_op, [](const T& t) { return t; }); + EXPECT_EQ(expected, result, "bad result from reduce(first, last, init, binary_op_op)"); + + invoke_on_all_policies(test_long_forms_for_one_policy(), in.begin(), in.end(), init, binary_op, expected); + invoke_on_all_policies(test_long_forms_for_one_policy(), in.cbegin(), in.cend(), init, binary_op, expected); + } +} + +struct test_two_short_forms +{ + +#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Sum init, Sum expected) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Sum init, Sum expected) + { + using namespace std; + + Sum r0 = init + reduce(exec, first, last); + EXPECT_EQ(expected, r0, "bad result from reduce(exec, first, last)"); + + Sum r1 = reduce(exec, first, last, init); + EXPECT_EQ(expected, r1, "bad result from reduce(exec, first, last, init)"); + } +}; + +// Test forms of reduce(...) that omit the binary_op or init operands. +void +test_short_forms() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sum init(42, OddTag()); + Sum expected(init); + Sequence in(n, [n](size_t k) { return Sum((int32_t(k ^ n) % 1000 - 500), OddTag()); }); + for (size_t k = 0; k < n; ++k) + expected = expected + in[k]; + invoke_on_all_policies(test_two_short_forms(), in.begin(), in.end(), init, expected); + invoke_on_all_policies(test_two_short_forms(), in.cbegin(), in.cend(), init, expected); + } +} + +int +main() +{ + // Test for popular types + test_long_form(42, std::plus(), [](int32_t x) { return x; }); + test_long_form(42.0, std::plus(), [](float64_t x) { return x; }); + + // Test for strict types + test_long_form(Number(42, OddTag()), Add(OddTag()), [](int32_t x) { return Number(x, OddTag()); }); + + // Short forms are just facade for long forms, so just test with a single type. + test_short_forms(); + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/scan.fail.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/scan.fail.cpp new file mode 100644 index 000000000000..13b2c9b751fe --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/scan.fail.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===-- scan.fail.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include +#include + +struct CustomPolicy +{ + constexpr std::false_type + __allow_vector() + { + return std::false_type{}; + } + constexpr std::false_type + __allow_parallel() + { + return std::false_type{}; + } +} policy; + +int32_t +main() +{ + int *first = nullptr, *last = nullptr, *result = nullptr; + + std::exclusive_scan(policy, first, last, result, 0); // expected-error {{no matching function for call to 'exclusive_scan'}} + std::exclusive_scan(policy, first, last, result, 0, std::plus()); // expected-error {{no matching function for call to 'exclusive_scan'}} + + return 0; +} diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/scan.pass.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/scan.pass.cpp new file mode 100644 index 000000000000..64156f001a5c --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/scan.pass.cpp @@ -0,0 +1,201 @@ +// -*- C++ -*- +//===-- scan.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// We provide the no execution policy versions of the exclusive_scan and inclusive_scan due checking correctness result of the versions with execution policies. +//TODO: to add a macro for availability of ver implementations +template +OutputIterator +exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init) +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = init + *first; + } + return result; +} + +template +OutputIterator +exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op) +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = binary_op(init, *first); + } + return result; +} + +// Note: N4582 is missing the ", class T". Issue was reported 2016-Apr-11 to cxxeditor@gmail.com +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, T init) +{ + for (; first != last; ++first, ++result) + { + init = binary_op(init, *first); + *result = init; + } + return result; +} + +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) +{ + if (first != last) + { + auto tmp = *first; + *result = tmp; + return inclusive_scan_serial(++first, last, ++result, binary_op, tmp); + } + else + { + return result; + } +} + +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result) +{ + typedef typename std::iterator_traits::value_type input_type; + return inclusive_scan_serial(first, last, result, std::plus()); +} + +// Most of the framework required for testing inclusive and exclusive scan is identical, +// so the tests for both are in this file. Which is being tested is controlled by the global +// flag inclusive, which is set to each alternative by main(). +static bool inclusive; + +template +void +check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) +{ + EXPECT_EQ_N(expected_first, out_first, n, + inclusive ? "wrong result from inclusive_scan" : "wrong result from exclusive_scan"); + std::fill_n(out_first, n, trash); +} + +struct test_scan_with_plus +{ + template + void + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, + Iterator3 expected_first, Iterator3, Size n, T init, T trash) + { + using namespace std; + + auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first) + : exclusive_scan_serial(in_first, in_last, expected_first, init); + (void)orr1; + auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first) + : exclusive_scan(exec, in_first, in_last, out_first, init); + EXPECT_TRUE(out_last == orr, + inclusive ? "inclusive_scan returned wrong iterator" : "exclusive_scan returned wrong iterator"); + + check_and_reset(expected_first, out_first, n, trash); + fill(out_first, out_last, trash); + } +}; + +template +void +test_with_plus(T init, T trash, Convert convert) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, convert); + Sequence expected(in); + Sequence out(n, [&](int32_t) { return trash; }); + + invoke_on_all_policies(test_scan_with_plus(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), init, trash); + invoke_on_all_policies(test_scan_with_plus(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), init, trash); + } +} +struct test_scan_with_binary_op +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, + Iterator3 expected_first, Iterator3, Size n, T init, BinaryOp binary_op, T trash) + { + using namespace std; + + auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first, binary_op, init) + : exclusive_scan_serial(in_first, in_last, expected_first, init, binary_op); + (void)orr1; + auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first, binary_op, init) + : exclusive_scan(exec, in_first, in_last, out_first, init, binary_op); + + EXPECT_TRUE(out_last == orr, "scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, Iterator1, Iterator1, Iterator2, Iterator2, Iterator3, Iterator3, Size, T, BinaryOp, T) + { + } +}; + +template +void +test_matrix(Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k, k + 1); }); + + Sequence out(n, [&](size_t) { return trash; }); + Sequence expected(n, [&](size_t) { return trash; }); + + invoke_on_all_policies(test_scan_with_binary_op(), in.begin(), in.end(), out.begin(), out.end(), + expected.begin(), expected.end(), in.size(), init, binary_op, trash); + invoke_on_all_policies(test_scan_with_binary_op(), in.cbegin(), in.cend(), out.begin(), out.end(), + expected.begin(), expected.end(), in.size(), init, binary_op, trash); + } +} + +int +main() +{ + for (int32_t mode = 0; mode < 2; ++mode) + { + inclusive = mode != 0; +#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN + // Test with highly restricted type and associative but not commutative operation + test_matrix, Matrix2x2>(Matrix2x2(), multiply_matrix, + Matrix2x2(-666, 666)); +#endif + + // Since the implict "+" forms of the scan delegate to the generic forms, + // there's little point in using a highly restricted type, so just use double. + test_with_plus(inclusive ? 0.0 : -1.0, -666.0, + [](uint32_t k) { return float64_t((k % 991 + 1) ^ (k % 997 + 2)); }); + } + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/transform_reduce.pass.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/transform_reduce.pass.cpp new file mode 100644 index 000000000000..dd8bb875e8e3 --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/transform_reduce.pass.cpp @@ -0,0 +1,129 @@ +// -*- C++ -*- +//===-- transform_reduce.pass.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// Functor for xor-operation for modeling binary operations in inner_product +class XOR +{ + public: + template + T + operator()(const T& left, const T& right) const + { + return left ^ right; + } +}; + +// Model of User-defined class +class MyClass +{ + public: + int32_t my_field; + MyClass() { my_field = 0; } + MyClass(int32_t in) { my_field = in; } + MyClass(const MyClass& in) { my_field = in.my_field; } + + friend MyClass + operator+(const MyClass& x, const MyClass& y) + { + return MyClass(x.my_field + y.my_field); + } + friend MyClass + operator-(const MyClass& x) + { + return MyClass(-x.my_field); + } + friend MyClass operator*(const MyClass& x, const MyClass& y) + { + return MyClass(x.my_field * y.my_field); + } + friend bool operator==(const MyClass& x, const MyClass& y) + { + return x.my_field == y.my_field; + } +}; + +template +void +CheckResults(const T& expected, const T& in) +{ + EXPECT_TRUE(expected == in, "wrong result of transform_reduce"); +} + +// We need to check correctness only for "int" (for example) except cases +// if we have "floating-point type"-specialization +void +CheckResults(const float32_t&, const float32_t&) +{ +} + +// Test for different types and operations with different iterators +struct test_transform_reduce +{ + template + void + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2, + T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU) + { + + auto expectedB = std::inner_product(first1, last1, first2, init, opB1, opB2); + auto expectedU = transform_reduce_serial(first1, last1, init, opB1, opU); + T resRA = std::transform_reduce(exec, first1, last1, first2, init, opB1, opB2); + CheckResults(expectedB, resRA); + resRA = std::transform_reduce(exec, first1, last1, init, opB1, opU); + CheckResults(expectedU, resRA); + } +}; + +template +void +test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU, Initializer initObj) +{ + + std::size_t maxSize = 100000; + Sequence in1(maxSize, initObj); + Sequence in2(maxSize, initObj); + + for (std::size_t n = 0; n < maxSize; n = n < 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_transform_reduce(), in1.begin(), in1.begin() + n, in2.begin(), in2.begin() + n, + init, opB1, opB2, opU); + invoke_on_all_policies(test_transform_reduce(), in1.cbegin(), in1.cbegin() + n, in2.cbegin(), in2.cbegin() + n, + init, opB1, opB2, opU); + } +} + +int +main() +{ + test_by_type(42, std::plus(), std::multiplies(), std::negate(), + [](std::size_t) -> int32_t { return int32_t(rand() % 1000); }); + test_by_type(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(), + [](const int64_t& x) -> int64_t { return x * 2; }, + [](std::size_t) -> int64_t { return int64_t(rand() % 1000); }); + test_by_type( + 1.0f, std::multiplies(), [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, + [](const float32_t& x) -> float32_t { return x + 2; }, [](std::size_t) -> float32_t { return rand() % 1000; }); + test_by_type(MyClass(), std::plus(), std::multiplies(), std::negate(), + [](std::size_t) -> MyClass { return MyClass(rand() % 1000); }); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/numerics/numeric.ops/transform_scan.pass.cpp b/libcxx/test/std/pstl/numerics/numeric.ops/transform_scan.pass.cpp new file mode 100644 index 000000000000..a7dd44a8be2f --- /dev/null +++ b/libcxx/test/std/pstl/numerics/numeric.ops/transform_scan.pass.cpp @@ -0,0 +1,177 @@ +// -*- C++ -*- +//===-- transform_scan.pass.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// Most of the framework required for testing inclusive and exclusive transform-scans is identical, +// so the tests for both are in this file. Which is being tested is controlled by the global +// flag inclusive, which is set to each alternative by main(). +static bool inclusive; + +template +void +check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) +{ + EXPECT_EQ_N(expected_first, out_first, n, + inclusive ? "wrong result from transform_inclusive_scan" + : "wrong result from transform_exclusive_scan"); + std::fill_n(out_first, n, trash); +} + +struct test_transform_scan +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator, Size n, UnaryOp unary_op, T init, + BinaryOp binary_op, T trash) + { + using namespace std; + + auto orr1 = + inclusive + ? transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op, init) + : transform_exclusive_scan(std::execution::seq, first, last, expected_first, init, binary_op, unary_op); + auto orr2 = inclusive ? transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op, init) + : transform_exclusive_scan(exec, first, last, out_first, init, binary_op, unary_op); + EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + + // Checks inclusive scan if init is not provided + if (inclusive && n > 0) + { + orr1 = transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op); + orr2 = transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op); + EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + } + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&&, InputIterator, InputIterator, OutputIterator, OutputIterator, OutputIterator, OutputIterator, + Size, UnaryOp, T, BinaryOp, T) + { + } +}; + +const uint32_t encryption_mask = 0x314; + +template +std::pair +transform_inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, + T init, BinaryOperation binary_op) noexcept +{ + for (; first != last; ++first, ++result) + { + init = binary_op(init, unary_op(*first)); + *result = init; + } + return std::make_pair(result, init); +} + +template +std::pair +transform_exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, + T init, BinaryOperation binary_op) noexcept +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = binary_op(init, unary_op(*first)); + } + return std::make_pair(result, init); +} + +template +void +test(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k ^ encryption_mask); }); + + Out tmp = init; + Sequence expected(n, [&](size_t k) -> Out { + if (inclusive) + { + tmp = binary_op(tmp, unary_op(in[k])); + return tmp; + } + else + { + Out val = tmp; + tmp = binary_op(tmp, unary_op(in[k])); + return val; + } + }); + + Sequence out(n, [&](size_t) { return trash; }); + + auto result = + inclusive + ? transform_inclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op) + : transform_exclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op); + (void)result; + check_and_reset(expected.begin(), out.begin(), out.size(), trash); + + invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + } +} + +template +void +test_matrix(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k, k + 1); }); + + Sequence out(n, [&](size_t) { return trash; }); + Sequence expected(n, [&](size_t) { return trash; }); + + invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + } +} + +int +main() +{ + for (int32_t mode = 0; mode < 2; ++mode) + { + inclusive = mode != 0; +#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN + test_matrix, Matrix2x2>([](const Matrix2x2 x) { return x; }, + Matrix2x2(), multiply_matrix, + Matrix2x2(-666, 666)); +#endif + test([](int32_t x) { return x++; }, -123, [](int32_t x, int32_t y) { return x + y; }, 666); + } + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp new file mode 100644 index 000000000000..c9c1e79fb40d --- /dev/null +++ b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp @@ -0,0 +1,123 @@ +// -*- C++ -*- +//===-- uninitialized_construct.pass.cpp ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for uninitialized_default_construct, uninitialized_default_construct_n, +// uninitialized_value_construct, uninitialized_value_construct_n + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// function of checking correctness for uninitialized.construct.value +template +bool +IsCheckValueCorrectness(Iterator begin, Iterator end) +{ + for (; begin != end; ++begin) + { + if (*begin != T()) + { + return false; + } + } + return true; +} + +struct test_uninit_construct +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::false_type) + { + typedef typename std::iterator_traits::value_type T; + // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) + // and for cleaning memory after last calling of uninitialized_value_construct_n. + // It is important for non-trivial types + std::destroy_n(exec, begin, n); + + // reset counter of constructors + T::SetCount(0); + // run algorithm + std::uninitialized_default_construct(exec, begin, end); + // compare counter of constructors to length of container + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct"); + // destroy objects for testing new algorithms on same memory + std::destroy(exec, begin, end); + + std::uninitialized_default_construct_n(exec, begin, n); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct_n"); + std::destroy_n(exec, begin, n); + + std::uninitialized_value_construct(exec, begin, end); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct"); + std::destroy(exec, begin, end); + + std::uninitialized_value_construct_n(exec, begin, n); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct_n"); + } + + template + void + operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::true_type) + { + typedef typename std::iterator_traits::value_type T; + + std::uninitialized_default_construct(exec, begin, end); + std::destroy(exec, begin, end); + + std::uninitialized_default_construct_n(exec, begin, n); + std::destroy_n(exec, begin, n); + + std::uninitialized_value_construct(exec, begin, end); + // check correctness for uninitialized.construct.value + EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct"); + std::destroy(exec, begin, end); + + std::uninitialized_value_construct_n(exec, begin, n); + EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct_n"); + std::destroy_n(exec, begin, n); + } +}; + +template +void +test_uninit_construct_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninit_construct(), p.get(), std::next(p.get(), n), n, std::is_trivial()); + } +} + +int +main() +{ + + // for user-defined types +#if !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN + test_uninit_construct_by_type>(); + test_uninit_construct_by_type>>(); +#endif + + // for trivial types + test_uninit_construct_by_type(); + test_uninit_construct_by_type(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp new file mode 100644 index 000000000000..d1c9e3a7a071 --- /dev/null +++ b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp @@ -0,0 +1,143 @@ +// -*- C++ -*- +//===-- uninitialized_copy_move.pass.cpp ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// Tests for uninitialized_copy, uninitialized_copy_n, uninitialized_move, uninitialized_move_n + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +// function of checking correctness for uninitialized.construct.value +template +bool +IsCheckValueCorrectness(InputIterator first1, OutputIterator first2, Size n) +{ + for (Size i = 0; i < n; ++i, ++first1, ++first2) + { + if (*first1 != *first2) + { + return false; + } + } + return true; +} + +struct test_uninitialized_copy_move +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, + /*is_trivial=*/std::false_type) + { + typedef typename std::iterator_traits::value_type T; + // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) + // and for cleaning memory after last calling of uninitialized_value_construct_n. + // It is important for non-trivial types + std::destroy_n(exec, out_first, n); + + // reset counter of constructors + T::SetCount(0); + // run algorithm + std::uninitialized_copy(exec, first, last, out_first); + // compare counter of constructors to length of container + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy"); + // destroy objects for testing new algorithms on same memory + std::destroy_n(exec, out_first, n); + + std::uninitialized_copy_n(exec, first, n, out_first); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy_n"); + std::destroy_n(exec, out_first, n); + + // For move + std::uninitialized_move(exec, first, last, out_first); + // compare counter of constructors to length of container + EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move"); + // destroy objects for testing new algorithms on same memory + std::destroy_n(exec, out_first, n); + + std::uninitialized_move_n(exec, first, n, out_first); + EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move_n"); + std::destroy_n(exec, out_first, n); + } + +#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + size_t n, /*is_trivial=*/std::true_type) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, size_t n, /*is_trivial=*/std::true_type) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, + /*is_trivial=*/std::true_type) + { + std::uninitialized_copy(exec, first, last, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_copy_n(exec, first, n, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy_n"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_move(exec, first, last, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_move_n(exec, first, n, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move_n"); + std::destroy_n(exec, out_first, n); + } +}; + +template +void +test_uninitialized_copy_move_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [=](size_t k) -> T { return T(k); }); + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninitialized_copy_move(), in.begin(), in.end(), p.get(), n, std::is_trivial()); + } +} + +int +main() +{ + + // for trivial types + test_uninitialized_copy_move_by_type(); + test_uninitialized_copy_move_by_type(); + + // for user-defined types +#if !_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && !_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && \ + !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN + test_uninitialized_copy_move_by_type>(); +#endif + + std::cout << done() << std::endl; + return 0; +} diff --git a/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp new file mode 100644 index 000000000000..fe85f32a1f7b --- /dev/null +++ b/libcxx/test/std/pstl/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp @@ -0,0 +1,93 @@ +// -*- C++ -*- +//===-- uninitialized_fill_destroy.pass.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include "support/pstl_test_config.h" + +#include +#include + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_uninitialized_fill_destroy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::false_type) + { + using namespace std; + { + T::SetCount(0); + uninitialized_fill(exec, first, last, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_TRUE(n == count, "wrong work of uninitialized_fill"); + destroy(exec, first, last); + EXPECT_TRUE(T::Count() == 0, "wrong work of destroy"); + } + + { + auto res = uninitialized_fill_n(exec, first, n, in); + EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_TRUE(n == count, "wrong work of uninitialized_fill_n"); + destroy_n(exec, first, n); + EXPECT_TRUE(T::Count() == 0, "wrong work of destroy_n"); + } + } + template + void + operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::true_type) + { + using namespace std; + { + destroy(exec, first, last); + uninitialized_fill(exec, first, last, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_EQ(n, count, "wrong work of uninitialized:_fill"); + } + { + destroy_n(exec, first, n); + auto res = uninitialized_fill_n(exec, first, n, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_EQ(n, count, "wrong work of uninitialized_fill_n"); + EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); + } + } +}; + +template +void +test_uninitialized_fill_destroy_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninitialized_fill_destroy(), p.get(), std::next(p.get(), n), T(), n, + std::is_trivial()); + } +} + +int +main() +{ + // for trivial types + test_uninitialized_fill_destroy_by_type(); + test_uninitialized_fill_destroy_by_type(); + + // for user-defined types + test_uninitialized_fill_destroy_by_type>(); + test_uninitialized_fill_destroy_by_type>(); + std::cout << done() << std::endl; + + return 0; +} diff --git a/llvm/lib/Transforms/CMakeLists.txt b/llvm/lib/Transforms/CMakeLists.txt index dda5f6de11e3..77724656ed8f 100644 --- a/llvm/lib/Transforms/CMakeLists.txt +++ b/llvm/lib/Transforms/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(Hello) add_subdirectory(ObjCARC) add_subdirectory(Coroutines) add_subdirectory(CFGuard) +add_subdirectory(AntiHack) diff --git a/llvm/lib/Transforms/IPO/LLVMBuild.txt b/llvm/lib/Transforms/IPO/LLVMBuild.txt index ea207e81fce8..990037435826 100644 --- a/llvm/lib/Transforms/IPO/LLVMBuild.txt +++ b/llvm/lib/Transforms/IPO/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = IPO parent = Transforms library_name = ipo -required_libraries = AggressiveInstCombine Analysis BitReader BitWriter Core FrontendOpenMP InstCombine IRReader Linker Object ProfileData Scalar Support TransformUtils Vectorize Instrumentation +required_libraries = AggressiveInstCombine Analysis BitReader BitWriter Core FrontendOpenMP InstCombine IRReader Linker Object ProfileData Scalar Support TransformUtils Vectorize Instrumentation AntiHack diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 04f2099b3dd4..b120c646773e 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -48,9 +48,21 @@ #include "llvm/Transforms/Vectorize/LoopVectorize.h" #include "llvm/Transforms/Vectorize/SLPVectorizer.h" #include "llvm/Transforms/Vectorize/VectorCombine.h" +#include "llvm/Transforms/AntiHack/AntiHack.h" + using namespace llvm; +//DECLANG CODES BEGIN +static cl::opt +FinalizerOpt("no-finalizer", cl::init(false), cl::Hidden, + cl::ZeroOrMore, cl::desc("no finalizer option")); + +static cl::opt +AntiHackOpt("antihack", cl::init(""), cl::Hidden, + cl::ZeroOrMore, cl::desc("antihack pass")); +//DECLANG CODES END + static cl::opt RunPartialInlining("enable-partial-inlining", cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::desc("Run Partial inlinining pass")); @@ -885,6 +897,10 @@ void PassManagerBuilder::populateModulePassManager( } MPM.add(createAnnotationRemarksLegacyPass()); + + //DECLANG CODES BEGIN + MPM.add(createAntiHack(AntiHackOpt)); + //DECLANG CODES END } void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { diff --git a/llvm/lib/Transforms/LLVMBuild.txt b/llvm/lib/Transforms/LLVMBuild.txt index 5fb5efcc068c..d69c0f7e1fbf 100644 --- a/llvm/lib/Transforms/LLVMBuild.txt +++ b/llvm/lib/Transforms/LLVMBuild.txt @@ -15,7 +15,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = AggressiveInstCombine Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC CFGuard +subdirectories = AggressiveInstCombine Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC CFGuard AntiHack [component_0] type = Group diff --git a/script/build.sh b/script/build.sh new file mode 100644 index 000000000000..1e4b4e8ad949 --- /dev/null +++ b/script/build.sh @@ -0,0 +1,65 @@ +set -e + +pushd $(dirname $0) > /dev/null + +cd ../ + +rm -f clang/lib/Driver/DeClangExtraProcess.cpp +rm -f llvm/lib/Transforms/AntiHack +rm -f llvm/include/llvm/Transforms/AntiHack +rm -f tools + +if [[ -e AntiHackDeNA ]]; then + ln -s ../../../AntiHackDeNA/clang/DeClangExtraProcess.cpp clang/lib/Driver/DeClangExtraProcess.cpp + ln -s ../../../AntiHackDeNA/src llvm/lib/Transforms/AntiHack + ln -s ../../../../AntiHackDeNA/include llvm/include/llvm/Transforms/AntiHack + ln -s AntiHackDeNA/tools tools +else + ln -s ../../../AntiHackOSS/clang/DeClangExtraProcess.cpp clang/lib/Driver/DeClangExtraProcess.cpp + ln -s ../../../AntiHackOSS/src llvm/lib/Transforms/AntiHack + ln -s ../../../../AntiHackOSS/include llvm/include/llvm/Transforms/AntiHack + ln -s AntiHackOSS/tools tools +fi + +# mkdir -p build/ +# cd build/ +# if [[ ! -e Makefile ]]; then +# use_ccache="false" +# if [ $(which ccache) ]; then +# use_ccache="true" +# fi +# +# if [[ "_$OS" = "_Windows_NT" ]]; then +# cmake \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DLLVM_ENABLE_DUMP=ON \ +# -DLLVM_ENABLE_PROJECTS=clang \ +# -DLLVM_CCACHE_BUILD=${use_ccache}\ +# -DLLVM_USE_CRT_RELEASE=MT \ +# -DLLVM_USE_CRT_RELWITHDEBINFO=MT \ +# -A x64\ +# -Thost=x64\ +# -G "Visual Studio 15 2017" ../llvm +# +# else +# cmake \ +# -DLLVM_ENABLE_DUMP=ON \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DLLVM_ENABLE_PROJECTS=clang \ +# -DLLVM_CCACHE_BUILD=${use_ccache}\ +# -G "Unix Makefiles" ../llvm +# fi +# +# fi +# +# +# if [[ "_$OS" = "_Windows_NT" ]]; then +# # TODO Community版以外でも動くようにする +# echo "Build Release x64 in Visual Studio" +# cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" && msbuild /p:Configuration=Release;Platform=x64 tools\clang\tools\driver\clang.vcxproj' +# else +# make llvm-headers +# make -j 16 +# fi + +popd > /dev/null diff --git a/script/build_tools.sh b/script/build_tools.sh new file mode 100644 index 000000000000..42fcb2d51827 --- /dev/null +++ b/script/build_tools.sh @@ -0,0 +1,8 @@ +set -e + +pushd $(dirname $0) > /dev/null + +cd -P ../tools/ +exec bash build_tools.sh $1 + +popd > /dev/null diff --git a/script/ndk_setup.sh b/script/ndk_setup.sh new file mode 100644 index 000000000000..8d08fbf85490 --- /dev/null +++ b/script/ndk_setup.sh @@ -0,0 +1,50 @@ +set -e + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 {ndk_path}" >&2 + exit 1 +fi + +ndk_path=$1 +dir=`dirname "$ndk_path"` + +pushd "$dir" > /dev/null + +if [[ -z "$DECLANG_HOME" ]]; then + HOMEDIR=$HOME +else + HOMEDIR=$DECLANG_HOME +fi +compiler_path="$HOMEDIR"/.DeClang/compiler/ + +if [ "_$OS" = "_Windows_NT" ]; then + ndk_clang_path=`find "$ndk_path" -type f -name "clang++.exe"` +else + ndk_clang_path=`find "$ndk_path" -type f -name "clang++"` +fi + +darwin_path=`dirname "$ndk_clang_path"` +darwin_path=`dirname "$darwin_path"` + +echo "$darwin_path" + +# backup +if [[ ! -f "${darwin_path}"/bin/clang.orig ]]; then + cp "${darwin_path}"/bin/clang "${darwin_path}"/bin/clang.orig +fi + +if [[ ! -f "${darwin_path}"/bin/clang++.orig ]]; then + cp "${darwin_path}"/bin/clang++ "${darwin_path}"/bin/clang++.orig +fi + +# copy bin and lib +cp -v "${compiler_path}"/bin/clang "${darwin_path}"/bin/clang +cp -v "${compiler_path}"/bin/clang++ "${darwin_path}"/bin/clang++ + +mkdir -p "${darwin_path}"/lib/ +if [[ ! -d "${darwin_path}"/lib.orig ]]; then + cp -r "${darwin_path}"/lib "${darwin_path}"/lib.orig +fi +cp -r "${compiler_path}"/lib/clang "${darwin_path}"/lib/ + +popd >/dev/null diff --git a/script/ndk_unset.sh b/script/ndk_unset.sh new file mode 100644 index 000000000000..fdd26466391b --- /dev/null +++ b/script/ndk_unset.sh @@ -0,0 +1,39 @@ +set -e + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 {ndk_path}" >&2 + exit 1 +fi + +ndk_path=$1 +dir=`dirname "$ndk_path"` + +pushd "$dir" > /dev/null + +if [ "_$OS" = "_Windows_NT" ]; then + ndk_clang_path=`find "$ndk_path" -type f -name "clang++.exe"` +else + ndk_clang_path=`find "$ndk_path" -type f -name "clang++"` +fi + +darwin_path=`dirname "$ndk_clang_path"` +darwin_path=`dirname "$darwin_path"` + +echo "$darwin_path" + +# restore bin +if [[ -f "${darwin_path}"/bin/clang.orig ]]; then + cp -v "${darwin_path}"/bin/clang.orig "${darwin_path}"/bin/clang + rm "${darwin_path}"/bin/clang.orig +fi +if [[ -f "${darwin_path}"/bin/clang++.orig ]]; then + cp -v "${darwin_path}"/bin/clang++.orig "${darwin_path}"/bin/clang++ + rm "${darwin_path}"/bin/clang++.orig +fi + +if [[ -d "${darwin_path}"/lib.orig ]]; then + rm -rf "${darwin_path}"/lib/ + mv "${darwin_path}"/lib.orig "${darwin_path}"/lib +fi + +popd >/dev/null diff --git a/script/release.sh b/script/release.sh new file mode 100644 index 000000000000..4de91f70197e --- /dev/null +++ b/script/release.sh @@ -0,0 +1,8 @@ +set -e + +pushd $(dirname $0) > /dev/null + +cd ../tools/ +exec bash release.sh $1 + +popd > /dev/null diff --git a/script/xcode_setup.sh b/script/xcode_setup.sh new file mode 100644 index 000000000000..a5c2fd99e548 --- /dev/null +++ b/script/xcode_setup.sh @@ -0,0 +1,79 @@ +set -e + +POSITIONAL=() +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -x|--xcode-appdir) + xcode_app_dir="$2" + shift # past argument + shift # past value + ;; + -p|--xcodeproj) + xcode_project_path="$2" + shift # past argument + shift # past value + ;; + -h|--help) + echo "Usage: $0 -x={xcode_app_dir} -p={xcode_project_path}" >&2 + exit + shift # past argument + ;; + *) # unknown option + POSITIONAL+=("$1") # save it in an array for later + shift # past argument + ;; +esac +done +set -- "${POSITIONAL[@]}" # restore positional parameters + + +if [[ $xcode_app_dir = "" ]] +then + xcode_app_dir="/Applications/Xcode.app/" +fi +echo xcode_app_dir = $xcode_app_dir +echo xcode_project_path = $xcode_project_path + +# $pwd=`pwd` +# pushd $(dirname $pwd) > /dev/null + +xcode_clang_path="$xcode_app_dir/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/" +xcode_lib_path=`find "$xcode_clang_path" -d -name "darwin"` + +pbxproj=`find $xcode_project_path -name "*.pbxproj"` + +if [[ ! -f ${pbxproj}.orig ]]; then + cp $pbxproj ${pbxproj}.orig +fi + + +echo modifying $pbxproj +# sed -i '' $'s~COMPILER_INDEX_STORE_ENABLE = YES;~COMPILER_INDEX_STORE_ENABLE = NO;\\\n{CC_placeholder}\\\n{CXX_placeholder}~g' "$pbxproj" +# sed -i '' "s~{CC_placeholder}~CC = ${clang_8};~g" "$pbxproj" +# sed -i '' "s~{CXX_placeholder}~CPLUSPLUS = ${clang_8};~g" "$pbxproj" + +perl -i -pe 'BEGIN{undef $/;} s~(OTHER_LDFLAGS = \(.*?)\);~$1"-L{/path/to/xcode_lib_path}",\n"-lclang_rt.ios",\n"-lc++",\n);~smg' "$pbxproj" +sed -i '' "s~{/path/to/xcode_lib_path}~${xcode_lib_path}~g" "$pbxproj" + +if [[ -z "$DECLANG_HOME" ]]; then + HOMEDIR=$HOME +else + HOMEDIR=$DECLANG_HOME +fi + +DECLANG=$HOMEDIR/.DeClang/compiler/bin/clang +DECLANGXX=$HOMEDIR/.DeClang/compiler/bin/clang++ +sed -i '' $"s~buildSettings = {~buildSettings = {\\ +CC = \"${DECLANG}\";\\ +CPLUSPLUS = \"${DECLANGXX}\";\\ +LD = \"${DECLANG}\";\\ +LDPLUSPLUS = \"${DECLANGXX}\";\\ +COMPILER_INDEX_STORE_ENABLE = NO;\\ +~g" "$pbxproj" +sed -i '' $'s~COMPILER_INDEX_STORE_ENABLE = YES;~COMPILER_INDEX_STORE_ENABLE = NO;~g' "$pbxproj" +sed -i '' $'s~COMPILER_INDEX_STORE_ENABLE = DEFAULT;~COMPILER_INDEX_STORE_ENABLE = NO;~g' "$pbxproj" + +# popd >/dev/null diff --git a/script/xcode_unset.sh b/script/xcode_unset.sh new file mode 100644 index 000000000000..ffcd52f44c32 --- /dev/null +++ b/script/xcode_unset.sh @@ -0,0 +1,18 @@ +set -e + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 {xcodeproj_path}" >&2 + exit 1 +fi + +project_path=$1 + +pushd $(dirname $1) > /dev/null + +pbxproj=`find . -name "*.pbxproj"` +if [[ -f ${pbxproj}.orig ]]; then + cp ${pbxproj}.orig ${pbxproj} + rm ${pbxproj}.orig +fi + +popd >/dev/null