From: Andreas Beckmann Date: Thu, 8 Feb 2024 21:48:18 +0000 (+0100) Subject: Import spirv-llvm-translator-15_15.0.0-6.debian.tar.xz X-Git-Tag: archive/raspbian/15.0.0-6+rpi1^2~81^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b16457360073a937b23e21db5223009a1704eb93;p=spirv-llvm-translator-15.git Import spirv-llvm-translator-15_15.0.0-6.debian.tar.xz [dgit import tarball spirv-llvm-translator-15 15.0.0-6 spirv-llvm-translator-15_15.0.0-6.debian.tar.xz] --- b16457360073a937b23e21db5223009a1704eb93 diff --git a/changelog b/changelog new file mode 100644 index 0000000..01b4d8b --- /dev/null +++ b/changelog @@ -0,0 +1,370 @@ +spirv-llvm-translator-15 (15.0.0-6) unstable; urgency=medium + + * Add build-needed autopkgtest for spirv-headers compat check. + * Update from llvm_release_150 branch. + * Bump spirv-headers dependency to 1.6.1+1.3.275.0. + + -- Andreas Beckmann Thu, 08 Feb 2024 22:48:18 +0100 + +spirv-llvm-translator-15 (15.0.0-5) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Fri, 29 Sep 2023 13:48:15 +0200 + +spirv-llvm-translator-15 (15.0.0-4) unstable; urgency=medium + + [ Andreas Beckmann ] + * Update .symbols control file for gcc-13 builds. + + [ Gianfranco Costamagna ] + * Mark some more symbols as optional as they don't appear on Ubuntu (LTO?). + (Closes: #1042819) + + -- Andreas Beckmann Thu, 03 Aug 2023 11:46:40 +0200 + +spirv-llvm-translator-15 (15.0.0-3) unstable; urgency=medium + + * Fix compatibility with newer spirv-as. (Closes: #1040056) + + -- Andreas Beckmann Tue, 11 Jul 2023 15:05:17 +0200 + +spirv-llvm-translator-15 (15.0.0-2) unstable; urgency=medium + + * Merge changes from spirv-llvm-translator-14 14.0.0-5. + * Restrict watch file to 15.* releases. + * Bump Standards-Version to 4.6.2. + + -- Andreas Beckmann Tue, 04 Apr 2023 11:24:20 +0200 + +spirv-llvm-translator-15 (15.0.0-1) unstable; urgency=medium + + * New upstream release. + * Fork source package as spirv-llvm-translator-15. + * Rename binary packages: *14* => *15*. + * Build with llvm 15. + + -- Andreas Beckmann Mon, 03 Oct 2022 02:09:37 +0200 + +spirv-llvm-translator-14 (14.0.0-10) unstable; urgency=medium + + * Add build-needed autopkgtest for spirv-headers compat check. + * Update from llvm_release_140 branch. + * Bump spirv-headers dependency to 1.6.1+1.3.275.0. + * Update .symbols control file. + + -- Andreas Beckmann Thu, 08 Feb 2024 03:47:14 +0100 + +spirv-llvm-translator-14 (14.0.0-9) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Fri, 29 Sep 2023 13:39:11 +0200 + +spirv-llvm-translator-14 (14.0.0-8) unstable; urgency=medium + + [ Gianfranco Costamagna ] + * Mark some more symbols as optional as they don't appear on Ubuntu (LTO?). + (Closes: #1042819) + + -- Andreas Beckmann Tue, 01 Aug 2023 14:45:06 +0200 + +spirv-llvm-translator-14 (14.0.0-7) unstable; urgency=medium + + * Update .symbols control file for gcc-13 builds. + + -- Andreas Beckmann Mon, 31 Jul 2023 11:05:53 +0200 + +spirv-llvm-translator-14 (14.0.0-6) unstable; urgency=medium + + * Fix compatibility with newer spirv-as. (Closes: #1040055) + * Bump Standards-Version to 4.6.2. + + -- Andreas Beckmann Tue, 11 Jul 2023 14:03:54 +0200 + +spirv-llvm-translator-14 (14.0.0-5) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Wed, 26 Oct 2022 09:11:37 +0200 + +spirv-llvm-translator-14 (14.0.0-4) unstable; urgency=medium + + * Build with -fvisibility=hidden -fvisibility-inlines-hidden. + * Drop hidden symbols from .symbols control file. + + -- Andreas Beckmann Mon, 24 Oct 2022 17:41:42 +0200 + +spirv-llvm-translator-14 (14.0.0-3) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Sun, 02 Oct 2022 13:48:53 +0200 + +spirv-llvm-translator-14 (14.0.0-2) unstable; urgency=medium + + * Restrict watch file to 14.* releases. + * Build with spirv-tools. + * Add autopkgtest, ignore failures on !amd64. + * Enable build-time tests, ignore failures on !amd64. + * Use pkg-kde-tools to manage the .symbols. + * Add .symbols control file. + + -- Andreas Beckmann Fri, 30 Sep 2022 18:00:36 +0200 + +spirv-llvm-translator-14 (14.0.0-1) unstable; urgency=medium + + * New upstream release. + * Fork source package as spirv-llvm-translator-14. + * Rename binary packages: *13* => *14*. + * Build with llvm 14. + + -- Andreas Beckmann Mon, 16 May 2022 09:29:32 +0200 + +spirv-llvm-translator (13.0.0-6) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Fri, 30 Sep 2022 16:36:05 +0200 + +spirv-llvm-translator (13.0.0-5) unstable; urgency=medium + + * Use pkg-kde-tools to manage the .symbols. + * Add .symbols control file. + * Update Lintian overrides. + + -- Andreas Beckmann Thu, 29 Sep 2022 22:34:44 +0200 + +spirv-llvm-translator (13.0.0-4) unstable; urgency=medium + + * Rename /usr/bin/llvm-spirv to /usr/bin/llvm-spirv-13. + * Restrict watch file to 13.* releases. + * Enable all hardening flags. + * Bump Standards-Version to 4.6.1. + + -- Andreas Beckmann Mon, 16 May 2022 01:58:34 +0200 + +spirv-llvm-translator (13.0.0-3) unstable; urgency=medium + + * Rename OpConstFunctionPointerINTEL to OpConstantFunctionPointerINTEL to + fix FTBFS with spirv-headers 1.5.5. (Closes: #1005458) + * rules: Parse llvm version from Build-Depends. + * control: Provide virtual package libllvmspirvlib-13-dev. + * control: Set Rules-Requires-Root: no. + * control, install: Multiarchify the packages. + * upstream/metadata: Add. + * copyright: Update/remove outdated file patterns. + * Fix typo. + * Update Lintian overrides. + * Add myself to Uploaders. + + -- Andreas Beckmann Wed, 16 Feb 2022 23:28:24 +0100 + +spirv-llvm-translator (13.0.0-2) unstable; urgency=medium + + * control: Drop lldb-13 from build-depends, it's not used and prevents + build on mips/mipsel. + + -- Timo Aaltonen Wed, 17 Nov 2021 11:00:43 +0200 + +spirv-llvm-translator (13.0.0-1) unstable; urgency=medium + + * New upstream release. + * control: Bump debhelper to 13. + * control: Bump policy to 4.6.0. + + -- Timo Aaltonen Wed, 27 Oct 2021 10:41:14 +0300 + +spirv-llvm-translator (13.0~git20210929-1) unstable; urgency=medium + + * New upstream snapshot. + * Build with llvm 13. + * Add spirv-headers to build-depends, set headers dir. + + -- Timo Aaltonen Wed, 29 Sep 2021 14:40:45 +0300 + +spirv-llvm-translator-12 (12.0.0-6) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Thu, 29 Sep 2022 21:34:40 +0200 + +spirv-llvm-translator-12 (12.0.0-5) unstable; urgency=medium + + * Use pkg-kde-tools to manage the .symbols. + * Add .symbols control file. + * Update Lintian overrides. + + -- Andreas Beckmann Thu, 29 Sep 2022 04:13:09 +0200 + +spirv-llvm-translator-12 (12.0.0-4) unstable; urgency=medium + + * Restrict watch file to 12.* releases. + * Enable all hardening flags. + * Bump Standards-Version to 4.6.1. + + -- Andreas Beckmann Sun, 15 May 2022 23:58:08 +0200 + +spirv-llvm-translator-12 (12.0.0-3) unstable; urgency=medium + + [ Timo Aaltonen ] + * control: Bump debhelper to 13. + * control: Bump policy to 4.6.0. + * control: Drop lldb-12 from build-depends, it's not used and prevents + build on mips/mipsel. + + [ Andreas Beckmann ] + * rules: Parse llvm version from Build-Depends. + * control: Set Rules-Requires-Root: no. + * control, install: Multiarchify the packages. + * upstream/metadata: Add. + * copyright: Update/remove outdated file patterns. + * Fix typo. + * Update Lintian overrides. + * Add myself to Uploaders. + * Have one set of packages per llvm version: + - Fork source package as spirv-llvm-translator-12. + - Rename binary packages: + + libllvmspirvlib-dev => libllvmspirvlib-12-dev, + + llvm-spirv => llvm-spirv-12. + - Rename /usr/bin/llvm-spirv to /usr/bin/llvm-spirv-12. + + -- Andreas Beckmann Wed, 09 Feb 2022 20:05:39 +0100 + +spirv-llvm-translator (12.0.0-2) unstable; urgency=medium + + * Upload to unstable. + + -- Timo Aaltonen Mon, 16 Aug 2021 09:59:48 +0300 + +spirv-llvm-translator (12.0.0-1) experimental; urgency=medium + + * New upstream release. + + -- Timo Aaltonen Mon, 07 Jun 2021 12:24:54 +0300 + +spirv-llvm-translator (12.0~git20210212-2) experimental; urgency=medium + + * control: Fix libllvmspirvlib-dev depends. + + -- Timo Aaltonen Mon, 10 May 2021 12:17:08 +0300 + +spirv-llvm-translator (12.0~git20210212-1) experimental; urgency=medium + + * New upstream snapshot. + * Build against llvm-12. + + -- Timo Aaltonen Mon, 12 Apr 2021 20:24:01 +0300 + +spirv-llvm-translator-11 (11.0.0-4) unstable; urgency=medium + + * Update .symbols control file. + + -- Andreas Beckmann Thu, 29 Sep 2022 03:48:48 +0200 + +spirv-llvm-translator-11 (11.0.0-3) unstable; urgency=medium + + * Use pkg-kde-tools to manage the .symbols. + * Add .symbols control file. + * Update Lintian overrides. + + -- Andreas Beckmann Wed, 28 Sep 2022 19:10:39 +0200 + +spirv-llvm-translator-11 (11.0.0-2) unstable; urgency=medium + + [ Timo Aaltonen ] + * control: Bump debhelper to 13. + * control: Bump policy to 4.6.0. + * control: Drop lldb-11 from build-depends, it's not used and prevents + build on mips/mipsel. + + [ Andreas Beckmann ] + * rules: Parse llvm version from Build-Depends. + * control: Set Rules-Requires-Root: no. + * control, install: Multiarchify the packages. + * upstream/metadata: Add. + * copyright: Update/remove outdated file patterns. + * Fix typo. + * Update Lintian overrides. + * Add myself to Uploaders. + * Have one set of packages per llvm version: + - Fork source package as spirv-llvm-translator-11. + - Rename binary packages: + + libllvmspirvlib-dev => libllvmspirvlib-11-dev, + + llvm-spirv => llvm-spirv-11. + - Rename /usr/bin/llvm-spirv to /usr/bin/llvm-spirv-11. + * Allow overriding BASE_LLVM_VERSION. + * Restrict watch file to 11.* releases. + * Enable all hardening flags. + + -- Andreas Beckmann Mon, 11 Apr 2022 10:32:52 +0200 + +spirv-llvm-translator (11.0.0-1) unstable; urgency=medium + + * New upstream release. + * control: Mark -dev as M-A: same. + + -- Timo Aaltonen Tue, 20 Oct 2020 11:24:57 +0300 + +spirv-llvm-translator (11.0~git20200922-1) unstable; urgency=medium + + * New upstream snapshot. + * Build against llvm-11. + + -- Timo Aaltonen Tue, 22 Sep 2020 19:45:26 +0300 + +spirv-llvm-translator (10.0.0-1) unstable; urgency=medium + + * New upstream release. + * watch: Updated. + * Build against llvm-10. + * control: Use debhelper-compat, bump to 12. + * control: Bump policy to 4.5.0. + + -- Timo Aaltonen Wed, 01 Apr 2020 20:44:04 +0300 + +spirv-llvm-translator (9.0.0-1) unstable; urgency=medium + + * New upstream release. + * d/copyright: spirv.hpp is Expat. + * Build with llvm-9. + * patches: Dropped the only patch, applied upstream. + + -- Timo Aaltonen Tue, 24 Sep 2019 12:04:15 +0300 + +spirv-llvm-translator (8.0.1-1) unstable; urgency=medium + + * New upstream release. + * rules: Set build type as 'Release'. + * debian/patches: Refreshed. + + -- Timo Aaltonen Thu, 01 Aug 2019 10:06:44 +0300 + +spirv-llvm-translator (8.0.0+git20190314-1) experimental; urgency=medium + + * New upstream snapshot. + * Build a shared library. + * Package llvm-spirv. + * Add patch to support clang block syntax. + * rules: Drop rpath. + + -- Timo Aaltonen Wed, 20 Mar 2019 17:24:46 +0200 + +spirv-llvm-translator (8.0.0-3) experimental; urgency=medium + + * rules: Rebuild the archive index after stripping. + + -- Timo Aaltonen Fri, 15 Mar 2019 09:23:42 +0200 + +spirv-llvm-translator (8.0.0-2) experimental; urgency=medium + + * rules: Build with -fPIC. + * rules: Strip the library. + + -- Timo Aaltonen Thu, 14 Mar 2019 23:53:32 +0200 + +spirv-llvm-translator (8.0.0-1) experimental; urgency=medium + + * Initial release (Closes: #921422) + + -- Timo Aaltonen Wed, 06 Feb 2019 01:40:18 +0200 diff --git a/control b/control new file mode 100644 index 0000000..715deaf --- /dev/null +++ b/control @@ -0,0 +1,72 @@ +Source: spirv-llvm-translator-15 +Section: libdevel +Priority: optional +Maintainer: Debian OpenCL team +Uploaders: + Timo Aaltonen , + Andreas Beckmann , +Build-Depends: debhelper-compat (= 13), + dh-sequence-pkgkde-symbolshelper, + cmake, + gcc (>= 4:13), + pkgconf, + spirv-headers (>= 1.6.1+1.3.275.0), + spirv-tools, +# keep the clang/llvm version in sync, don't forget debian/tests/control + libclang-15-dev, + llvm-15-dev, + clang-15 , +Rules-Requires-Root: no +Standards-Version: 4.6.2 +Homepage: https://github.com/KhronosGroup/SPIRV-LLVM-Translator +Vcs-Browser: https://salsa.debian.org/opencl-team/spirv-llvm-translator +Vcs-Git: https://salsa.debian.org/opencl-team/spirv-llvm-translator.git -b llvm15/main + +Package: libllvmspirvlib15 +Architecture: any +Multi-Arch: same +Section: libs +Depends: + ${shlibs:Depends}, + ${misc:Depends} +Description: bi-directional translator for LLVM/SPIRV -- shared library + SPIRV-LLVM-translator is a LLVM/SPIRV bi-directional translator. This + package includes a library and a tool for translation between LLVM IR + and SPIR-V. + . + This package includes the shared library. + +Package: libllvmspirvlib-15-dev +Architecture: any +Multi-Arch: same +Depends: + libllvmspirvlib15 (= ${binary:Version}), + ${misc:Depends} +Conflicts: + libllvmspirvlib-x.y-dev, +Breaks: + libllvmspirvlib-dev (<< 13.0.0-3~), +Replaces: + libllvmspirvlib-dev (<< 13.0.0-3~), + libllvmspirvlib-x.y-dev, +Provides: + libllvmspirvlib-x.y-dev, +Description: bi-directional translator for LLVM/SPIRV -- development files + SPIRV-LLVM-translator is a LLVM/SPIRV bi-directional translator. This + package includes a library and a tool for translation between LLVM IR + and SPIR-V. + . + This package includes static libs and headers for development. + +Package: llvm-spirv-15 +Architecture: any +Depends: + libllvmspirvlib15 (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: bi-directional translator for LLVM/SPIRV + SPIRV-LLVM-translator is a LLVM/SPIRV bi-directional translator. This + package includes a library and a tool for translation between LLVM IR + and SPIR-V. + . + This package includes the llvm-spirv-15 binary. diff --git a/copyright b/copyright new file mode 100644 index 0000000..a6950dd --- /dev/null +++ b/copyright @@ -0,0 +1,70 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: spirv-llvm-translator +Source: https://github.com/KhronosGroup/SPIRV-LLVM-Translator + +Files: * +Copyright: 2014 Advanced Micro Devices, Inc. + 2018-2021 Intel Corporation +License: BSD-3-clause + +Files: + lib/SPIRV/libSPIRV/OpenCL.std.h + lib/SPIRV/libSPIRV/spirv_internal.hpp +Copyright: 2015-2020 The Khronos Group Inc. +License: Expat + +Files: debian/* +Copyright: 2019 Timo Aaltonen + © 2022-2024 Andreas Beckmann +License: BSD-3-clause + +License: BSD-3-clause + 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 LLVM Team, University of Illinois at + Urbana-Champaign, 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. + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), + to deal in the Materials without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Materials, and to permit persons to whom the + Materials are furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Materials. + . + MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS + STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND + HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ + . + THE MATERIALS ARE 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 AUTHORS 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 MATERIALS OR THE USE OR OTHER DEALINGS + IN THE MATERIALS. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..c543182 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,3 @@ +[DEFAULT] +upstream-vcs-tag = v%(version)s +debian-branch = llvm15/main diff --git a/libllvmspirvlib-15-dev.install b/libllvmspirvlib-15-dev.install new file mode 100644 index 0000000..82bf111 --- /dev/null +++ b/libllvmspirvlib-15-dev.install @@ -0,0 +1,3 @@ +usr/include +usr/lib/libLLVMSPIRVLib.so usr/lib/${DEB_HOST_MULTIARCH}/ +usr/lib/pkgconfig/LLVMSPIRVLib.pc usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig/ diff --git a/libllvmspirvlib15.install b/libllvmspirvlib15.install new file mode 100644 index 0000000..6fb00df --- /dev/null +++ b/libllvmspirvlib15.install @@ -0,0 +1 @@ +usr/lib/libLLVMSPIRVLib.so.* usr/lib/${DEB_HOST_MULTIARCH}/ diff --git a/libllvmspirvlib15.symbols b/libllvmspirvlib15.symbols new file mode 100644 index 0000000..582f86d --- /dev/null +++ b/libllvmspirvlib15.symbols @@ -0,0 +1,491 @@ +# SymbolsHelper-Confirmed: 15.0.0-4~gcc13 amd64 arm64 armel armhf i386 mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x x32 +libLLVMSPIRVLib.so.15 #PACKAGE# #MINVER# +* Build-Depends-Package: libllvmspirvlib-15-dev + _ZGVZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb0EEclEcE5__nul@Base 0 + _ZGVZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb1EEclEcE5__nul@Base 0 + _ZGVZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb0EEclEcE5__nul@Base 0 + _ZGVZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb1EEclEcE5__nul@Base 0 + _ZN4llvm10writeSpirvEPNS_6ModuleERKN5SPIRV14TranslatorOptsERSoRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm10writeSpirvEPNS_6ModuleERSoRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm16getSpecConstInfoERSiRSt6vectorISt4pairIjjESaIS3_EE@Base 0 + _ZN4llvm18convertSpirvToLLVMERNS_11LLVMContextERN5SPIRV11SPIRVModuleERKNS2_14TranslatorOptsERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm18convertSpirvToLLVMERNS_11LLVMContextERN5SPIRV11SPIRVModuleERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm19mangleOpenClBuiltinERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_8ArrayRefIPNS_4TypeEEENS8_INS_14PointerIntPairISA_Lj1EbNS_21PointerLikeTypeTraitsISA_EENS_18PointerIntPairInfoISA_Lj1ESE_EEEEEERS5_@Base 15 + _ZN4llvm21createSPIRVWriterPassERSo@Base 0 + _ZN4llvm21createSPIRVWriterPassERSoRKN5SPIRV14TranslatorOptsE@Base 0 + _ZN4llvm22createOCLToSPIRVLegacyEv@Base 13 + _ZN4llvm22regularizeLlvmForSpirvEPNS_6ModuleERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm22regularizeLlvmForSpirvEPNS_6ModuleERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN5SPIRV14TranslatorOptsE@Base 0 + _ZN4llvm23createLLVMToSPIRVLegacyEPN5SPIRV11SPIRVModuleE@Base 13 + _ZN4llvm24createSPIRVToOCL12LegacyEv@Base 13 + _ZN4llvm24createSPIRVToOCL20LegacyEv@Base 13 + _ZN4llvm26createOCLTypeToSPIRVLegacyEv@Base 13 + _ZN4llvm26createSPIRVBIsLoweringPassERNS_6ModuleEN5SPIRV17BIsRepresentationE@Base 0 + _ZN4llvm26createSPIRVLowerBoolLegacyEv@Base 13 + _ZN4llvm29createSPIRVLowerMemmoveLegacyEv@Base 13 + _ZN4llvm30createPreprocessMetadataLegacyEv@Base 13 + _ZN4llvm30initializeOCLToSPIRVLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm31createSPIRVLowerConstExprLegacyEv@Base 13 + _ZN4llvm31createSPIRVLowerOCLBlocksLegacyEv@Base 13 + _ZN4llvm31createSPIRVRegularizeLLVMLegacyEv@Base 13 + _ZN4llvm31initializeLLVMToSPIRVLegacyPassERNS_12PassRegistryE@Base 13 +#MISSING: 14.0.0-10~# _ZN4llvm32createSPIRVLowerSPIRBlocksLegacyEv@Base 13 + _ZN4llvm32initializeSPIRVToOCL12LegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm32initializeSPIRVToOCL20LegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm34initializeOCLTypeToSPIRVLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm34initializeSPIRVLowerBoolLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm36createSPIRVLowerSaddIntrinsicsLegacyEv@Base 14.0.0-10~ + _ZN4llvm37initializeSPIRVLowerMemmoveLegacyPassERNS_12PassRegistryE@Base 13 +#MISSING: 14.0.0-10~# _ZN4llvm38createSPIRVLowerSaddWithOverflowLegacyEv@Base 13 + _ZN4llvm38initializePreprocessMetadataLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm39initializeSPIRVLowerConstExprLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm39initializeSPIRVLowerOCLBlocksLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm39initializeSPIRVRegularizeLLVMLegacyPassERNS_12PassRegistryE@Base 13 +#MISSING: 14.0.0-10~# _ZN4llvm40initializeSPIRVLowerSPIRBlocksLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm44initializeSPIRVLowerSaddIntrinsicsLegacyPassERNS_12PassRegistryE@Base 14.0.0-10~ + _ZN4llvm46createSPIRVLowerBitCastToNonStandardTypeLegacyERKN5SPIRV14TranslatorOptsE@Base 14 +#MISSING: 14.0.0-10~# _ZN4llvm46initializeSPIRVLowerSaddWithOverflowLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm54initializeSPIRVLowerBitCastToNonStandardTypeLegacyPassERNS_12PassRegistryE@Base 13 + _ZN4llvm9readSpirvERNS_11LLVMContextERKN5SPIRV14TranslatorOptsERSiRPNS_6ModuleERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN4llvm9readSpirvERNS_11LLVMContextERSiRPNS_6ModuleERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN5SPIRV12convertSpirvERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_S6_b@Base 0 + _ZN5SPIRV12convertSpirvERSiRSoRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbb@Base 0 + _ZN5SPIRV14TranslatorOpts30setSPIRVAllowUnknownIntrinsicsEN4llvm11SmallVectorINS1_9StringRefELj4EEE@Base 13 + _ZN5SPIRV15readSpirvModuleERSiRKNS_14TranslatorOptsERNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN5SPIRV15readSpirvModuleERSiRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0 + _ZN5SPIRV18SPIRVUseTextFormatE@Base 0 + _ZNK5SPIRV14TranslatorOpts25isUnknownIntrinsicAllowedEPN4llvm13IntrinsicInstE@Base 13 + _ZNK5SPIRV14TranslatorOpts36isSPIRVAllowUnknownIntrinsicsEnabledEv@Base 13 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNKSt10_HashtableIjjSaIjENSt8__detail9_IdentityESt8equal_toIjESt4hashIjENS1_18_Mod_range_hashingENS1_20_Default_ranged_hashENS1_20_Prime_rehash_policyENS1_17_Hashtable_traitsILb0ELb1ELb1EEEE4findERKj@Base 14 + (optional=templinst)_ZNKSt7__cxx1112regex_traitsIcE16lookup_classnameIPKcEENS1_10_RegexMaskET_S6_b@Base 0 + (optional=templinst)_ZNKSt7__cxx1112regex_traitsIcE18lookup_collatenameIPKcEENS_12basic_stringIcSt11char_traitsIcESaIcEEET_SA_@Base 0 + (optional=templinst)_ZNKSt7__cxx1114regex_iteratorIPKccNS_12regex_traitsIcEEEeqERKS5_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNKSt8_Rb_treeIN3spv2OpESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE4findERS3_@Base 14 + (optional=templinst)_ZNKSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv2OpEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE4findERS7_@Base 0 + (optional=templinst)_ZNKSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE16_M_word_boundaryEv@Base 0 + (optional=templinst)_ZNKSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE16_M_word_boundaryEv@Base 0 + (optional=templinst|subst)_ZNSt10_HashtableIPKN4llvm8FunctionES3_SaIS3_ENSt8__detail9_IdentityESt8equal_toIS3_ESt4hashIS3_ENS5_18_Mod_range_hashingENS5_20_Default_ranged_hashENS5_20_Prime_rehash_policyENS5_17_Hashtable_traitsILb0ELb1ELb1EEEE21_M_insert_unique_nodeE{size_t}{size_t}PNS5_10_Hash_nodeIS3_Lb0EEE{size_t}@Base 0 + (optional=templinst|subst)_ZNSt10_HashtableIjSt4pairIKj{uint64_t}ESaIS2_ENSt8__detail10_Select1stESt8equal_toIjESt4hashIjENS4_18_Mod_range_hashingENS4_20_Default_ranged_hashENS4_20_Prime_rehash_policyENS4_17_Hashtable_traitsILb0ELb0ELb1EEEE18_M_assign_elementsIRKSF_EEvOT_@Base 0 + (optional=templinst|subst|arch=!armel !armhf !mipsel !powerpc)_ZNSt10_HashtableIjSt4pairIKj{uint64_t}ESaIS2_ENSt8__detail10_Select1stESt8equal_toIjESt4hashIjENS4_18_Mod_range_hashingENS4_20_Default_ranged_hashENS4_20_Prime_rehash_policyENS4_17_Hashtable_traitsILb0ELb0ELb1EEEE9_M_assignIRKSF_NS4_17_ReuseOrAllocNodeISaINS4_10_Hash_nodeIS2_Lb0EEEEEEEEvOT_RKT0_@Base 0 + (optional=templinst|arch=armel armhf i386 mipsel powerpc x32)_ZNSt10_HashtableIjjSaIjENSt8__detail9_IdentityESt8equal_toIjESt4hashIjENS1_18_Mod_range_hashingENS1_20_Default_ranged_hashENS1_20_Prime_rehash_policyENS1_17_Hashtable_traitsILb0ELb1ELb1EEEE21_M_insert_unique_nodeEjjPNS1_10_Hash_nodeIjLb0EEEj@Base 15.0.0-4~gcc13~ + (optional=templinst|arch=!armel !armhf !i386 !mipsel !powerpc !x32)_ZNSt10_HashtableIjjSaIjENSt8__detail9_IdentityESt8equal_toIjESt4hashIjENS1_18_Mod_range_hashingENS1_20_Default_ranged_hashENS1_20_Prime_rehash_policyENS1_17_Hashtable_traitsILb0ELb1ELb1EEEE21_M_insert_unique_nodeEmmPNS1_10_Hash_nodeIjLb0EEEm@Base 15.0.0-4~gcc13~ +#MISSING: 14.0.0-7~gcc13# (optional=templinst|subst)_ZNSt10_HashtableIjjSaIjENSt8__detail9_IdentityESt8equal_toIjESt4hashIjENS1_18_Mod_range_hashingENS1_20_Default_ranged_hashENS1_20_Prime_rehash_policyENS1_17_Hashtable_traitsILb0ELb1ELb1EEEEC1IPjEET_SF_{size_t}RKS6_RKS4_RKS0_St17integral_constantIbLb1EE@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|subst)_ZNSt10_HashtableIjjSaIjENSt8__detail9_IdentityESt8equal_toIjESt4hashIjENS1_18_Mod_range_hashingENS1_20_Default_ranged_hashENS1_20_Prime_rehash_policyENS1_17_Hashtable_traitsILb0ELb1ELb1EEEEC2IPjEET_SF_{size_t}RKS6_RKS4_RKS0_St17integral_constantIbLb1EE@Base 0 + (optional=templinst|arch=mips64el mipsel riscv64 sparc64 x32|subst)_ZNSt11_Deque_baseIlSaIlEE17_M_initialize_mapE{size_t}@Base 0 + (optional=templinst)_ZNSt11_Deque_baseIlSaIlEED1Ev@Base 0 + (optional=templinst)_ZNSt11_Deque_baseIlSaIlEED2Ev@Base 0 + (optional=templinst|subst|arch=!ppc64 !s390x)_ZNSt17_Temporary_bufferIN9__gnu_cxx17__normal_iteratorIPSt4pairIjjESt6vectorIS3_SaIS3_EEEES3_EC1ES8_{ssize_t}@Base 13 + (optional=templinst|subst|arch=!ppc64 !s390x)_ZNSt17_Temporary_bufferIN9__gnu_cxx17__normal_iteratorIPSt4pairIjjESt6vectorIS3_SaIS3_EEEES3_EC2ES8_{ssize_t}@Base 13 + (optional=templinst)_ZNSt5dequeINSt8__detail9_StateSeqINSt7__cxx1112regex_traitsIcEEEESaIS5_EE12emplace_backIJS5_EEEvDpOT_@Base 0 + (optional=templinst)_ZNSt5dequeINSt8__detail9_StateSeqINSt7__cxx1112regex_traitsIcEEEESaIS5_EE16_M_push_back_auxIJRKS5_EEEvDpOT_@Base 0 + (optional=templinst|arch=!amd64 !arm64 !x32)_ZNSt5dequeINSt8__detail9_StateSeqINSt7__cxx1112regex_traitsIcEEEESaIS5_EE16_M_push_back_auxIJS5_EEEvDpOT_@Base 0 + (optional=templinst|subst)_ZNSt5dequeINSt8__detail9_StateSeqINSt7__cxx1112regex_traitsIcEEEESaIS5_EE17_M_reallocate_mapE{size_t}b@Base 0 + (optional=templinst)_ZNSt5dequeIlSaIlEE16_M_push_back_auxIJRKlEEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIN3spv10CapabilityESaIS1_EE12emplace_backIJS1_EEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIN3spv10CapabilityESaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 0 + (optional=templinst|subst)_ZNSt6vectorIN3spv15AccessQualifierESaIS1_EE17_M_default_appendE{size_t}@Base 0 + (optional=templinst)_ZNSt6vectorIN3spv15AccessQualifierESaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 0 + (optional=templinst|arch=mipsel)_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE12emplace_backIJS5_EEEvDpOT_@Base 15.0.0-4~gcc13~ + (optional=templinst)_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_realloc_insertIJRKS5_EEEvN9__gnu_cxx17__normal_iteratorIPS5_S7_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EE17_M_realloc_insertIJS5_EEEvN9__gnu_cxx17__normal_iteratorIPS5_S7_EEDpOT_@Base 14.0.0-10~ + (optional=templinst)_ZNSt6vectorINSt7__cxx1112regex_traitsIcE10_RegexMaskESaIS3_EE17_M_realloc_insertIJRKS3_EEEvN9__gnu_cxx17__normal_iteratorIPS3_S5_EEDpOT_@Base 0 + (optional=templinst|subst)_ZNSt6vectorINSt7__cxx119sub_matchIPKcEESaIS4_EE14_M_fill_assignE{size_t}RKS4_@Base 0 + (optional=templinst)_ZNSt6vectorINSt8__detail6_StateIcEESaIS2_EE17_M_realloc_insertIJS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIPN4llvm8FunctionESaIS2_EE17_M_realloc_insertIJS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_@Base 0 +#MISSING: 14.0.0-10~# (optional=templinst)_ZNSt6vectorISt4pairIN3spv10DecorationENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESaIS9_EE12emplace_backIJS2_RA1_KcEEEvDpOT_@Base 0 +#MISSING: 14.0.0-10~# (optional=templinst)_ZNSt6vectorISt4pairIN3spv10DecorationENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESaIS9_EE12emplace_backIJS2_S8_EEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorISt4pairIN3spv10DecorationES_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS8_EEESaISB_EE12emplace_backIJS2_SA_EEEvDpOT_@Base 14.0.0-10~ + (optional=templinst)_ZNSt6vectorISt4pairIN3spv10DecorationES_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS8_EEESaISB_EE17_M_realloc_insertIJRS2_SA_EEEvN9__gnu_cxx17__normal_iteratorIPSB_SD_EEDpOT_@Base 14.0.0-10~ + (optional=templinst)_ZNSt6vectorISt4pairIN3spv10DecorationES_INSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS8_EEESaISB_EE17_M_realloc_insertIJS2_SA_EEEvN9__gnu_cxx17__normal_iteratorIPSB_SD_EEDpOT_@Base 14.0.0-10~ + (optional=templinst)_ZNSt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_ESaIS7_EE17_M_realloc_insertIJS7_EEEvN9__gnu_cxx17__normal_iteratorIPS7_S9_EEDpOT_@Base 0 +#MISSING: 14.0.0-10~# (optional=templinst)_ZNSt6vectorISt4pairIPN4llvm8FunctionEN3spv2OpEESaIS6_EE17_M_realloc_insertIJS6_EEEvN9__gnu_cxx17__normal_iteratorIPS6_S8_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorISt4pairIccESaIS1_EE17_M_realloc_insertIJS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJN3spv15LoopControlMaskERjEEEvDpOT_@Base 12 + (optional=templinst|arch=!armel !armhf !hurd-i386 !i386 !mipsel !powerpc !x32)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJN3spv15LoopControlMaskERmEEEvDpOT_@Base 12 + (optional=templinst)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJN3spv15LoopControlMaskEiEEEvDpOT_@Base 12 + (optional=templinst|arch=armel armhf hurd-i386 i386 mipsel powerpc x32)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJN3spv15LoopControlMaskEjEEEvDpOT_@Base 12 + (optional=templinst|arch=!armel !armhf !hurd-i386 !i386 !mipsel !powerpc !x32)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJN3spv15LoopControlMaskEmEEEvDpOT_@Base 12 + (optional=templinst)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJRKN3spv15LoopControlMaskEjEEEvDpOT_@Base 13 + (optional=templinst)_ZNSt6vectorISt4pairIjjESaIS1_EE12emplace_backIJRKjRjEEEvDpOT_@Base 0 + (optional=templinst|arch=armel armhf hurd-i386 i386 mipsel powerpc)_ZNSt6vectorISt4pairIjjESaIS1_EE17_M_realloc_insertIJRjS5_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorISt4pairIjjESaIS1_EE17_M_realloc_insertIJS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_@Base 0 + (optional=templinst|arch=!x32)_ZNSt6vectorISt4pairIlS_INSt7__cxx119sub_matchIPKcEESaIS5_EEESaIS8_EE12emplace_backIJRlRKS7_EEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorISt4pairIlS_INSt7__cxx119sub_matchIPKcEESaIS5_EEESaIS8_EE17_M_realloc_insertIJRlRKS7_EEEvN9__gnu_cxx17__normal_iteratorIPS8_SA_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIcSaIcEE12emplace_backIJcEEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIcSaIcEE17_M_realloc_insertIJcEEEvN9__gnu_cxx17__normal_iteratorIPcS1_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIiSaIiEE12emplace_backIJiEEEvDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIiSaIiEE17_M_realloc_insertIJiEEEvN9__gnu_cxx17__normal_iteratorIPiS1_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIjSaIjEE12emplace_backIJjEEEvDpOT_@Base 0 + (optional=templinst|arch=armel armhf hurd-i386 i386 mipsel powerpc x32)_ZNSt6vectorIjSaIjEE14_M_fill_insertEN9__gnu_cxx17__normal_iteratorIPjS1_EEjRKj@Base 12 + (optional=templinst|arch=!armel !armhf !hurd-i386 !i386 !mipsel !powerpc !x32)_ZNSt6vectorIjSaIjEE14_M_fill_insertEN9__gnu_cxx17__normal_iteratorIPjS1_EEmRKj@Base 12 + (optional=templinst|subst)_ZNSt6vectorIjSaIjEE17_M_default_appendE{size_t}@Base 0 + (optional=templinst)_ZNSt6vectorIjSaIjEE17_M_realloc_insertIJRKjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_@Base 0 + (optional=templinst)_ZNSt6vectorIjSaIjEE17_M_realloc_insertIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_@Base 0 + (optional=templinst|arch=!armel !armhf !hurd-i386 !i386 !mipsel !powerpc !x32)_ZNSt6vectorImSaImEE17_M_realloc_insertIJRKmEEEvN9__gnu_cxx17__normal_iteratorIPmS1_EEDpOT_@Base 0 + (optional=templinst|subst)_ZNSt6vectorI{uint64_t}SaI{uint64_t}EE17_M_realloc_insertIJ{uint64_t}EEEvN9__gnu_cxx17__normal_iteratorIP{uint64_t}S1_EEDpOT_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS2_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE24_M_get_insert_unique_posERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS2_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE24_M_get_insert_unique_posERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv15FPOperationModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS2_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv15FPOperationModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE24_M_get_insert_unique_posERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeI14VCFloatControlSt4pairIKS0_N3spv15FPOperationModeEESt10_Select1stIS5_ESt4lessIS0_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN10SPIRVDebug11EncodingTagESt4pairIKS1_N4llvm5dwarf8TypeKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug11EncodingTagESt4pairIKS1_N4llvm5dwarf8TypeKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug11EncodingTagESt4pairIKS1_N4llvm5dwarf8TypeKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug11InstructionESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug11InstructionESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN10SPIRVDebug16CompositeTypeTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug16CompositeTypeTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug16CompositeTypeTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN10SPIRVDebug16ExpressionOpCodeESt4pairIKS1_N4llvm5dwarf12LocationAtomEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug16ExpressionOpCodeESt4pairIKS1_N4llvm5dwarf12LocationAtomEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug16ExpressionOpCodeESt4pairIKS1_N4llvm5dwarf12LocationAtomEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug16ExpressionOpCodeESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug16ExpressionOpCodeESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN10SPIRVDebug16TypeQualifierTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug16TypeQualifierTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug16TypeQualifierTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN10SPIRVDebug17ImportedEntityTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN10SPIRVDebug17ImportedEntityTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN10SPIRVDebug17ImportedEntityTagESt4pairIKS1_N4llvm5dwarf3TagEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN17VectorComputeUtil11VCFloatTypeESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_N7OCLUtil6OclExt4KindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_N7OCLUtil6OclExt4KindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_N7OCLUtil6OclExt4KindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_St6vectorIS1_SaIS1_EEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv10CapabilityESt4pairIKS1_St6vectorIS1_SaIS1_EEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv10DecorationESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv10DecorationESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv10DecorationESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv10DecorationESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv11LinkageTypeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv11LinkageTypeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv12FPDenormModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv12FPDenormModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv12FPDenormModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv12StorageClassESt4pairIKS1_N5SPIRV16SPIRAddressSpaceEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv12StorageClassESt4pairIKS1_N5SPIRV16SPIRAddressSpaceEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv12StorageClassESt4pairIKS1_N5SPIRV16SPIRAddressSpaceEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv12StorageClassESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv12StorageClassESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_12FPDenormModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_12FPDenormModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_12FPDenormModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_14FPRoundingModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_15FPOperationModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_15FPOperationModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_NS0_15FPOperationModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv13ExecutionModeESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14ExecutionModelESt4pairIKS1_St3setIjSt4lessIjESaIjEEESt10_Select1stIS9_ES5_IS1_ESaIS9_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14ExecutionModelESt4pairIKS1_St3setIjSt4lessIjESaIjEEESt10_Select1stIS9_ES5_IS1_ESaIS9_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS9_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14ExecutionModelESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14ExecutionModelESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14FPRoundingModeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv14GroupOperationESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv14GroupOperationESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv15AccessQualifierESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv15AccessQualifierESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_14VCFloatControlESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESG_IJEEEEESt17_Rb_tree_iteratorIS5_ESt23_Rb_tree_const_iteratorIS5_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv15FPOperationModeESt4pairIKS1_NS0_13ExecutionModeEESt10_Select1stIS5_ESt4lessIS1_ESaIS5_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS5_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv19FunctionControlMaskESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv19FunctionControlMaskESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv19FunctionControlMaskESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil15OCLMemFenceKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil15OCLMemFenceKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil15OCLMemFenceKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil23OCLMemFenceExtendedKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil23OCLMemFenceExtendedKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv19MemorySemanticsMaskESt4pairIKS1_N7OCLUtil23OCLMemFenceExtendedKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv26FunctionParameterAttributeESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv26FunctionParameterAttributeESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv26FunctionParameterAttributeESt4pairIKS1_N4llvm9Attribute8AttrKindEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm13AtomicRMWInst5BinOpEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm13AtomicRMWInst5BinOpEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm13AtomicRMWInst5BinOpEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm7CmpInst9PredicateEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm7CmpInst9PredicateEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_N4llvm7CmpInst9PredicateEESt10_Select1stIS7_ESt4lessIS1_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_S1_ESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_S1_ESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_S1_ESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv2OpESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN3spv5ScopeESt4pairIKS1_N7OCLUtil12OCLScopeKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv5ScopeESt4pairIKS1_N7OCLUtil12OCLScopeKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv5ScopeESt4pairIKS1_N7OCLUtil12OCLScopeKindEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv5ScopeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv5ScopeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv7BuiltInESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv7BuiltInESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv7BuiltInESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE24_M_get_insert_unique_posERS3_@Base 12 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv7BuiltInESt4pairIKS1_St6vectorINS0_10CapabilityESaIS5_EEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS3_@Base 12 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN3spv8internal25InternalJointMatrixLayoutESt4pairIKS2_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISB_ESt4lessIS2_ESaISB_EE24_M_get_insert_unique_posERS4_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN3spv8internal25InternalJointMatrixLayoutESt4pairIKS2_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISB_ESt4lessIS2_ESaISB_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISB_ERS4_@Base 14 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm13AtomicRMWInst5BinOpESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm13AtomicRMWInst5BinOpESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm13AtomicRMWInst5BinOpESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm5dwarf12LocationAtomESt4pairIKS2_N10SPIRVDebug16ExpressionOpCodeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm5dwarf12LocationAtomESt4pairIKS2_N10SPIRVDebug16ExpressionOpCodeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm5dwarf12LocationAtomESt4pairIKS2_N10SPIRVDebug16ExpressionOpCodeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16CompositeTypeTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16CompositeTypeTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16CompositeTypeTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16TypeQualifierTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16TypeQualifierTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug16TypeQualifierTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug17ImportedEntityTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug17ImportedEntityTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm5dwarf3TagESt4pairIKS2_N10SPIRVDebug17ImportedEntityTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm5dwarf8TypeKindESt4pairIKS2_N10SPIRVDebug11EncodingTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm5dwarf8TypeKindESt4pairIKS2_N10SPIRVDebug11EncodingTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm5dwarf8TypeKindESt4pairIKS2_N10SPIRVDebug11EncodingTagEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm7CmpInst9PredicateESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm7CmpInst9PredicateESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm7CmpInst9PredicateESt4pairIKS2_N3spv2OpEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv19FunctionControlMaskEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv19FunctionControlMaskEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv19FunctionControlMaskEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv26FunctionParameterAttributeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv26FunctionParameterAttributeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN4llvm9Attribute8AttrKindESt4pairIKS2_N3spv26FunctionParameterAttributeEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV11ExtensionIDESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN5SPIRV11ExtensionIDESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV11ExtensionIDESt4pairIKS1_bESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJOS1_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV11ExtensionIDESt4pairIKS1_bESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN5SPIRV11ExtensionIDESt4pairIKS1_bESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV14SPIRVErrorCodeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN5SPIRV14SPIRVErrorCodeESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN5SPIRV16SPIRAddressSpaceESt4pairIKS1_N3spv12StorageClassEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV16SPIRAddressSpaceESt4pairIKS1_N3spv12StorageClassEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN5SPIRV16SPIRAddressSpaceESt4pairIKS1_N3spv12StorageClassEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV19SPIRVExtInstSetKindESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN5SPIRV19SPIRVExtInstSetKindESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV19SPIRVExtInstSetKindESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN5SPIRV19SPIRVExtInstSetKindESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN7OCLUtil12OCLScopeKindESt4pairIKS1_N3spv5ScopeEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil12OCLScopeKindESt4pairIKS1_N3spv5ScopeEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil12OCLScopeKindESt4pairIKS1_N3spv5ScopeEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemFenceKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemFenceKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemFenceKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemOrderKindESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemOrderKindESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil15OCLMemOrderKindESt4pairIKS1_jESt10_Select1stIS4_ESt4lessIS1_ESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN7OCLUtil23OCLMemFenceExtendedKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS3_EESH_IJEEEEESt17_Rb_tree_iteratorIS6_ESt23_Rb_tree_const_iteratorIS6_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil23OCLMemFenceExtendedKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil23OCLMemFenceExtendedKindESt4pairIKS1_N3spv19MemorySemanticsMaskEESt10_Select1stIS6_ESt4lessIS1_ESaIS6_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS6_ERS3_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE16_M_insert_uniqueIRKS2_EESt4pairISt17_Rb_tree_iteratorIS2_EbEOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE24_M_get_insert_unique_posERKS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS2_ERKS2_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindESt4pairIKS2_N3spv10CapabilityEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS4_EESI_IJEEEEESt17_Rb_tree_iteratorIS7_ESt23_Rb_tree_const_iteratorIS7_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindESt4pairIKS2_N3spv10CapabilityEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindESt4pairIKS2_N3spv10CapabilityEESt10_Select1stIS7_ESt4lessIS2_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindESt4pairIKS2_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISB_ESt4lessIS2_ESaISB_EE24_M_get_insert_unique_posERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN7OCLUtil6OclExt4KindESt4pairIKS2_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISB_ESt4lessIS2_ESaISB_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISB_ERS4_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIN9OpenCLLIB11EntrypointsESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE24_M_get_insert_unique_posERS3_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIN9OpenCLLIB11EntrypointsESt4pairIKS1_NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEESt10_Select1stISA_ESt4lessIS1_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS3_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St9_IdentityIS5_ESt4lessIS5_ESaIS5_EE16_M_insert_uniqueIRKS5_EESt4pairISt17_Rb_tree_iteratorIS5_EbEOT_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St9_IdentityIS5_ESt4lessIS5_ESaIS5_EE16_M_insert_uniqueIS5_EESt4pairISt17_Rb_tree_iteratorIS5_EbEOT_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St9_IdentityIS5_ESt4lessIS5_ESaIS5_EE24_M_get_insert_unique_posERKS5_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES5_St9_IdentityIS5_ESt4lessIS5_ESaIS5_EE4findERKS5_@Base 14 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N10SPIRVDebug11InstructionEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N10SPIRVDebug11InstructionEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N18NonSemanticAuxData11InstructionEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 14.0.0-10~ + (optional=templinst|arch=!armel !armhf !hurd-i386 !i386 !powerpc !ppc64 !s390x)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N18NonSemanticAuxData11InstructionEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 14.0.0-10~ + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv10CapabilityEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv10CapabilityEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv10DecorationEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv10DecorationEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv11LinkageTypeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv11LinkageTypeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv14FPRoundingModeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv14FPRoundingModeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv14GroupOperationEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv14GroupOperationEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv15AccessQualifierEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv15AccessQualifierEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv2OpEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv2OpEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv5ScopeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 14 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv5ScopeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 14 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv7BuiltInEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv7BuiltInEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv8internal25InternalJointMatrixLayoutEESt10_Select1stISB_ESt4lessIS5_ESaISB_EE24_M_get_insert_unique_posERS7_@Base 14 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N3spv8internal25InternalJointMatrixLayoutEESt10_Select1stISB_ESt4lessIS5_ESaISB_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISB_ERS7_@Base 14 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV11ExtensionIDEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV11ExtensionIDEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV14SPIRVErrorCodeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV14SPIRVErrorCodeEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV19SPIRVExtInstSetKindEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N5SPIRV19SPIRVExtInstSetKindEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N7OCLUtil6OclExt4KindEESt10_Select1stISB_ESt4lessIS5_ESaISB_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N7OCLUtil6OclExt4KindEESt10_Select1stISB_ESt4lessIS5_ESaISB_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISB_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9OpenCLLIB11EntrypointsEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9OpenCLLIB11EntrypointsEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorISA_ERS7_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_jESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE24_M_get_insert_unique_posERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_jESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS7_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIPN4llvm8FunctionES2_St9_IdentityIS2_ESt4lessIS2_ESaIS2_EE16_M_insert_uniqueIRKS2_EESt4pairISt17_Rb_tree_iteratorIS2_EbEOT_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_10DecorationEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE24_M_get_insert_unique_posERS6_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_10DecorationEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS6_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_12StorageClassEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE24_M_get_insert_unique_posERS6_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_12StorageClassEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS6_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_13ExecutionModeEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE24_M_get_insert_unique_posERS6_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_13ExecutionModeEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS6_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_14ExecutionModelEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE24_M_get_insert_unique_posERS6_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_14ExecutionModelEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS6_@Base 0 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_7BuiltInEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE24_M_get_insert_unique_posERS6_@Base 12 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_NS1_7BuiltInEESt10_Select1stIS8_ESt4lessIS4_ESaIS8_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS8_ERS6_@Base 12 + (optional=templinst)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_S2_ESt10_Select1stIS7_ESt4lessIS4_ESaIS7_EE24_M_get_insert_unique_posERS6_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeISt6vectorIN3spv10CapabilityESaIS2_EESt4pairIKS4_S2_ESt10_Select1stIS7_ESt4lessIS4_ESaIS7_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS7_ERS6_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIjSt4pairIKjN17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS4_ESt4lessIjESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS1_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIjSt4pairIKjN17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS4_ESt4lessIjESaIS4_EE24_M_get_insert_unique_posERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIjSt4pairIKjN17VectorComputeUtil11VCFloatTypeEESt10_Select1stIS4_ESt4lessIjESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIjSt4pairIKjN3spv2OpEESt10_Select1stIS4_ESt4lessIjESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS1_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIjSt4pairIKjN3spv2OpEESt10_Select1stIS4_ESt4lessIjESaIS4_EE24_M_get_insert_unique_posERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIjSt4pairIKjN3spv2OpEESt10_Select1stIS4_ESt4lessIjESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIjSt4pairIKjN5SPIRV19SPIRVExtInstSetKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS1_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIjSt4pairIKjN5SPIRV19SPIRVExtInstSetKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE24_M_get_insert_unique_posERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIjSt4pairIKjN5SPIRV19SPIRVExtInstSetKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=!amd64 !arm64 !mips64el !ppc64el !riscv64 !sparc64 !x32)_ZNSt8_Rb_treeIjSt4pairIKjN7OCLUtil15OCLMemOrderKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS1_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIjSt4pairIKjN7OCLUtil15OCLMemOrderKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE24_M_get_insert_unique_posERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIjSt4pairIKjN7OCLUtil15OCLMemOrderKindEESt10_Select1stIS4_ESt4lessIjESaIS4_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS4_ERS1_@Base 0 + (optional=templinst|arch=!mips64el !ppc64el !riscv64 !sparc64)_ZNSt8_Rb_treeIjjSt9_IdentityIjESt4lessIjESaIjEE16_M_insert_uniqueIRKjEESt4pairISt17_Rb_tree_iteratorIjEbEOT_@Base 0 + (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIjjSt9_IdentityIjESt4lessIjESaIjEE16_M_insert_uniqueIjEESt4pairISt17_Rb_tree_iteratorIjEbEOT_@Base 13 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIjjSt9_IdentityIjESt4lessIjESaIjEE24_M_get_insert_unique_posERKj@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIlSt4pairIKllESt10_Select1stIS2_ESt4lessIlESaIS2_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJRS1_EESD_IJEEEEESt17_Rb_tree_iteratorIS2_ESt23_Rb_tree_const_iteratorIS2_EDpOT_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZNSt8_Rb_treeIlSt4pairIKllESt10_Select1stIS2_ESt4lessIlESaIS2_EE24_M_get_insert_unique_posERS1_@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 mips64el ppc64el riscv64 sparc64 x32)_ZNSt8_Rb_treeIlSt4pairIKllESt10_Select1stIS2_ESt4lessIlESaIS2_EE29_M_get_insert_hint_unique_posESt23_Rb_tree_const_iteratorIS2_ERS1_@Base 0 + (optional=templinst)_ZNSt8__detail17__regex_algo_implIPKcSaINSt7__cxx119sub_matchIS2_EEEcNS3_12regex_traitsIcEEEEbT_S9_RNS3_13match_resultsIS9_T0_EERKNS3_11basic_regexIT1_T2_EENSt15regex_constants15match_flag_typeENS_20_RegexExecutorPolicyEb@Base 0 + (optional=templinst)_ZNSt8__detail18__to_chars_10_implIjEEvPcjT_@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE12_M_eat_classEc@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE14_M_scan_normalEv@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE16_M_scan_in_braceEv@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE17_M_eat_escape_awkEv@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE18_M_eat_escape_ecmaEv@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE18_M_scan_in_bracketEv@Base 0 + (optional=templinst)_ZNSt8__detail8_ScannerIcE19_M_eat_escape_posixEv@Base 0 + (optional=templinst|arch=!mipsel)_ZNSt8__detail8_ScannerIcEC1EPKcS3_NSt15regex_constants18syntax_option_typeESt6locale@Base 0 + (optional=templinst|arch=!mipsel)_ZNSt8__detail8_ScannerIcEC2EPKcS3_NSt15regex_constants18syntax_option_typeESt6locale@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE11_M_try_charEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE12_M_assertionEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE13_M_quantifierEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE14_M_alternativeEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE14_M_disjunctionEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE16_M_cur_int_valueEi@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE18_M_expression_termILb0ELb0EEEbRNS4_13_BracketStateERNS_15_BracketMatcherIS3_XT_EXT0_EEE@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE18_M_expression_termILb0ELb1EEEbRNS4_13_BracketStateERNS_15_BracketMatcherIS3_XT_EXT0_EEE@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE18_M_expression_termILb1ELb0EEEbRNS4_13_BracketStateERNS_15_BracketMatcherIS3_XT_EXT0_EEE@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE18_M_expression_termILb1ELb1EEEbRNS4_13_BracketStateERNS_15_BracketMatcherIS3_XT_EXT0_EEE@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE21_M_bracket_expressionEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE25_M_insert_bracket_matcherILb0ELb0EEEvb@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE25_M_insert_bracket_matcherILb0ELb1EEEvb@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE25_M_insert_bracket_matcherILb1ELb0EEEvb@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE25_M_insert_bracket_matcherILb1ELb1EEEvb@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE33_M_insert_character_class_matcherILb0ELb0EEEvv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE33_M_insert_character_class_matcherILb0ELb1EEEvv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE33_M_insert_character_class_matcherILb1ELb0EEEvv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE33_M_insert_character_class_matcherILb1ELb1EEEvv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEE7_M_atomEv@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEEC1EPKcS6_RKSt6localeNSt15regex_constants18syntax_option_typeE@Base 0 + (optional=templinst)_ZNSt8__detail9_CompilerINSt7__cxx1112regex_traitsIcEEEC2EPKcS6_RKSt6localeNSt15regex_constants18syntax_option_typeE@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE12_M_lookaheadEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE16_M_rep_once_moreENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE17_M_handle_backrefENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE6_M_dfsENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE12_M_lookaheadEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE16_M_rep_once_moreENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE17_M_handle_backrefENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE6_M_dfsENS9_11_Match_modeEl@Base 0 + (optional=templinst)_ZNSt8__detail9_StateSeqINSt7__cxx1112regex_traitsIcEEE8_M_cloneEv@Base 0 + (optional=templinst)_ZSt13binary_searchIN9__gnu_cxx17__normal_iteratorIPKcSt6vectorIcSaIcEEEEcEbT_S8_RKT0_@Base 0 + (optional=templinst|subst)_ZSt17__rotate_adaptiveIN9__gnu_cxx17__normal_iteratorIPSt4pairIjjESt6vectorIS3_SaIS3_EEEES4_{ssize_t}ET_S9_S9_S9_T1_SA_T0_SA_@Base 13 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|arch=amd64 arm64 x32)_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_@Base 0 + (arch=armel riscv64)_ZTIN9__gnu_cxx7__mutexE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb0EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb1EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb0EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb1EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0ELb0EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0ELb1EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1ELb0EEE@Base 13 + _ZTINSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1ELb1EEE@Base 13 + _ZTINSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0EEE@Base 13 + _ZTINSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1EEE@Base 13 + _ZTINSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0EEE@Base 13 + _ZTINSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1EEE@Base 13 + _ZTINSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0EEE@Base 13 + _ZTINSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1EEE@Base 13 + _ZTINSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0EEE@Base 13 + _ZTINSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1EEE@Base 13 + (arch=armel riscv64)_ZTISt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (arch=!armel !riscv64)_ZTISt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 13 + (arch=armel riscv64)_ZTISt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (arch=!armel !riscv64)_ZTISt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 13 + (arch=armel armhf)_ZTISt19_Sp_make_shared_tag@Base 13 + (optional=templinst|arch=armel riscv64)_ZTISt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (optional=templinst|arch=!armel !riscv64)_ZTISt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE2EE@Base 13 + (arch=armel riscv64)_ZTSN9__gnu_cxx7__mutexE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb0EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb1EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb0EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb1EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0ELb0EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0ELb1EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1ELb0EEE@Base 13 + _ZTSNSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1ELb1EEE@Base 13 + _ZTSNSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0EEE@Base 13 + _ZTSNSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1EEE@Base 13 + _ZTSNSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0EEE@Base 13 + _ZTSNSt8__detail12_CharMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1EEE@Base 13 + _ZTSNSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0EEE@Base 13 + _ZTSNSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1EEE@Base 13 + _ZTSNSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb1ELb0EEE@Base 13 + _ZTSNSt8__detail15_BracketMatcherINSt7__cxx1112regex_traitsIcEELb1ELb1EEE@Base 13 + (arch=armel riscv64)_ZTSSt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (arch=!armel !riscv64)_ZTSSt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 13 + (arch=armel riscv64)_ZTSSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (arch=!armel !riscv64)_ZTSSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 13 + _ZTSSt19_Sp_make_shared_tag@Base 13 + (optional=templinst|arch=armel riscv64)_ZTSSt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE1EE@Base 13 + (optional=templinst|arch=!armel !riscv64)_ZTSSt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE2EE@Base 13 + (optional=templinst|arch=armel riscv64)_ZTVSt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE1EE@Base 0 + (optional=templinst|arch=!armel !riscv64)_ZTVSt23_Sp_counted_ptr_inplaceINSt8__detail4_NFAINSt7__cxx1112regex_traitsIcEEEESaIvELN9__gnu_cxx12_Lock_policyE2EE@Base 0 + (optional=templinst)_ZZNKSt7__cxx1112regex_traitsIcE16lookup_classnameIPKcEENS1_10_RegexMaskET_S6_bE12__classnames@Base 0 + (optional=templinst)_ZZNKSt7__cxx1112regex_traitsIcE18lookup_collatenameIPKcEENS_12basic_stringIcSt11char_traitsIcESaIcEEET_SA_E14__collatenames@Base 0 + (optional=templinst)_ZZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb0EEclEcE5__nul@Base 0 + (optional=templinst)_ZZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb0ELb1EEclEcE5__nul@Base 0 + (optional=templinst)_ZZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb0EEclEcE5__nul@Base 0 + (optional=templinst)_ZZNKSt8__detail11_AnyMatcherINSt7__cxx1112regex_traitsIcEELb0ELb1ELb1EEclEcE5__nul@Base 0 + (optional=templinst)_ZZNKSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb0EE10_M_is_wordEcE3__s@Base 0 + (optional=templinst)_ZZNKSt8__detail9_ExecutorIPKcSaINSt7__cxx119sub_matchIS2_EEENS3_12regex_traitsIcEELb1EE10_M_is_wordEcE3__s@Base 0 + _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst)_ZZNSt8__detail18__to_chars_10_implIjEEvPcjT_E8__digits@Base 0 +#MISSING: 14.0.0-7~gcc13# (optional=templinst|subst)_ZZNSt8__detail18__to_chars_10_implI{uint64_t}EEvPcjT_E8__digits@Base 13 + (optional=templinst|arch=!powerpc !ppc64)_ZZNSt9once_flag18_Prepare_executionC4IZSt9call_onceIRFPvRN4llvm12PassRegistryEEJSt17reference_wrapperIS5_EEEvRS_OT_DpOT0_EUlvE_EERSC_ENUlvE_4_FUNEv@Base 0 diff --git a/llvm-spirv-15.install b/llvm-spirv-15.install new file mode 100644 index 0000000..d060cd8 --- /dev/null +++ b/llvm-spirv-15.install @@ -0,0 +1 @@ +usr/bin/llvm-spirv-* diff --git a/patches/0001-Integer-dot-product-4x8-packed-translation-1654.patch b/patches/0001-Integer-dot-product-4x8-packed-translation-1654.patch new file mode 100644 index 0000000..ee2e850 --- /dev/null +++ b/patches/0001-Integer-dot-product-4x8-packed-translation-1654.patch @@ -0,0 +1,196 @@ +From ba262e63d59a09fec358c742adc13035a851d4f8 Mon Sep 17 00:00:00 2001 +From: Jakub Czarnecki +Date: Mon, 17 Oct 2022 17:24:28 +0200 +Subject: [PATCH 01/79] Integer dot product 4x8 packed translation (#1654) + +Changed the integer dot translation to use the correct function names +(i.e. dot_4x8packed or dot_acc_sat_4x8packed) to translate them into +proper OpCodes. Additionally removed unused variables from visitCallDot +--- + lib/SPIRV/OCLToSPIRV.cpp | 63 +++++++++++-------- + lib/SPIRV/OCLUtil.h | 2 + + ..._KHR_integer_dot_product_OCLtoSPIRV_int.ll | 32 +++++----- + 3 files changed, 54 insertions(+), 43 deletions(-) + +diff --git a/lib/SPIRV/OCLToSPIRV.cpp b/lib/SPIRV/OCLToSPIRV.cpp +index 95e52cc8..7db6d37f 100644 +--- a/lib/SPIRV/OCLToSPIRV.cpp ++++ b/lib/SPIRV/OCLToSPIRV.cpp +@@ -328,7 +328,9 @@ void OCLToSPIRVBase::visitCallInst(CallInst &CI) { + return; + } + if (DemangledName == kOCLBuiltinName::Dot || +- DemangledName == kOCLBuiltinName::DotAccSat) { ++ DemangledName == kOCLBuiltinName::DotAccSat || ++ DemangledName.startswith(kOCLBuiltinName::Dot4x8PackedPrefix) || ++ DemangledName.startswith(kOCLBuiltinName::DotAccSat4x8PackedPrefix)) { + if (CI.getOperand(0)->getType()->isVectorTy()) { + auto *VT = (VectorType *)(CI.getOperand(0)->getType()); + if (!isa(VT->getElementType())) { +@@ -1323,19 +1325,11 @@ void OCLToSPIRVBase::visitCallDot(CallInst *CI, StringRef MangledName, + // translation for dot function calls, + // to differentiate between integer dot products + +- SmallVector Args; +- Args.push_back(CI->getOperand(0)); +- Args.push_back(CI->getOperand(1)); + bool IsFirstSigned, IsSecondSigned; + bool IsDot = DemangledName == kOCLBuiltinName::Dot; +- std::string FunName = (IsDot) ? "DotKHR" : "DotAccSatKHR"; +- if (CI->arg_size() > 2) { +- Args.push_back(CI->getOperand(2)); +- } +- if (CI->arg_size() > 3) { +- Args.push_back(CI->getOperand(3)); +- } +- if (CI->getOperand(0)->getType()->isVectorTy()) { ++ bool IsAccSat = DemangledName.contains(kOCLBuiltinName::DotAccSat); ++ bool IsPacked = CI->getOperand(0)->getType()->isIntegerTy(); ++ if (!IsPacked) { + if (IsDot) { + // dot(char4, char4) _Z3dotDv4_cS_ + // dot(char4, uchar4) _Z3dotDv4_cDv4_h +@@ -1376,21 +1370,28 @@ void OCLToSPIRVBase::visitCallDot(CallInst *CI, StringRef MangledName, + } + } else { + // for packed format +- // dot(int, int, int) _Z3dotiii +- // dot(int, uint, int) _Z3dotiji +- // dot(uint, int, int) _Z3dotjii +- // dot(uint, uint, int) _Z3dotjji ++ // dot_4x8packed_ss_int(uint, uint) _Z20dot_4x8packed_ss_intjj ++ // dot_4x8packed_su_int(uint, uint) _Z20dot_4x8packed_su_intjj ++ // dot_4x8packed_us_int(uint, uint) _Z20dot_4x8packed_us_intjj ++ // dot_4x8packed_uu_uint(uint, uint) _Z21dot_4x8packed_uu_uintjj + // or +- // dot_acc_sat(int, int, int, int) _Z11dot_acc_satiiii +- // dot_acc_sat(int, uint, int, int) _Z11dot_acc_satijii +- // dot_acc_sat(uint, int, int, int) _Z11dot_acc_satjiii +- // dot_acc_sat(uint, uint, int, int) _Z11dot_acc_satjjii +- assert(MangledName.startswith("_Z3dot") || +- MangledName.startswith("_Z11dot_acc_sat")); +- IsFirstSigned = (IsDot) ? (MangledName[MangledName.size() - 3] == 'i') +- : (MangledName[MangledName.size() - 4] == 'i'); +- IsSecondSigned = (IsDot) ? (MangledName[MangledName.size() - 2] == 'i') +- : (MangledName[MangledName.size() - 3] == 'i'); ++ // dot_acc_sat_4x8packed_ss_int(uint, uint, int) ++ // _Z28dot_acc_sat_4x8packed_ss_intjji ++ // dot_acc_sat_4x8packed_su_int(uint, uint, int) ++ // _Z28dot_acc_sat_4x8packed_su_intjji ++ // dot_acc_sat_4x8packed_us_int(uint, uint, int) ++ // _Z28dot_acc_sat_4x8packed_us_intjji ++ // dot_acc_sat_4x8packed_uu_uint(uint, uint, uint) ++ // _Z29dot_acc_sat_4x8packed_uu_uintjjj ++ assert(MangledName.startswith("_Z20dot_4x8packed") || ++ MangledName.startswith("_Z21dot_4x8packed") || ++ MangledName.startswith("_Z28dot_acc_sat_4x8packed") || ++ MangledName.startswith("_Z29dot_acc_sat_4x8packed")); ++ size_t SignIndex = IsAccSat ++ ? strlen(kOCLBuiltinName::DotAccSat4x8PackedPrefix) ++ : strlen(kOCLBuiltinName::Dot4x8PackedPrefix); ++ IsFirstSigned = DemangledName[SignIndex] == 's'; ++ IsSecondSigned = DemangledName[SignIndex + 1] == 's'; + } + AttributeList Attrs = CI->getCalledFunction()->getAttributes(); + mutateCallInstSPIRV( +@@ -1403,7 +1404,7 @@ void OCLToSPIRVBase::visitCallDot(CallInst *CI, StringRef MangledName, + std::swap(Args[0], Args[1]); + } + Op OC; +- if (IsDot) { ++ if (!IsAccSat) { + OC = (IsFirstSigned != IsSecondSigned + ? OpSUDot + : ((IsFirstSigned) ? OpSDot : OpUDot)); +@@ -1412,6 +1413,14 @@ void OCLToSPIRVBase::visitCallDot(CallInst *CI, StringRef MangledName, + ? OpSUDotAccSat + : ((IsFirstSigned) ? OpSDotAccSat : OpUDotAccSat)); + } ++ if (IsPacked) { ++ // As per SPIRV specification the dot OpCodes ++ // which use scalar integers to represent ++ // packed vectors need additional argument ++ // specified - the Packed Vector Format ++ Args.push_back( ++ getInt32(M, PackedVectorFormatPackedVectorFormat4x8BitKHR)); ++ } + return getSPIRVFuncName(OC); + }, + &Attrs); +diff --git a/lib/SPIRV/OCLUtil.h b/lib/SPIRV/OCLUtil.h +index 6497ecb6..1c0d8605 100644 +--- a/lib/SPIRV/OCLUtil.h ++++ b/lib/SPIRV/OCLUtil.h +@@ -234,6 +234,8 @@ const static char Clamp[] = "clamp"; + const static char ConvertPrefix[] = "convert_"; + const static char Dot[] = "dot"; + const static char DotAccSat[] = "dot_acc_sat"; ++const static char Dot4x8PackedPrefix[] = "dot_4x8packed_"; ++const static char DotAccSat4x8PackedPrefix[] = "dot_acc_sat_4x8packed_"; + const static char EnqueueKernel[] = "enqueue_kernel"; + const static char FixedSqrtINTEL[] = "intel_arbitrary_fixed_sqrt"; + const static char FixedRecipINTEL[] = "intel_arbitrary_fixed_recip"; +diff --git a/test/transcoding/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll b/test/transcoding/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll +index 7a7b5cab..bb4fb700 100644 +--- a/test/transcoding/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll ++++ b/test/transcoding/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll +@@ -31,40 +31,40 @@ target triple = "spir" + ; Function Attrs: convergent norecurse nounwind + define spir_kernel void @test1(i32 %ia, i32 %ua, i32 %ib, i32 %ub, i32 %ires, i32 %ures) local_unnamed_addr #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !6 { + entry: +- %call = tail call spir_func i32 @_Z3dotiii(i32 %ia, i32 %ib, i32 0) #2 +- %call1 = tail call spir_func i32 @_Z3dotiji(i32 %ia, i32 %ub, i32 0) #2 +- %call2 = tail call spir_func i32 @_Z3dotjii(i32 %ua, i32 %ib, i32 0) #2 +- %call3 = tail call spir_func i32 @_Z3dotjji(i32 %ua, i32 %ub, i32 0) #2 +- %call4 = tail call spir_func i32 @_Z11dot_acc_satiiii(i32 %ia, i32 %ib, i32 %ires, i32 0) #2 +- %call5 = tail call spir_func i32 @_Z11dot_acc_satijii(i32 %ia, i32 %ub, i32 %ires, i32 0) #2 +- %call6 = tail call spir_func i32 @_Z11dot_acc_satjiii(i32 %ua, i32 %ib, i32 %ires, i32 0) #2 +- %call7 = tail call spir_func i32 @_Z11dot_acc_satjjji(i32 %ua, i32 %ub, i32 %ures, i32 0) #2 ++ %call = tail call spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32 %ia, i32 %ib) #2 ++ %call1 = tail call spir_func i32 @_Z20dot_4x8packed_su_intjj(i32 %ia, i32 %ub) #2 ++ %call2 = tail call spir_func i32 @_Z20dot_4x8packed_us_intjj(i32 %ua, i32 %ib) #2 ++ %call3 = tail call spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32 %ua, i32 %ub) #2 ++ %call4 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32 %ia, i32 %ib, i32 %ires) #2 ++ %call5 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32 %ia, i32 %ub, i32 %ires) #2 ++ %call6 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32 %ua, i32 %ib, i32 %ires) #2 ++ %call7 = tail call spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32 %ua, i32 %ub, i32 %ures) #2 + ret void + } + + ; Function Attrs: convergent +-declare spir_func i32 @_Z3dotiii(i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z3dotiji(i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z20dot_4x8packed_su_intjj(i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z3dotjii(i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z20dot_4x8packed_us_intjj(i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z3dotjji(i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z11dot_acc_satiiii(i32, i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z11dot_acc_satijii(i32, i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z11dot_acc_satjiii(i32, i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare spir_func i32 @_Z11dot_acc_satjjji(i32, i32, i32, i32) local_unnamed_addr #1 ++declare spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32, i32, i32) local_unnamed_addr #1 + + attributes #0 = { convergent norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #1 = { convergent "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-- +2.20.1 + diff --git a/patches/0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch b/patches/0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch new file mode 100644 index 0000000..8a80e94 --- /dev/null +++ b/patches/0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch @@ -0,0 +1,801 @@ +From 2478920a91bff5c59ca65ea9bce8ffaa5af8fa88 Mon Sep 17 00:00:00 2001 +From: Haonan Yang +Date: Thu, 20 Oct 2022 19:46:13 +0800 +Subject: [PATCH 02/79] Add support for split barriers extension + SPV_INTEL_split_barrier (#1424) (#1663) + +This PR adds support for split barriers and the SPV_INTEL_split_barrier extension. + +The related SPIR-V extension spec can be found here: + +* https://github.com/KhronosGroup/SPIRV-Registry/pull/136 + +The related OpenCL C extension spec can be found here: + +* https://github.com/KhronosGroup/OpenCL-Docs/pull/765 + +Co-authored-by: Ben Ashbaugh +--- + include/LLVMSPIRVExtensions.inc | 1 + + lib/SPIRV/OCLToSPIRV.cpp | 35 ++++ + lib/SPIRV/OCLToSPIRV.h | 3 + + lib/SPIRV/OCLUtil.cpp | 7 +- + lib/SPIRV/OCLUtil.h | 1 + + lib/SPIRV/SPIRVReader.cpp | 2 +- + lib/SPIRV/SPIRVToOCL.cpp | 4 + + lib/SPIRV/SPIRVToOCL.h | 16 ++ + lib/SPIRV/SPIRVToOCL12.cpp | 13 ++ + lib/SPIRV/SPIRVToOCL20.cpp | 22 +++ + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 18 ++ + lib/SPIRV/libSPIRV/SPIRVOpCode.h | 5 + + lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h | 2 + + .../split_work_group_barrier_12.ll | 99 ++++++++++ + .../split_work_group_barrier_20.ll | 175 ++++++++++++++++++ + .../split_work_group_barrier_spirv.ll | 170 +++++++++++++++++ + 16 files changed, 571 insertions(+), 2 deletions(-) + create mode 100644 test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll + create mode 100644 test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll + create mode 100644 test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 8eaf24de..3d0eae8c 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -53,3 +53,4 @@ EXT(SPV_INTEL_hw_thread_queries) + EXT(SPV_INTEL_global_variable_decorations) + EXT(SPV_INTEL_non_constant_addrspace_printf) + EXT(SPV_INTEL_complex_float_mul_div) ++EXT(SPV_INTEL_split_barrier) +diff --git a/lib/SPIRV/OCLToSPIRV.cpp b/lib/SPIRV/OCLToSPIRV.cpp +index 7db6d37f..8870a299 100644 +--- a/lib/SPIRV/OCLToSPIRV.cpp ++++ b/lib/SPIRV/OCLToSPIRV.cpp +@@ -381,6 +381,10 @@ void OCLToSPIRVBase::visitCallInst(CallInst &CI) { + visitSubgroupImageMediaBlockINTEL(&CI, DemangledName); + return; + } ++ if (DemangledName.find(kOCLBuiltinName::SplitBarrierINTELPrefix) == 0) { ++ visitCallSplitBarrierINTEL(&CI, DemangledName); ++ return; ++ } + // Handle 'cl_intel_device_side_avc_motion_estimation' extension built-ins + if (DemangledName.find(kOCLSubgroupsAVCIntel::Prefix) == 0 || + // Workaround for a bug in the extension specification +@@ -1879,6 +1883,37 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler( + &Attrs); + } + ++void OCLToSPIRVBase::visitCallSplitBarrierINTEL(CallInst *CI, ++ StringRef DemangledName) { ++ auto Lit = getBarrierLiterals(CI); ++ AttributeList Attrs = CI->getCalledFunction()->getAttributes(); ++ Op OpCode = ++ StringSwitch(DemangledName) ++ .Case("intel_work_group_barrier_arrive", OpControlBarrierArriveINTEL) ++ .Case("intel_work_group_barrier_wait", OpControlBarrierWaitINTEL) ++ .Default(OpNop); ++ ++ mutateCallInstSPIRV( ++ M, CI, ++ [=](CallInst *, std::vector &Args) { ++ Args.resize(3); ++ // Execution scope ++ Args[0] = addInt32(map(std::get<2>(Lit))); ++ // Memory scope ++ Args[1] = addInt32(map(std::get<1>(Lit))); ++ // Memory semantics ++ // OpControlBarrierArriveINTEL -> Release, ++ // OpControlBarrierWaitINTEL -> Acquire ++ unsigned MemFenceFlag = std::get<0>(Lit); ++ OCLMemOrderKind MemOrder = OpCode == OpControlBarrierArriveINTEL ++ ? OCLMO_release ++ : OCLMO_acquire; ++ Args[2] = addInt32(mapOCLMemSemanticToSPIRV(MemFenceFlag, MemOrder)); ++ return getSPIRVFuncName(OpCode); ++ }, ++ &Attrs); ++} ++ + void OCLToSPIRVBase::visitCallLdexp(CallInst *CI, StringRef MangledName, + StringRef DemangledName) { + auto Args = getArguments(CI); +diff --git a/lib/SPIRV/OCLToSPIRV.h b/lib/SPIRV/OCLToSPIRV.h +index 7b1c3086..8707ad88 100644 +--- a/lib/SPIRV/OCLToSPIRV.h ++++ b/lib/SPIRV/OCLToSPIRV.h +@@ -247,6 +247,9 @@ public: + void visitSubgroupAVCBuiltinCallWithSampler(CallInst *CI, + StringRef DemangledName); + ++ /// For cl_intel_split_work_group_barrier built-ins: ++ void visitCallSplitBarrierINTEL(CallInst *CI, StringRef DemangledName); ++ + void visitCallLdexp(CallInst *CI, StringRef MangledName, + StringRef DemangledName); + +diff --git a/lib/SPIRV/OCLUtil.cpp b/lib/SPIRV/OCLUtil.cpp +index c696e25b..53ebc362 100644 +--- a/lib/SPIRV/OCLUtil.cpp ++++ b/lib/SPIRV/OCLUtil.cpp +@@ -432,6 +432,9 @@ template <> void SPIRVMap::init() { + _SPIRV_OP(bitfield_extract_signed, BitFieldSExtract) + _SPIRV_OP(bitfield_extract_unsigned, BitFieldUExtract) + _SPIRV_OP(bit_reverse, BitReverse) ++ // cl_khr_split_work_group_barrier ++ _SPIRV_OP(intel_work_group_barrier_arrive, ControlBarrierArriveINTEL) ++ _SPIRV_OP(intel_work_group_barrier_wait, ControlBarrierWaitINTEL) + #undef _SPIRV_OP + } + +@@ -1038,7 +1041,9 @@ public: + } else if (NameRef.contains("barrier")) { + addUnsignedArg(0); + if (NameRef.equals("work_group_barrier") || +- NameRef.equals("sub_group_barrier")) ++ NameRef.equals("sub_group_barrier") || ++ NameRef.equals("intel_work_group_barrier_arrive") || ++ NameRef.equals("intel_work_group_barrier_wait")) + setEnumArg(1, SPIR::PRIMITIVE_MEMORY_SCOPE); + } else if (NameRef.startswith("atomic_work_item_fence")) { + addUnsignedArg(0); +diff --git a/lib/SPIRV/OCLUtil.h b/lib/SPIRV/OCLUtil.h +index 1c0d8605..2bfe78f6 100644 +--- a/lib/SPIRV/OCLUtil.h ++++ b/lib/SPIRV/OCLUtil.h +@@ -307,6 +307,7 @@ const static char SubgroupBlockWriteINTELPrefix[] = + "intel_sub_group_block_write"; + const static char SubgroupImageMediaBlockINTELPrefix[] = + "intel_sub_group_media_block"; ++const static char SplitBarrierINTELPrefix[] = "intel_work_group_barrier_"; + const static char LDEXP[] = "ldexp"; + #define _SPIRV_OP(x) \ + const static char ConvertBFloat16##x##AsUShort##x[] = \ +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index cbf2dd33..cbfc7499 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3146,7 +3146,7 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName, + Func->addFnAttr(Attribute::NoUnwind); + auto OC = BI->getOpCode(); + if (isGroupOpCode(OC) || isIntelSubgroupOpCode(OC) || +- OC == OpControlBarrier) ++ isSplitBarrierINTELOpCode(OC) || OC == OpControlBarrier) + Func->addFnAttr(Attribute::Convergent); + } + auto Call = +diff --git a/lib/SPIRV/SPIRVToOCL.cpp b/lib/SPIRV/SPIRVToOCL.cpp +index f66ac077..c255b60a 100644 +--- a/lib/SPIRV/SPIRVToOCL.cpp ++++ b/lib/SPIRV/SPIRVToOCL.cpp +@@ -118,6 +118,10 @@ void SPIRVToOCLBase::visitCallInst(CallInst &CI) { + if (OC == OpControlBarrier) { + visitCallSPIRVControlBarrier(&CI); + } ++ if (isSplitBarrierINTELOpCode(OC)) { ++ visitCallSPIRVSplitBarrierINTEL(&CI, OC); ++ return; ++ } + if (isAtomicOpCode(OC)) { + visitCallSPIRVAtomicBuiltin(&CI, OC); + return; +diff --git a/lib/SPIRV/SPIRVToOCL.h b/lib/SPIRV/SPIRVToOCL.h +index 92afee9d..944b978f 100644 +--- a/lib/SPIRV/SPIRVToOCL.h ++++ b/lib/SPIRV/SPIRVToOCL.h +@@ -222,6 +222,12 @@ public: + /// - OCL1.2: barrier + virtual void visitCallSPIRVControlBarrier(CallInst *CI) = 0; + ++ /// Transform split __spirv_ControlBarrierArriveINTEL and ++ /// __spirv_ControlBarrierWaitINTEL barrier to: ++ /// - OCL2.0: overload with a memory_scope argument ++ /// - OCL1.2: overload with no memory_scope argument ++ virtual void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) = 0; ++ + /// Transform __spirv_EnqueueKernel to __enqueue_kernel + virtual void visitCallSPIRVEnqueueKernel(CallInst *CI, Op OC) = 0; + +@@ -305,6 +311,11 @@ public: + /// barrier(flag(sema)) + void visitCallSPIRVControlBarrier(CallInst *CI) override; + ++ /// Transform split __spirv_ControlBarrierArriveINTEL and ++ /// __spirv_ControlBarrierWaitINTEL barrier to overloads without a ++ /// memory_scope argument. ++ void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override; ++ + /// Transform __spirv_OpAtomic functions. It firstly conduct generic + /// mutations for all builtins and then mutate some of them seperately + Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) override; +@@ -394,6 +405,11 @@ public: + /// sub_group_barrier(flag(sema), map(memScope)) + void visitCallSPIRVControlBarrier(CallInst *CI) override; + ++ /// Transform split __spirv_ControlBarrierArriveINTEL and ++ /// __spirv_ControlBarrierWaitINTEL barrier to overloads with a ++ /// memory_scope argument. ++ void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override; ++ + /// Transform __spirv_Atomic* to atomic_*. + /// __spirv_Atomic*(atomic_op, scope, sema, ops, ...) => + /// atomic_*(generic atomic_op, ops, ..., order(sema), map(scope)) +diff --git a/lib/SPIRV/SPIRVToOCL12.cpp b/lib/SPIRV/SPIRVToOCL12.cpp +index 0af545e1..091a5f35 100644 +--- a/lib/SPIRV/SPIRVToOCL12.cpp ++++ b/lib/SPIRV/SPIRVToOCL12.cpp +@@ -100,6 +100,19 @@ void SPIRVToOCL12Base::visitCallSPIRVControlBarrier(CallInst *CI) { + &Attrs); + } + ++void SPIRVToOCL12Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) { ++ AttributeList Attrs = CI->getCalledFunction()->getAttributes(); ++ mutateCallInstOCL( ++ M, CI, ++ [=](CallInst *, std::vector &Args) { ++ Value *MemFenceFlags = ++ SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI); ++ Args.assign(1, MemFenceFlags); ++ return OCLSPIRVBuiltinMap::rmap(OC); ++ }, ++ &Attrs); ++} ++ + Instruction *SPIRVToOCL12Base::visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) { + AttributeList Attrs = CI->getCalledFunction()->getAttributes(); + return mutateCallInstOCL( +diff --git a/lib/SPIRV/SPIRVToOCL20.cpp b/lib/SPIRV/SPIRVToOCL20.cpp +index 8a679d64..58d66564 100644 +--- a/lib/SPIRV/SPIRVToOCL20.cpp ++++ b/lib/SPIRV/SPIRVToOCL20.cpp +@@ -123,6 +123,28 @@ void SPIRVToOCL20Base::visitCallSPIRVControlBarrier(CallInst *CI) { + &NewAttrs); + } + ++void SPIRVToOCL20Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) { ++ AttributeList Attrs = CI->getCalledFunction()->getAttributes(); ++ mutateCallInstOCL( ++ M, CI, ++ [=](CallInst *, std::vector &Args) { ++ auto GetArg = [=](unsigned I) { ++ return cast(Args[I])->getZExtValue(); ++ }; ++ Value *MemScope = ++ getInt32(M, rmap(static_cast(GetArg(1)))); ++ Value *MemFenceFlags = ++ SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI); ++ ++ Args.resize(2); ++ Args[0] = MemFenceFlags; ++ Args[1] = MemScope; ++ ++ return OCLSPIRVBuiltinMap::rmap(OC); ++ }, ++ &Attrs); ++} ++ + std::string SPIRVToOCL20Base::mapFPAtomicName(Op OC) { + assert(isFPAtomicOpCode(OC) && "Not intended to handle other opcodes than " + "AtomicF{Add/Min/Max}EXT!"); +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 5cb3363b..5c83b1ec 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3327,6 +3327,24 @@ _SPIRV_OP(JointMatrixMad, true, 7) + _SPIRV_OP(JointMatrixWorkItemLength, true, 4) + #undef _SPIRV_OP + ++class SPIRVSplitBarrierINTELBase : public SPIRVInstTemplateBase { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(CapabilitySplitBarrierINTEL); ++ } ++ ++ llvm::Optional getRequiredExtension() const override { ++ return ExtensionID::SPV_INTEL_split_barrier; ++ } ++}; ++ ++#define _SPIRV_OP(x, ...) \ ++ typedef SPIRVInstTemplate \ ++ SPIRV##x; ++_SPIRV_OP(ControlBarrierArriveINTEL, false, 4) ++_SPIRV_OP(ControlBarrierWaitINTEL, false, 4) ++#undef _SPIRV_OP ++ + class SPIRVGroupUniformArithmeticKHRInstBase : public SPIRVInstTemplateBase { + public: + SPIRVCapVec getRequiredCapability() const override { +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCode.h b/lib/SPIRV/libSPIRV/SPIRVOpCode.h +index 35062463..da1f4b1a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCode.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCode.h +@@ -252,6 +252,11 @@ inline bool isEventOpCode(Op OpCode) { + return OpRetainEvent <= OpCode && OpCode <= OpCaptureEventProfilingInfo; + } + ++inline bool isSplitBarrierINTELOpCode(Op OpCode) { ++ return OpCode == OpControlBarrierArriveINTEL || ++ OpCode == OpControlBarrierWaitINTEL; ++} ++ + } // namespace SPIRV + + #endif // SPIRV_LIBSPIRV_SPIRVOPCODE_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +index 9d7da279..94197e7b 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +@@ -547,6 +547,8 @@ _SPIRV_OP(TypeBufferSurfaceINTEL, 6086) + _SPIRV_OP(TypeStructContinuedINTEL, 6090) + _SPIRV_OP(ConstantCompositeContinuedINTEL, 6091) + _SPIRV_OP(SpecConstantCompositeContinuedINTEL, 6092) ++_SPIRV_OP(ControlBarrierArriveINTEL, 6142) ++_SPIRV_OP(ControlBarrierWaitINTEL, 6143) + _SPIRV_OP(GroupIMulKHR, 6401) + _SPIRV_OP(GroupFMulKHR, 6402) + _SPIRV_OP(GroupBitwiseAndKHR, 6403) +diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll +new file mode 100644 +index 00000000..8ab1e85c +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll +@@ -0,0 +1,99 @@ ++;; kernel void test(global uint* dst) ++;; { ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE); ++;; intel_work_group_barrier_arrive(CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_GLOBAL_MEM_FENCE); ++;; ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); ++;;} ++ ++; Test for SPV_INTEL_split_barrier (OpenCL C LLVM IR) ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=CL1.2 ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier ++ ++; ModuleID = 'split_barrier.cl' ++source_filename = "split_barrier.cl" ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++; CHECK-SPIRV: Capability SplitBarrierINTEL ++; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier" ++; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0 ++; ++; Scopes: ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2 ++; ++; Memory Semantics: ++; 0x2 Acquire + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258 ++; 0x4 Release + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260 ++; 0x2 Acquire + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514 ++; 0x4 Release + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516 ++; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770 ++; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772 ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]] ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]] ++ ++; CHECK-LLVM-LABEL: define spir_kernel void @test ++; Function Attrs: convergent norecurse nounwind ++define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 2) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 2) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 3) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 3) ++ ret void ++} ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef) local_unnamed_addr #1 ++ ++attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" } ++attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } ++attributes #2 = { convergent nounwind } ++ ++!llvm.module.flags = !{!0, !1} ++!opencl.ocl.version = !{!2} ++!opencl.spir.version = !{!2} ++!llvm.ident = !{!3} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 7, !"frame-pointer", i32 2} ++!2 = !{i32 1, i32 2} ++!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"} ++!4 = !{i32 1} ++!5 = !{!"none"} ++!6 = !{!"uint*"} ++!7 = !{!""} +diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll +new file mode 100644 +index 00000000..4cdbcf23 +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll +@@ -0,0 +1,175 @@ ++;; kernel void test(global uint* dst) ++;; { ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE); ++;; intel_work_group_barrier_arrive(CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_arrive(CLK_IMAGE_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_IMAGE_MEM_FENCE); ++;; ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE | CLK_IMAGE_MEM_FENCE); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE | CLK_IMAGE_MEM_FENCE); ++;; ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_work_item); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_work_item); ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_work_group); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_work_group); ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_device); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_device); ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_all_svm_devices); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_all_svm_devices); ++;; intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_sub_group); ++;; intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_sub_group); ++;;} ++ ++; Test for SPV_INTEL_split_barrier (OpenCL C LLVM IR) ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=CL2.0 ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier ++ ++; ModuleID = 'split_barrier.cl' ++source_filename = "split_barrier.cl" ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++; CHECK-SPIRV: Capability SplitBarrierINTEL ++; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier" ++; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0 ++; ++; Scopes: ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_INVOCATION:[0-9]+]] 4 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_DEVICE:[0-9]+]] 1 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_CROSS_DEVICE:[0-9]+]] 0 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_SUBGROUP:[0-9]+]] 3 ++; ++; Memory Semantics: ++; 0x2 Acquire + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258 ++; 0x4 Release + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260 ++; 0x2 Acquire + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514 ++; 0x4 Release + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516 ++; 0x2 Acquire + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_IMAGE:[0-9]+]] 2050 ++; 0x4 Acquire + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_IMAGE:[0-9]+]] 2052 ++; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770 ++; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772 ++; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2818 ++; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2820 ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_IMAGE]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_IMAGE]] ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL_IMAGE]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE]] ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[ACQUIRE_LOCAL]] ++ ++; CHECK-LLVM-LABEL: define spir_kernel void @test ++; Function Attrs: convergent norecurse nounwind ++define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 2, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 2, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 4) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 4, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 4) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 4, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 3, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 3, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 7) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 7, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 7) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 7, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 0) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 0) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 0) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 0) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 1) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 1) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 1) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 2) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 2) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 2) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 3) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 3) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 3) ++ tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 4) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 4) ++ tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 4) #2 ++ ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 4) ++ ret void ++} ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef, i32 noundef) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef, i32 noundef) local_unnamed_addr #1 ++ ++attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" } ++attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } ++attributes #2 = { convergent nounwind } ++ ++!llvm.module.flags = !{!0, !1} ++!opencl.ocl.version = !{!2} ++!opencl.spir.version = !{!2} ++!llvm.ident = !{!3} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 7, !"frame-pointer", i32 2} ++!2 = !{i32 2, i32 0} ++!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"} ++!4 = !{i32 1} ++!5 = !{!"none"} ++!6 = !{!"uint*"} ++!7 = !{!""} +diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll +new file mode 100644 +index 00000000..ae5b57f1 +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll +@@ -0,0 +1,170 @@ ++;; kernel void test(global uint* dst) ++;; { ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 260); // local ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 258); // local ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 516); // global ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 514); // global ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 2052); // image ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 2050); // image ++;; ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 772); // local + global ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 770); // local + global ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 2820); // local + global + image ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 2818); // local + global + image ++;; ++;; __spirv_ControlBarrierArriveINTEL(2, 4, 260); // local, work_item ++;; __spirv_ControlBarrierWaitINTEL(2, 4, 258); // local, work_item ++;; __spirv_ControlBarrierArriveINTEL(2, 2, 260); // local, work_group ++;; __spirv_ControlBarrierWaitINTEL(2, 2, 258); // local, work_group ++;; __spirv_ControlBarrierArriveINTEL(2, 1, 260); // local, device ++;; __spirv_ControlBarrierWaitINTEL(2, 1, 258); // local, device ++;; __spirv_ControlBarrierArriveINTEL(2, 0, 260); // local, all_svm_devices ++;; __spirv_ControlBarrierWaitINTEL(2, 0, 258); // local, all_svm_devices ++;; __spirv_ControlBarrierArriveINTEL(2, 3, 260); // local, subgroup ++;; __spirv_ControlBarrierWaitINTEL(2, 3, 258); // local, subgroup ++;;} ++ ++; Test for SPV_INTEL_split_barrier (SPIR-V friendly LLVM IR) ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++ ++; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=SPV-IR ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier ++ ++; ModuleID = 'split_barrier_spirv.cl' ++source_filename = "split_barrier_spirv.cl" ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++; CHECK-SPIRV: Capability SplitBarrierINTEL ++; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier" ++; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0 ++; ++; Scopes: ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_INVOCATION:[0-9]+]] 4 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_DEVICE:[0-9]+]] 1 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_CROSS_DEVICE:[0-9]+]] 0 ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_SUBGROUP:[0-9]+]] 3 ++; ++; Memory Semantics: ++; 0x2 Acquire + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258 ++; 0x4 Release + 0x100 WorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260 ++; 0x2 Acquire + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514 ++; 0x4 Release + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516 ++; 0x2 Acquire + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_IMAGE:[0-9]+]] 2050 ++; 0x4 Acquire + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_IMAGE:[0-9]+]] 2052 ++; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770 ++; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772 ++; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2818 ++; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory ++; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2820 ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_IMAGE]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_IMAGE]] ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL_IMAGE]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE]] ++; ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[ACQUIRE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[RELEASE_LOCAL]] ++; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[ACQUIRE_LOCAL]] ++ ++; CHECK-LLVM-LABEL: define spir_kernel void @test ++; Function Attrs: convergent norecurse nounwind ++define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 258) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 516) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 516) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 514) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 514) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2052) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 2052) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2050) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 2050) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 772) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 772) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 770) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 770) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2820) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 2820) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2818) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 2818) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 4, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 4, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 4, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 4, i32 258) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 258) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 1, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 1, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 1, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 1, i32 258) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 0, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 0, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 0, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 0, i32 258) #1 ++ tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 3, i32 noundef 260) #2 ++ ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 3, i32 260) #1 ++ tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 3, i32 noundef 258) #2 ++ ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 3, i32 258) #1 ++ ret void ++} ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1 ++ ++attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" } ++attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } ++attributes #2 = { convergent nounwind } ++ ++!llvm.module.flags = !{!0, !1} ++!opencl.ocl.version = !{!2} ++!opencl.spir.version = !{!2} ++!llvm.ident = !{!3} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 7, !"frame-pointer", i32 2} ++!2 = !{i32 2, i32 0} ++!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"} ++!4 = !{i32 1} ++!5 = !{!"none"} ++!6 = !{!"uint*"} ++!7 = !{!""} +-- +2.20.1 + diff --git a/patches/0003-CI-Upgrade-to-Ubuntu-20.04.patch b/patches/0003-CI-Upgrade-to-Ubuntu-20.04.patch new file mode 100644 index 0000000..caf3e2a --- /dev/null +++ b/patches/0003-CI-Upgrade-to-Ubuntu-20.04.patch @@ -0,0 +1,84 @@ +From ef7b39f38f2cf6295e47f347f413bed29565f2f4 Mon Sep 17 00:00:00 2001 +From: Sven van Haastregt +Date: Thu, 18 Aug 2022 09:46:20 +0100 +Subject: [PATCH 03/79] [CI] Upgrade to Ubuntu 20.04 + +The Ubuntu 18.04 image is marked deprecated [1], so move to a newer +image. + +[1] https://github.com/actions/runner-images +--- + .github/workflows/check-code-style.yml | 4 ++-- + .github/workflows/check-in-tree-build.yml | 6 +++--- + .github/workflows/check-out-of-tree-build.yml | 6 +++--- + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/.github/workflows/check-code-style.yml b/.github/workflows/check-code-style.yml +index 13e9ffae..5d242143 100644 +--- a/.github/workflows/check-code-style.yml ++++ b/.github/workflows/check-code-style.yml +@@ -29,7 +29,7 @@ env: + jobs: + clang-format-and-tidy: + name: clang-format & clang-tidy +- runs-on: ubuntu-18.04 ++ runs-on: ubuntu-20.04 + steps: + - name: Checkout sources + uses: actions/checkout@v2 +@@ -64,7 +64,7 @@ jobs: + # launched, so, we need to setup llvm package to perform cmake + # configuration step to generate that database + curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - +- echo "deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-15 main" | sudo tee -a /etc/apt/sources.list ++ echo "deb https://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" | sudo tee -a /etc/apt/sources.list + sudo apt-get update + sudo apt-get install -yqq \ + clang-format-${{ env.LLVM_VERSION }} clang-tidy-${{ env.LLVM_VERSION }} \ +diff --git a/.github/workflows/check-in-tree-build.yml b/.github/workflows/check-in-tree-build.yml +index a71461ef..29d1a425 100644 +--- a/.github/workflows/check-in-tree-build.yml ++++ b/.github/workflows/check-in-tree-build.yml +@@ -45,14 +45,14 @@ jobs: + - build_type: Release + shared_libs: EnableSharedLibs + fail-fast: false +- runs-on: ubuntu-18.04 ++ runs-on: ubuntu-20.04 + steps: + - name: Install dependencies + run: | + curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - + curl -L "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add - +- echo "deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-15 main" | sudo tee -a /etc/apt/sources.list +- echo "deb https://packages.lunarg.com/vulkan bionic main" | sudo tee -a /etc/apt/sources.list ++ echo "deb https://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" | sudo tee -a /etc/apt/sources.list ++ echo "deb https://packages.lunarg.com/vulkan focal main" | sudo tee -a /etc/apt/sources.list + sudo apt-get update + sudo apt-get -yq --no-install-suggests --no-install-recommends install \ + clang-${{ env.LLVM_VERSION }} \ +diff --git a/.github/workflows/check-out-of-tree-build.yml b/.github/workflows/check-out-of-tree-build.yml +index ade5f546..f6d628fa 100644 +--- a/.github/workflows/check-out-of-tree-build.yml ++++ b/.github/workflows/check-out-of-tree-build.yml +@@ -38,14 +38,14 @@ jobs: + matrix: + build_type: [Release, Debug] + fail-fast: false +- runs-on: ubuntu-18.04 ++ runs-on: ubuntu-20.04 + steps: + - name: Install dependencies + run: | + curl -L "https://apt.llvm.org/llvm-snapshot.gpg.key" | sudo apt-key add - + curl -L "https://packages.lunarg.com/lunarg-signing-key-pub.asc" | sudo apt-key add - +- echo "deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-15 main" | sudo tee -a /etc/apt/sources.list +- echo "deb https://packages.lunarg.com/vulkan bionic main" | sudo tee -a /etc/apt/sources.list ++ echo "deb https://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" | sudo tee -a /etc/apt/sources.list ++ echo "deb https://packages.lunarg.com/vulkan focal main" | sudo tee -a /etc/apt/sources.list + sudo apt-get update + sudo apt-get -yq --no-install-suggests --no-install-recommends install \ + clang-${{ env.LLVM_VERSION }} \ +-- +2.20.1 + diff --git a/patches/0004-NFC-Replace-getPointerElementType-in-SPIRVRegularize.patch b/patches/0004-NFC-Replace-getPointerElementType-in-SPIRVRegularize.patch new file mode 100644 index 0000000..7914753 --- /dev/null +++ b/patches/0004-NFC-Replace-getPointerElementType-in-SPIRVRegularize.patch @@ -0,0 +1,34 @@ +From 29d8d3a7f74217fc7fffbeb1a97447492be683ec Mon Sep 17 00:00:00 2001 +From: "Sidorov, Dmitry" +Date: Tue, 8 Nov 2022 01:43:49 -0800 +Subject: [PATCH 04/79] [NFC] Replace getPointerElementType in + SPIRVRegularizeLLVM + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVRegularizeLLVM.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/SPIRV/SPIRVRegularizeLLVM.cpp b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +index 3300aab1..d0e3ae1e 100644 +--- a/lib/SPIRV/SPIRVRegularizeLLVM.cpp ++++ b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +@@ -371,12 +371,13 @@ void SPIRVRegularizeLLVMBase::adaptStructTypes(StructType *ST) { + // register by OpCompositeConstruct. And we can't claim, that the Result type + // of OpCompositeConstruct instruction is always the joint matrix type, it's + // simply not true. +- if (MangledName == "__spirv_JointMatrixINTEL") { ++ if (MangledName == "__spirv_JointMatrixINTEL" && !ST->isOpaquePointerTy()) { + auto *PtrTy = dyn_cast(ST->getElementType(0)); + assert(PtrTy && + "Expected a pointer to an array to represent joint matrix type"); + std::vector TypeLayout; +- ArrayType *ArrayTy = dyn_cast(PtrTy->getPointerElementType()); ++ ArrayType *ArrayTy = ++ dyn_cast(PtrTy->getNonOpaquePointerElementType()); + assert(ArrayTy && "Expected a pointer element type of an array type to " + "represent joint matrix type"); + TypeLayout.push_back(ArrayTy->getNumElements()); +-- +2.20.1 + diff --git a/patches/0005-NFC-Initialize-a-variable.patch b/patches/0005-NFC-Initialize-a-variable.patch new file mode 100644 index 0000000..e040a8e --- /dev/null +++ b/patches/0005-NFC-Initialize-a-variable.patch @@ -0,0 +1,26 @@ +From c5961bda8281592e3a347ab360275b38f9a9c380 Mon Sep 17 00:00:00 2001 +From: "Sidorov, Dmitry" +Date: Tue, 8 Nov 2022 01:50:02 -0800 +Subject: [PATCH 05/79] [NFC] Initialize a variable + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVWriter.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 34246e5d..fd890a93 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -4491,7 +4491,7 @@ bool LLVMToSPIRVBase::transExecutionMode() { + return false; + + auto AddSingleArgExecutionMode = [&](ExecutionMode EMode) { +- uint32_t Arg; ++ uint32_t Arg = 0; + N.get(Arg); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode(BF, EMode, Arg))); + }; +-- +2.20.1 + diff --git a/patches/0006-Backport-to-15-Add-SPV_INTEL_masked_gather_scatter-e.patch b/patches/0006-Backport-to-15-Add-SPV_INTEL_masked_gather_scatter-e.patch new file mode 100644 index 0000000..4b3cc78 --- /dev/null +++ b/patches/0006-Backport-to-15-Add-SPV_INTEL_masked_gather_scatter-e.patch @@ -0,0 +1,619 @@ +From c1afe2312430ed14d5c9733bca034c4405530a06 Mon Sep 17 00:00:00 2001 +From: Stanley Gambarin +Date: Tue, 8 Nov 2022 08:04:36 -0800 +Subject: [PATCH 06/79] [Backport to 15] Add SPV_INTEL_masked_gather_scatter + extension (#1580) (#1695) + +This extension allows TypeVector to have a Physical Pointer Type +Component Type and introduces gather/scatter instructions. +It will be useful for explicitly vectorized kernels. + +Spec: https://github.com/intel/llvm/pull/6613 + +Signed-off-by: Sidorov, Dmitry +--- + include/LLVMSPIRVExtensions.inc | 1 + + lib/SPIRV/SPIRVReader.cpp | 36 ++++- + lib/SPIRV/SPIRVRegularizeLLVM.cpp | 18 ++- + lib/SPIRV/SPIRVWriter.cpp | 62 +++++++- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 148 ++++++++++++++++++ + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 1 + + lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h | 2 + + lib/SPIRV/libSPIRV/SPIRVType.cpp | 4 + + lib/SPIRV/libSPIRV/SPIRVType.h | 1 + + lib/SPIRV/libSPIRV/spirv_internal.hpp | 9 +- + .../vector_elem.ll | 2 +- + .../intel-basic-vector-pointers.ll | 70 +++++++++ + .../intel-gather-scatter.ll | 67 ++++++++ + 13 files changed, 411 insertions(+), 10 deletions(-) + create mode 100644 test/transcoding/SPV_INTEL_masked_gather_scatter/intel-basic-vector-pointers.ll + create mode 100644 test/transcoding/SPV_INTEL_masked_gather_scatter/intel-gather-scatter.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 3d0eae8c..4f970d2a 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -54,3 +54,4 @@ EXT(SPV_INTEL_global_variable_decorations) + EXT(SPV_INTEL_non_constant_addrspace_printf) + EXT(SPV_INTEL_complex_float_mul_div) + EXT(SPV_INTEL_split_barrier) ++EXT(SPV_INTEL_masked_gather_scatter) +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index cbfc7499..500bebb9 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -2177,7 +2177,12 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, + case OpInBoundsPtrAccessChain: { + auto AC = static_cast(BV); + auto Base = transValue(AC->getBase(), F, BB); +- Type *BaseTy = transType(AC->getBase()->getType()->getPointerElementType()); ++ SPIRVType *BaseSPVTy = AC->getBase()->getType(); ++ Type *BaseTy = ++ BaseSPVTy->isTypeVector() ++ ? transType( ++ BaseSPVTy->getVectorComponentType()->getPointerElementType()) ++ : transType(BaseSPVTy->getPointerElementType()); + auto Index = transValue(AC->getIndices(), F, BB); + if (!AC->hasPtrIndex()) + Index.insert(Index.begin(), getInt32(M, 0)); +@@ -2590,6 +2595,29 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, + return mapValue( + BV, Builder.CreateIntrinsic(Intrinsic::arithmetic_fence, RetTy, Val)); + } ++ case internal::OpMaskedGatherINTEL: { ++ IRBuilder<> Builder(BB); ++ auto *Inst = static_cast(BV); ++ Type *RetTy = transType(Inst->getType()); ++ Value *PtrVector = transValue(Inst->getOperand(0), F, BB); ++ uint32_t Alignment = Inst->getOpWord(1); ++ Value *Mask = transValue(Inst->getOperand(2), F, BB); ++ Value *FillEmpty = transValue(Inst->getOperand(3), F, BB); ++ return mapValue(BV, Builder.CreateMaskedGather(RetTy, PtrVector, ++ Align(Alignment), Mask, ++ FillEmpty)); ++ } ++ ++ case internal::OpMaskedScatterINTEL: { ++ IRBuilder<> Builder(BB); ++ auto *Inst = static_cast(BV); ++ Value *InputVector = transValue(Inst->getOperand(0), F, BB); ++ Value *PtrVector = transValue(Inst->getOperand(1), F, BB); ++ uint32_t Alignment = Inst->getOpWord(2); ++ Value *Mask = transValue(Inst->getOperand(3), F, BB); ++ return mapValue(BV, Builder.CreateMaskedScatter(InputVector, PtrVector, ++ Align(Alignment), Mask)); ++ } + + default: { + auto OC = BV->getOpCode(); +@@ -3197,7 +3225,11 @@ std::string getSPIRVFuncSuffix(SPIRVInstruction *BI) { + } + if (BI->getOpCode() == OpGenericCastToPtrExplicit) { + Suffix += kSPIRVPostfix::Divider; +- auto GenericCastToPtrInst = BI->getType()->getPointerStorageClass(); ++ auto *Ty = BI->getType(); ++ auto GenericCastToPtrInst = ++ Ty->isTypeVectorPointer() ++ ? Ty->getVectorComponentType()->getPointerStorageClass() ++ : Ty->getPointerStorageClass(); + switch (GenericCastToPtrInst) { + case StorageClassCrossWorkgroup: + Suffix += std::string(kSPIRVPostfix::ToGlobal); +diff --git a/lib/SPIRV/SPIRVRegularizeLLVM.cpp b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +index d0e3ae1e..e1e2f707 100644 +--- a/lib/SPIRV/SPIRVRegularizeLLVM.cpp ++++ b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +@@ -539,11 +539,19 @@ bool SPIRVRegularizeLLVMBase::regularize() { + // Add an additional bitcast in case address space cast also changes + // pointer element type. + if (auto *ASCast = dyn_cast(&II)) { +- PointerType *DestTy = cast(ASCast->getDestTy()); +- PointerType *SrcTy = cast(ASCast->getSrcTy()); +- if (!DestTy->hasSameElementTypeAs(SrcTy)) { +- PointerType *InterTy = PointerType::getWithSamePointeeType( +- DestTy, SrcTy->getPointerAddressSpace()); ++ Type *DestTy = ASCast->getDestTy(); ++ Type *SrcTy = ASCast->getSrcTy(); ++ if (!II.getContext().supportsTypedPointers()) ++ continue; ++ if (DestTy->getScalarType()->getNonOpaquePointerElementType() != ++ SrcTy->getScalarType()->getNonOpaquePointerElementType()) { ++ Type *InterTy = PointerType::getWithSamePointeeType( ++ cast(DestTy->getScalarType()), ++ cast(SrcTy->getScalarType()) ++ ->getPointerAddressSpace()); ++ if (DestTy->isVectorTy()) ++ InterTy = VectorType::get( ++ InterTy, cast(DestTy)->getElementCount()); + BitCastInst *NewBCast = new BitCastInst( + ASCast->getPointerOperand(), InterTy, /*NameStr=*/"", ASCast); + AddrSpaceCastInst *NewASCast = +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index fd890a93..3593375a 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -342,9 +342,28 @@ SPIRVType *LLVMToSPIRVBase::transType(Type *T) { + return transPointerType(ET, AddrSpc); + } + +- if (auto *VecTy = dyn_cast(T)) ++ if (auto *VecTy = dyn_cast(T)) { ++ if (VecTy->getElementType()->isPointerTy()) { ++ // SPV_INTEL_masked_gather_scatter extension changes 2.16.1. Universal ++ // Validation Rules: ++ // Vector types must be parameterized only with numerical types, ++ // [Physical Pointer Type] types or the [OpTypeBool] type. ++ // Without it vector of pointers is not allowed in SPIR-V. ++ if (!BM->isAllowedToUseExtension( ++ ExtensionID::SPV_INTEL_masked_gather_scatter)) { ++ BM->getErrorLog().checkError( ++ false, SPIRVEC_RequiresExtension, ++ "SPV_INTEL_masked_gather_scatter\n" ++ "NOTE: LLVM module contains vector of pointers, translation " ++ "of which requires this extension"); ++ return nullptr; ++ } ++ BM->addExtension(ExtensionID::SPV_INTEL_masked_gather_scatter); ++ BM->addCapability(internal::CapabilityMaskedGatherScatterINTEL); ++ } + return mapType(T, BM->addVectorType(transType(VecTy->getElementType()), + VecTy->getNumElements())); ++ } + + if (T->isArrayTy()) { + // SPIR-V 1.3 s3.32.6: Length is the number of elements in the array. +@@ -3824,6 +3843,47 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + } + return Op; + } ++ case Intrinsic::masked_gather: { ++ if (!BM->isAllowedToUseExtension( ++ ExtensionID::SPV_INTEL_masked_gather_scatter)) { ++ BM->getErrorLog().checkError( ++ BM->isUnknownIntrinsicAllowed(II), SPIRVEC_InvalidFunctionCall, II, ++ "Translation of llvm.masked.gather intrinsic requires " ++ "SPV_INTEL_masked_gather_scatter extension or " ++ "-spirv-allow-unknown-intrinsics option."); ++ return nullptr; ++ } ++ SPIRVType *Ty = transType(II->getType()); ++ auto *PtrVector = transValue(II->getArgOperand(0), BB); ++ uint32_t Alignment = ++ cast(II->getArgOperand(1))->getZExtValue(); ++ auto *Mask = transValue(II->getArgOperand(2), BB); ++ auto *FillEmpty = transValue(II->getArgOperand(3), BB); ++ std::vector Ops = {PtrVector->getId(), Alignment, Mask->getId(), ++ FillEmpty->getId()}; ++ return BM->addInstTemplate(internal::OpMaskedGatherINTEL, Ops, BB, Ty); ++ } ++ case Intrinsic::masked_scatter: { ++ if (!BM->isAllowedToUseExtension( ++ ExtensionID::SPV_INTEL_masked_gather_scatter)) { ++ BM->getErrorLog().checkError( ++ BM->isUnknownIntrinsicAllowed(II), SPIRVEC_InvalidFunctionCall, II, ++ "Translation of llvm.masked.scatter intrinsic requires " ++ "SPV_INTEL_masked_gather_scatter extension or " ++ "-spirv-allow-unknown-intrinsics option."); ++ return nullptr; ++ } ++ auto *InputVector = transValue(II->getArgOperand(0), BB); ++ auto *PtrVector = transValue(II->getArgOperand(1), BB); ++ uint32_t Alignment = ++ cast(II->getArgOperand(2))->getZExtValue(); ++ auto *Mask = transValue(II->getArgOperand(3), BB); ++ std::vector Ops = {InputVector->getId(), PtrVector->getId(), ++ Alignment, Mask->getId()}; ++ return BM->addInstTemplate(internal::OpMaskedScatterINTEL, Ops, BB, ++ nullptr); ++ } ++ + default: + if (BM->isUnknownIntrinsicAllowed(II)) + return BM->addCallInst( +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 5c83b1ec..2ffd4c3a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3413,6 +3413,154 @@ class SPIRVComplexFloatInst + _SPIRV_OP(ComplexFMulINTEL) + _SPIRV_OP(ComplexFDivINTEL) + #undef _SPIRV_OP ++ ++class SPIRVMaskedGatherScatterINTELInstBase : public SPIRVInstTemplateBase { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(internal::CapabilityMaskedGatherScatterINTEL); ++ } ++ llvm::Optional getRequiredExtension() const override { ++ return ExtensionID::SPV_INTEL_masked_gather_scatter; ++ } ++}; ++ ++class SPIRVMaskedGatherINTELInst ++ : public SPIRVMaskedGatherScatterINTELInstBase { ++ void validate() const override { ++ SPIRVInstruction::validate(); ++ SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); ++ std::string InstName = "MaskedGatherINTEL"; ++ ++ SPIRVType *ResTy = this->getType(); ++ SPVErrLog.checkError(ResTy->isTypeVector(), SPIRVEC_InvalidInstruction, ++ InstName + "\nResult must be a vector type\n"); ++ SPIRVWord ResCompCount = ResTy->getVectorComponentCount(); ++ SPIRVType *ResCompTy = ResTy->getVectorComponentType(); ++ ++ SPIRVValue *PtrVec = ++ const_cast(this)->getOperand(0); ++ SPIRVType *PtrVecTy = PtrVec->getType(); ++ SPVErrLog.checkError( ++ PtrVecTy->isTypeVectorPointer(), SPIRVEC_InvalidInstruction, ++ InstName + "\nPtrVector must be a vector of pointers type\n"); ++ SPIRVWord PtrVecCompCount = PtrVecTy->getVectorComponentCount(); ++ SPIRVType *PtrVecCompTy = PtrVecTy->getVectorComponentType(); ++ SPIRVType *PtrElemTy = PtrVecCompTy->getPointerElementType(); ++ ++ SPVErrLog.checkError( ++ this->isOperandLiteral(1), SPIRVEC_InvalidInstruction, ++ InstName + "\nAlignment must be a constant expression integer\n"); ++ const uint32_t Align = ++ static_cast( ++ const_cast(this)->getOperand(2)) ++ ->getZExtIntValue(); ++ SPVErrLog.checkError( ++ ((Align & (Align - 1)) == 0), SPIRVEC_InvalidInstruction, ++ InstName + "\nAlignment must be 0 or power-of-two integer\n"); ++ ++ SPIRVValue *Mask = ++ const_cast(this)->getOperand(2); ++ SPIRVType *MaskTy = Mask->getType(); ++ SPVErrLog.checkError(MaskTy->isTypeVector(), SPIRVEC_InvalidInstruction, ++ InstName + "\nMask must be a vector type\n"); ++ SPIRVType *MaskCompTy = MaskTy->getVectorComponentType(); ++ SPVErrLog.checkError(MaskCompTy->isTypeBool(), SPIRVEC_InvalidInstruction, ++ InstName + "\nMask must be a boolean vector type\n"); ++ SPIRVWord MaskCompCount = MaskTy->getVectorComponentCount(); ++ ++ SPIRVValue *FillEmpty = ++ const_cast(this)->getOperand(3); ++ SPIRVType *FillEmptyTy = FillEmpty->getType(); ++ SPVErrLog.checkError(FillEmptyTy->isTypeVector(), ++ SPIRVEC_InvalidInstruction, ++ InstName + "\nFillEmpty must be a vector type\n"); ++ SPIRVWord FillEmptyCompCount = FillEmptyTy->getVectorComponentCount(); ++ SPIRVType *FillEmptyCompTy = FillEmptyTy->getVectorComponentType(); ++ ++ SPVErrLog.checkError( ++ ResCompCount == PtrVecCompCount && ++ PtrVecCompCount == FillEmptyCompCount && ++ FillEmptyCompCount == MaskCompCount, ++ SPIRVEC_InvalidInstruction, ++ InstName + "\nResult, PtrVector, Mask and FillEmpty vectors must have " ++ "the same size\n"); ++ ++ SPVErrLog.checkError( ++ ResCompTy == PtrElemTy && PtrElemTy == FillEmptyCompTy, ++ SPIRVEC_InvalidInstruction, ++ InstName + "\nComponent Type of Result and FillEmpty vector must be " ++ "same as base type of PtrVector the same base type\n"); ++ } ++}; ++ ++class SPIRVMaskedScatterINTELInst ++ : public SPIRVMaskedGatherScatterINTELInstBase { ++ void validate() const override { ++ SPIRVInstruction::validate(); ++ SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); ++ std::string InstName = "MaskedScatterINTEL"; ++ ++ SPIRVValue *InputVec = ++ const_cast(this)->getOperand(0); ++ SPIRVType *InputVecTy = InputVec->getType(); ++ SPVErrLog.checkError( ++ InputVecTy->isTypeVector(), SPIRVEC_InvalidInstruction, ++ InstName + "\nInputVector must be a vector of pointers type\n"); ++ SPIRVWord InputVecCompCount = InputVecTy->getVectorComponentCount(); ++ SPIRVType *InputVecCompTy = InputVecTy->getVectorComponentType(); ++ ++ SPIRVValue *PtrVec = ++ const_cast(this)->getOperand(1); ++ SPIRVType *PtrVecTy = PtrVec->getType(); ++ SPVErrLog.checkError( ++ PtrVecTy->isTypeVectorPointer(), SPIRVEC_InvalidInstruction, ++ InstName + "\nPtrVector must be a vector of pointers type\n"); ++ SPIRVWord PtrVecCompCount = PtrVecTy->getVectorComponentCount(); ++ SPIRVType *PtrVecCompTy = PtrVecTy->getVectorComponentType(); ++ SPIRVType *PtrElemTy = PtrVecCompTy->getPointerElementType(); ++ ++ SPVErrLog.checkError( ++ this->isOperandLiteral(2), SPIRVEC_InvalidInstruction, ++ InstName + "\nAlignment must be a constant expression integer\n"); ++ const uint32_t Align = ++ static_cast( ++ const_cast(this)->getOperand(2)) ++ ->getZExtIntValue(); ++ SPVErrLog.checkError( ++ ((Align & (Align - 1)) == 0), SPIRVEC_InvalidInstruction, ++ InstName + "\nAlignment must be 0 or power-of-two integer\n"); ++ ++ SPIRVValue *Mask = ++ const_cast(this)->getOperand(2); ++ SPIRVType *MaskTy = Mask->getType(); ++ SPVErrLog.checkError(MaskTy->isTypeVector(), SPIRVEC_InvalidInstruction, ++ InstName + "\nMask must be a vector type\n"); ++ SPIRVType *MaskCompTy = MaskTy->getVectorComponentType(); ++ SPVErrLog.checkError(MaskCompTy->isTypeBool(), SPIRVEC_InvalidInstruction, ++ InstName + "\nMask must be a boolean vector type\n"); ++ SPIRVWord MaskCompCount = MaskTy->getVectorComponentCount(); ++ ++ SPVErrLog.checkError( ++ InputVecCompCount == PtrVecCompCount && ++ PtrVecCompCount == MaskCompCount, ++ SPIRVEC_InvalidInstruction, ++ InstName + "\nInputVector, PtrVector and Mask vectors must have " ++ "the same size\n"); ++ ++ SPVErrLog.checkError( ++ InputVecCompTy == PtrElemTy, SPIRVEC_InvalidInstruction, ++ InstName + "\nComponent Type of InputVector must be " ++ "same as base type of PtrVector the same base type\n"); ++ } ++}; ++ ++#define _SPIRV_OP(x, ...) \ ++ typedef SPIRVInstTemplate \ ++ SPIRV##x##INTEL; ++_SPIRV_OP(MaskedGather, true, 7) ++_SPIRV_OP(MaskedScatter, false, 5) ++#undef _SPIRV_OP + } // namespace SPIRV + + #endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index 88071dd7..fd8c5790 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -617,6 +617,7 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityNonConstantAddrspacePrintfINTEL, + "NonConstantAddrspacePrintfINTEL"); + add(internal::CapabilityComplexFloatMulDivINTEL, "ComplexFloatMulDivINTEL"); ++ add(internal::CapabilityMaskedGatherScatterINTEL, "MaskedGatherScatterINTEL"); + } + SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +index 22d3aabe..0ed0d855 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +@@ -13,3 +13,5 @@ _SPIRV_OP_INTERNAL(JointMatrixWorkItemLengthINTEL, + internal::OpJointMatrixWorkItemLengthINTEL) + _SPIRV_OP_INTERNAL(ComplexFMulINTEL, internal::ComplexFMulINTEL) + _SPIRV_OP_INTERNAL(ComplexFDivINTEL, internal::ComplexFDivINTEL) ++_SPIRV_OP_INTERNAL(MaskedGatherINTEL, internal::OpMaskedGatherINTEL) ++_SPIRV_OP_INTERNAL(MaskedScatterINTEL, internal::OpMaskedScatterINTEL) +diff --git a/lib/SPIRV/libSPIRV/SPIRVType.cpp b/lib/SPIRV/libSPIRV/SPIRVType.cpp +index add2d459..0314b54d 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVType.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVType.cpp +@@ -218,6 +218,10 @@ bool SPIRVType::isTypeVectorOrScalarBool() const { + return isTypeBool() || isTypeVectorBool(); + } + ++bool SPIRVType::isTypeVectorPointer() const { ++ return isTypeVector() && getVectorComponentType()->isTypePointer(); ++} ++ + bool SPIRVType::isTypeSubgroupAvcINTEL() const { + return isSubgroupAvcINTELTypeOpCode(OpCode); + } +diff --git a/lib/SPIRV/libSPIRV/SPIRVType.h b/lib/SPIRV/libSPIRV/SPIRVType.h +index 312aeb2f..af1a86d9 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVType.h ++++ b/lib/SPIRV/libSPIRV/SPIRVType.h +@@ -102,6 +102,7 @@ public: + bool isTypeVectorOrScalarInt() const; + bool isTypeVectorOrScalarFloat() const; + bool isTypeVectorOrScalarBool() const; ++ bool isTypeVectorPointer() const; + bool isTypeSubgroupAvcINTEL() const; + bool isTypeSubgroupAvcMceINTEL() const; + }; +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index dc41a04f..9073eccd 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -46,6 +46,8 @@ enum InternalOp { + IOpJointMatrixWorkItemLengthINTEL = 6410, + IOpComplexFMulINTEL = 6415, + IOpComplexFDivINTEL = 6416, ++ IOpMaskedGatherINTEL = 6428, ++ IOpMaskedScatterINTEL = 6429, + IOpPrev = OpMax - 2, + IOpForward + }; +@@ -76,7 +78,8 @@ enum InternalCapability { + ICapFPArithmeticFenceINTEL = 6144, + ICapGlobalVariableDecorationsINTEL = 6146, + ICapabilityNonConstantAddrspacePrintfINTEL = 6411, +- ICapabilityComplexFloatMulDivINTEL = 6414 ++ ICapabilityComplexFloatMulDivINTEL = 6414, ++ ICapabilityMaskedGatherScatterINTEL = 6427 + }; + + enum InternalFunctionControlMask { IFunctionControlOptNoneINTELMask = 0x10000 }; +@@ -121,6 +124,10 @@ _SPIRV_OP(Capability, NonConstantAddrspacePrintfINTEL) + _SPIRV_OP(Capability, ComplexFloatMulDivINTEL) + _SPIRV_OP(Op, ComplexFMulINTEL) + _SPIRV_OP(Op, ComplexFDivINTEL) ++ ++_SPIRV_OP(Capability, MaskedGatherScatterINTEL) ++_SPIRV_OP(Op, MaskedGatherINTEL) ++_SPIRV_OP(Op, MaskedScatterINTEL) + #undef _SPIRV_OP + + constexpr Op OpForward = static_cast(IOpForward); +diff --git a/test/transcoding/SPV_INTEL_function_pointers/vector_elem.ll b/test/transcoding/SPV_INTEL_function_pointers/vector_elem.ll +index ab832f9d..421a3466 100644 +--- a/test/transcoding/SPV_INTEL_function_pointers/vector_elem.ll ++++ b/test/transcoding/SPV_INTEL_function_pointers/vector_elem.ll +@@ -1,4 +1,4 @@ +-; RUN: llvm-as < %s | llvm-spirv -spirv-text --spirv-ext=+SPV_INTEL_function_pointers | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-as < %s | llvm-spirv -spirv-text --spirv-ext=+SPV_INTEL_function_pointers,+SPV_INTEL_masked_gather_scatter | FileCheck %s --check-prefix=CHECK-SPIRV + + ; CHECK-SPIRV-DAG: 6 Name [[F1:[0-9+]]] "_Z2f1u2CMvb32_j" + ; CHECK-SPIRV-DAG: 6 Name [[F2:[0-9+]]] "_Z2f2u2CMvb32_j" +diff --git a/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-basic-vector-pointers.ll b/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-basic-vector-pointers.ll +new file mode 100644 +index 00000000..0d2d93c0 +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-basic-vector-pointers.ll +@@ -0,0 +1,70 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_masked_gather_scatter -o %t.spv ++; RUN: llvm-spirv %t.spv --to-text -o %t.spt ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_masked_gather_scatter ++; CHECK-ERROR-NEXT: NOTE: LLVM module contains vector of pointers, translation of which requires this extension ++ ++ ++; CHECK-SPIRV-DAG: Capability MaskedGatherScatterINTEL ++; CHECK-SPIRV-DAG: Extension "SPV_INTEL_masked_gather_scatter" ++ ++; CHECK-SPIRV-DAG: TypeInt [[#INTTYPE1:]] 32 0 ++; CHECK-SPIRV-DAG: TypeInt [[#INTTYPE2:]] 8 0 ++; CHECK-SPIRV-DAG: TypePointer [[#PTRTYPE1:]] 5 [[#INTTYPE1]] ++; CHECK-SPIRV-DAG: TypeVector [[#VECTYPE1:]] [[#PTRTYPE1]] 4 ++; CHECK-SPIRV-DAG: TypePointer [[#PTRTYPE2:]] 8 [[#INTTYPE2]] ++; CHECK-SPIRV-DAG: TypeVector [[#VECTYPE2:]] [[#PTRTYPE2]] 4 ++; CHECK-SPIRV-DAG: TypePointer [[#PTRTOVECTYPE:]] 7 [[#VECTYPE2]] ++; CHECK-SPIRV-DAG: TypePointer [[#PTRTYPE3:]] 8 [[#INTTYPE1]] ++; CHECK-SPIRV-DAG: TypeVector [[#VECTYPE3:]] [[#PTRTYPE3]] 4 ++ ++; CHECK-SPIRV: Variable [[#PTRTOVECTYPE]] ++; CHECK-SPIRV: Variable [[#PTRTOVECTYPE]] ++; CHECK-SPIRV: Load [[#VECTYPE2]] ++; CHECK-SPIRV: Store ++; CHECK-SPIRV: Bitcast [[#VECTYPE3]] ++; CHECK-SPIRV: GenericCastToPtr [[#VECTYPE1]] ++; CHECK-SPIRV: FunctionCall [[#VECTYPE1]] ++; CHECK-SPIRV: InBoundsPtrAccessChain [[#PTRTYPE1]] ++ ++; CHECK-LLVM: alloca <4 x i8 addrspace(4)*> ++; CHECK-LLVM-NEXT: alloca <4 x i8 addrspace(4)*> ++; CHECK-LLVM-NEXT: load <4 x i8 addrspace(4)*>, <4 x i8 addrspace(4)*>* ++; CHECK-LLVM-NEXT: store <4 x i8 addrspace(4)*> %[[#]], <4 x i8 addrspace(4)*>* ++; CHECK-LLVM-NEXT: bitcast <4 x i8 addrspace(4)*> %[[#]] to <4 x i32 addrspace(4)*> ++; CHECK-LLVM-NEXT: addrspacecast <4 x i32 addrspace(4)*> %{{.*}} to <4 x i32 addrspace(1)*> ++; CHECK-LLVM-NEXT: call spir_func <4 x i32 addrspace(1)*> @boo(<4 x i32 addrspace(1)*> ++; CHECK-LLVM-NEXT: getelementptr inbounds i32, <4 x i32 addrspace(1)*> %{{.*}}, i32 1 ++ ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir" ++ ++; Function Attrs: nounwind readnone ++define spir_kernel void @foo() { ++entry: ++ %arg1 = alloca <4 x i8 addrspace(4)*> ++ %arg2 = alloca <4 x i8 addrspace(4)*> ++ %0 = load <4 x i8 addrspace(4)*>, <4 x i8 addrspace(4)*>* %arg1 ++ store <4 x i8 addrspace(4)*> %0, <4 x i8 addrspace(4)*>* %arg2 ++ %tmp1 = bitcast <4 x i8 addrspace(4)*> %0 to <4 x i32 addrspace(4)*> ++ %tmp2 = addrspacecast <4 x i32 addrspace(4)*> %tmp1 to <4 x i32 addrspace(1)*> ++ %tmp3 = call <4 x i32 addrspace(1)*> @boo(<4 x i32 addrspace(1)*> %tmp2) ++ %tmp4 = getelementptr inbounds i32, <4 x i32 addrspace(1)*> %tmp3, i32 1 ++ %tmp5 = addrspacecast <4 x i32 addrspace(4)*> %tmp1 to <4 x i8 addrspace(1)*> ++ ret void ++} ++ ++declare <4 x i32 addrspace(1)*> @boo(<4 x i32 addrspace(1)*> %a) ++ ++!llvm.module.flags = !{!0} ++!opencl.spir.version = !{!1} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 1, i32 2} +diff --git a/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-gather-scatter.ll b/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-gather-scatter.ll +new file mode 100644 +index 00000000..78a9fab5 +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_masked_gather_scatter/intel-gather-scatter.ll +@@ -0,0 +1,67 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_masked_gather_scatter -o %t.spv ++; RUN: llvm-spirv %t.spv --to-text -o %t.spt ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_masked_gather_scatter ++; CHECK-ERROR-NEXT: NOTE: LLVM module contains vector of pointers, translation of which requires this extension ++ ++; CHECK-SPIRV-DAG: Capability MaskedGatherScatterINTEL ++; CHECK-SPIRV-DAG: Extension "SPV_INTEL_masked_gather_scatter" ++ ++; CHECK-SPIRV-DAG: TypeInt [[#TYPEINT:]] 32 0 ++; CHECK-SPIRV-DAG: TypePointer [[#TYPEPTRINT:]] [[#]] [[#TYPEINT]] ++; CHECK-SPIRV-DAG: TypeVector [[#TYPEVECPTR:]] [[#TYPEPTRINT]] 4 ++; CHECK-SPIRV-DAG: TypeVector [[#TYPEVECINT:]] [[#TYPEINT]] 4 ++ ++; CHECK-SPIRV-DAG: Constant [[#TYPEINT]] [[#CONST4:]] 4 ++; CHECK-SPIRV-DAG: Constant [[#TYPEINT]] [[#CONST0:]] 0 ++; CHECK-SPIRV-DAG: Constant [[#TYPEINT]] [[#CONST1:]] 1 ++; CHECK-SPIRV-DAG: ConstantTrue [[#]] [[#TRUE:]] ++; CHECK-SPIRV-DAG: ConstantFalse [[#]] [[#FALSE:]] ++; CHECK-SPIRV-DAG: ConstantComposite [[#]] [[#MASK1:]] [[#TRUE]] [[#FALSE]] [[#TRUE]] [[#TRUE]] ++; CHECK-SPIRV-DAG: ConstantComposite [[#]] [[#FILL:]] [[#CONST4]] [[#CONST0]] [[#CONST1]] [[#CONST0]] ++; CHECK-SPIRV-DAG: ConstantComposite [[#]] [[#MASK2:]] [[#TRUE]] [[#TRUE]] [[#TRUE]] [[#TRUE]] ++ ++; CHECK-SPIRV: Load [[#TYPEVECPTR]] [[#VECGATHER:]] ++; CHECK-SPIRV: Load [[#TYPEVECPTR]] [[#VECSCATTER:]] ++; CHECK-SPIRV: MaskedGatherINTEL [[#TYPEVECINT]] [[#GATHER:]] [[#VECGATHER]] 4 [[#MASK1]] 23 ++; CHECK-SPIRV: MaskedScatterINTEL [[#GATHER]] [[#VECSCATTER]] 4 [[#MASK2]] ++ ++; CHECK-LLVM: %[[#VECGATHER:]] = load <4 x i32 addrspace(4)*>, <4 x i32 addrspace(4)*>* ++; CHECK-LLVM: %[[#VECSCATTER:]] = load <4 x i32 addrspace(4)*>, <4 x i32 addrspace(4)*>* ++; CHECK-LLVM: %[[GATHER:[a-z0-9]+]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p4i32(<4 x i32 addrspace(4)*> %[[#VECGATHER]], i32 4, <4 x i1> , <4 x i32> ) ++; CHECK-LLVM: call void @llvm.masked.scatter.v4i32.v4p4i32(<4 x i32> %[[GATHER]], <4 x i32 addrspace(4)*> %[[#VECSCATTER]], i32 4, <4 x i1> ) ++ ++; CHECK-LLVM-DAG: declare <4 x i32> @llvm.masked.gather.v4i32.v4p4i32(<4 x i32 addrspace(4)*>, i32 immarg, <4 x i1>, <4 x i32>) ++; CHECK-LLVM-DAG: declare void @llvm.masked.scatter.v4i32.v4p4i32(<4 x i32>, <4 x i32 addrspace(4)*>, i32 immarg, <4 x i1>) ++ ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir" ++ ++; Function Attrs: nounwind readnone ++define spir_kernel void @foo() { ++entry: ++ %arg0 = alloca <4 x i32 addrspace(4)*> ++ %arg1 = alloca <4 x i32 addrspace(4)*> ++ %0 = load <4 x i32 addrspace(4)*>, <4 x i32 addrspace(4)*>* %arg0 ++ %1 = load <4 x i32 addrspace(4)*>, <4 x i32 addrspace(4)*>* %arg1 ++ %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p4i32(<4 x i32 addrspace(4)*> %0, i32 4, <4 x i1> , <4 x i32> ) ++ call void @llvm.masked.scatter.v4i32.v4p4i32(<4 x i32> %res, <4 x i32 addrspace(4)*> %1, i32 4, <4 x i1> ) ++ ret void ++} ++ ++declare <4 x i32> @llvm.masked.gather.v4i32.v4p4i32(<4 x i32 addrspace(4)*>, i32, <4 x i1>, <4 x i32>) ++ ++declare void @llvm.masked.scatter.v4i32.v4p4i32(<4 x i32>, <4 x i32 addrspace(4)*>, i32, <4 x i1>) ++ ++!llvm.module.flags = !{!0} ++!opencl.spir.version = !{!1} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 1, i32 2} +-- +2.20.1 + diff --git a/patches/0007-Backport-to-15-Translate-llvm.loop.unroll.full-metad.patch b/patches/0007-Backport-to-15-Translate-llvm.loop.unroll.full-metad.patch new file mode 100644 index 0000000..246ceb3 --- /dev/null +++ b/patches/0007-Backport-to-15-Translate-llvm.loop.unroll.full-metad.patch @@ -0,0 +1,575 @@ +From 40c693bca9392026442c395bfa86a231e57eb5d4 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 8 Nov 2022 21:32:27 +0100 +Subject: [PATCH 07/79] [Backport to 15] Translate llvm.loop.unroll.full + metadata (#1673) + +It can be generated via #pragma clang unroll(full) pragma. +llvm.loop.unroll.full means attempt to do full unroll of the +loop and disable the unrolling if the trip count is not known +at compile time. + +Unroll mask to which it was previously mapped doesn't much the +description. + +The way the patch represents it in SPIR-V is: + Unroll mask + PartialCount mask with '1' parameter + +This patch also removes some overtesting for unroll metadata. + +This backports: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/1664 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVReader.cpp | 10 +- + lib/SPIRV/SPIRVWriter.cpp | 12 ++- + test/DebugInfo/DebugControlFlow.cl | 4 +- + .../DebugInfo/DebugUnstructuredControlFlow.cl | 4 +- + test/OpLoopMergeDontUnroll.spt | 92 ------------------- + test/OpLoopMergeDontUnrollHint1.spt | 88 ------------------ + test/OpLoopMergePartialUnroll.spt | 88 ------------------ + test/OpLoopMergeUnroll.spt | 89 ------------------ + test/transcoding/LoopUnroll.ll | 38 ++++++++ + 9 files changed, 59 insertions(+), 366 deletions(-) + delete mode 100644 test/OpLoopMergeDontUnroll.spt + delete mode 100644 test/OpLoopMergeDontUnrollHint1.spt + delete mode 100644 test/OpLoopMergePartialUnroll.spt + delete mode 100644 test/OpLoopMergeUnroll.spt + +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 500bebb9..0209ccfb 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -745,7 +745,7 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM, + // i.e. check smaller-numbered bits first. + // Unroll and UnrollCount loop controls can't be applied simultaneously with + // DontUnroll loop control. +- if (LC & LoopControlUnrollMask) ++ if (LC & LoopControlUnrollMask && !(LC & LoopControlPartialCountMask)) + Metadata.push_back(getMetadataFromName("llvm.loop.unroll.enable")); + else if (LC & LoopControlDontUnrollMask) + Metadata.push_back(getMetadataFromName("llvm.loop.unroll.disable")); +@@ -783,9 +783,11 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM, + "Missing loop control parameter!"); + } + if (LC & LoopControlPartialCountMask && !(LC & LoopControlDontUnrollMask)) { +- // If unroll factor is set as '1' - disable loop unrolling +- if (1 == LoopControlParameters[NumParam]) +- Metadata.push_back(getMetadataFromName("llvm.loop.unroll.disable")); ++ // If unroll factor is set as '1' and Unroll mask is applied attempt to do ++ // full unrolling and disable it if the trip count is not known at compile ++ // time. ++ if (1 == LoopControlParameters[NumParam] && (LC & LoopControlUnrollMask)) ++ Metadata.push_back(getMetadataFromName("llvm.loop.unroll.full")); + else + Metadata.push_back(llvm::MDNode::get( + *Context, +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 3593375a..b4d7f33f 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -1393,8 +1393,18 @@ LLVMToSPIRVBase::getLoopControl(const BranchInst *Branch, + // appear first. + if (S == "llvm.loop.unroll.disable") + LoopControl |= spv::LoopControlDontUnrollMask; +- else if (S == "llvm.loop.unroll.full" || S == "llvm.loop.unroll.enable") ++ else if (S == "llvm.loop.unroll.enable") + LoopControl |= spv::LoopControlUnrollMask; ++ // Attempt to do full unroll of the loop and disable unrolling if the trip ++ // count is not known at compile time by setting PartialCount to 1 ++ else if (S == "llvm.loop.unroll.full") { ++ LoopControl |= spv::LoopControlUnrollMask; ++ if (BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)) { ++ BM->setMinSPIRVVersion(VersionNumber::SPIRV_1_4); ++ ParametersToSort.emplace_back(spv::LoopControlPartialCountMask, 1); ++ LoopControl |= spv::LoopControlPartialCountMask; ++ } ++ } + // PartialCount must not be used with the DontUnroll bit + else if (S == "llvm.loop.unroll.count" && + !(LoopControl & LoopControlDontUnrollMask)) { +diff --git a/test/DebugInfo/DebugControlFlow.cl b/test/DebugInfo/DebugControlFlow.cl +index ffe963b2..4224f23b 100644 +--- a/test/DebugInfo/DebugControlFlow.cl ++++ b/test/DebugInfo/DebugControlFlow.cl +@@ -14,11 +14,11 @@ + kernel + void sample() { + int arr[10]; +- #pragma clang loop unroll(full) ++ #pragma clang loop unroll(enable) + for (int i = 0; i < 10; i++) + arr[i] = 0; + int j = 0; +- #pragma clang loop unroll(full) ++ #pragma clang loop unroll(enable) + do { + arr[j] = 0; + } while (j++ < 10); +diff --git a/test/DebugInfo/DebugUnstructuredControlFlow.cl b/test/DebugInfo/DebugUnstructuredControlFlow.cl +index 344fcc1c..cb85eba8 100644 +--- a/test/DebugInfo/DebugUnstructuredControlFlow.cl ++++ b/test/DebugInfo/DebugUnstructuredControlFlow.cl +@@ -18,9 +18,9 @@ void sample() { + // Check that all Line items are retained + // CHECK-SPIRV: Line [[File:[0-9]+]] 15 0 + // Loop control +-// CHECK-SPIRV: 2 LoopControlINTEL 1 ++// CHECK-SPIRV: LoopControlINTEL 257 1 + // CHECK-SPIRV-NEXT: Branch + + // CHECK-LLVM: br label %{{.*}}, !dbg !{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] + // CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} +-// CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.enable"} ++// CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.full"} +diff --git a/test/OpLoopMergeDontUnroll.spt b/test/OpLoopMergeDontUnroll.spt +deleted file mode 100644 +index 44e7d67c..00000000 +--- a/test/OpLoopMergeDontUnroll.spt ++++ /dev/null +@@ -1,92 +0,0 @@ +-119734787 65536 458752 46 0 +-2 Capability Addresses +-2 Capability Linkage +-2 Capability Kernel +-2 Capability Int64 +-3 MemoryModel 2 2 +-11 EntryPoint 6 1 "loop_merge_branch_dont_unroll" +-3 Source 3 102000 +-3 Name 2 "res" +-3 Name 3 "in" +-3 Name 4 "rep" +-3 Name 5 "num" +-4 Decorate 6 FuncParamAttr 5 +-2 DecorationGroup 6 +-4 Decorate 7 BuiltIn 28 +-3 Decorate 7 Constant +-11 Decorate 7 LinkageAttributes "__spirv_GlobalInvocationId" Import +-4 GroupDecorate 6 2 3 +-4 TypeInt 8 64 0 +-4 TypeInt 14 32 0 +-5 Constant 8 11 32 0 +-4 Constant 14 15 0 +-4 Constant 14 16 1 +-4 TypeVector 9 8 3 +-4 TypePointer 10 0 9 +-2 TypeBool 12 +-2 TypeVoid 13 +-4 TypePointer 17 5 14 +-4 TypePointer 18 7 14 +-7 TypeFunction 19 13 17 17 14 14 +-4 Variable 10 7 0 +- +-5 Function 13 1 0 19 +-3 FunctionParameter 17 2 +-3 FunctionParameter 17 3 +-3 FunctionParameter 14 4 +-3 FunctionParameter 14 5 +- +-2 Label 20 +-4 Variable 18 26 7 +-4 Variable 18 27 7 +-6 Load 9 21 7 2 0 +-5 CompositeExtract 8 22 21 0 +-5 ShiftLeftLogical 8 23 22 11 +-5 ShiftRightArithmetic 8 24 23 11 +-4 SConvert 14 25 24 +-5 Store 26 15 2 4 +-5 Store 27 15 2 4 +-2 Branch 28 +- +-2 Label 28 +-4 LoopMerge 29 30 2 +-2 Branch 31 +- +-2 Label 31 +-4 Load 14 32 27 +-5 SLessThan 12 33 32 4 +-4 BranchConditional 33 34 29 +- +-2 Label 34 +-4 Load 14 35 27 +-5 IMul 14 36 35 5 +-5 IAdd 14 37 25 36 +-5 InBoundsPtrAccessChain 17 38 3 37 +-4 Load 14 39 38 +-4 Load 14 40 26 +-5 IAdd 14 41 40 39 +-5 Store 26 41 2 4 +-2 Branch 30 +- +-2 Label 30 +-4 Load 14 42 27 +-5 IAdd 14 43 42 16 +-3 Store 27 43 +-2 Branch 28 +- +-2 Label 29 +-4 Load 14 44 26 +-5 InBoundsPtrAccessChain 17 45 2 24 +-5 Store 45 44 2 4 +-1 Return +- +-1 FunctionEnd +- +-; RUN: llvm-spirv %s -to-binary -o %t.spv +-; RUN: spirv-val %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.bc +-; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM +- +-; CHECK-LLVM: br label %{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] +-; CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll_disable:[0-9]+]]} +-; CHECK-LLVM: ![[MD_unroll_disable]] = !{!"llvm.loop.unroll.disable"} +diff --git a/test/OpLoopMergeDontUnrollHint1.spt b/test/OpLoopMergeDontUnrollHint1.spt +deleted file mode 100644 +index 59b3da40..00000000 +--- a/test/OpLoopMergeDontUnrollHint1.spt ++++ /dev/null +@@ -1,88 +0,0 @@ +-119734787 65536 458752 45 0 +-2 Capability Addresses +-2 Capability Linkage +-2 Capability Kernel +-2 Capability Int64 +-3 MemoryModel 2 2 +-13 EntryPoint 6 1 "loop_merge_branch_conditional_unroll" +-3 Source 3 102000 +-3 Name 2 "res" +-3 Name 3 "in" +-3 Name 4 "rep" +-3 Name 5 "num" +-4 Decorate 6 FuncParamAttr 5 +-2 DecorationGroup 6 +-4 Decorate 7 BuiltIn 28 +-3 Decorate 7 Constant +-11 Decorate 7 LinkageAttributes "__spirv_GlobalInvocationId" Import +-4 GroupDecorate 6 2 3 +-4 TypeInt 8 64 0 +-4 TypeInt 14 32 1 +-5 Constant 8 11 32 0 +-4 Constant 14 15 0 +-4 Constant 14 16 1 +-4 TypeVector 9 8 3 +-4 TypePointer 10 0 9 +-2 TypeBool 12 +-2 TypeVoid 13 +-4 TypePointer 17 5 14 +-4 TypePointer 18 7 14 +-7 TypeFunction 19 13 17 17 14 14 +-4 Variable 10 7 0 +- +-5 Function 13 1 0 19 +-3 FunctionParameter 17 2 +-3 FunctionParameter 17 3 +-3 FunctionParameter 14 4 +-3 FunctionParameter 14 5 +- +-2 Label 20 +-6 Load 9 21 7 2 0 +-5 CompositeExtract 8 22 21 0 +-5 ShiftLeftLogical 8 23 22 11 +-5 ShiftRightArithmetic 8 24 23 11 +-4 SConvert 14 25 24 +-4 Variable 18 26 7 +-4 Variable 18 27 7 +-5 Store 26 15 2 4 +-5 Store 27 15 2 4 +-2 Branch 28 +- +-2 Label 28 +-4 Load 14 29 27 +-5 SLessThan 12 30 29 4 +-5 LoopMerge 31 32 256 1 +-4 BranchConditional 30 33 31 +- +-2 Label 33 +-4 Load 14 34 27 +-5 IMul 14 35 34 5 +-5 IAdd 14 36 25 35 +-5 InBoundsPtrAccessChain 17 37 3 36 +-4 Load 14 38 37 +-4 Load 14 39 26 +-5 IAdd 14 40 39 38 +-5 Store 26 40 2 4 +-2 Branch 32 +- +-2 Label 32 +-4 Load 14 41 27 +-5 IAdd 14 42 41 16 +-3 Store 27 42 +-2 Branch 28 +- +-2 Label 31 +-4 Load 14 43 26 +-5 InBoundsPtrAccessChain 17 44 2 24 +-5 Store 44 43 2 4 +-1 Return +- +-1 FunctionEnd +- +-; RUN: llvm-spirv %s -to-binary -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.bc +-; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM +- +-; CHECK-LLVM: br label %{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] +-; CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} +-; CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.disable"} +diff --git a/test/OpLoopMergePartialUnroll.spt b/test/OpLoopMergePartialUnroll.spt +deleted file mode 100644 +index 9118fc63..00000000 +--- a/test/OpLoopMergePartialUnroll.spt ++++ /dev/null +@@ -1,88 +0,0 @@ +-119734787 65536 458752 45 0 +-2 Capability Addresses +-2 Capability Linkage +-2 Capability Kernel +-2 Capability Int64 +-3 MemoryModel 2 2 +-13 EntryPoint 6 1 "loop_merge_branch_conditional_unroll" +-3 Source 3 102000 +-3 Name 2 "res" +-3 Name 3 "in" +-3 Name 4 "rep" +-3 Name 5 "num" +-4 Decorate 6 FuncParamAttr 5 +-2 DecorationGroup 6 +-4 Decorate 7 BuiltIn 28 +-3 Decorate 7 Constant +-11 Decorate 7 LinkageAttributes "__spirv_GlobalInvocationId" Import +-4 GroupDecorate 6 2 3 +-4 TypeInt 8 64 0 +-4 TypeInt 14 32 1 +-5 Constant 8 11 32 0 +-4 Constant 14 15 0 +-4 Constant 14 16 1 +-4 TypeVector 9 8 3 +-4 TypePointer 10 0 9 +-2 TypeBool 12 +-2 TypeVoid 13 +-4 TypePointer 17 5 14 +-4 TypePointer 18 7 14 +-7 TypeFunction 19 13 17 17 14 14 +-4 Variable 10 7 0 +- +-5 Function 13 1 0 19 +-3 FunctionParameter 17 2 +-3 FunctionParameter 17 3 +-3 FunctionParameter 14 4 +-3 FunctionParameter 14 5 +- +-2 Label 20 +-6 Load 9 21 7 2 0 +-5 CompositeExtract 8 22 21 0 +-5 ShiftLeftLogical 8 23 22 11 +-5 ShiftRightArithmetic 8 24 23 11 +-4 SConvert 14 25 24 +-4 Variable 18 26 7 +-4 Variable 18 27 7 +-5 Store 26 15 2 4 +-5 Store 27 15 2 4 +-2 Branch 28 +- +-2 Label 28 +-4 Load 14 29 27 +-5 SLessThan 12 30 29 4 +-5 LoopMerge 31 32 256 4 +-4 BranchConditional 30 33 31 +- +-2 Label 33 +-4 Load 14 34 27 +-5 IMul 14 35 34 5 +-5 IAdd 14 36 25 35 +-5 InBoundsPtrAccessChain 17 37 3 36 +-4 Load 14 38 37 +-4 Load 14 39 26 +-5 IAdd 14 40 39 38 +-5 Store 26 40 2 4 +-2 Branch 32 +- +-2 Label 32 +-4 Load 14 41 27 +-5 IAdd 14 42 41 16 +-3 Store 27 42 +-2 Branch 28 +- +-2 Label 31 +-4 Load 14 43 26 +-5 InBoundsPtrAccessChain 17 44 2 24 +-5 Store 44 43 2 4 +-1 Return +- +-1 FunctionEnd +- +-; RUN: llvm-spirv %s -to-binary -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.bc +-; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM +- +-; CHECK-LLVM: br label %{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] +-; CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} +-; CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.count", i32 4} +diff --git a/test/OpLoopMergeUnroll.spt b/test/OpLoopMergeUnroll.spt +deleted file mode 100644 +index d976168d..00000000 +--- a/test/OpLoopMergeUnroll.spt ++++ /dev/null +@@ -1,89 +0,0 @@ +-119734787 65536 458752 45 0 +-2 Capability Addresses +-2 Capability Linkage +-2 Capability Kernel +-2 Capability Int64 +-3 MemoryModel 2 2 +-13 EntryPoint 6 1 "loop_merge_branch_conditional_unroll" +-3 Source 3 102000 +-3 Name 2 "res" +-3 Name 3 "in" +-3 Name 4 "rep" +-3 Name 5 "num" +-4 Decorate 6 FuncParamAttr 5 +-2 DecorationGroup 6 +-4 Decorate 7 BuiltIn 28 +-3 Decorate 7 Constant +-11 Decorate 7 LinkageAttributes "__spirv_GlobalInvocationId" Import +-4 GroupDecorate 6 2 3 +-4 TypeInt 8 64 0 +-4 TypeInt 14 32 0 +-5 Constant 8 11 32 0 +-4 Constant 14 15 0 +-4 Constant 14 16 1 +-4 TypeVector 9 8 3 +-4 TypePointer 10 0 9 +-2 TypeBool 12 +-2 TypeVoid 13 +-4 TypePointer 17 5 14 +-4 TypePointer 18 7 14 +-7 TypeFunction 19 13 17 17 14 14 +-4 Variable 10 7 0 +- +-5 Function 13 1 0 19 +-3 FunctionParameter 17 2 +-3 FunctionParameter 17 3 +-3 FunctionParameter 14 4 +-3 FunctionParameter 14 5 +- +-2 Label 20 +-4 Variable 18 26 7 +-4 Variable 18 27 7 +-6 Load 9 21 7 2 0 +-5 CompositeExtract 8 22 21 0 +-5 ShiftLeftLogical 8 23 22 11 +-5 ShiftRightArithmetic 8 24 23 11 +-4 SConvert 14 25 24 +-5 Store 26 15 2 4 +-5 Store 27 15 2 4 +-2 Branch 28 +- +-2 Label 28 +-4 Load 14 29 27 +-5 SLessThan 12 30 29 4 +-4 LoopMerge 31 32 1 +-4 BranchConditional 30 33 31 +- +-2 Label 33 +-4 Load 14 34 27 +-5 IMul 14 35 34 5 +-5 IAdd 14 36 25 35 +-5 InBoundsPtrAccessChain 17 37 3 36 +-4 Load 14 38 37 +-4 Load 14 39 26 +-5 IAdd 14 40 39 38 +-5 Store 26 40 2 4 +-2 Branch 32 +- +-2 Label 32 +-4 Load 14 41 27 +-5 IAdd 14 42 41 16 +-3 Store 27 42 +-2 Branch 28 +- +-2 Label 31 +-4 Load 14 43 26 +-5 InBoundsPtrAccessChain 17 44 2 24 +-5 Store 44 43 2 4 +-1 Return +- +-1 FunctionEnd +- +-; RUN: llvm-spirv %s -to-binary -o %t.spv +-; RUN: spirv-val %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.bc +-; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM +- +-; CHECK-LLVM: br label %{{[0-9]+}}, !llvm.loop ![[MD:[0-9]+]] +-; CHECK-LLVM: ![[MD]] = distinct !{![[MD]], ![[MD_unroll:[0-9]+]]} +-; CHECK-LLVM: ![[MD_unroll]] = !{!"llvm.loop.unroll.enable"} +diff --git a/test/transcoding/LoopUnroll.ll b/test/transcoding/LoopUnroll.ll +index 0bd924d8..832d5388 100644 +--- a/test/transcoding/LoopUnroll.ll ++++ b/test/transcoding/LoopUnroll.ll +@@ -35,6 +35,16 @@ + ; + ; Command: + ; clang -cc1 -triple spir64 -O0 LoopUnroll.cl -emit-llvm -o /test/SPIRV/transcoding/LoopUnroll.ll ++; ++; unroll_full() test was generated from the following source with -O2 ++; void foo(); ++; ++; void unroll_full() { ++; #pragma clang unroll(full) ++; for (int i = 0; i != 1024; ++i) { ++; foo(); ++; } ++; } + + ; RUN: llvm-as < %s > %t.bc + ; RUN: llvm-spirv %t.bc -o %t.spv +@@ -243,6 +253,30 @@ for.end: ; preds = %for.cond + ret void + } + ++; CHECK-SPIRV: Function ++; CHECK-SPIRV: Label ++; CHECK-SPIRV: Branch [[#Header:]] ++; CHECK-SPIRV: Label [[#Return:]] ++; CHECK-SPIRV: LoopMerge [[#Return]] [[#Header]] 257 1 ++; CHECK-SPIRV: BranchConditional [[#]] [[#Return]] [[#Header]] ++; Function Attrs: noinline nounwind optnone ++define spir_func void @unroll_full() { ++ br label %2 ++ ++1: ; preds = %2 ++ ret void ++ ++2: ; preds = %0, %2 ++ %3 = phi i32 [ 0, %0 ], [ %4, %2 ] ++ tail call void @_Z3foov() ++ %4 = add nuw nsw i32 %3, 1 ++ %5 = icmp eq i32 %4, 1024 ++ ; CHECK-LLVM: br i1 %[[#]], label %[[#]], label %[[#]], !llvm.loop ![[#FULL:]] ++ br i1 %5, label %1, label %2, !llvm.loop !11 ++} ++ ++declare void @_Z3foov() ++ + attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} +@@ -265,6 +299,8 @@ attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-ma + !8 = !{!"llvm.loop.unroll.count", i32 8} + !9 = distinct !{!9, !10} + !10 = !{!"llvm.loop.unroll.enable"} ++!11 = distinct !{!11, !12} ++!12 = !{!"llvm.loop.unroll.full"} + + ; CHECK-LLVM: ![[#UNROLLDISABLE]] = distinct !{![[#UNROLLDISABLE]], ![[#DISABLE:]]} + ; CHECK-LLVM: ![[#DISABLE]] = !{!"llvm.loop.unroll.disable"} +@@ -273,3 +309,5 @@ attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-ma + ; CHECK-LLVM: ![[#UNROLLENABLE1]] = distinct !{![[#UNROLLENABLE1]], ![[#ENABLE:]]} + ; CHECK-LLVM: ![[#ENABLE]] = !{!"llvm.loop.unroll.enable"} + ; CHECK-LLVM: ![[#UNROLLENABLE2]] = distinct !{![[#UNROLLENABLE2]], ![[#ENABLE]]} ++; CHECK-LLVM: ![[#FULL]] = distinct !{![[#FULL]], ![[#UNROLLFULL:]]} ++; CHECK-LLVM: ![[#UNROLLFULL]] = !{!"llvm.loop.unroll.full"} +-- +2.20.1 + diff --git a/patches/0008-Backport-to-15-Implement-SPV_INTEL_tensor_float32_co.patch b/patches/0008-Backport-to-15-Implement-SPV_INTEL_tensor_float32_co.patch new file mode 100644 index 0000000..aa7a3aa --- /dev/null +++ b/patches/0008-Backport-to-15-Implement-SPV_INTEL_tensor_float32_co.patch @@ -0,0 +1,223 @@ +From 7e583b112d792af53ad9cbc87b42d7918bccf37e Mon Sep 17 00:00:00 2001 +From: Stanley Gambarin +Date: Fri, 11 Nov 2022 02:31:34 -0800 +Subject: [PATCH 08/79] [Backport to 15] Implement + SPV_INTEL_tensor_float32_conversion extension (#1656) (#1700) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This extension adds conversion instruction from float to tensor float (TF32) +data format. TF32 uses 1 bit for a sign, 8 bits for an exponent and 10 bits +for a fraction. This extension doesn’t introduce TF32 type in SPIR-V, instead +instruction below uses 32-bit float type to represent TF32 value. + +Spec: https://github.com/intel/llvm/pull/6990 + +Co-authored-by: Dmitry Sidorov +--- + include/LLVMSPIRVExtensions.inc | 3 +- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 58 +++++++++++++++++++ + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 2 + + lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h | 3 +- + lib/SPIRV/libSPIRV/spirv_internal.hpp | 5 ++ + .../convert_tensor_float32.ll | 50 ++++++++++++++++ + 6 files changed, 119 insertions(+), 2 deletions(-) + create mode 100644 test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 4f970d2a..edad4ab4 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -54,4 +54,5 @@ EXT(SPV_INTEL_global_variable_decorations) + EXT(SPV_INTEL_non_constant_addrspace_printf) + EXT(SPV_INTEL_complex_float_mul_div) + EXT(SPV_INTEL_split_barrier) +-EXT(SPV_INTEL_masked_gather_scatter) ++EXT(SPV_INTEL_tensor_float32_conversion) ++EXT(SPV_INTEL_masked_gather_scatter) +\ No newline at end of file +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 2ffd4c3a..cd91461c 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3414,6 +3414,64 @@ _SPIRV_OP(ComplexFMulINTEL) + _SPIRV_OP(ComplexFDivINTEL) + #undef _SPIRV_OP + ++template ++class SPIRVTensorFloat32ConversionINTELInstBase : public SPIRVUnaryInst { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(internal::CapabilityTensorFloat32ConversionINTEL); ++ } ++ ++ llvm::Optional getRequiredExtension() const override { ++ return ExtensionID::SPV_INTEL_tensor_float32_conversion; ++ } ++ ++ void validate() const override { ++ SPIRVUnaryInst::validate(); ++ ++ SPIRVType *ResCompTy = this->getType(); ++ SPIRVWord ResCompCount = 1; ++ if (ResCompTy->isTypeVector()) { ++ ResCompCount = ResCompTy->getVectorComponentCount(); ++ ResCompTy = ResCompTy->getVectorComponentType(); ++ } ++ ++ // validate is a const method, whilst getOperand is non-const method ++ // because it may call a method of class Module that may modify LiteralMap ++ // of Module field. That modification is not impacting validate method for ++ // these instructions, so const_cast is safe here. ++ using SPVTF32ConvTy = SPIRVTensorFloat32ConversionINTELInstBase; ++ SPIRVValue *Input = const_cast(this)->getOperand(0); ++ ++ SPIRVType *InCompTy = Input->getType(); ++ SPIRVWord InCompCount = 1; ++ if (InCompTy->isTypeVector()) { ++ InCompCount = InCompTy->getVectorComponentCount(); ++ InCompTy = InCompTy->getVectorComponentType(); ++ } ++ ++ auto InstName = OpCodeNameMap::map(OC); ++ SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); ++ ++ SPVErrLog.checkError( ++ ResCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, ++ InstName + "\nResult value must be a scalar or vector of floating-point" ++ " 32-bit type\n"); ++ SPVErrLog.checkError(InCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, ++ InstName + ++ "\nInput value must be a scalar or vector of " ++ "floating-point 32-bit type\n"); ++ SPVErrLog.checkError( ++ ResCompCount == InCompCount, SPIRVEC_InvalidInstruction, ++ InstName + "\nInput type must have the same number of components as " ++ "result type\n"); ++ } ++}; ++ ++#define _SPIRV_OP(x) \ ++ typedef SPIRVTensorFloat32ConversionINTELInstBase SPIRV##x; ++_SPIRV_OP(ConvertFToTF32INTEL) ++#undef _SPIRV_OP ++ + class SPIRVMaskedGatherScatterINTELInstBase : public SPIRVInstTemplateBase { + protected: + SPIRVCapVec getRequiredCapability() const override { +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index fd8c5790..d73fdee7 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -617,6 +617,8 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityNonConstantAddrspacePrintfINTEL, + "NonConstantAddrspacePrintfINTEL"); + add(internal::CapabilityComplexFloatMulDivINTEL, "ComplexFloatMulDivINTEL"); ++ add(internal::CapabilityTensorFloat32ConversionINTEL, ++ "TensorFloat32ConversionINTEL"); + add(internal::CapabilityMaskedGatherScatterINTEL, "MaskedGatherScatterINTEL"); + } + SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +index 0ed0d855..b5e4cefd 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +@@ -13,5 +13,6 @@ _SPIRV_OP_INTERNAL(JointMatrixWorkItemLengthINTEL, + internal::OpJointMatrixWorkItemLengthINTEL) + _SPIRV_OP_INTERNAL(ComplexFMulINTEL, internal::ComplexFMulINTEL) + _SPIRV_OP_INTERNAL(ComplexFDivINTEL, internal::ComplexFDivINTEL) ++_SPIRV_OP_INTERNAL(ConvertFToTF32INTEL, internal::ConvertFToTF32INTEL) + _SPIRV_OP_INTERNAL(MaskedGatherINTEL, internal::OpMaskedGatherINTEL) +-_SPIRV_OP_INTERNAL(MaskedScatterINTEL, internal::OpMaskedScatterINTEL) ++_SPIRV_OP_INTERNAL(MaskedScatterINTEL, internal::OpMaskedScatterINTEL) +\ No newline at end of file +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index 9073eccd..3938ac4c 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -46,6 +46,7 @@ enum InternalOp { + IOpJointMatrixWorkItemLengthINTEL = 6410, + IOpComplexFMulINTEL = 6415, + IOpComplexFDivINTEL = 6416, ++ IOpConvertFToTF32INTEL = 6426, + IOpMaskedGatherINTEL = 6428, + IOpMaskedScatterINTEL = 6429, + IOpPrev = OpMax - 2, +@@ -79,6 +80,7 @@ enum InternalCapability { + ICapGlobalVariableDecorationsINTEL = 6146, + ICapabilityNonConstantAddrspacePrintfINTEL = 6411, + ICapabilityComplexFloatMulDivINTEL = 6414, ++ ICapabilityTensorFloat32ConversionINTEL = 6425, + ICapabilityMaskedGatherScatterINTEL = 6427 + }; + +@@ -125,6 +127,9 @@ _SPIRV_OP(Capability, ComplexFloatMulDivINTEL) + _SPIRV_OP(Op, ComplexFMulINTEL) + _SPIRV_OP(Op, ComplexFDivINTEL) + ++_SPIRV_OP(Capability, TensorFloat32ConversionINTEL) ++_SPIRV_OP(Op, ConvertFToTF32INTEL) ++ + _SPIRV_OP(Capability, MaskedGatherScatterINTEL) + _SPIRV_OP(Op, MaskedGatherINTEL) + _SPIRV_OP(Op, MaskedScatterINTEL) +diff --git a/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll b/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll +new file mode 100644 +index 00000000..1f027069 +--- /dev/null ++++ b/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll +@@ -0,0 +1,50 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_tensor_float32_conversion ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.spv -o %t.rev.bc -r -emit-opaque-pointers --spirv-target-env=SPV-IR ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_INTEL_tensor_float32_conversion ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-SPIRV: Capability TensorFloat32ConversionINTEL ++; CHECK-SPIRV: Extension "SPV_INTEL_tensor_float32_conversion" ++; CHECK-SPIRV: TypeFloat [[#FP32Ty:]] 32 ++; CHECK-SPIRV: TypeVector [[#FP32v8Ty:]] [[#FP32Ty]] 8 ++; CHECK-SPIRV: Constant [[#FP32Ty]] [[#CONST:]] 1065353216 ++ ++; CHECK-SPIRV: FunctionParameter [[#FP32Ty]] [[FP32ValId:.*]] ++; CHECK-SPIRV: FunctionParameter [[#FP32v8Ty]] [[FP32v8ValId:.*]] ++ ++; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32Ty]] [[#]] [[FP32ValId]] ++; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32v8Ty]] [[#]] [[FP32v8ValId]] ++; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32Ty]] [[#]] [[#CONST]] ++ ++; CHECK-LLVM: call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float ++; CHECK-LLVM: call spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float> ++; CHECK-LLVM: call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float 1.000000e+00) ++ ++define spir_func void @_Z2opffv8(float %a, <8 x float> %in) { ++ %1 = tail call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float %a) ++ %2 = tail call spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float> %in) ++ %3 = tail call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float 1.000000e+00) ++ ret void ++} ++ ++declare spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float) ++ ++declare spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float>) ++ ++!opencl.spir.version = !{!0} ++!spirv.Source = !{!1} ++!llvm.ident = !{!2} ++ ++!0 = !{i32 1, i32 2} ++!1 = !{i32 4, i32 100000} ++!2 = !{!"clang version 16.0.0"} +-- +2.20.1 + diff --git a/patches/0009-Backport-to-15-Fix-builtin-vars-translation.patch b/patches/0009-Backport-to-15-Fix-builtin-vars-translation.patch new file mode 100644 index 0000000..ce6b5f9 --- /dev/null +++ b/patches/0009-Backport-to-15-Fix-builtin-vars-translation.patch @@ -0,0 +1,83 @@ +From 54b5801ee7f0098543c9a8f880154d8f903f8f61 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 29 Nov 2022 13:57:59 +0100 +Subject: [PATCH 09/79] [Backport to 15] Fix builtin vars translation + +The translator was crashing in case if builin GV was accessed via +GEP without AS cast due to incorrect assumption. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVUtil.cpp | 6 ++++ + test/transcoding/builtin_vars_gep.ll | 42 ++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + create mode 100644 test/transcoding/builtin_vars_gep.ll + +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 8325b320..9ff96c36 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -2033,6 +2033,12 @@ bool lowerBuiltinVariableToCall(GlobalVariable *GV, + llvm_unreachable("Unexpected pattern!"); + } + } ++ } else if (auto *GEP = dyn_cast(UI)) { ++ GEPs.push_back(GEP); ++ for (auto *GEPUser : GEP->users()) { ++ if (!ReplaceIfLoad(GEPUser)) ++ llvm_unreachable("Unexpected pattern!"); ++ } + } else if (!ReplaceIfLoad(UI)) { + llvm_unreachable("Unexpected pattern!"); + } +diff --git a/test/transcoding/builtin_vars_gep.ll b/test/transcoding/builtin_vars_gep.ll +new file mode 100644 +index 00000000..133fcf56 +--- /dev/null ++++ b/test/transcoding/builtin_vars_gep.ll +@@ -0,0 +1,42 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.out.bc ++; RUN: llvm-dis %t.out.bc -o - | FileCheck %s --check-prefix=CHECK-OCL-IR ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv --spirv-target-env=SPV-IR -o %t.out.bc ++; RUN: llvm-dis %t.out.bc -o - | FileCheck %s --check-prefix=CHECK-SPV-IR ++ ++; Check that produced builtin-call-based SPV-IR is recognized by the translator ++; RUN: llvm-spirv -spirv-text %t.out.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++ ++; CHECK-SPIRV: Decorate [[Id:[0-9]+]] BuiltIn 28 ++; CHECK-SPIRV: Variable {{[0-9]+}} [[Id:[0-9]+]] ++ ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir-unknown-unknown" ++ ++@__spirv_BuiltInGlobalInvocationId = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32 ++ ++; Function Attrs: nounwind readnone ++define spir_kernel void @f() { ++entry: ++ %0 = load i64, i64 addrspace(1)* getelementptr (<3 x i64>, <3 x i64> addrspace(1)* @__spirv_BuiltInGlobalInvocationId, i64 0, i64 0), align 32 ++ ; CHECK-OCL-IR: %[[#ID1:]] = call spir_func i64 @_Z13get_global_idj(i32 0) ++ ; CHECK-OCL-IR: %[[#VEC1:]] = insertelement <3 x i64> undef, i64 %[[#ID1]], i32 0 ++ ; CHECK-OCL-IR: %[[#ID2:]] = call spir_func i64 @_Z13get_global_idj(i32 1) ++ ; CHECK-OCL-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1 ++ ; CHECK-OCL-IR: %[[#ID3:]] = call spir_func i64 @_Z13get_global_idj(i32 2) ++ ; CHECK-OCL-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2 ++ ; CHECK-OCL-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0 ++ ++ ; CHECK-SPV-IR: %[[#ID1:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 0) ++ ; CHECK-SPV-IR: %[[#VEC1:]] = insertelement <3 x i64> undef, i64 %[[#ID1]], i32 0 ++ ; CHECK-SPV-IR: %[[#ID2:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1) ++ ; CHECK-SPV-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1 ++ ; CHECK-SPV-IR: %[[#ID3:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 2) ++ ; CHECK-SPV-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2 ++ ; CHECK-SPV-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0 ++ ++ ret void ++} +-- +2.20.1 + diff --git a/patches/0010-Backport-to-15-Relax-OpenCL-extended-instruction-res.patch b/patches/0010-Backport-to-15-Relax-OpenCL-extended-instruction-res.patch new file mode 100644 index 0000000..6ebb65d --- /dev/null +++ b/patches/0010-Backport-to-15-Relax-OpenCL-extended-instruction-res.patch @@ -0,0 +1,276 @@ +From 78ad93b9952cb78889b86e9aa390d013c49dca0b Mon Sep 17 00:00:00 2001 +From: Stanley Gambarin +Date: Thu, 8 Dec 2022 07:01:41 -0800 +Subject: [PATCH 10/79] [Backport to 15] Relax OpenCL extended instruction + restrictions (#1755) + +* [Backport to 15] Relax OpenCL extended instruction restrictions (#1724) + +When VectorAnyINTEL capability is enabled, OpenCL extended instructions +are able to work on vector types with any number of components greater +then or equal to 2. + +* [Backport to 15] Translate LLVM intrinsics into native_* OpenCL instructions (#1729) + +When an intrinsic function is called with `afn` flag, it's allowed to +substitute an approximate calculations. So the translator can emit +native versions of OpenCL extended instructions. + +Co-authored-by: Victor Mustya +--- + lib/SPIRV/SPIRVUtil.cpp | 6 +- + lib/SPIRV/SPIRVWriter.cpp | 77 +++++++++++++------ + test/llvm-intrinsics/sqrt.ll | 5 +- + ...wer-non-standard-vec-intrinsic-with-ext.ll | 42 ++++++++++ + 4 files changed, 105 insertions(+), 25 deletions(-) + create mode 100644 test/lower-non-standard-vec-intrinsic-with-ext.ll + +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 9ff96c36..72e9eb5d 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1829,7 +1829,8 @@ bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) { + Ty = VecTy->getElementType(); + } + if ((!Ty->isFloatTy() && !Ty->isDoubleTy() && !Ty->isHalfTy()) || +- ((NumElems > 4) && (NumElems != 8) && (NumElems != 16))) { ++ (!BM->hasCapability(CapabilityVectorAnyINTEL) && ++ ((NumElems > 4) && (NumElems != 8) && (NumElems != 16)))) { + BM->SPIRVCK( + false, InvalidFunctionCall, II->getCalledOperand()->getName().str()); + return false; +@@ -1844,7 +1845,8 @@ bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) { + Ty = VecTy->getElementType(); + } + if ((!Ty->isIntegerTy()) || +- ((NumElems > 4) && (NumElems != 8) && (NumElems != 16))) { ++ (!BM->hasCapability(CapabilityVectorAnyINTEL) && ++ ((NumElems > 4) && (NumElems != 8) && (NumElems != 16)))) { + BM->SPIRVCK( + false, InvalidFunctionCall, II->getCalledOperand()->getName().str()); + } +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index b4d7f33f..f219fcc0 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -1613,7 +1613,7 @@ void transAliasingMemAccess(SPIRVModule *BM, MDNode *AliasingListMD, + std::vector &MemoryAccess, + SPIRVWord MemAccessMask) { + if (!BM->isAllowedToUseExtension( +- ExtensionID::SPV_INTEL_memory_access_aliasing)) ++ ExtensionID::SPV_INTEL_memory_access_aliasing)) + return; + auto *MemAliasList = addMemAliasingINTELInstructions(BM, AliasingListMD); + if (!MemAliasList) +@@ -2543,20 +2543,17 @@ bool LLVMToSPIRVBase::transAlign(Value *V, SPIRVValue *BV) { + void LLVMToSPIRVBase::transMemAliasingINTELDecorations(Instruction *Inst, + SPIRVValue *BV) { + if (!BM->isAllowedToUseExtension( +- ExtensionID::SPV_INTEL_memory_access_aliasing)) ++ ExtensionID::SPV_INTEL_memory_access_aliasing)) + return; +- if (MDNode *AliasingListMD = +- Inst->getMetadata(LLVMContext::MD_alias_scope)) { +- auto *MemAliasList = +- addMemAliasingINTELInstructions(BM, AliasingListMD); ++ if (MDNode *AliasingListMD = Inst->getMetadata(LLVMContext::MD_alias_scope)) { ++ auto *MemAliasList = addMemAliasingINTELInstructions(BM, AliasingListMD); + if (!MemAliasList) + return; + BV->addDecorate(new SPIRVDecorateId(DecorationAliasScopeINTEL, BV, + MemAliasList->getId())); + } + if (MDNode *AliasingListMD = Inst->getMetadata(LLVMContext::MD_noalias)) { +- auto *MemAliasList = +- addMemAliasingINTELInstructions(BM, AliasingListMD); ++ auto *MemAliasList = addMemAliasingINTELInstructions(BM, AliasingListMD); + if (!MemAliasList) + return; + BV->addDecorate( +@@ -3318,6 +3315,38 @@ static SPIRVWord getBuiltinIdForIntrinsic(Intrinsic::ID IID) { + } + } + ++static SPIRVWord getNativeBuiltinIdForIntrinsic(Intrinsic::ID IID) { ++ switch (IID) { ++ case Intrinsic::cos: ++ return OpenCLLIB::Native_cos; ++ case Intrinsic::exp: ++ return OpenCLLIB::Native_exp; ++ case Intrinsic::exp2: ++ return OpenCLLIB::Native_exp2; ++ case Intrinsic::log: ++ return OpenCLLIB::Native_log; ++ case Intrinsic::log10: ++ return OpenCLLIB::Native_log10; ++ case Intrinsic::log2: ++ return OpenCLLIB::Native_log2; ++ case Intrinsic::sin: ++ return OpenCLLIB::Native_sin; ++ case Intrinsic::sqrt: ++ return OpenCLLIB::Native_sqrt; ++ default: ++ return getBuiltinIdForIntrinsic(IID); ++ } ++} ++ ++static bool allowsApproxFunction(IntrinsicInst *II) { ++ auto *Ty = II->getType(); ++ // OpenCL native_* built-ins only support single precision data type ++ return II->hasApproxFunc() && ++ (Ty->isFloatTy() || ++ (Ty->isVectorTy() && ++ cast(Ty)->getElementType()->isFloatTy())); ++} ++ + SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + SPIRVBasicBlock *BB) { + auto GetMemoryAccess = [](MemIntrinsic *MI) -> std::vector { +@@ -3342,7 +3371,8 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + // LLVM intrinsics with known translation to SPIR-V are handled here. They + // also must be registered at isKnownIntrinsic function in order to make + // -spirv-allow-unknown-intrinsics work correctly. +- switch (II->getIntrinsicID()) { ++ auto IID = II->getIntrinsicID(); ++ switch (IID) { + case Intrinsic::assume: { + // llvm.assume translation is currently supported only within + // SPV_KHR_expect_assume extension, ignore it otherwise, since it's +@@ -3379,7 +3409,9 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + case Intrinsic::trunc: { + if (!checkTypeForSPIRVExtendedInstLowering(II, BM)) + break; +- SPIRVWord ExtOp = getBuiltinIdForIntrinsic(II->getIntrinsicID()); ++ const SPIRVWord ExtOp = allowsApproxFunction(II) ++ ? getNativeBuiltinIdForIntrinsic(IID) ++ : getBuiltinIdForIntrinsic(IID); + SPIRVType *STy = transType(II->getType()); + std::vector Ops(1, transValue(II->getArgOperand(0), BB)); + return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops, +@@ -3395,7 +3427,9 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + case Intrinsic::minnum: { + if (!checkTypeForSPIRVExtendedInstLowering(II, BM)) + break; +- SPIRVWord ExtOp = getBuiltinIdForIntrinsic(II->getIntrinsicID()); ++ const SPIRVWord ExtOp = allowsApproxFunction(II) ++ ? getNativeBuiltinIdForIntrinsic(IID) ++ : getBuiltinIdForIntrinsic(IID); + SPIRVType *STy = transType(II->getType()); + std::vector Ops{transValue(II->getArgOperand(0), BB), + transValue(II->getArgOperand(1), BB)}; +@@ -3410,13 +3444,12 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + SPIRVValue *FirstArgVal = transValue(II->getArgOperand(0), BB); + SPIRVValue *SecondArgVal = transValue(II->getArgOperand(1), BB); + +- Op OC = (II->getIntrinsicID() == Intrinsic::smin) +- ? OpSLessThan +- : ((II->getIntrinsicID() == Intrinsic::smax) +- ? OpSGreaterThan +- : ((II->getIntrinsicID() == Intrinsic::umin) +- ? OpULessThan +- : OpUGreaterThan)); ++ const Op OC = ++ (IID == Intrinsic::smin) ++ ? OpSLessThan ++ : ((IID == Intrinsic::smax) ++ ? OpSGreaterThan ++ : ((IID == Intrinsic::umin) ? OpULessThan : OpUGreaterThan)); + if (auto *VecTy = dyn_cast(II->getArgOperand(0)->getType())) + BoolTy = VectorType::get(BoolTy, VecTy->getElementCount()); + SPIRVValue *Cmp = +@@ -3451,8 +3484,8 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + } + case Intrinsic::ctlz: + case Intrinsic::cttz: { +- SPIRVWord ExtOp = II->getIntrinsicID() == Intrinsic::ctlz ? OpenCLLIB::Clz +- : OpenCLLIB::Ctz; ++ const SPIRVWord ExtOp = ++ IID == Intrinsic::ctlz ? OpenCLLIB::Clz : OpenCLLIB::Ctz; + SPIRVType *Ty = transType(II->getType()); + std::vector Ops(1, transValue(II->getArgOperand(0), BB)); + return BM->addExtInst(Ty, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops, +@@ -3904,8 +3937,8 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, + else + // Other LLVM intrinsics shouldn't get to SPIRV, because they + // can't be represented in SPIRV or aren't implemented yet. +- BM->SPIRVCK( +- false, InvalidFunctionCall, II->getCalledOperand()->getName().str()); ++ BM->SPIRVCK(false, InvalidFunctionCall, ++ II->getCalledOperand()->getName().str()); + } + return nullptr; + } +diff --git a/test/llvm-intrinsics/sqrt.ll b/test/llvm-intrinsics/sqrt.ll +index 09170ea7..68e9092a 100644 +--- a/test/llvm-intrinsics/sqrt.ll ++++ b/test/llvm-intrinsics/sqrt.ll +@@ -20,9 +20,13 @@ entry: + %0 = call float @llvm.sqrt.f32(float 0x40091EB860000000) + %1 = call double @llvm.sqrt.f64(double 2.710000e+00) + %2 = call <4 x double> @llvm.sqrt.v4f64(<4 x double> ) ++ %3 = call afn float @llvm.sqrt.f32(float 0x40091EB860000000) ++ %4 = call afn double @llvm.sqrt.f64(double 2.710000e+00) + ; CHECK: ExtInst [[Float]] {{[0-9]+}} [[ExtInstSetId]] sqrt [[FloatArg]] + ; CHECK: ExtInst [[Double]] {{[0-9]+}} [[ExtInstSetId]] sqrt [[DoubleArg]] + ; CHECK: ExtInst [[Double4]] {{[0-9]+}} [[ExtInstSetId]] sqrt [[Double4Arg]] ++; CHECK: ExtInst [[Float]] {{[0-9]+}} [[ExtInstSetId]] native_sqrt [[FloatArg]] ++; CHECK: ExtInst [[Double]] {{[0-9]+}} [[ExtInstSetId]] sqrt [[DoubleArg]] + ret void + } + +@@ -43,4 +47,3 @@ attributes #1 = { nounwind readnone speculatable willreturn } + + !0 = !{i32 1, !"wchar_size", i32 4} + !1 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git b89131cdda5871731a9139664aef2b70c6d72bbd)"} +- +diff --git a/test/lower-non-standard-vec-intrinsic-with-ext.ll b/test/lower-non-standard-vec-intrinsic-with-ext.ll +new file mode 100644 +index 00000000..c38065f0 +--- /dev/null ++++ b/test/lower-non-standard-vec-intrinsic-with-ext.ll +@@ -0,0 +1,42 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: not llvm-spirv -s %t.bc ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_vector_compute %t.bc ++; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s ++ ++; CHECK: ExtInstImport [[ExtInstSetId:[0-9]+]] "OpenCL.std" ++; CHECK: TypeFloat [[Float:[0-9]+]] 32 ++; CHECK: TypeVector [[Float5:[0-9]+]] [[Float]] 5 ++ ++; ModuleID = 'lower-non-standard-vec-with-ext' ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++@Id = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32 ++ ++declare <5 x float> @llvm.sqrt.f32(<5 x float> %x) ++ ++; Function Attrs: convergent norecurse ++define dso_local spir_func <5 x float> @test_sqrt(<5 x float> %src) local_unnamed_addr #0 !sycl_explicit_simd !4 !intel_reqd_sub_group_size !6 { ++entry: ++ %res = call <5 x float> @llvm.sqrt.f32(<5 x float> %src) ++; CHECK: ExtInst [[Float5]] {{[0-9]+}} [[ExtInstSetId]] sqrt ++ ret <5 x float> %res ++} ++ ++attributes #0 = { convergent norecurse "frame-pointer"="all" "min-legal-vector-width"="256" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="lower-external-funcs-with-z.cpp" } ++ ++!llvm.module.flags = !{!0, !1} ++!opencl.spir.version = !{!2} ++!spirv.Source = !{!3} ++!opencl.used.extensions = !{!4} ++!opencl.used.optional.core.features = !{!4} ++!opencl.compiler.options = !{!4} ++!llvm.ident = !{!5} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} ++!1 = !{i32 7, !"frame-pointer", i32 2} ++!2 = !{i32 1, i32 2} ++!3 = !{i32 0, i32 100000} ++!4 = !{} ++!5 = !{!"Compiler"} ++!6 = !{i32 1} +-- +2.20.1 + diff --git a/patches/0011-Backport-to-15-Add-SPV_EXT_relaxed_printf_string_add.patch b/patches/0011-Backport-to-15-Add-SPV_EXT_relaxed_printf_string_add.patch new file mode 100644 index 0000000..0fb087e --- /dev/null +++ b/patches/0011-Backport-to-15-Add-SPV_EXT_relaxed_printf_string_add.patch @@ -0,0 +1,180 @@ +From 959c79a859e0aaba4207c7909af6456140987119 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 2 Dec 2022 14:05:05 +0100 +Subject: [PATCH 11/79] [Backport to 15] Add + SPV_EXT_relaxed_printf_string_address_space extension + +The original change: #1749 + +The extension was added in https://github.com/KhronosGroup/SPIRV-Registry/pull/148 + +Starting from this PR SPV_INTEL_non_constant_addrspace_printf will +be step by step deprecated. + +Signed-off-by: Sidorov, Dmitry +--- + include/LLVMSPIRVExtensions.inc | 3 +- + lib/SPIRV/SPIRVWriter.cpp | 18 ++-- + .../non-constant-printf.ll | 88 +++++++++++++++++++ + .../non-constant-printf.ll | 2 +- + 4 files changed, 104 insertions(+), 7 deletions(-) + create mode 100644 test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index edad4ab4..a6cf69b1 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -55,4 +55,5 @@ EXT(SPV_INTEL_non_constant_addrspace_printf) + EXT(SPV_INTEL_complex_float_mul_div) + EXT(SPV_INTEL_split_barrier) + EXT(SPV_INTEL_tensor_float32_conversion) +-EXT(SPV_INTEL_masked_gather_scatter) +\ No newline at end of file ++EXT(SPV_INTEL_masked_gather_scatter) ++EXT(SPV_EXT_relaxed_printf_string_address_space) +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index f219fcc0..fcab77cd 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -4025,18 +4025,26 @@ SPIRVValue *LLVMToSPIRVBase::transDirectCallInst(CallInst *CI, + auto *FormatStrPtr = cast(CI->getArgOperand(0)->getType()); + if (FormatStrPtr->getAddressSpace() != + SPIR::TypeAttributeEnum::ATTR_CONST) { +- if (!BM->isAllowedToUseExtension( +- ExtensionID::SPV_INTEL_non_constant_addrspace_printf)) { ++ if (BM->isAllowedToUseExtension( ++ ExtensionID::SPV_EXT_relaxed_printf_string_address_space)) { ++ BM->addExtension( ++ ExtensionID::SPV_EXT_relaxed_printf_string_address_space); ++ } else if (BM->isAllowedToUseExtension( ++ ExtensionID::SPV_INTEL_non_constant_addrspace_printf)) { ++ BM->addExtension( ++ ExtensionID::SPV_INTEL_non_constant_addrspace_printf); ++ BM->addCapability( ++ internal::CapabilityNonConstantAddrspacePrintfINTEL); ++ } else { + std::string ErrorStr = +- "The SPV_INTEL_non_constant_addrspace_printf extension should be " ++ "Either SPV_EXT_relaxed_printf_string_address_space or " ++ "SPV_INTEL_non_constant_addrspace_printf extension should be " + "allowed to translate this module, because this LLVM module " + "contains the printf function with format string, whose address " + "space is not equal to 2 (constant)."; + getErrorLog().checkError(false, SPIRVEC_RequiresExtension, CI, + ErrorStr); + } +- BM->addExtension(ExtensionID::SPV_INTEL_non_constant_addrspace_printf); +- BM->addCapability(internal::CapabilityNonConstantAddrspacePrintfINTEL); + } + } + +diff --git a/test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll b/test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +new file mode 100644 +index 00000000..d621949c +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +@@ -0,0 +1,88 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT ++ ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space,+SPV_INTEL_non_constant_addrspace_printf ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++ ++; RUN: llvm-spirv -to-binary %t.spt -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-WO-EXT: Either SPV_EXT_relaxed_printf_string_address_space or SPV_INTEL_non_constant_addrspace_printf extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). ++ ++; CHECK-SPIRV-NOT: Capability NonConstantAddrspacePrintfINTEL ++; CHECK-SPIRV-NOT: Extension "SPV_INTEL_non_constant_addrspace_printf" ++; CHECK-SPIRV: Extension "SPV_EXT_relaxed_printf_string_address_space" ++; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std" ++; CHECK-SPIRV: TypeInt [[#TypeInt8Id:]] 8 0 ++; CHECK-SPIRV: TypeInt [[#TypeInt32Id:]] 32 0 ++; CHECK-SPIRV: TypePointer [[#FunctionStorClassPtrTy:]] 7 [[#TypeInt8Id]] ++; CHECK-SPIRV: TypePointer [[#WGStorClassPtrTy:]] 5 [[#TypeInt8Id]] ++; CHECK-SPIRV: TypePointer [[#CrossWFStorClassPtrTy:]] 4 [[#TypeInt8Id]] ++; CHECK-SPIRV: TypePointer [[#GenericStorCalssPtrTy:]] 8 [[#TypeInt8Id]] ++; CHECK-SPIRV: InBoundsPtrAccessChain [[#FunctionStorClassPtrTy]] [[#GEP1:]] ++; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP1]] ++; CHECK-SPIRV: InBoundsPtrAccessChain [[#WGStorClassPtrTy]] [[#GEP2:]] ++; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP2]] ++; CHECK-SPIRV: InBoundsPtrAccessChain [[#CrossWFStorClassPtrTy:]] [[#GEP3:]] ++; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP3]] ++; CHECK-SPIRV: InBoundsPtrAccessChain [[#GenericStorCalssPtrTy:]] [[#GEP4:]] ++; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP4]] ++ ++; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPc(ptr {{.*}} ++; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(ptr addrspace(1) {{.*}} ++; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(ptr addrspace(3) {{.*}} ++; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(ptr addrspace(4) {{.*}} ++ ++; ModuleID = 'non-constant-printf' ++target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" ++target triple = "spir-unknown-unknown" ++ ++@0 = internal unnamed_addr addrspace(0) constant [6 x i8] c"Test\0A\00", align 1 ++@1 = internal unnamed_addr addrspace(1) constant [6 x i8] c"Test\0A\00", align 1 ++@2 = internal unnamed_addr addrspace(3) constant [6 x i8] c"Test\0A\00", align 1 ++@3 = internal unnamed_addr addrspace(4) constant [6 x i8] c"Test\0A\00", align 1 ++ ++; Function Attrs: nounwind ++define spir_kernel void @test() #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !3 !kernel_arg_type !3 !kernel_arg_type_qual !3 !kernel_arg_base_type !3 { ++ %1 = getelementptr inbounds [6 x i8], [6 x i8]* @0, i32 0, i32 0 ++ %2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(i8* %1) #0 ++ %3 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(1)* @1, i32 0, i32 0 ++ %4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)* %3) #0 ++ %5 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(3)* @2, i32 0, i32 0 ++ %6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)* %5) #0 ++ %7 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(4)* @3, i32 0, i32 0 ++ %8 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)* %7) #0 ++ ret void ++} ++ ++; Function Attrs: nounwind ++declare spir_func i32 @_Z18__spirv_ocl_printfPc(i8*) #0 ++ ++; Function Attrs: nounwind ++declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)*) #0 ++ ++; Function Attrs: nounwind ++declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)*) #0 ++ ++; Function Attrs: nounwind ++declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)*) #0 ++ ++attributes #0 = { nounwind } ++ ++!spirv.MemoryModel = !{!0} ++!opencl.enable.FP_CONTRACT = !{} ++!spirv.Source = !{!1} ++!opencl.spir.version = !{!2} ++!opencl.ocl.version = !{!2} ++!opencl.used.extensions = !{!3} ++!opencl.used.optional.core.features = !{!3} ++!spirv.Generator = !{!4} ++ ++!0 = !{i32 1, i32 2} ++!1 = !{i32 3, i32 200000} ++!2 = !{i32 2, i32 0} ++!3 = !{} ++!4 = !{i16 7, i16 0} +diff --git a/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll b/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll +index 6d8ae4eb..84c420e8 100644 +--- a/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll ++++ b/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll +@@ -10,7 +10,7 @@ + ; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM + + ; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension: +-; CHECK-WO-EXT: The SPV_INTEL_non_constant_addrspace_printf extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). ++; CHECK-WO-EXT: Either SPV_EXT_relaxed_printf_string_address_space or SPV_INTEL_non_constant_addrspace_printf extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). + + ; CHECK-SPIRV: Capability NonConstantAddrspacePrintfINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_non_constant_addrspace_printf" +-- +2.20.1 + diff --git a/patches/0012-Deprecate-SPV_INTEL_non_constant_addrspace_printf-ex.patch b/patches/0012-Deprecate-SPV_INTEL_non_constant_addrspace_printf-ex.patch new file mode 100644 index 0000000..b0a6c12 --- /dev/null +++ b/patches/0012-Deprecate-SPV_INTEL_non_constant_addrspace_printf-ex.patch @@ -0,0 +1,231 @@ +From 855eb2798599356631bce6e6e4971c312e84b756 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Sat, 21 Jan 2023 21:45:36 +0100 +Subject: [PATCH 12/79] Deprecate SPV_INTEL_non_constant_addrspace_printf + extension (#1818) + +This change continues #1749. +We are removing SPV_INTEL_non_constant_addrspace_printf extension in +favor of SPV_EXT_relaxed_printf_string_address_space, which are +basically the same. + +Signed-off-by: Maksimova, Viktoria +--- + include/LLVMSPIRVExtensions.inc | 1 - + lib/SPIRV/SPIRVWriter.cpp | 22 ++--- + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 2 - + lib/SPIRV/libSPIRV/spirv_internal.hpp | 3 - + .../non-constant-printf.ll | 6 +- + .../non-constant-printf.ll | 87 ------------------- + 6 files changed, 9 insertions(+), 112 deletions(-) + rename test/{extensions/EXT => transcoding}/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll (89%) + delete mode 100644 test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index a6cf69b1..bbb2c201 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -51,7 +51,6 @@ EXT(SPV_INTEL_bfloat16_conversion) + EXT(SPV_INTEL_joint_matrix) + EXT(SPV_INTEL_hw_thread_queries) + EXT(SPV_INTEL_global_variable_decorations) +-EXT(SPV_INTEL_non_constant_addrspace_printf) + EXT(SPV_INTEL_complex_float_mul_div) + EXT(SPV_INTEL_split_barrier) + EXT(SPV_INTEL_tensor_float32_conversion) +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index fcab77cd..13d2a314 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -4025,26 +4025,18 @@ SPIRVValue *LLVMToSPIRVBase::transDirectCallInst(CallInst *CI, + auto *FormatStrPtr = cast(CI->getArgOperand(0)->getType()); + if (FormatStrPtr->getAddressSpace() != + SPIR::TypeAttributeEnum::ATTR_CONST) { +- if (BM->isAllowedToUseExtension( ++ if (!BM->isAllowedToUseExtension( + ExtensionID::SPV_EXT_relaxed_printf_string_address_space)) { +- BM->addExtension( +- ExtensionID::SPV_EXT_relaxed_printf_string_address_space); +- } else if (BM->isAllowedToUseExtension( +- ExtensionID::SPV_INTEL_non_constant_addrspace_printf)) { +- BM->addExtension( +- ExtensionID::SPV_INTEL_non_constant_addrspace_printf); +- BM->addCapability( +- internal::CapabilityNonConstantAddrspacePrintfINTEL); +- } else { + std::string ErrorStr = +- "Either SPV_EXT_relaxed_printf_string_address_space or " +- "SPV_INTEL_non_constant_addrspace_printf extension should be " +- "allowed to translate this module, because this LLVM module " +- "contains the printf function with format string, whose address " +- "space is not equal to 2 (constant)."; ++ "Either SPV_EXT_relaxed_printf_string_address_space extension " ++ "should be allowed to translate this module, because this LLVM " ++ "module contains the printf function with format string, whose " ++ "address space is not equal to 2 (constant)."; + getErrorLog().checkError(false, SPIRVEC_RequiresExtension, CI, + ErrorStr); + } ++ BM->addExtension( ++ ExtensionID::SPV_EXT_relaxed_printf_string_address_space); + } + } + +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index d73fdee7..0d94b0fa 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -614,8 +614,6 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityHWThreadQueryINTEL, "HWThreadQueryINTEL"); + add(internal::CapabilityGlobalVariableDecorationsINTEL, + "GlobalVariableDecorationsINTEL"); +- add(internal::CapabilityNonConstantAddrspacePrintfINTEL, +- "NonConstantAddrspacePrintfINTEL"); + add(internal::CapabilityComplexFloatMulDivINTEL, "ComplexFloatMulDivINTEL"); + add(internal::CapabilityTensorFloat32ConversionINTEL, + "TensorFloat32ConversionINTEL"); +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index 3938ac4c..a39633e3 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -78,7 +78,6 @@ enum InternalCapability { + ICapabilityHWThreadQueryINTEL = 6134, + ICapFPArithmeticFenceINTEL = 6144, + ICapGlobalVariableDecorationsINTEL = 6146, +- ICapabilityNonConstantAddrspacePrintfINTEL = 6411, + ICapabilityComplexFloatMulDivINTEL = 6414, + ICapabilityTensorFloat32ConversionINTEL = 6425, + ICapabilityMaskedGatherScatterINTEL = 6427 +@@ -121,8 +120,6 @@ _SPIRV_OP(Capability, HWThreadQueryINTEL) + _SPIRV_OP(BuiltIn, SubDeviceIDINTEL) + _SPIRV_OP(BuiltIn, GlobalHWThreadIDINTEL) + +-_SPIRV_OP(Capability, NonConstantAddrspacePrintfINTEL) +- + _SPIRV_OP(Capability, ComplexFloatMulDivINTEL) + _SPIRV_OP(Op, ComplexFMulINTEL) + _SPIRV_OP(Op, ComplexFDivINTEL) +diff --git a/test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll b/test/transcoding/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +similarity index 89% +rename from test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +rename to test/transcoding/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +index d621949c..c790770c 100644 +--- a/test/extensions/EXT/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll ++++ b/test/transcoding/SPV_EXT_relaxed_printf_string_address_space/non-constant-printf.ll +@@ -1,7 +1,7 @@ + ; RUN: llvm-as %s -o %t.bc + ; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT + +-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space,+SPV_INTEL_non_constant_addrspace_printf ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_EXT_relaxed_printf_string_address_space + ; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV + + ; RUN: llvm-spirv -to-binary %t.spt -o %t.spv +@@ -10,10 +10,8 @@ + ; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM + + ; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension: +-; CHECK-WO-EXT: Either SPV_EXT_relaxed_printf_string_address_space or SPV_INTEL_non_constant_addrspace_printf extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). ++; CHECK-WO-EXT: SPV_EXT_relaxed_printf_string_address_space extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). + +-; CHECK-SPIRV-NOT: Capability NonConstantAddrspacePrintfINTEL +-; CHECK-SPIRV-NOT: Extension "SPV_INTEL_non_constant_addrspace_printf" + ; CHECK-SPIRV: Extension "SPV_EXT_relaxed_printf_string_address_space" + ; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std" + ; CHECK-SPIRV: TypeInt [[#TypeInt8Id:]] 8 0 +diff --git a/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll b/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll +deleted file mode 100644 +index 84c420e8..00000000 +--- a/test/transcoding/SPV_INTEL_non_constant_addrspace_printf/non-constant-printf.ll ++++ /dev/null +@@ -1,87 +0,0 @@ +-; RUN: llvm-as %s -o %t.bc +-; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-WO-EXT +- +-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-ext=+SPV_INTEL_non_constant_addrspace_printf +-; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV +- +-; RUN: llvm-spirv -to-binary %t.spt -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +-; RUN: llvm-dis %t.rev.bc -o %t.rev.ll +-; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM +- +-; CHECK-WO-EXT: RequiresExtension: Feature requires the following SPIR-V extension: +-; CHECK-WO-EXT: Either SPV_EXT_relaxed_printf_string_address_space or SPV_INTEL_non_constant_addrspace_printf extension should be allowed to translate this module, because this LLVM module contains the printf function with format string, whose address space is not equal to 2 (constant). +- +-; CHECK-SPIRV: Capability NonConstantAddrspacePrintfINTEL +-; CHECK-SPIRV: Extension "SPV_INTEL_non_constant_addrspace_printf" +-; CHECK-SPIRV: ExtInstImport [[#ExtInstSetId:]] "OpenCL.std" +-; CHECK-SPIRV: TypeInt [[#TypeInt8Id:]] 8 0 +-; CHECK-SPIRV: TypeInt [[#TypeInt32Id:]] 32 0 +-; CHECK-SPIRV: TypePointer [[#FunctionStorClassPtrTy:]] 7 [[#TypeInt8Id]] +-; CHECK-SPIRV: TypePointer [[#WGStorClassPtrTy:]] 5 [[#TypeInt8Id]] +-; CHECK-SPIRV: TypePointer [[#CrossWFStorClassPtrTy:]] 4 [[#TypeInt8Id]] +-; CHECK-SPIRV: TypePointer [[#GenericStorCalssPtrTy:]] 8 [[#TypeInt8Id]] +-; CHECK-SPIRV: InBoundsPtrAccessChain [[#FunctionStorClassPtrTy]] [[#GEP1:]] +-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP1]] +-; CHECK-SPIRV: InBoundsPtrAccessChain [[#WGStorClassPtrTy]] [[#GEP2:]] +-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP2]] +-; CHECK-SPIRV: InBoundsPtrAccessChain [[#CrossWFStorClassPtrTy:]] [[#GEP3:]] +-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP3]] +-; CHECK-SPIRV: InBoundsPtrAccessChain [[#GenericStorCalssPtrTy:]] [[#GEP4:]] +-; CHECK-SPIRV: ExtInst [[#TypeInt32Id]] [[#]] [[#ExtInstSetId:]] printf [[#GEP4]] +- +-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPc(i8* {{.*}} +-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)* {{.*}} +-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)* {{.*}} +-; CHECK-LLVM: call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)* {{.*}} +- +-; ModuleID = 'non-constant-printf' +-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" +-target triple = "spir-unknown-unknown" +- +-@0 = internal unnamed_addr addrspace(0) constant [6 x i8] c"Test\0A\00", align 1 +-@1 = internal unnamed_addr addrspace(1) constant [6 x i8] c"Test\0A\00", align 1 +-@2 = internal unnamed_addr addrspace(3) constant [6 x i8] c"Test\0A\00", align 1 +-@3 = internal unnamed_addr addrspace(4) constant [6 x i8] c"Test\0A\00", align 1 +- +-; Function Attrs: nounwind +-define spir_kernel void @test() #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !3 !kernel_arg_type !3 !kernel_arg_type_qual !3 !kernel_arg_base_type !3 { +- %1 = getelementptr inbounds [6 x i8], [6 x i8]* @0, i32 0, i32 0 +- %2 = call spir_func i32 @_Z18__spirv_ocl_printfPc(i8* %1) #0 +- %3 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(1)* @1, i32 0, i32 0 +- %4 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)* %3) #0 +- %5 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(3)* @2, i32 0, i32 0 +- %6 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)* %5) #0 +- %7 = getelementptr inbounds [6 x i8], [6 x i8] addrspace(4)* @3, i32 0, i32 0 +- %8 = call spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)* %7) #0 +- ret void +-} +- +-; Function Attrs: nounwind +-declare spir_func i32 @_Z18__spirv_ocl_printfPc(i8*) #0 +- +-; Function Attrs: nounwind +-declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS1c(i8 addrspace(1)*) #0 +- +-; Function Attrs: nounwind +-declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS3c(i8 addrspace(3)*) #0 +- +-; Function Attrs: nounwind +-declare spir_func i32 @_Z18__spirv_ocl_printfPU3AS4c(i8 addrspace(4)*) #0 +- +-attributes #0 = { nounwind } +- +-!spirv.MemoryModel = !{!0} +-!opencl.enable.FP_CONTRACT = !{} +-!spirv.Source = !{!1} +-!opencl.spir.version = !{!2} +-!opencl.ocl.version = !{!2} +-!opencl.used.extensions = !{!3} +-!opencl.used.optional.core.features = !{!3} +-!spirv.Generator = !{!4} +- +-!0 = !{i32 1, i32 2} +-!1 = !{i32 3, i32 200000} +-!2 = !{i32 2, i32 0} +-!3 = !{} +-!4 = !{i16 7, i16 0} +-- +2.20.1 + diff --git a/patches/0013-Backport-to-15-Translate-readnone-attribute-as-funct.patch b/patches/0013-Backport-to-15-Translate-readnone-attribute-as-funct.patch new file mode 100644 index 0000000..50637f0 --- /dev/null +++ b/patches/0013-Backport-to-15-Translate-readnone-attribute-as-funct.patch @@ -0,0 +1,328 @@ +From f38a2573031bda21410337d75e1e830a2af1193b Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 8 Nov 2022 10:40:39 +0100 +Subject: [PATCH 13/79] [Backport to 15] Translate readnone attribute as + function parameter attribute (#1697) + +Community restricted readnone, readonly and writeonly attributes +to be only function parameter attributes. This patch aligns +the translator with llvm.org. + +It also fixes a bug, when readnone attribute is being mapped +to NoWrite SPIR-V function parameter attribute. + +Signed-off-by: Sidorov, Dmitry + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVInternal.h | 3 +-- + lib/SPIRV/SPIRVReader.cpp | 4 ++- + lib/SPIRV/SPIRVUtil.cpp | 4 ++- + lib/SPIRV/SPIRVWriter.cpp | 4 ++- + test/transcoding/OpGenericPtrMemSemantics.ll | 4 +-- + test/transcoding/OpImageSampleExplicitLod.ll | 4 +-- + test/transcoding/OpSwitch32.ll | 6 ++--- + test/transcoding/OpSwitch64.ll | 6 ++--- + test/transcoding/bitcast.ll | 6 ++--- + test/transcoding/builtin_calls.ll | 2 +- + .../builtin_function_readnone_attr.ll | 25 ++++++++++++------- + test/transcoding/builtin_vars_arithmetics.ll | 2 +- + test/transcoding/isequal.ll | 8 +++--- + test/transcoding/unreachable.ll | 4 +-- + 14 files changed, 47 insertions(+), 35 deletions(-) + +diff --git a/lib/SPIRV/SPIRVInternal.h b/lib/SPIRV/SPIRVInternal.h +index 0629c9c6..e593856a 100644 +--- a/lib/SPIRV/SPIRVInternal.h ++++ b/lib/SPIRV/SPIRVInternal.h +@@ -240,6 +240,7 @@ inline void SPIRVMap::init() { + add(Attribute::NoAlias, FunctionParameterAttributeNoAlias); + add(Attribute::NoCapture, FunctionParameterAttributeNoCapture); + add(Attribute::ReadOnly, FunctionParameterAttributeNoWrite); ++ add(Attribute::ReadNone, FunctionParameterAttributeNoReadWrite); + } + typedef SPIRVMap + SPIRSPIRVFuncParamAttrMap; +@@ -247,8 +248,6 @@ typedef SPIRVMap + template <> + inline void + SPIRVMap::init() { +- add(Attribute::ReadNone, FunctionControlPureMask); +- add(Attribute::ReadOnly, FunctionControlConstMask); + add(Attribute::AlwaysInline, FunctionControlInlineMask); + add(Attribute::NoInline, FunctionControlDontInlineMask); + add(Attribute::OptimizeNone, internal::FunctionControlOptNoneINTELMask); +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 0209ccfb..c75d0e6d 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -4413,7 +4413,9 @@ Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC, + if (isFuncNoUnwind()) + F->addFnAttr(Attribute::NoUnwind); + if (isFuncReadNone(UnmangledName)) +- F->addFnAttr(Attribute::ReadNone); ++ for (llvm::Argument &Arg : F->args()) ++ if (Arg.getType()->isPointerTy()) ++ Arg.addAttr(Attribute::ReadNone); + } + auto Args = transValue(BC->getArgValues(), F, BB); + SPIRVDBG(dbgs() << "[transOCLBuiltinFromExtInst] Function: " << *F +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 72e9eb5d..98a90516 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1946,8 +1946,10 @@ bool lowerBuiltinVariableToCall(GlobalVariable *GV, + Func = Function::Create(FT, GlobalValue::ExternalLinkage, MangledName, M); + Func->setCallingConv(CallingConv::SPIR_FUNC); + Func->addFnAttr(Attribute::NoUnwind); +- Func->addFnAttr(Attribute::ReadNone); + Func->addFnAttr(Attribute::WillReturn); ++ for (llvm::Argument &Arg : Func->args()) ++ if (Arg.getType()->isPointerTy()) ++ Arg.addAttr(Attribute::ReadNone); + } + + // Collect instructions in these containers to remove them later. +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 13d2a314..c923642b 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -844,8 +844,10 @@ SPIRVFunction *LLVMToSPIRVBase::transFunctionDecl(Function *F) { + BA->addAttr(FunctionParameterAttributeNoCapture); + if (I->hasStructRetAttr()) + BA->addAttr(FunctionParameterAttributeSret); +- if (I->onlyReadsMemory()) ++ if (Attrs.hasParamAttr(ArgNo, Attribute::ReadOnly)) + BA->addAttr(FunctionParameterAttributeNoWrite); ++ if (Attrs.hasParamAttr(ArgNo, Attribute::ReadNone)) ++ BA->addAttr(FunctionParameterAttributeNoReadWrite); + if (Attrs.hasParamAttr(ArgNo, Attribute::ZExt)) + BA->addAttr(FunctionParameterAttributeZext); + if (Attrs.hasParamAttr(ArgNo, Attribute::SExt)) +diff --git a/test/transcoding/OpGenericPtrMemSemantics.ll b/test/transcoding/OpGenericPtrMemSemantics.ll +index 8b7545e7..9da8e260 100644 +--- a/test/transcoding/OpGenericPtrMemSemantics.ll ++++ b/test/transcoding/OpGenericPtrMemSemantics.ll +@@ -24,7 +24,7 @@ target triple = "spir-unknown-unknown" + + @gint = addrspace(1) global i32 1, align 4 + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + define spir_func i32 @isFenceValid(i32 %fence) #0 { + entry: + %switch = icmp ult i32 %fence, 4 +@@ -66,7 +66,7 @@ entry: + + declare spir_func i32 @_Z13get_global_idj(i32) #2 + +-attributes #0 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #3 = { nounwind } +diff --git a/test/transcoding/OpImageSampleExplicitLod.ll b/test/transcoding/OpImageSampleExplicitLod.ll +index c214ff9d..b41b7d07 100644 +--- a/test/transcoding/OpImageSampleExplicitLod.ll ++++ b/test/transcoding/OpImageSampleExplicitLod.ll +@@ -43,14 +43,14 @@ entry: + ; Function Attrs: nounwind + declare spir_func float @_Z11read_imagef20ocl_image2d_depth_ro11ocl_samplerDv2_i(%opencl.image2d_depth_ro_t addrspace(1)*, i32, <2 x i32>) #0 + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i32 @_Z13get_global_idj(i32) #1 + + ; Function Attrs: nounwind + declare spir_func <2 x i32> @_Z13get_image_dim20ocl_image2d_depth_ro(%opencl.image2d_depth_ro_t addrspace(1)*) #0 + + attributes #0 = { nounwind } +-attributes #1 = { nounwind readnone } ++attributes #1 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !opencl.spir.version = !{!6} +diff --git a/test/transcoding/OpSwitch32.ll b/test/transcoding/OpSwitch32.ll +index 228e9324..0954e608 100644 +--- a/test/transcoding/OpSwitch32.ll ++++ b/test/transcoding/OpSwitch32.ll +@@ -75,12 +75,12 @@ sw.epilog: ; preds = %entry, %sw.bb1, %sw + ret void + } + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i64 @_Z13get_global_idj(i32) #1 + + attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #2 = { nounwind readnone } ++attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #2 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !opencl.spir.version = !{!6} +diff --git a/test/transcoding/OpSwitch64.ll b/test/transcoding/OpSwitch64.ll +index 43d52389..c5dd16f0 100644 +--- a/test/transcoding/OpSwitch64.ll ++++ b/test/transcoding/OpSwitch64.ll +@@ -86,12 +86,12 @@ sw.epilog: ; preds = %entry, %sw.bb3, %sw + ret void + } + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i64 @_Z13get_global_idj(i32) #1 + + attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #2 = { nounwind readnone } ++attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #2 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !opencl.spir.version = !{!6} +diff --git a/test/transcoding/bitcast.ll b/test/transcoding/bitcast.ll +index b1ed929f..44c5f3f2 100644 +--- a/test/transcoding/bitcast.ll ++++ b/test/transcoding/bitcast.ll +@@ -26,12 +26,12 @@ entry: + ret void + } + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i64 @_Z13get_global_idj(i32) #1 + + attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #2 = { nounwind readnone } ++attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #2 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !opencl.spir.version = !{!6} +diff --git a/test/transcoding/builtin_calls.ll b/test/transcoding/builtin_calls.ll +index bf2dd880..1fac8632 100644 +--- a/test/transcoding/builtin_calls.ll ++++ b/test/transcoding/builtin_calls.ll +@@ -16,7 +16,7 @@ target triple = "spir-unknown-unknown" + ; CHECK-SPIRV: Variable {{[0-9]+}} [[Id:[0-9]+]] + ; CHECK-SPIRV: Variable {{[0-9]+}} [[Id:[0-9]+]] + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + define spir_kernel void @f() #0 !kernel_arg_addr_space !0 !kernel_arg_access_qual !0 !kernel_arg_type !0 !kernel_arg_base_type !0 !kernel_arg_type_qual !0 { + entry: + %0 = call spir_func i32 @_Z29__spirv_BuiltInGlobalLinearIdv() +diff --git a/test/transcoding/builtin_function_readnone_attr.ll b/test/transcoding/builtin_function_readnone_attr.ll +index 5bfb5d04..c99098fa 100644 +--- a/test/transcoding/builtin_function_readnone_attr.ll ++++ b/test/transcoding/builtin_function_readnone_attr.ll +@@ -1,13 +1,23 @@ + ; RUN: llvm-as %s -o %t.bc + ; RUN: llvm-spirv %t.bc -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.bc ++; RUN: llvm-spirv %t.spv -to-text -o %t.spt ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.bc + ; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM + ++; CHECK-SPIRV: Name [[#A:]] "a" ++; CHECK-SPIRV: Name [[#B:]] "b" ++; CHECK-SPIRV: Decorate [[#A]] FuncParamAttr 5 ++; CHECK-SPIRV: Decorate [[#A]] FuncParamAttr 6 ++; CHECK-SPIRV: Decorate [[#B]] FuncParamAttr 7 ++ ++; CHECK-LLVM: {{.*}}void @test_builtin_readnone(ptr nocapture readonly %{{.*}}, ptr nocapture readnone %{{.*}}) ++ + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "spir-unknown-unknown" + + ; Function Attrs: convergent nofree norecurse nounwind uwtable +-define dso_local spir_kernel void @test_builtin_readnone(double* nocapture readonly %a, double* nocapture %b) local_unnamed_addr #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !6 { ++define dso_local spir_kernel void @test_builtin_readnone(double* nocapture readonly %a, double* nocapture readnone %b) local_unnamed_addr #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !6 { + entry: + %0 = load double, double* %a, align 8, !tbaa !7 + %call = tail call double @_Z3expd(double %0) #2 +@@ -18,18 +28,15 @@ entry: + ret void + } + +-; Function Attrs: convergent nounwind readnone +-; CHECK-LLVM: declare{{.*}}@_Z3expd{{.*}}#[[#Attrs:]] ++; Function Attrs: convergent nounwind + declare dso_local double @_Z3expd(double) local_unnamed_addr #1 + +-; Function Attrs: convergent nounwind readnone +-; CHECK-LLVM: declare{{.*}}@_Z3cosd{{.*}}#[[#Attrs]] ++; Function Attrs: convergent nounwind + declare dso_local double @_Z3cosd(double) local_unnamed_addr #1 + + attributes #0 = { convergent nofree norecurse nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "uniform-work-group-size"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } +-; CHECK-LLVM: attributes #[[#Attrs]] {{.*}} readnone +-attributes #1 = { convergent nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #2 = { convergent nounwind readnone } ++attributes #1 = { convergent nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #2 = { convergent nounwind } + + !llvm.module.flags = !{!0} + !opencl.ocl.version = !{!1} +diff --git a/test/transcoding/builtin_vars_arithmetics.ll b/test/transcoding/builtin_vars_arithmetics.ll +index 4ecbbb49..0fa2f04b 100644 +--- a/test/transcoding/builtin_vars_arithmetics.ll ++++ b/test/transcoding/builtin_vars_arithmetics.ll +@@ -123,7 +123,7 @@ entry: + + attributes #0 = { norecurse "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="test.cpp" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } + +-; CHECK-LLVM-OCL: attributes #1 = { nounwind readnone willreturn } ++; CHECK-LLVM-OCL: attributes #1 = { nounwind willreturn } + + !llvm.module.flags = !{!0} + !opencl.spir.version = !{!1} +diff --git a/test/transcoding/isequal.ll b/test/transcoding/isequal.ll +index 17841517..777a4967 100644 +--- a/test/transcoding/isequal.ll ++++ b/test/transcoding/isequal.ll +@@ -30,15 +30,15 @@ entry: + ret void + } + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i64 @_Z13get_global_idj(i32) #1 + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func <8 x i32> @_Z7isequalDv8_fDv8_f(<8 x float>, <8 x float>) #1 + + attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +-attributes #2 = { nounwind readnone } ++attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++attributes #2 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !opencl.spir.version = !{!6} +diff --git a/test/transcoding/unreachable.ll b/test/transcoding/unreachable.ll +index e6b15761..466c107b 100644 +--- a/test/transcoding/unreachable.ll ++++ b/test/transcoding/unreachable.ll +@@ -30,11 +30,11 @@ define spir_kernel void @unreachable_simple(i32 addrspace(1)* nocapture %in, i32 + ret void + } + +-; Function Attrs: nounwind readnone ++; Function Attrs: nounwind + declare spir_func i64 @_Z13get_global_idj(i32) #1 + + attributes #0 = { nounwind } +-attributes #1 = { nounwind readnone } ++attributes #1 = { nounwind } + + !opencl.enable.FP_CONTRACT = !{} + !spirv.Source = !{!6} +-- +2.20.1 + diff --git a/patches/0014-Backport-to-15-Put-memory-none-attribute-instead-of-.patch b/patches/0014-Backport-to-15-Put-memory-none-attribute-instead-of-.patch new file mode 100644 index 0000000..a96443d --- /dev/null +++ b/patches/0014-Backport-to-15-Put-memory-none-attribute-instead-of-.patch @@ -0,0 +1,67 @@ +From fce7e50343b129db188684c69e204b006f5ad11c Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 29 Nov 2022 12:55:12 +0100 +Subject: [PATCH 14/79] [Backport to 15] Put memory(none) attribute instead of + readnone (#1746) + +Instead of creating readnone attributes on each parameter of +a function it's better to put just memory(none) which was recently +introduced. + +See https://reviews.llvm.org/D135780 + +Co-authored by: Zou, Feng + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVReader.cpp | 4 +--- + lib/SPIRV/SPIRVUtil.cpp | 4 +--- + test/transcoding/builtin_vars_arithmetics.ll | 2 +- + 3 files changed, 3 insertions(+), 7 deletions(-) + +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index c75d0e6d..6a84d54d 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -4413,9 +4413,7 @@ Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC, + if (isFuncNoUnwind()) + F->addFnAttr(Attribute::NoUnwind); + if (isFuncReadNone(UnmangledName)) +- for (llvm::Argument &Arg : F->args()) +- if (Arg.getType()->isPointerTy()) +- Arg.addAttr(Attribute::ReadNone); ++ F->setDoesNotAccessMemory(); + } + auto Args = transValue(BC->getArgValues(), F, BB); + SPIRVDBG(dbgs() << "[transOCLBuiltinFromExtInst] Function: " << *F +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 98a90516..4889d7b5 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1947,9 +1947,7 @@ bool lowerBuiltinVariableToCall(GlobalVariable *GV, + Func->setCallingConv(CallingConv::SPIR_FUNC); + Func->addFnAttr(Attribute::NoUnwind); + Func->addFnAttr(Attribute::WillReturn); +- for (llvm::Argument &Arg : Func->args()) +- if (Arg.getType()->isPointerTy()) +- Arg.addAttr(Attribute::ReadNone); ++ Func->setDoesNotAccessMemory(); + } + + // Collect instructions in these containers to remove them later. +diff --git a/test/transcoding/builtin_vars_arithmetics.ll b/test/transcoding/builtin_vars_arithmetics.ll +index 0fa2f04b..4ecbbb49 100644 +--- a/test/transcoding/builtin_vars_arithmetics.ll ++++ b/test/transcoding/builtin_vars_arithmetics.ll +@@ -123,7 +123,7 @@ entry: + + attributes #0 = { norecurse "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="test.cpp" "uniform-work-group-size"="true" "unsafe-fp-math"="false" "use-soft-float"="false" } + +-; CHECK-LLVM-OCL: attributes #1 = { nounwind willreturn } ++; CHECK-LLVM-OCL: attributes #1 = { nounwind readnone willreturn } + + !llvm.module.flags = !{!0} + !opencl.spir.version = !{!1} +-- +2.20.1 + diff --git a/patches/0015-Allow-ReadNone-and-ReadOnly-as-Function-attributes.patch b/patches/0015-Allow-ReadNone-and-ReadOnly-as-Function-attributes.patch new file mode 100644 index 0000000..b1963e3 --- /dev/null +++ b/patches/0015-Allow-ReadNone-and-ReadOnly-as-Function-attributes.patch @@ -0,0 +1,25 @@ +From e6ecc0a953b0fea2ef6f2fbb48563dbaf4bb1084 Mon Sep 17 00:00:00 2001 +From: Stanley Gambarin +Date: Mon, 13 Feb 2023 16:24:44 -0800 +Subject: [PATCH 15/79] Allow ReadNone and ReadOnly as Function attributes + +--- + lib/SPIRV/SPIRVInternal.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/SPIRV/SPIRVInternal.h b/lib/SPIRV/SPIRVInternal.h +index e593856a..9eaaf6c0 100644 +--- a/lib/SPIRV/SPIRVInternal.h ++++ b/lib/SPIRV/SPIRVInternal.h +@@ -248,6 +248,8 @@ typedef SPIRVMap + template <> + inline void + SPIRVMap::init() { ++ add(Attribute::ReadNone, FunctionControlPureMask); ++ add(Attribute::ReadOnly, FunctionControlConstMask); + add(Attribute::AlwaysInline, FunctionControlInlineMask); + add(Attribute::NoInline, FunctionControlDontInlineMask); + add(Attribute::OptimizeNone, internal::FunctionControlOptNoneINTELMask); +-- +2.20.1 + diff --git a/patches/0016-Fix-mangling-of-opcodes-from-SPV_KHR_bit_instruction.patch b/patches/0016-Fix-mangling-of-opcodes-from-SPV_KHR_bit_instruction.patch new file mode 100644 index 0000000..c53a03f --- /dev/null +++ b/patches/0016-Fix-mangling-of-opcodes-from-SPV_KHR_bit_instruction.patch @@ -0,0 +1,99 @@ +From 363e143bb394641fd5f77eab23b0c68e38d0554e Mon Sep 17 00:00:00 2001 +From: Andrzej Ratajewski +Date: Tue, 7 Mar 2023 13:51:36 +0100 +Subject: [PATCH 16/79] Fix mangling of opcodes from SPV_KHR_bit_instructions + in SPV-IR (#1869) + +--- + lib/SPIRV/SPIRVUtil.cpp | 3 +++ + test/transcoding/cl_khr_extended_bit_ops.cl | 20 ++++++++++++++------ + 2 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 4889d7b5..44c03848 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -2233,6 +2233,7 @@ public: + case OpGroupNonUniformBallotFindMSB: + addUnsignedArg(1); + break; ++ case OpBitFieldSExtract: + case OpGroupNonUniformBallotBitExtract: + addUnsignedArg(1); + addUnsignedArg(2); +@@ -2253,6 +2254,7 @@ public: + case OpGroupNonUniformLogicalXor: + addUnsignedArg(3); + break; ++ case OpBitFieldInsert: + case OpGroupNonUniformUMax: + case OpGroupNonUniformUMin: + addUnsignedArg(2); +@@ -2303,6 +2305,7 @@ public: + case OpSubgroupAvcImeSetSingleReferenceINTEL: + addUnsignedArg(1); + break; ++ case OpBitFieldUExtract: + case OpSubgroupAvcImeInitializeINTEL: + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: +diff --git a/test/transcoding/cl_khr_extended_bit_ops.cl b/test/transcoding/cl_khr_extended_bit_ops.cl +index 3da301be..363d0772 100644 +--- a/test/transcoding/cl_khr_extended_bit_ops.cl ++++ b/test/transcoding/cl_khr_extended_bit_ops.cl +@@ -3,12 +3,15 @@ + // RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_bit_instructions -o %t.spv + // RUN: llvm-spirv -r %t.spv -o %t.rev.bc + // RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++// RUN: llvm-spirv -r --spirv-target-env=SPV-IR -emit-opaque-pointers %t.spv -o %t.rev.bc ++// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR + + // CHECK-SPIRV: Capability BitInstructions + // CHECK-SPIRV: Extension "SPV_KHR_bit_instructions" + + // CHECK-LLVM-LABEL: @testInsert +-// CHECK-LLVM: call spir_func <2 x i32> @_Z15bitfield_insertDv2_iS_jj ++// CHECK-LLVM: call spir_func <2 x i32> @_Z15bitfield_insertDv2_iS_jj( ++// CHECK-SPV-IR: call spir_func <2 x i32> @_Z22__spirv_BitFieldInsertDv2_iS_jj( + // CHECK-SPIRV: Function + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[insbase:[0-9]+]] + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[insins:[0-9]+]] +@@ -18,8 +21,10 @@ kernel void testInsert(int2 b, int2 i, global int2 *res) { + } + + // CHECK-LLVM-LABEL: @testExtractS +-// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj +-// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj ++// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj( ++// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj( ++// CHECK-SPV-IR: call spir_func i16 @_Z24__spirv_BitFieldSExtractsjj( ++// CHECK-SPV-IR: call spir_func i16 @_Z24__spirv_BitFieldSExtractsjj( + // CHECK-SPIRV: Function + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[sextrbase:[0-9]+]] + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[sextrbaseu:[0-9]+]] +@@ -31,8 +36,10 @@ kernel void testExtractS(short b, ushort bu, global short *res) { + } + + // CHECK-LLVM-LABEL: @testExtractU +-// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj +-// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj ++// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj( ++// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj( ++// CHECK-SPV-IR: call spir_func <8 x i8> @_Z24__spirv_BitFieldUExtractDv8_hjj( ++// CHECK-SPV-IR: call spir_func <8 x i8> @_Z24__spirv_BitFieldUExtractDv8_hjj( + // CHECK-SPIRV: Function + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[uextrbase:[0-9]+]] + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[uextrbaseu:[0-9]+]] +@@ -44,7 +51,8 @@ kernel void testExtractU(char8 b, uchar8 bu, global uchar8 *res) { + } + + // CHECK-LLVM-LABEL: @testBitReverse +-// CHECK-LLVM: call <4 x i64> @llvm.bitreverse.v4i64 ++// CHECK-LLVM: call <4 x i64> @llvm.bitreverse.v4i64( ++// CHECK-SPV-IR: call <4 x i64> @llvm.bitreverse.v4i64( + // CHECK-SPIRV: Function + // CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[revbase:[0-9]+]] + // CHECK-SPIRV: BitReverse {{[0-9]+}} {{[0-9]+}} [[revbase]] +-- +2.20.1 + diff --git a/patches/0017-Update-spirv-as-invocations-1933.patch b/patches/0017-Update-spirv-as-invocations-1933.patch new file mode 100644 index 0000000..40142ef --- /dev/null +++ b/patches/0017-Update-spirv-as-invocations-1933.patch @@ -0,0 +1,43 @@ +From 068260b61669d7b3e50ce82b19737be548e0762f Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 31 Mar 2023 13:40:26 +0200 +Subject: [PATCH 17/79] Update spirv-as invocations (#1933) + +After SPIRV-Tools commit 2e0f4b52 ("tools: refactorize tools flags +parsing. (#5111)", 2023-02-27), spirv-as needs to be told explicitly +when reading from stdin. + +Co-authored-by: Sven van Haastregt +--- + test/GroupAndSubgroupInstructions.spvasm | 2 +- + test/spirv-tools-dis.ll | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/test/GroupAndSubgroupInstructions.spvasm b/test/GroupAndSubgroupInstructions.spvasm +index 4fef6b3e..a3990d87 100644 +--- a/test/GroupAndSubgroupInstructions.spvasm ++++ b/test/GroupAndSubgroupInstructions.spvasm +@@ -31,7 +31,7 @@ + ; spirv-dis tmp.spv -o llvm-spirv/test/GroupAndSubgroupInstructions.spvasm + + ; REQUIRES: spirv-as +-; RUN: spirv-as < %s --target-env spv1.0 -o %t.spv ++; RUN: spirv-as %s --target-env spv1.0 -o %t.spv + ; RUN: spirv-val %t.spv + ; RUN: llvm-spirv -r %t.spv --spirv-target-env=CL1.2 -o %t.bc + ; RUN: llvm-dis %t.bc -o %t.ll +diff --git a/test/spirv-tools-dis.ll b/test/spirv-tools-dis.ll +index 21409dc3..791f5010 100644 +--- a/test/spirv-tools-dis.ll ++++ b/test/spirv-tools-dis.ll +@@ -1,6 +1,6 @@ + ; RUN: llvm-as %s -o %t.bc + ; RUN: llvm-spirv %t.bc --spirv-tools-dis -o - | FileCheck %s +-; RUN: llvm-spirv %t.bc --spirv-tools-dis -o - | spirv-as ++; RUN: llvm-spirv %t.bc --spirv-tools-dis -o - | spirv-as - + + ; Verify that the --spirv-tools-dis options results in SPIRV-Tools compatible assembly. + +-- +2.20.1 + diff --git a/patches/0018-Backport-to-15-Initial-support-NonSemantic.Kernel.De.patch b/patches/0018-Backport-to-15-Initial-support-NonSemantic.Kernel.De.patch new file mode 100644 index 0000000..3b481bd --- /dev/null +++ b/patches/0018-Backport-to-15-Initial-support-NonSemantic.Kernel.De.patch @@ -0,0 +1,651 @@ +From b42bb0a101125c51334768568793be06a7bd70ff Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Mon, 20 Feb 2023 14:22:05 -0800 +Subject: [PATCH 18/79] [Backport to 15] Initial support + NonSemantic.Kernel.DebugInfo.100 (#1846) + +This patch implements the initial support for the new debug specification NonSemantic.Kernel.DebugInfo.100. +It also introduces support for the new debug instruction DISubrange. + +Spec: KhronosGroup/SPIRV-Registry#186 +--- + include/LLVMSPIRVOpts.h | 6 +- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 88 ++++++++++++ + lib/SPIRV/LLVMToSPIRVDbgTran.h | 3 + + lib/SPIRV/SPIRVReader.cpp | 1 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 68 +++++++++- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 8 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 14 +- + lib/SPIRV/libSPIRV/SPIRVEnum.h | 3 + + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + lib/SPIRV/libSPIRV/SPIRVFunction.cpp | 6 +- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 5 +- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 3 +- + lib/SPIRV/libSPIRV/SPIRVModule.h | 2 + + .../NonSemanticKernel100/DebugInfoSubrange.ll | 128 ++++++++++++++++++ + .../{ => OpenCL100}/DebugInfoSubrange.ll | 0 + tools/llvm-spirv/llvm-spirv.cpp | 12 +- + 16 files changed, 340 insertions(+), 8 deletions(-) + create mode 100644 test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll + rename test/DebugInfo/{ => OpenCL100}/DebugInfoSubrange.ll (100%) + +diff --git a/include/LLVMSPIRVOpts.h b/include/LLVMSPIRVOpts.h +index 8c73b644..8c140377 100644 +--- a/include/LLVMSPIRVOpts.h ++++ b/include/LLVMSPIRVOpts.h +@@ -80,7 +80,11 @@ enum class BIsRepresentation : uint32_t { OpenCL12, OpenCL20, SPIRVFriendlyIR }; + + enum class FPContractMode : uint32_t { On, Off, Fast }; + +-enum class DebugInfoEIS : uint32_t { SPIRV_Debug, OpenCL_DebugInfo_100 }; ++enum class DebugInfoEIS : uint32_t { ++ SPIRV_Debug, ++ OpenCL_DebugInfo_100, ++ NonSemantic_Kernel_DebugInfo_100 ++}; + + /// \brief Helper class to manage SPIR-V translation + class TranslatorOpts { +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 411bed3b..d6da1a82 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -277,6 +277,12 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + case dwarf::DW_TAG_array_type: + return transDbgArrayType(cast(DIEntry)); + ++ case dwarf::DW_TAG_subrange_type: ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ return transDbgSubrangeType(cast(DIEntry)); ++ else ++ return getDebugInfoNone(); ++ + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_volatile_type: +@@ -552,6 +558,14 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgQualifiedType(const DIDerivedType *QT) { + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) { ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ return transDbgArrayTypeNonSemantic(AT); ++ ++ return transDbgArrayTypeOpenCL(AT); ++} ++ ++SPIRVEntry * ++LLVMToSPIRVDbgTran::transDbgArrayTypeOpenCL(const DICompositeType *AT) { + using namespace SPIRVDebug::Operand::TypeArray; + SPIRVWordVec Ops(MinOperandCount); + SPIRVEntry *Base = transDbgEntry(AT->getBaseType()); +@@ -594,6 +608,80 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) { + return BM->addDebugInfo(SPIRVDebug::TypeArray, getVoidTy(), Ops); + } + ++SPIRVEntry * ++LLVMToSPIRVDbgTran::transDbgArrayTypeNonSemantic(const DICompositeType *AT) { ++ using namespace SPIRVDebug::Operand::TypeArray; ++ SPIRVWordVec Ops(MinOperandCount); ++ SPIRVEntry *Base = transDbgEntry(AT->getBaseType()); ++ Ops[BaseTypeIdx] = Base->getId(); ++ ++ DINodeArray AR(AT->getElements()); ++ // For N-dimensianal arrays AR.getNumElements() == N ++ const unsigned N = AR.size(); ++ Ops.resize(SubrangesIdx + N); ++ for (unsigned I = 0; I < N; ++I) { ++ DISubrange *SR = cast(AR[I]); ++ ConstantInt *Count = SR->getCount().get(); ++ if (AT->isVector()) { ++ assert(N == 1 && "Multidimensional vector is not expected!"); ++ Ops[ComponentCountIdx] = static_cast(Count->getZExtValue()); ++ return BM->addDebugInfo(SPIRVDebug::TypeVector, getVoidTy(), Ops); ++ } ++ Ops[SubrangesIdx + I] = transDbgEntry(SR)->getId(); ++ } ++ return BM->addDebugInfo(SPIRVDebug::TypeArray, getVoidTy(), Ops); ++} ++ ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgSubrangeType(const DISubrange *ST) { ++ using namespace SPIRVDebug::Operand::TypeSubrange; ++ SPIRVWordVec Ops(OperandCount); ++ auto TransOperand = [&Ops, this, ST](int Idx) -> void { ++ Metadata *RawNode = nullptr; ++ switch (Idx) { ++ case LowerBoundIdx: ++ RawNode = ST->getRawLowerBound(); ++ break; ++ case UpperBoundIdx: ++ RawNode = ST->getRawUpperBound(); ++ break; ++ case CountIdx: ++ RawNode = ST->getRawCountNode(); ++ break; ++ case StrideIdx: ++ RawNode = ST->getRawStride(); ++ break; ++ } ++ if (!RawNode) { ++ Ops[Idx] = getDebugInfoNoneId(); ++ return; ++ } ++ if (auto *Node = dyn_cast(RawNode)) { ++ Ops[Idx] = transDbgEntry(Node)->getId(); ++ } else { ++ ConstantInt *IntNode = nullptr; ++ switch (Idx) { ++ case LowerBoundIdx: ++ IntNode = ST->getLowerBound().get(); ++ break; ++ case UpperBoundIdx: ++ IntNode = ST->getUpperBound().get(); ++ break; ++ case CountIdx: ++ IntNode = ST->getCount().get(); ++ break; ++ case StrideIdx: ++ IntNode = ST->getStride().get(); ++ break; ++ } ++ Ops[Idx] = IntNode ? SPIRVWriter->transValue(IntNode, nullptr)->getId() ++ : getDebugInfoNoneId(); ++ } ++ }; ++ for (int Idx = CountIdx; Idx < OperandCount; ++Idx) ++ TransOperand(Idx); ++ return BM->addDebugInfo(SPIRVDebug::TypeSubrange, getVoidTy(), Ops); ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTypeDef(const DIDerivedType *DT) { + using namespace SPIRVDebug::Operand::Typedef; + SPIRVWordVec Ops(OperandCount); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 03d62a2d..7793403c 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -105,6 +105,9 @@ private: + SPIRVEntry *transDbgPointerType(const DIDerivedType *PT); + SPIRVEntry *transDbgQualifiedType(const DIDerivedType *QT); + SPIRVEntry *transDbgArrayType(const DICompositeType *AT); ++ SPIRVEntry *transDbgArrayTypeOpenCL(const DICompositeType *AT); ++ SPIRVEntry *transDbgArrayTypeNonSemantic(const DICompositeType *AT); ++ SPIRVEntry *transDbgSubrangeType(const DISubrange *ST); + SPIRVEntry *transDbgTypeDef(const DIDerivedType *D); + SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT); + SPIRVEntry *transDbgEnumType(const DICompositeType *ET); +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 6a84d54d..b998abcd 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -2376,6 +2376,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, + return mapValue(BV, transOCLBuiltinFromExtInst(ExtInst, BB)); + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: + return mapValue(BV, DbgTran->transDebugIntrinsic(ExtInst, BB)); + default: + llvm_unreachable("Unknown extended instruction set!"); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index ec396e68..94c3616f 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -91,7 +91,8 @@ SPIRVExtInst *SPIRVToLLVMDbgTran::getDbgInst(const SPIRVId Id) { + if (isa(E)) { + SPIRVExtInst *EI = static_cast(E); + if (EI->getExtSetKind() == SPIRV::SPIRVEIS_Debug || +- EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100) ++ EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100 || ++ EI->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) + return EI; + } + return nullptr; +@@ -193,6 +194,14 @@ DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { + + DICompositeType * + SPIRVToLLVMDbgTran::transTypeArray(const SPIRVExtInst *DebugInst) { ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ return transTypeArrayNonSemantic(DebugInst); ++ ++ return transTypeArrayOpenCL(DebugInst); ++} ++ ++DICompositeType * ++SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeArray; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); +@@ -247,6 +256,28 @@ SPIRVToLLVMDbgTran::transTypeArray(const SPIRVExtInst *DebugInst) { + return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); + } + ++DICompositeType * ++SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeArray; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ DIType *BaseTy = ++ transDebugInst(BM->get(Ops[BaseTypeIdx])); ++ size_t TotalCount = 1; ++ SmallVector Subscripts; ++ if (DebugInst->getExtOp() == SPIRVDebug::TypeArray) { ++ for (size_t I = SubrangesIdx; I < Ops.size(); ++I) { ++ auto *SR = transDebugInst(BM->get(Ops[I])); ++ if (auto *Count = SR->getCount().get()) ++ TotalCount *= Count->getZExtValue() > 0 ? Count->getZExtValue() : 0; ++ Subscripts.push_back(SR); ++ } ++ } ++ DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; ++ return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); ++} ++ + DICompositeType * + SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeVector; +@@ -287,6 +318,8 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + SPIRVEntry *SizeEntry = BM->getEntry(Ops[SizeIdx]); + if (!(SizeEntry->isExtInst(SPIRVEIS_Debug, SPIRVDebug::DebugInfoNone) || + SizeEntry->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, ++ SPIRVDebug::DebugInfoNone) || ++ SizeEntry->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVDebug::DebugInfoNone))) { + Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); + } +@@ -342,6 +375,36 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + return CT; + } + ++DISubrange * ++SPIRVToLLVMDbgTran::transTypeSubrange(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeSubrange; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() == OperandCount && "Invalid number of operands"); ++ std::vector TranslatedOps(OperandCount, nullptr); ++ auto TransOperand = [&Ops, &TranslatedOps, this](int Idx) -> void { ++ if (!getDbgInst(Ops[Idx])) { ++ if (auto *GlobalVar = getDbgInst(Ops[Idx])) { ++ TranslatedOps[Idx] = ++ cast(transDebugInst(GlobalVar)); ++ } else if (auto *LocalVar = ++ getDbgInst(Ops[Idx])) { ++ TranslatedOps[Idx] = ++ cast(transDebugInst(LocalVar)); ++ } else if (auto *Expr = getDbgInst(Ops[Idx])) { ++ TranslatedOps[Idx] = cast(transDebugInst(Expr)); ++ } else if (auto *Const = BM->get(Ops[Idx])) { ++ int64_t ConstantAsInt = static_cast(Const->getZExtIntValue()); ++ TranslatedOps[Idx] = cast(ConstantAsMetadata::get( ++ ConstantInt::get(M->getContext(), APInt(64, ConstantAsInt)))); ++ } ++ } ++ }; ++ for (int Idx = CountIdx; Idx < OperandCount; ++Idx) ++ TransOperand(Idx); ++ return Builder.getOrCreateSubrange(TranslatedOps[0], TranslatedOps[1], ++ TranslatedOps[2], TranslatedOps[3]); ++} ++ + DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeMember; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +@@ -888,6 +951,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::TypeArray: + return transTypeArray(DebugInst); + ++ case SPIRVDebug::TypeSubrange: ++ return transTypeSubrange(DebugInst); ++ + case SPIRVDebug::TypeVector: + return transTypeVector(DebugInst); + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index a95c99cb..3a0f78d4 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -70,7 +70,9 @@ public: + template + T *transDebugInst(const SPIRVExtInst *DebugInst) { + assert((DebugInst->getExtSetKind() == SPIRVEIS_Debug || +- DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100) && ++ DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 || ++ DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + "Unexpected extended instruction set"); + auto It = DebugInstCache.find(DebugInst); + if (It != DebugInstCache.end()) +@@ -107,11 +109,15 @@ private: + DIType *transTypePointer(const SPIRVExtInst *DebugInst); + + DICompositeType *transTypeArray(const SPIRVExtInst *DebugInst); ++ DICompositeType *transTypeArrayOpenCL(const SPIRVExtInst *DebugInst); ++ DICompositeType *transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst); + + DICompositeType *transTypeVector(const SPIRVExtInst *DebugInst); + + DICompositeType *transTypeComposite(const SPIRVExtInst *DebugInst); + ++ DISubrange *transTypeSubrange(const SPIRVExtInst *DebugInst); ++ + DINode *transTypeMember(const SPIRVExtInst *DebugInst); + + DINode *transTypeEnum(const SPIRVExtInst *DebugInst); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 026a3083..007783cb 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -50,7 +50,8 @@ enum Instruction { + ImportedEntity = 34, + Source = 35, + ModuleINTEL = 36, +- InstCount = 37 ++ InstCount = 37, ++ TypeSubrange = 110 + }; + + enum Flag { +@@ -323,12 +324,23 @@ namespace TypeArray { + enum { + BaseTypeIdx = 0, + ComponentCountIdx = 1, ++ SubrangesIdx = 1, + MinOperandCount = 2 + }; + } + + namespace TypeVector = TypeArray; + ++namespace TypeSubrange { ++enum { ++ CountIdx = 0, ++ LowerBoundIdx = 1, ++ UpperBoundIdx = 2, ++ StrideIdx = 3, ++ OperandCount = 4 ++}; ++} ++ + namespace Typedef { + enum { + NameIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 3695fd56..4e4cbf82 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -78,6 +78,7 @@ enum SPIRVExtInstSetKind { + SPIRVEIS_OpenCL, + SPIRVEIS_Debug, + SPIRVEIS_OpenCL_DebugInfo_100, ++ SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVEIS_Count, + }; + +@@ -129,6 +130,8 @@ template <> inline void SPIRVMap::init() { + add(SPIRVEIS_OpenCL, "OpenCL.std"); + add(SPIRVEIS_Debug, "SPIRV.debug"); + add(SPIRVEIS_OpenCL_DebugInfo_100, "OpenCL.DebugInfo.100"); ++ add(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ "NonSemantic.Kernel.DebugInfo.100"); + } + typedef SPIRVMap SPIRVBuiltinSetNameMap; + +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 9f1aa91a..24555290 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -239,6 +239,7 @@ template <> inline void SPIRVMap::init() { + "DebugTemplateTemplateParameter"); + add(SPIRVDebug::TypeTemplate, "DebugTemplate"); + add(SPIRVDebug::TypePtrToMember, "DebugTypePtrToMember,"); ++ add(SPIRVDebug::TypeSubrange, "DebugTypeSubrange"); + add(SPIRVDebug::Inheritance, "DebugInheritance"); + add(SPIRVDebug::Function, "DebugFunction"); + add(SPIRVDebug::FunctionDecl, "DebugFunctionDecl"); +diff --git a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +index da1ba0df..c91a6506 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +@@ -161,10 +161,14 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + Module->add(Inst); + } else { + if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::Scope) || +- Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope)) { ++ Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ SPIRVDebug::Scope)) { + DebugScope = Inst; + } else if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::NoScope) || + Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, ++ SPIRVDebug::NoScope) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVDebug::NoScope)) { + DebugScope = nullptr; + } else { +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index cd91461c..69a12ca6 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -1761,7 +1761,8 @@ public: + assert(Module && "Invalid module"); + ExtSetKind = Module->getBuiltinSet(ExtSetId); + assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug || +- ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100) && ++ ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100 || ++ ExtSetKind == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + "not supported"); + } + void encode(spv_ostream &O) const override { +@@ -1772,6 +1773,7 @@ public: + break; + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: + getEncoder(O) << ExtOpDebug; + break; + default: +@@ -1789,6 +1791,7 @@ public: + break; + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: + getDecoder(I) >> ExtOpDebug; + break; + default: +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index b5c14cbe..cc64266b 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -642,7 +642,8 @@ void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) { + case OpExtInst: { + SPIRVExtInst *EI = static_cast(E); + if ((EI->getExtSetKind() == SPIRVEIS_Debug || +- EI->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100) && ++ EI->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 || ++ EI->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + EI->getExtOp() != SPIRVDebug::Declare && + EI->getExtOp() != SPIRVDebug::Value && + EI->getExtOp() != SPIRVDebug::Scope && +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h +index a8c15445..2ec832c0 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.h ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.h +@@ -528,6 +528,8 @@ public: + return SPIRVEIS_Debug; + case DebugInfoEIS::OpenCL_DebugInfo_100: + return SPIRVEIS_OpenCL_DebugInfo_100; ++ case DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100: ++ return SPIRVEIS_NonSemantic_Kernel_DebugInfo_100; + } + assert(false && "Unexpected debug info EIS!"); + return SPIRVEIS_Debug; +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll b/test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll +new file mode 100644 +index 00000000..0a901ae8 +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll +@@ -0,0 +1,128 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -to-binary %t.spt -o %t.spv ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++ ++; CHECK-SPIRV: String [[#LocalVarNameId:]] "A$1$upperbound" ++; CHECK-SPIRV: TypeInt [[#TyInt64Id:]] 64 0 ++; CHECK-SPIRV-DAG: Constant [[#TyInt64Id]] [[#Constant1Id:]] 1 0 ++; CHECK-SPIRV-DAG: Constant [[#TyInt64Id]] [[#Constant1000Id:]] 1000 0 ++; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone ++ ++; CHECK-SPIRV: [[#DebugFuncId:]] [[#EISId]] DebugFunction ++; CHECK-SPIRV: [[#DebugTemplate:]] [[#EISId]] DebugTemplate [[#DebugFuncId]] ++; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugTemplate]] ++; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#DINoneId]] [[#Constant1Id]] [[#LocalVarId]] [[#DINoneId]] ++ ++; CHECK-SPIRV: [[#DIExprId:]] [[#EISId]] DebugExpression ++; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#DINoneId]] [[#DIExprId]] [[#DIExprId]] [[#DINoneId]] ++ ++; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#Constant1000Id]] [[#Constant1Id]] [[#DINoneId]] [[#DINoneId]] ++ ++; CHECK-LLVM: [[#Subrange1:]] = !DISubrange(lowerBound: 1, upperBound: ![[#UpperBound:]]) ++; CHECK-LLVM: [[#UpperBound]] = !DILocalVariable(name: "A$1$upperbound" ++; CHECK-LLVM: !DISubrange(lowerBound: !DIExpression(), upperBound: !DIExpression()) ++; CHECK-LLVM: !DISubrange(count: 1000, lowerBound: 1) ++ ++; ModuleID = 'DebugInfoSubrangeUpperBound.bc' ++target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" ++target triple = "spir64-unknown-unknown" ++ ++%structtype = type { [72 x i1] } ++%"QNCA_a0$float" = type { float addrspace(4)*, i64, i64, i64, i64, i64, [1 x %structtype2] } ++%structtype2 = type { i64, i64, i64 } ++ ++; Function Attrs: noinline nounwind ++define spir_kernel void @__omp_offloading_811_198142f_random_fill_sp_l25(i32 addrspace(1)* noalias %0, %structtype* byval(%structtype) %"ascast$val", [1000 x i32] addrspace(1)* noalias %"ascastB$val") #0 !kernel_arg_addr_space !9 !kernel_arg_access_qual !10 !kernel_arg_type !11 !kernel_arg_type_qual !12 !kernel_arg_base_type !11 { ++newFuncRoot: ++ %.ascast = bitcast %structtype* %"ascast$val" to %"QNCA_a0$float"* ++ call void @llvm.dbg.value(metadata %"QNCA_a0$float"* %.ascast, metadata !13, metadata !DIExpression(DW_OP_deref)), !dbg !27 ++ call void @llvm.dbg.value(metadata %"QNCA_a0$float"* %.ascast, metadata !28, metadata !DIExpression(DW_OP_deref)), !dbg !42 ++ call void @llvm.dbg.value(metadata [1000 x i32] addrspace(1)* %"ascastB$val", metadata !47, metadata !DIExpression(DW_OP_deref)), !dbg !51 ++ call void @llvm.dbg.value(metadata i32 addrspace(1)* %0, metadata !54, metadata !DIExpression(DW_OP_deref)), !dbg !59 ++ ret void ++} ++ ++; Function Attrs: nofree nosync nounwind readnone speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) #1 ++ ++attributes #0 = { noinline nounwind } ++attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } ++ ++!llvm.module.flags = !{!0, !1} ++!llvm.dbg.cu = !{!2} ++!spirv.MemoryModel = !{!4} ++!opencl.enable.FP_CONTRACT = !{} ++!spirv.Source = !{!5} ++!opencl.spir.version = !{!6} ++!opencl.ocl.version = !{!6} ++!opencl.used.extensions = !{!7} ++!opencl.used.optional.core.features = !{!7} ++!spirv.Generator = !{!8} ++ ++!0 = !{i32 7, !"Dwarf Version", i32 4} ++!1 = !{i32 2, !"Debug Info Version", i32 3} ++!2 = distinct !DICompileUnit(language: DW_LANG_OpenCL, file: !3, producer: "Fortran", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) ++!3 = !DIFile(filename: "f.f90", directory: "Fortran") ++!4 = !{i32 2, i32 2} ++!5 = !{i32 4, i32 200000} ++!6 = !{i32 2, i32 0} ++!7 = !{} ++!8 = !{i16 6, i16 14} ++!9 = !{i32 0} ++!10 = !{!"none"} ++!11 = !{!"structtype"} ++!12 = !{!""} ++!13 = !DILocalVariable(name: "a", scope: !14, file: !3, line: 15, type: !18) ++!14 = distinct !DISubprogram(name: "random_fill_sp.DIR.OMP.TARGET.8.split.split.split.split", scope: null, file: !3, line: 25, type: !15, scopeLine: 25, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, templateParams: !7, retainedNodes: !17) ++!15 = !DISubroutineType(types: !16) ++!16 = !{null} ++!17 = !{!13} ++!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64) ++!19 = !DICompositeType(tag: DW_TAG_array_type, baseType: !20, size: 32, elements: !21) ++!20 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float) ++!21 = !{!22} ++!22 = !DISubrange(lowerBound: 1, upperBound: !23) ++!23 = !DILocalVariable(name: "A$1$upperbound", scope: !24, type: !26, flags: DIFlagArtificial) ++!24 = distinct !DISubprogram(name: "random_fill_sp", linkageName: "random_fill_sp", scope: null, file: !3, line: 15, type: !15, scopeLine: 15, spFlags: DISPFlagDefinition, unit: !2, templateParams: !7, retainedNodes: !25) ++!25 = !{!23} ++!26 = !DIBasicType(name: "INTEGER*8", size: 64, encoding: DW_ATE_signed) ++!27 = !DILocation(line: 15, column: 67, scope: !14) ++!28 = !DILocalVariable(name: "a", scope: !29, file: !3, line: 15, type: !33) ++!29 = distinct !DISubprogram(name: "random_fill_sp.DIR.OMP.TARGET.8.split.split.split.split", scope: null, file: !3, line: 25, type: !30, scopeLine: 25, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, templateParams: !7, retainedNodes: !32) ++!30 = !DISubroutineType(types: !31) ++!31 = !{null} ++!32 = !{!28} ++!33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 64) ++!34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !35, size: 32, elements: !36) ++!35 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float) ++!36 = !{!37} ++!37 = !DISubrange(lowerBound: !DIExpression(), upperBound: !DIExpression()) ++!38 = !DILocalVariable(name: "A$1$upperbound", scope: !39, type: !41, flags: DIFlagArtificial) ++!39 = distinct !DISubprogram(name: "random_fill_sp", linkageName: "random_fill_sp", scope: null, file: !3, line: 15, type: !30, scopeLine: 15, spFlags: DISPFlagDefinition, unit: !2, templateParams: !7, retainedNodes: !40) ++!40 = !{!38} ++!41 = !DIBasicType(name: "INTEGER*8", size: 64, encoding: DW_ATE_signed) ++!42 = !DILocation(line: 15, column: 67, scope: !29) ++!43 = !DIBasicType(name: "INTEGER*4", size: 32, encoding: DW_ATE_signed) ++!44 = !{} ++!45 = !DISubroutineType(types: !44) ++!46 = distinct !DISubprogram(name: "test_target_map_array_default_IP_test_array_map_no_map_type_.DIR.OMP.TARGET.340.split", scope: !3, file: !3, line: 32, type: !45, scopeLine: 32, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2) ++!47 = !DILocalVariable(name: "compute_array", scope: !46, file: !3, line: 27, type: !48) ++!48 = !DICompositeType(tag: DW_TAG_array_type, baseType: !43, elements: !49) ++!49 = !{!50} ++!50 = !DISubrange(count: 1000, lowerBound: 1) ++!51 = !DILocation(line: 27, column: 24, scope: !46) ++!52 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 51, type: !53, scopeLine: 51, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2) ++!53 = !DISubroutineType(types: !7) ++!54 = !DILocalVariable(name: "isHost", scope: !52, file: !3, line: 34, type: !55) ++!55 = !DICompositeType(tag: DW_TAG_array_type, baseType: !56, elements: !57) ++!56 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!57 = !{!58} ++!58 = !DISubrange(count: -1) ++!59 = !DILocation(line: 34, column: 33, scope: !52) +diff --git a/test/DebugInfo/DebugInfoSubrange.ll b/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +similarity index 100% +rename from test/DebugInfo/DebugInfoSubrange.ll +rename to test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp +index cbc77539..60254ac4 100644 +--- a/tools/llvm-spirv/llvm-spirv.cpp ++++ b/tools/llvm-spirv/llvm-spirv.cpp +@@ -225,7 +225,14 @@ static cl::opt DebugEIS( + clEnumValN(SPIRV::DebugInfoEIS::OpenCL_DebugInfo_100, "ocl-100", + "Emit debug info compliant with the OpenCL.DebugInfo.100 " + "extended instruction set. This version of SPIR-V debug " +- "info format is compatible with the SPIRV-Tools"))); ++ "info format is compatible with the SPIRV-Tools"), ++ clEnumValN( ++ SPIRV::DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100, ++ "nonsemantic-kernel-100", ++ "Emit debug info compliant with the " ++ "NonSemantic.Kernel.DebugInfo.100 extended instruction set. This " ++ "version of SPIR-V debug info format is compatible with the rules " ++ "regarding non-semantic instruction sets."))); + + static cl::opt SPIRVReplaceLLVMFmulAddWithOpenCLMad( + "spirv-replace-fmuladd-with-ocl-mad", +@@ -715,6 +722,9 @@ int main(int Ac, char **Av) { + "affects translation from LLVM IR to SPIR-V"; + } else { + Opts.setDebugInfoEIS(DebugEIS); ++ if (DebugEIS.getValue() == ++ SPIRV::DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100) ++ Opts.setAllowExtraDIExpressionsEnabled(true); + } + } + +-- +2.20.1 + diff --git a/patches/0019-Backport-to-15-DebugInfo-Add-Target-Function-optiona.patch b/patches/0019-Backport-to-15-DebugInfo-Add-Target-Function-optiona.patch new file mode 100644 index 0000000..4a17204 --- /dev/null +++ b/patches/0019-Backport-to-15-DebugInfo-Add-Target-Function-optiona.patch @@ -0,0 +1,145 @@ +From 3d1bf93488f9410db4401a94470549691c90ecac Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Thu, 23 Feb 2023 19:11:30 +0100 +Subject: [PATCH 19/79] [Backport to 15][DebugInfo] Add Target Function + optional parameter to DebugFunction (#1853) + +It's being added in +KhronosGroup/SPIRV-Registry#186 + +In DWARF it's used in 'trampoline' functions generated for Fortran external function calls. +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 10 +++- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 13 +++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 1 + + .../DebugInfoTargetFunction.ll | 59 +++++++++++++++++++ + 4 files changed, 80 insertions(+), 3 deletions(-) + create mode 100644 test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index d6da1a82..6985665d 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -988,8 +988,16 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + + if (DISubprogram *FuncDecl = Func->getDeclaration()) + Ops.push_back(transDbgEntry(FuncDecl)->getId()); +- else ++ else { + Ops.push_back(getDebugInfoNoneId()); ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) { ++ // Translate targetFuncName mostly for Fortran trampoline function if it ++ // is the case ++ StringRef TargetFunc = Func->getTargetFuncName(); ++ if (!TargetFunc.empty()) ++ Ops.push_back(BM->getString(TargetFunc.str())->getId()); ++ } ++ } + + DebugFunc = BM->addDebugInfo(SPIRVDebug::Function, getVoidTy(), Ops); + MDMap.insert(std::make_pair(Func, DebugFunc)); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 94c3616f..b9e1679b 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -609,9 +609,18 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + !IsDefinition) + DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, + nullptr, Flags, SPFlags, TParamsArray); +- else ++ else { ++ // Create targetFuncName mostly for Fortran trampoline function if it is ++ // the case ++ StringRef TargetFunction; ++ if (Ops.size() > TargetFunctionNameIdx) { ++ TargetFunction = getString(Ops[TargetFunctionNameIdx]); ++ } + DIS = Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty, +- ScopeLine, Flags, SPFlags, TParamsArray, FD); ++ ScopeLine, Flags, SPFlags, TParamsArray, FD, ++ /*ThrownTypes*/ nullptr, ++ /*Annotations*/ nullptr, TargetFunction); ++ } + DebugInstCache[DebugInst] = DIS; + SPIRVId RealFuncId = Ops[FunctionIdIdx]; + FuncMap[RealFuncId] = DIS; +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 007783cb..dcebe6ea 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -513,6 +513,7 @@ enum { + ScopeLineIdx = 8, + FunctionIdIdx = 9, + DeclarationIdx = 10, ++ TargetFunctionNameIdx = 11, + MinOperandCount = 10 + }; + } +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll b/test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll +new file mode 100644 +index 00000000..25d5330b +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll +@@ -0,0 +1,59 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -to-binary %t.spt -o %t.spv ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV-DAG: String [[#Func:]] "foo_wrapper" ++; CHECK-SPIRV-DAG: String [[#TargetFunc:]] "_Z3foov" ++ ++; CHECK-SPIRV-DAG: ExtInst [[#]] [[#DebugNone:]] [[#]] DebugInfoNone ++; CHECK-SPIRV-DAG: ExtInst [[#]] [[#]] [[#]] DebugFunction [[#Func]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#DebugNone]] [[#TargetFunc]] ++ ++; CHECK-LLVM: define spir_func void @_Z11foo_wrapperv() {{.*}} !dbg ![[#DbgSubProg:]] { ++; CHECK-LLVM: ![[#DbgSubProg]] = distinct !DISubprogram(name: "foo_wrapper", linkageName: "_Z11foo_wrapperv", scope: null, file: ![[#]], line: 3, type: ![[#]], scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], templateParams: ![[#]], retainedNodes: ![[#]], targetFuncName: "_Z3foov") ++ ++; ModuleID = 'example.bc' ++target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" ++target triple = "spir64-unknown-unknown" ++ ++define spir_func void @_Z11foo_wrapperv() !dbg !10 { ++ call void @_Z3foov(), !dbg !15 ++ ret void, !dbg !16 ++} ++ ++declare spir_func void @_Z3foov() ++ ++define spir_func void @_Z3boov() !dbg !17 { ++ call void @_Z11foo_wrapperv(), !dbg !18 ++ ret void, !dbg !19 ++} ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} ++!llvm.ident = !{!9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 88bd2601c013e349fa907b3f878312a94e16e9f6)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "/app/example.cpp", directory: "/app") ++!2 = !{i32 7, !"Dwarf Version", i32 4} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 8, !"PIC Level", i32 2} ++!6 = !{i32 7, !"PIE Level", i32 2} ++!7 = !{i32 7, !"uwtable", i32 2} ++!8 = !{i32 7, !"frame-pointer", i32 2} ++!9 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git 88bd2601c013e349fa907b3f878312a94e16e9f6)"} ++!10 = distinct !DISubprogram(name: "foo_wrapper", linkageName: "_Z11foo_wrapperv", scope: !11, file: !11, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14, targetFuncName: "_Z3foov") ++!11 = !DIFile(filename: "example.cpp", directory: "/app") ++!12 = !DISubroutineType(types: !13) ++!13 = !{null} ++!14 = !{} ++!15 = !DILocation(line: 4, column: 5, scope: !10) ++!16 = !DILocation(line: 5, column: 1, scope: !10) ++!17 = distinct !DISubprogram(name: "boo", linkageName: "_Z3boov", scope: !11, file: !11, line: 7, type: !12, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) ++!18 = !DILocation(line: 8, column: 5, scope: !17) ++!19 = !DILocation(line: 9, column: 1, scope: !17) +-- +2.20.1 + diff --git a/patches/0020-Backport-to-15-DebugInfo-Add-new-Source-Languages-ta.patch b/patches/0020-Backport-to-15-DebugInfo-Add-new-Source-Languages-ta.patch new file mode 100644 index 0000000..10398e9 --- /dev/null +++ b/patches/0020-Backport-to-15-DebugInfo-Add-new-Source-Languages-ta.patch @@ -0,0 +1,335 @@ +From b4ac72e83607fa9bcc482f50a5b9a923cb80fd53 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Thu, 23 Feb 2023 10:10:43 -0800 +Subject: [PATCH 20/79] [Backport to 15][DebugInfo] Add new Source Languages + table used in DebugCompilationUnit (#1854) + +This extended source language table is used by DebugCompilationUnit instruction when the extension is enabled. It enables support for more languages than exists in a core specification. +Spec: KhronosGroup/SPIRV-Registry#186 + +Enabling of Fortran language also allowed to fix FortranArray test that was originally XFAIL-ed in 9e234d9. +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 5 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 5 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 102 +++++++++++++++++- + lib/SPIRV/libSPIRV/spirv_internal.hpp | 52 +++++++++ + .../NonSemanticKernel100}/FortranArray.ll | 14 +-- + .../SourceLanguageLLVMToSPIRV.ll | 40 +++++++ + 6 files changed, 202 insertions(+), 16 deletions(-) + rename test/{ => DebugInfo/NonSemanticKernel100}/FortranArray.ll (84%) + create mode 100644 test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 6985665d..cb456910 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -508,7 +508,10 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { + Ops[SourceIdx] = getSource(CU)->getId(); + auto DwarfLang = + static_cast(CU->getSourceLanguage()); +- Ops[LanguageIdx] = convertDWARFSourceLangToSPIRV(DwarfLang); ++ Ops[LanguageIdx] = ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100 ++ ? convertDWARFSourceLangToSPIRVNonSemanticDbgInfo(DwarfLang) ++ : convertDWARFSourceLangToSPIRV(DwarfLang); + BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); + // Cache CU in a member. + SPIRVCU = static_cast( +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index b9e1679b..e2d4e9ad 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -128,7 +128,10 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::CompilationUnit; + assert(Ops.size() == OperandCount && "Invalid number of operands"); + M->addModuleFlag(llvm::Module::Max, "Dwarf Version", Ops[DWARFVersionIdx]); +- unsigned SourceLang = convertSPIRVSourceLangToDWARF(Ops[LanguageIdx]); ++ unsigned SourceLang = ++ DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100 ++ ? convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(Ops[LanguageIdx]) ++ : convertSPIRVSourceLangToDWARF(Ops[LanguageIdx]); + auto Producer = findModuleProducer(); + CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, + false, "", 0); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index dcebe6ea..4c1c3d47 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -2,6 +2,7 @@ + #define SPIRV_DEBUG_H + #include "SPIRVUtil.h" + #include "spirv/unified1/spirv.hpp" ++#include "spirv_internal.hpp" + #include "llvm/BinaryFormat/Dwarf.h" + + namespace SPIRVDebug { +@@ -810,9 +811,6 @@ inline spv::SourceLanguage convertDWARFSourceLangToSPIRV(dwarf::SourceLanguage D + switch (DwarfLang) { + // When updating this function, make sure to also + // update convertSPIRVSourceLangToDWARF() +- +- // LLVM does not yet define DW_LANG_C_plus_plus_17 +- // case dwarf::SourceLanguage::DW_LANG_C_plus_plus_17: + case dwarf::SourceLanguage::DW_LANG_C_plus_plus_14: + case dwarf::SourceLanguage::DW_LANG_C_plus_plus: + return spv::SourceLanguage::SourceLanguageCPP_for_OpenCL; +@@ -831,8 +829,6 @@ inline dwarf::SourceLanguage convertSPIRVSourceLangToDWARF(unsigned SourceLang) + case spv::SourceLanguage::SourceLanguageOpenCL_CPP: + return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; + case spv::SourceLanguage::SourceLanguageCPP_for_OpenCL: +- // LLVM does not yet define DW_LANG_C_plus_plus_17 +- // SourceLang = dwarf::SourceLanguage::DW_LANG_C_plus_plus_17; + return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; + case spv::SourceLanguage::SourceLanguageOpenCL_C: + case spv::SourceLanguage::SourceLanguageESSL: +@@ -844,6 +840,102 @@ inline dwarf::SourceLanguage convertSPIRVSourceLangToDWARF(unsigned SourceLang) + } + } + ++inline spv::SourceLanguage convertDWARFSourceLangToSPIRVNonSemanticDbgInfo( ++ dwarf::SourceLanguage DwarfLang) { ++ switch (DwarfLang) { ++ // When updating this function, make sure to also ++ // update convertSPIRVSourceLangToDWARFNonSemanticDbgInfo() ++ case dwarf::SourceLanguage::DW_LANG_OpenCL: ++ return spv::SourceLanguage::SourceLanguageOpenCL_C; ++ ++ case dwarf::SourceLanguage::DW_LANG_C_plus_plus_14: ++ return spv::internal::SourceLanguageCPP14; ++ case dwarf::SourceLanguage::DW_LANG_C_plus_plus_11: ++ return spv::internal::SourceLanguageCPP11; ++ case dwarf::SourceLanguage::DW_LANG_C_plus_plus_03: ++ return spv::internal::SourceLanguageCPP03; ++ case dwarf::SourceLanguage::DW_LANG_C_plus_plus: ++ return spv::internal::SourceLanguageCPP; ++ ++ case dwarf::SourceLanguage::DW_LANG_C: ++ return spv::internal::SourceLanguageC; ++ case dwarf::SourceLanguage::DW_LANG_C99: ++ return spv::internal::SourceLanguageC99; ++ case dwarf::SourceLanguage::DW_LANG_C11: ++ return spv::internal::SourceLanguageC11; ++ ++ case dwarf::SourceLanguage::DW_LANG_Python: ++ return spv::internal::SourceLanguagePython; ++ case dwarf::SourceLanguage::DW_LANG_Julia: ++ return spv::internal::SourceLanguageJulia; ++ case dwarf::SourceLanguage::DW_LANG_Rust: ++ return spv::internal::SourceLanguageRust; ++ case dwarf::SourceLanguage::DW_LANG_D: ++ return spv::internal::SourceLanguageD; ++ ++ case dwarf::SourceLanguage::DW_LANG_Fortran95: ++ return spv::internal::SourceLanguageFortran95; ++ case dwarf::SourceLanguage::DW_LANG_Fortran03: ++ return spv::internal::SourceLanguageFortran2003; ++ case dwarf::SourceLanguage::DW_LANG_Fortran08: ++ return spv::internal::SourceLanguageFortran2008; ++ default: ++ return spv::SourceLanguage::SourceLanguageUnknown; ++ } ++} ++ ++inline dwarf::SourceLanguage ++convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(unsigned SourceLang) { ++ switch (SourceLang) { ++ // When updating this function, make sure to also ++ // update convertDWARFSourceLangToSPIRVNonSemanticDbgInfo() ++ case spv::SourceLanguage::SourceLanguageOpenCL_CPP: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; ++ case spv::SourceLanguage::SourceLanguageCPP_for_OpenCL: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; ++ ++ case spv::internal::SourceLanguageCPP14: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; ++ case spv::internal::SourceLanguageCPP11: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus_11; ++ case spv::internal::SourceLanguageCPP03: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus_03; ++ case spv::internal::SourceLanguageCPP: ++ return dwarf::SourceLanguage::DW_LANG_C_plus_plus; ++ ++ case spv::internal::SourceLanguageC: ++ return dwarf::SourceLanguage::DW_LANG_C; ++ case spv::internal::SourceLanguageC99: ++ return dwarf::SourceLanguage::DW_LANG_C99; ++ case spv::internal::SourceLanguageC11: ++ return dwarf::SourceLanguage::DW_LANG_C11; ++ ++ case spv::internal::SourceLanguagePython: ++ return dwarf::SourceLanguage::DW_LANG_Python; ++ case spv::internal::SourceLanguageJulia: ++ return dwarf::SourceLanguage::DW_LANG_Julia; ++ case spv::internal::SourceLanguageRust: ++ return dwarf::SourceLanguage::DW_LANG_Rust; ++ case spv::internal::SourceLanguageD: ++ return dwarf::SourceLanguage::DW_LANG_D; ++ ++ case spv::internal::SourceLanguageFortran95: ++ return dwarf::SourceLanguage::DW_LANG_Fortran95; ++ case spv::internal::SourceLanguageFortran2003: ++ return dwarf::SourceLanguage::DW_LANG_Fortran03; ++ case spv::internal::SourceLanguageFortran2008: ++ return dwarf::SourceLanguage::DW_LANG_Fortran08; ++ ++ case spv::SourceLanguage::SourceLanguageOpenCL_C: ++ case spv::SourceLanguage::SourceLanguageESSL: ++ case spv::SourceLanguage::SourceLanguageGLSL: ++ case spv::SourceLanguage::SourceLanguageHLSL: ++ case spv::SourceLanguage::SourceLanguageUnknown: ++ default: ++ return dwarf::DW_LANG_OpenCL; ++ } ++} ++ + namespace SPIRV { + typedef SPIRVMap DbgEncodingMap; + template <> +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index a39633e3..def8419c 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -29,6 +29,25 @@ + namespace spv { + namespace internal { + ++enum InternalSourceLanguageNonSemanticDI { ++ ISourceLanguagePython = 101, ++ ISourceLanguageJulia = 102, ++ ISourceLanguageRust = 103, ++ ISourceLanguageD = 104, ++ ISourceLanguageFortran95 = 105, ++ ISourceLanguageFortran2003 = 106, ++ ISourceLanguageFortran2008 = 107, ++ ISourceLanguageC = 108, ++ ISourceLanguageC99 = 109, ++ ISourceLanguageC11 = 110, ++ ISourceLanguageCPP = 111, ++ ISourceLanguageCPP03 = 112, ++ ISourceLanguageCPP11 = 113, ++ ISourceLanguageCPP14 = 114, ++ ISourceLanguageCPP17 = 115, ++ ISourceLanguageCPP20 = 116, ++}; ++ + enum InternalLinkageType { + ILTPrev = LinkageTypeMax - 2, + ILTInternal +@@ -132,6 +151,39 @@ _SPIRV_OP(Op, MaskedGatherINTEL) + _SPIRV_OP(Op, MaskedScatterINTEL) + #undef _SPIRV_OP + ++constexpr SourceLanguage SourceLanguagePython = ++ static_cast(ISourceLanguagePython); ++constexpr SourceLanguage SourceLanguageJulia = ++ static_cast(ISourceLanguageJulia); ++constexpr SourceLanguage SourceLanguageRust = ++ static_cast(ISourceLanguageRust); ++constexpr SourceLanguage SourceLanguageD = ++ static_cast(ISourceLanguageD); ++constexpr SourceLanguage SourceLanguageFortran95 = ++ static_cast(ISourceLanguageFortran95); ++constexpr SourceLanguage SourceLanguageFortran2003 = ++ static_cast(ISourceLanguageFortran2003); ++constexpr SourceLanguage SourceLanguageFortran2008 = ++ static_cast(ISourceLanguageFortran2008); ++constexpr SourceLanguage SourceLanguageC = ++ static_cast(ISourceLanguageC); ++constexpr SourceLanguage SourceLanguageC99 = ++ static_cast(ISourceLanguageC99); ++constexpr SourceLanguage SourceLanguageC11 = ++ static_cast(ISourceLanguageC11); ++constexpr SourceLanguage SourceLanguageCPP = ++ static_cast(ISourceLanguageCPP); ++constexpr SourceLanguage SourceLanguageCPP03 = ++ static_cast(ISourceLanguageCPP03); ++constexpr SourceLanguage SourceLanguageCPP11 = ++ static_cast(ISourceLanguageCPP11); ++constexpr SourceLanguage SourceLanguageCPP14 = ++ static_cast(ISourceLanguageCPP14); ++constexpr SourceLanguage SourceLanguageCPP17 = ++ static_cast(ISourceLanguageCPP17); ++constexpr SourceLanguage SourceLanguageCPP20 = ++ static_cast(ISourceLanguageCPP20); ++ + constexpr Op OpForward = static_cast(IOpForward); + constexpr Op OpTypeTokenINTEL = static_cast(IOpTypeTokenINTEL); + constexpr Op OpArithmeticFenceINTEL = static_cast(IOpArithmeticFenceINTEL); +diff --git a/test/FortranArray.ll b/test/DebugInfo/NonSemanticKernel100/FortranArray.ll +similarity index 84% +rename from test/FortranArray.ll +rename to test/DebugInfo/NonSemanticKernel100/FortranArray.ll +index 1cb0739a..b9d37447 100644 +--- a/test/FortranArray.ll ++++ b/test/DebugInfo/NonSemanticKernel100/FortranArray.ll +@@ -1,16 +1,12 @@ + ; RUN: llvm-as %s -o %t.bc + ; Translation shouldn't crash: +-; RUN: llvm-spirv %t.bc -spirv-text +-; RUN: llvm-spirv %t.bc -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +-; XFAIL: * +-; The language ID is not preserved when translating from .ll to .spv +-; and back to .ll. This causes the LLVM IR verifier to fail as there +-; are different rules for valid DISubRange depending on language ID. +- +-; CHECK-LLVM: !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus)) ++; CHECK-LLVM: !DICompileUnit(language: DW_LANG_Fortran95 ++; CHECK-LLVM: !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) + + source_filename = "llvm-link" + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +diff --git a/test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll b/test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll +new file mode 100644 +index 00000000..fd67dcbe +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll +@@ -0,0 +1,40 @@ ++; Test checks that DW_LANG_C99, DW_LANG_OpenCL, and all DW_LANG_C_plus_plus_X are mapped to ++; appropriate SourceLanguages in SPIRV when the extended debug info is enabled. ++ ++; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C99/' %s | llvm-as - -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-C99 ++ ++; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_OpenCL/' %s | llvm-as - -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-OPENCLC ++ ++; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus/' %s | llvm-as - -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP ++ ++; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus_14/' %s | llvm-as - -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP14 ++ ++; CHECK-C99: DebugCompileUnit [[#]] [[#]] [[#]] 109 ++; CHECK-OPENCLC: DebugCompileUnit [[#]] [[#]] [[#]] 3 ++; CHECK-CPP: DebugCompileUnit [[#]] [[#]] [[#]] 111 ++; CHECK-CPP14: DebugCompileUnit [[#]] [[#]] [[#]] 114 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64-unknown-unknown" ++ ++define dso_local spir_kernel void @func() local_unnamed_addr !dbg !7 !kernel_arg_addr_space !2 !kernel_arg_access_qual !2 !kernel_arg_type !2 !kernel_arg_base_type !2 !kernel_arg_type_qual !2 { ++entry: ++ ret void ++} ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!3, !4, !5} ++ ++!0 = distinct !DICompileUnit(language: INPUT_LANGUAGE, file: !1) ++!1 = !DIFile(filename: "test.cl", directory: "/tmp", checksumkind: CSK_MD5, checksum: "18aa9ce738eaafc7b7b7181c19092815") ++!2 = !{} ++!3 = !{i32 7, !"Dwarf Version", i32 5} ++!4 = !{i32 2, !"Debug Info Version", i32 3} ++!5 = !{i32 1, !"wchar_size", i32 4} ++!6 = !{i32 2, i32 0} ++!7 = distinct !DISubprogram(name: "func", scope: !8, file: !8, line: 1, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) ++!8 = !DIFile(filename: "test.cl", directory: "/tmp", checksumkind: CSK_MD5, checksum: "18aa9ce738eaafc7b7b7181c19092815") +-- +2.20.1 + diff --git a/patches/0021-Backport-to-15-DebugInfo-Add-an-option-for-NonSemant.patch b/patches/0021-Backport-to-15-DebugInfo-Add-an-option-for-NonSemant.patch new file mode 100644 index 0000000..a7489f2 --- /dev/null +++ b/patches/0021-Backport-to-15-DebugInfo-Add-an-option-for-NonSemant.patch @@ -0,0 +1,180 @@ +From 5e0c0e73a153d42b5099c1103a5674efdfa64a1c Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 1 Mar 2023 19:23:49 +0100 +Subject: [PATCH 21/79] [Backport to 15][DebugInfo] Add an option for + NonSemantic.Shader.DebugInfo.100 (#1855) + +Under this option this extended instruction set will be implemented +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc + +TODO: to rename NonSemantic.Kernel.DebugInfo.100 to +NonSemantic.Shader.DebugInfo.200 when the name is stable + +Signed-off-by: Sidorov, Dmitry +--- + include/LLVMSPIRVOpts.h | 1 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 2 ++ + lib/SPIRV/SPIRVToLLVMDbgTran.h | 2 ++ + lib/SPIRV/libSPIRV/SPIRVEnum.h | 3 +++ + lib/SPIRV/libSPIRV/SPIRVFunction.cpp | 4 ++++ + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 3 +++ + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 1 + + lib/SPIRV/libSPIRV/SPIRVModule.h | 2 ++ + tools/llvm-spirv/llvm-spirv.cpp | 7 +++++++ + 9 files changed, 25 insertions(+) + +diff --git a/include/LLVMSPIRVOpts.h b/include/LLVMSPIRVOpts.h +index 8c140377..e821a1fa 100644 +--- a/include/LLVMSPIRVOpts.h ++++ b/include/LLVMSPIRVOpts.h +@@ -83,6 +83,7 @@ enum class FPContractMode : uint32_t { On, Off, Fast }; + enum class DebugInfoEIS : uint32_t { + SPIRV_Debug, + OpenCL_DebugInfo_100, ++ NonSemantic_Shader_DebugInfo_100, + NonSemantic_Kernel_DebugInfo_100 + }; + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index e2d4e9ad..2178582f 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -92,6 +92,8 @@ SPIRVExtInst *SPIRVToLLVMDbgTran::getDbgInst(const SPIRVId Id) { + SPIRVExtInst *EI = static_cast(E); + if (EI->getExtSetKind() == SPIRV::SPIRVEIS_Debug || + EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100 || ++ EI->getExtSetKind() == ++ SPIRV::SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || + EI->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) + return EI; + } +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 3a0f78d4..68a8351c 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -71,6 +71,8 @@ public: + T *transDebugInst(const SPIRVExtInst *DebugInst) { + assert((DebugInst->getExtSetKind() == SPIRVEIS_Debug || + DebugInst->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 || ++ DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || + DebugInst->getExtSetKind() == + SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + "Unexpected extended instruction set"); +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 4e4cbf82..9bb59b6e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -78,6 +78,7 @@ enum SPIRVExtInstSetKind { + SPIRVEIS_OpenCL, + SPIRVEIS_Debug, + SPIRVEIS_OpenCL_DebugInfo_100, ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_100, + SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVEIS_Count, + }; +@@ -130,6 +131,8 @@ template <> inline void SPIRVMap::init() { + add(SPIRVEIS_OpenCL, "OpenCL.std"); + add(SPIRVEIS_Debug, "SPIRV.debug"); + add(SPIRVEIS_OpenCL_DebugInfo_100, "OpenCL.DebugInfo.100"); ++ add(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ "NonSemantic.Shader.DebugInfo.100"); + add(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + "NonSemantic.Kernel.DebugInfo.100"); + } +diff --git a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +index c91a6506..64aa40f6 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +@@ -162,12 +162,16 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + } else { + if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::Scope) || + Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::Scope) || + Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVDebug::Scope)) { + DebugScope = Inst; + } else if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::NoScope) || + Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, + SPIRVDebug::NoScope) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::NoScope) || + Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, + SPIRVDebug::NoScope)) { + DebugScope = nullptr; +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 69a12ca6..568885fb 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -1762,6 +1762,7 @@ public: + ExtSetKind = Module->getBuiltinSet(ExtSetId); + assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug || + ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100 || ++ ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || + ExtSetKind == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + "not supported"); + } +@@ -1773,6 +1774,7 @@ public: + break; + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_100: + case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: + getEncoder(O) << ExtOpDebug; + break; +@@ -1791,6 +1793,7 @@ public: + break; + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_100: + case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: + getDecoder(I) >> ExtOpDebug; + break; +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index cc64266b..5cbc2a80 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -643,6 +643,7 @@ void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) { + SPIRVExtInst *EI = static_cast(E); + if ((EI->getExtSetKind() == SPIRVEIS_Debug || + EI->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 || ++ EI->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || + EI->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && + EI->getExtOp() != SPIRVDebug::Declare && + EI->getExtOp() != SPIRVDebug::Value && +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h +index 2ec832c0..bd462aa4 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.h ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.h +@@ -528,6 +528,8 @@ public: + return SPIRVEIS_Debug; + case DebugInfoEIS::OpenCL_DebugInfo_100: + return SPIRVEIS_OpenCL_DebugInfo_100; ++ case DebugInfoEIS::NonSemantic_Shader_DebugInfo_100: ++ return SPIRVEIS_NonSemantic_Shader_DebugInfo_100; + case DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100: + return SPIRVEIS_NonSemantic_Kernel_DebugInfo_100; + } +diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp +index 60254ac4..8cb62b6a 100644 +--- a/tools/llvm-spirv/llvm-spirv.cpp ++++ b/tools/llvm-spirv/llvm-spirv.cpp +@@ -226,6 +226,13 @@ static cl::opt DebugEIS( + "Emit debug info compliant with the OpenCL.DebugInfo.100 " + "extended instruction set. This version of SPIR-V debug " + "info format is compatible with the SPIRV-Tools"), ++ clEnumValN( ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_100, ++ "nonsemantic-shader-100", ++ "Emit debug info compliant with the " ++ "NonSemantic.Shader.DebugInfo.100 extended instruction set. This " ++ "version of SPIR-V debug info format is compatible with the rules " ++ "regarding non-semantic instruction sets."), + clEnumValN( + SPIRV::DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100, + "nonsemantic-kernel-100", +-- +2.20.1 + diff --git a/patches/0022-Backport-to-15-DebugInfo-Add-DebugTypeArrayDynamic-t.patch b/patches/0022-Backport-to-15-DebugInfo-Add-DebugTypeArrayDynamic-t.patch new file mode 100644 index 0000000..f62196c --- /dev/null +++ b/patches/0022-Backport-to-15-DebugInfo-Add-DebugTypeArrayDynamic-t.patch @@ -0,0 +1,454 @@ +From bb4007f7dbdaed7d43e18ba4c824be0b799bb2b0 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 8 Mar 2023 19:22:53 +0100 +Subject: [PATCH 22/79] [Backport to 15][DebugInfo] Add DebugTypeArrayDynamic + translation (#1871) + +This instruction describes a dynamic array, mostly for Fortran 90. + +Unlike DebugTypeArray it has Data Location, Associated, Allocated +and Rank parameters. If the appropriate metadata parameters +appear in LLVM IR in DW_TAG_array_type metadata, then such +debug type becomes treated as dynamic array by the translator +(of course if the appropriate extended instruction set is enabled). + +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/pull/186 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 56 +++++++++++-- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 1 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 46 ++++++++++- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 1 + + lib/SPIRV/libSPIRV/SPIRV.debug.h | 15 +++- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + .../NonSemanticKernel100/FortranArray.ll | 5 +- + .../FortranDynamicArrayExpr.ll | 81 +++++++++++++++++++ + .../FortranDynamicArrayVar.ll | 74 +++++++++++++++++ + 9 files changed, 272 insertions(+), 8 deletions(-) + create mode 100644 test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll + create mode 100644 test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index cb456910..8aff387b 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -481,6 +481,14 @@ SPIRVWord adjustAccessFlags(DIScope *Scope, SPIRVWord Flags) { + return Flags; + } + ++// Fortran dynamic arrays can have following 'dataLocation', 'associated' ++// 'allocated' and 'rank' debug metadata. Such arrays are being mapped on ++// DebugTypeArrayDynamic from NonSemantic.Kernel.100 debug spec ++inline bool isFortranArrayDynamic(const DICompositeType *AT) { ++ return (AT->getRawDataLocation() || AT->getRawAssociated() || ++ AT->getRawAllocated() || AT->getRawRank()); ++} ++ + /// The following methods (till the end of the file) implement translation of + /// debug instrtuctions described in the spec. + +@@ -561,8 +569,11 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgQualifiedType(const DIDerivedType *QT) { + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) { +- if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) { ++ if (isFortranArrayDynamic(AT)) ++ return transDbgArrayTypeDynamic(AT); + return transDbgArrayTypeNonSemantic(AT); ++ } + + return transDbgArrayTypeOpenCL(AT); + } +@@ -571,8 +582,7 @@ SPIRVEntry * + LLVMToSPIRVDbgTran::transDbgArrayTypeOpenCL(const DICompositeType *AT) { + using namespace SPIRVDebug::Operand::TypeArray; + SPIRVWordVec Ops(MinOperandCount); +- SPIRVEntry *Base = transDbgEntry(AT->getBaseType()); +- Ops[BaseTypeIdx] = Base->getId(); ++ Ops[BaseTypeIdx] = transDbgEntry(AT->getBaseType())->getId(); + + DINodeArray AR(AT->getElements()); + // For N-dimensianal arrays AR.getNumElements() == N +@@ -615,8 +625,7 @@ SPIRVEntry * + LLVMToSPIRVDbgTran::transDbgArrayTypeNonSemantic(const DICompositeType *AT) { + using namespace SPIRVDebug::Operand::TypeArray; + SPIRVWordVec Ops(MinOperandCount); +- SPIRVEntry *Base = transDbgEntry(AT->getBaseType()); +- Ops[BaseTypeIdx] = Base->getId(); ++ Ops[BaseTypeIdx] = transDbgEntry(AT->getBaseType())->getId(); + + DINodeArray AR(AT->getElements()); + // For N-dimensianal arrays AR.getNumElements() == N +@@ -635,6 +644,43 @@ LLVMToSPIRVDbgTran::transDbgArrayTypeNonSemantic(const DICompositeType *AT) { + return BM->addDebugInfo(SPIRVDebug::TypeArray, getVoidTy(), Ops); + } + ++// The function is used to translate Fortran's dynamic arrays ++SPIRVEntry * ++LLVMToSPIRVDbgTran::transDbgArrayTypeDynamic(const DICompositeType *AT) { ++ using namespace SPIRVDebug::Operand::TypeArrayDynamic; ++ SPIRVWordVec Ops(MinOperandCount); ++ Ops[BaseTypeIdx] = transDbgEntry(AT->getBaseType())->getId(); ++ ++ // DataLocation, Associated, Allocated and Rank can be either DIExpression ++ // metadata or DIVariable ++ auto TransOperand = [&](llvm::Metadata *DIMD) -> SPIRVWord { ++ if (auto *DIExpr = dyn_cast_or_null(DIMD)) ++ return transDbgExpression(DIExpr)->getId(); ++ if (auto *DIVar = dyn_cast_or_null(DIMD)) { ++ if (const DILocalVariable *LV = dyn_cast(DIVar)) ++ return transDbgLocalVariable(LV)->getId(); ++ if (const DIGlobalVariable *GV = dyn_cast(DIVar)) ++ return transDbgGlobalVariable(GV)->getId(); ++ } ++ return getDebugInfoNoneId(); ++ }; ++ ++ Ops[DataLocationIdx] = TransOperand(AT->getRawDataLocation()); ++ Ops[AssociatedIdx] = TransOperand(AT->getRawAssociated()); ++ Ops[AllocatedIdx] = TransOperand(AT->getRawAllocated()); ++ Ops[RankIdx] = TransOperand(AT->getRawRank()); ++ ++ DINodeArray AR(AT->getElements()); ++ // For N-dimensianal arrays AR.getNumElements() == N ++ const unsigned N = AR.size(); ++ Ops.resize(SubrangesIdx + N); ++ for (unsigned I = 0; I < N; ++I) { ++ DISubrange *SR = cast(AR[I]); ++ Ops[SubrangesIdx + I] = transDbgEntry(SR)->getId(); ++ } ++ return BM->addDebugInfo(SPIRVDebug::TypeArrayDynamic, getVoidTy(), Ops); ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgSubrangeType(const DISubrange *ST) { + using namespace SPIRVDebug::Operand::TypeSubrange; + SPIRVWordVec Ops(OperandCount); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 7793403c..ae673b8c 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -107,6 +107,7 @@ private: + SPIRVEntry *transDbgArrayType(const DICompositeType *AT); + SPIRVEntry *transDbgArrayTypeOpenCL(const DICompositeType *AT); + SPIRVEntry *transDbgArrayTypeNonSemantic(const DICompositeType *AT); ++ SPIRVEntry *transDbgArrayTypeDynamic(const DICompositeType *AT); + SPIRVEntry *transDbgSubrangeType(const DISubrange *ST); + SPIRVEntry *transDbgTypeDef(const DIDerivedType *D); + SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 2178582f..9c1cc779 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -274,7 +274,7 @@ SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) { + for (size_t I = SubrangesIdx; I < Ops.size(); ++I) { + auto *SR = transDebugInst(BM->get(Ops[I])); + if (auto *Count = SR->getCount().get()) +- TotalCount *= Count->getZExtValue() > 0 ? Count->getZExtValue() : 0; ++ TotalCount *= Count->getSExtValue() > 0 ? Count->getSExtValue() : 0; + Subscripts.push_back(SR); + } + } +@@ -283,6 +283,47 @@ SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) { + return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); + } + ++DICompositeType * ++SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeArrayDynamic; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ DIType *BaseTy = ++ transDebugInst(BM->get(Ops[BaseTypeIdx])); ++ size_t TotalCount = 1; ++ SmallVector Subscripts; ++ for (size_t I = SubrangesIdx; I < Ops.size(); ++I) { ++ auto *SR = transDebugInst(BM->get(Ops[I])); ++ if (auto *Count = SR->getCount().get()) ++ TotalCount *= Count->getSExtValue() > 0 ? Count->getSExtValue() : 0; ++ Subscripts.push_back(SR); ++ } ++ DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; ++ ++ auto TransOperand = [&](SPIRVWord Idx) -> PointerUnion { ++ if (!getDbgInst(Ops[Idx])) { ++ if (const auto *GV = getDbgInst(Ops[Idx])) ++ return transDebugInst(GV); ++ if (const auto *LV = getDbgInst(Ops[Idx])) ++ return transDebugInst(LV); ++ if (const auto *DIExpr = getDbgInst(Ops[Idx])) ++ return transDebugInst(DIExpr); ++ } ++ return nullptr; ++ }; ++ PointerUnion DataLocation = ++ TransOperand(DataLocationIdx); ++ PointerUnion Associated = ++ TransOperand(AssociatedIdx); ++ PointerUnion Allocated = ++ TransOperand(AllocatedIdx); ++ PointerUnion Rank = TransOperand(RankIdx); ++ return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray, ++ DataLocation, Associated, Allocated, Rank); ++} ++ + DICompositeType * + SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeVector; +@@ -1038,6 +1079,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::Expression: + return transExpression(DebugInst); + ++ case SPIRVDebug::TypeArrayDynamic: ++ return transTypeArrayDynamic(DebugInst); ++ + default: + llvm_unreachable("Not implemented SPIR-V debug instruction!"); + } +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 68a8351c..8f3c5c70 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -113,6 +113,7 @@ private: + DICompositeType *transTypeArray(const SPIRVExtInst *DebugInst); + DICompositeType *transTypeArrayOpenCL(const SPIRVExtInst *DebugInst); + DICompositeType *transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst); ++ DICompositeType *transTypeArrayDynamic(const SPIRVExtInst *DebugInst); + + DICompositeType *transTypeVector(const SPIRVExtInst *DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 4c1c3d47..f6bf63a8 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -52,7 +52,8 @@ enum Instruction { + Source = 35, + ModuleINTEL = 36, + InstCount = 37, +- TypeSubrange = 110 ++ TypeSubrange = 110, ++ TypeArrayDynamic = 202 + }; + + enum Flag { +@@ -330,6 +331,18 @@ enum { + }; + } + ++namespace TypeArrayDynamic { ++enum { ++ BaseTypeIdx = 0, ++ DataLocationIdx = 1, ++ AssociatedIdx = 2, ++ AllocatedIdx = 3, ++ RankIdx = 4, ++ SubrangesIdx = 5, ++ MinOperandCount = 6 ++}; ++} ++ + namespace TypeVector = TypeArray; + + namespace TypeSubrange { +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 24555290..23576fc6 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -226,6 +226,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::TypeBasic, "DebugTypeBasic"); + add(SPIRVDebug::TypePointer, "DebugTypePointer"); + add(SPIRVDebug::TypeArray, "DebugTypeArray"); ++ add(SPIRVDebug::TypeArrayDynamic, "DebugTypeArrayDynamic"); + add(SPIRVDebug::TypeVector, "DebugTypeVector"); + add(SPIRVDebug::TypeQualifier, "DebugTypeQualifier"); + add(SPIRVDebug::TypeFunction, "DebugTypeFunction"); +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranArray.ll b/test/DebugInfo/NonSemanticKernel100/FortranArray.ll +index b9d37447..6b5d88a3 100644 +--- a/test/DebugInfo/NonSemanticKernel100/FortranArray.ll ++++ b/test/DebugInfo/NonSemanticKernel100/FortranArray.ll +@@ -6,7 +6,10 @@ + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + + ; CHECK-LLVM: !DICompileUnit(language: DW_LANG_Fortran95 +-; CHECK-LLVM: !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) ++; CHECK-LLVM: !DICompositeType(tag: DW_TAG_array_type, baseType: ![[#BaseT:]], size: 32, elements: ![[#Elements:]], dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref, DW_OP_constu, 0, DW_OP_or)) ++; CHECK-LLVM: ![[#BaseT:]] = !DIBasicType(name: "INTEGER*4", size: 32, encoding: DW_ATE_signed) ++; CHECK-LLVM: ![[#Elements]] = !{![[#SubRange:]]} ++; CHECK-LLVM: ![[#SubRange]] = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) + + source_filename = "llvm-link" + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll b/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll +new file mode 100644 +index 00000000..0aa4c1f7 +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll +@@ -0,0 +1,81 @@ ++;; The test checks, that Fortran dynamic arrays are being correctly represented ++;; by SPIR-V debug information ++;; Unlike 'static' arrays dynamic can have following parameters of ++;; DICompositeType metadata with DW_TAG_array_type tag: ++;; Data Location, Associated, Allocated and Rank which can be represented ++;; by either DIExpression or DIVariable (both local and global). ++;; This test if for expression representation. ++;; FortranDynamicArrayVar.ll is for variable representation. ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: ExtInstImport [[#Import:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV-DAG: String [[#BasicTName:]] "INTEGER*4" ++; CHECK-SPIRV-DAG: TypeInt [[#Int32T:]] 32 0 ++; CHECK-SPIRV-DAG: Constant [[#Int32T]] [[#IntConst:]] 32 ++; CHECK-SPIRV-DAG: TypeVoid [[#VoidT:]] ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgInfoNone:]] [[#Import]] DebugInfoNone ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#ArrayBasicT:]] [[#Import]] DebugTypeBasic [[#BasicTName]] [[#IntConst]] 4 ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprLocation:]] [[#Import]] DebugExpression [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprAssociated:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprLowerBound:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprUpperBound:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprCount:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgSubRangeId:]] [[#Import]] DebugTypeSubrange [[#DbgInfoNone]] [[#DbgExprLowerBound]] [[#DbgExprUpperBound]] [[#DbgExprCount]] ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgArrayId:]] [[#Import]] DebugTypeArrayDynamic [[#ArrayBasicT]] [[#DbgExprLocation]] [[#DbgExprAssociated]] [[#DbgInfoNone]] [[#DbgInfoNone]] [[#DbgSubRangeId]] ++ ++; CHECK-LLVM: %[[#Array:]] = alloca ++; CHECK-LLVM: call void @llvm.dbg.value(metadata ptr %[[#Array]], metadata ![[#DbgLVar:]] ++; CHECK-LLVM: ![[#DbgLVar]] = !DILocalVariable(name: "pint", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#DbgLVarT:]]) ++; CHECK-LLVM: ![[#DbgLVarT]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#DbgArrayT:]], size: 64) ++; CHECK-LLVM: ![[#DbgArrayT]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[#DbgArrayBaseT:]], size: 32, elements: ![[#Elements:]], dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref, DW_OP_constu, 0, DW_OP_or)) ++; CHECK-LLVM: ![[#DbgArrayBaseT]] = !DIBasicType(name: "INTEGER*4", size: 32, encoding: DW_ATE_signed) ++; CHECK-LLVM: ![[#Elements]] = !{![[#SubRange:]]} ++; CHECK-LLVM: ![[#SubRange]] = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) ++ ++ ++; ModuleID = 'reproducer.ll' ++source_filename = "test.f90" ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64" ++ ++%qnca = type { i32 addrspace(4)*, i64, i64, i64, i64, i64, [1 x { i64, i64, i64 }] } ++ ++; Function Attrs: noinline nounwind optnone ++define weak dso_local spir_kernel void @TEST() #0 !dbg !5 { ++newFuncRoot: ++ %0 = alloca %qnca, align 8 ++ call void @llvm.dbg.value(metadata %qnca* %0, metadata !8, metadata !DIExpression()), !dbg !14 ++ ret void ++} ++ ++; Function Attrs: nofree nosync nounwind readnone speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) #1 ++ ++attributes #0 = { noinline nounwind optnone } ++attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } ++ ++!llvm.module.flags = !{!0, !1} ++!llvm.dbg.cu = !{!2} ++!spirv.Source = !{!4} ++ ++!0 = !{i32 2, !"Debug Info Version", i32 3} ++!1 = !{i32 2, !"Dwarf Version", i32 4} ++!2 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "fortran", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) ++!3 = !DIFile(filename: "test.f90", directory: "/path/to") ++!4 = !{i32 4, i32 200000} ++!5 = distinct !DISubprogram(name: "test", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2) ++!6 = !DISubroutineType(types: !7) ++!7 = !{null} ++!8 = !DILocalVariable(name: "pint", scope: !5, file: !3, line: 3, type: !9) ++!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) ++!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, elements: !12, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref, DW_OP_constu, 0, DW_OP_or)) ++!11 = !DIBasicType(name: "INTEGER*4", size: 32, encoding: DW_ATE_signed) ++!12 = !{!13} ++!13 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 64, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref, DW_OP_plus, DW_OP_constu, 1, DW_OP_minus), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) ++!14 = !DILocation(line: 1, scope: !5) ++ +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll b/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll +new file mode 100644 +index 00000000..29f01ffd +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll +@@ -0,0 +1,74 @@ ++;; DebugInfo/dwarfdump-dataLocationVar.ll from llvm.org is used as base for this test ++;; The test checks, that Fortran dynamic arrays are being correctly represented ++;; by SPIR-V debug information ++;; Unlike 'static' arrays dynamic can have following parameters of ++;; DICompositeType metadata with DW_TAG_array_type tag: ++;; Data Location, Associated, Allocated and Rank which can be represented ++;; by either DIExpression or DIVariable (both local and global). ++;; This test if for variable representation. ++;; FortranDynamicArrayVar.ll is for expression representation. ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++;; Major SPIR-V checks are done in FortranDynamicArrayExpr.ll ++; CHECK-SPIRV: ExtInst [[#]] [[#DbgLVarId:]] [[#]] DebugLocalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugTypeArrayDynamic [[#]] [[#DbgLVarId]] [[#]] [[#]] [[#]] [[#]] ++ ++; CHECK-LLVM: %[[#Ptr:]] = alloca ptr ++; CHECK-LLVM: %[[#Array:]] = alloca [16 x i64] ++; CHECK-LLVM: call void @llvm.dbg.declare(metadata ptr %[[#Array]], metadata ![[#DbgLVarArray:]] ++; CHECK-LLVM: call void @llvm.dbg.declare(metadata ptr %[[#Ptr]], metadata ![[#DbgLVarPtr:]] ++ ++; CHECK-LLVM: ![[#DbgLVarPtr:]] = !DILocalVariable(scope: ![[#]], file: ![[#]], type: ![[#DbgPtrT:]], flags: DIFlagArtificial) ++; CHECK-LLVM: ![[#DbgPtrT:]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#DbgBasicT:]], size: 64) ++; CHECK-LLVM: ![[#DbgBasicT]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) ++; CHECK-LLVM: ![[#DbgLVarArray]] = !DILocalVariable(name: "arr", scope: ![[#]], file: ![[#]], type: ![[#DbgArrayT:]]) ++; CHECK-LLVM: ![[#DbgArrayT]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[#DbgBasicT]], size: 608, elements: ![[#Elements:]], dataLocation: ![[#DbgLVarPtr]]) ++; CHECK-LLVM: ![[#Elements]] = !{![[#SubRange:]]} ++; CHECK-LLVM: ![[#SubRange]] = !DISubrange(count: 19, lowerBound: 2) ++ ++; ModuleID = 'fortsubrange.ll' ++source_filename = "fortsubrange.ll" ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++define spir_func void @foo() !dbg !5 { ++L.entry: ++ %0 = alloca ptr, align 8 ++ %1 = alloca [16 x i64], align 8 ++ call void @llvm.dbg.declare(metadata ptr %1, metadata !8, metadata !DIExpression()), !dbg !16 ++ call void @llvm.dbg.declare(metadata ptr %0, metadata !14, metadata !DIExpression()), !dbg !16 ++ ret void, !dbg !17 ++} ++ ++; Function Attrs: nounwind readnone speculatable willreturn ++declare void @llvm.dbg.declare(metadata, metadata, metadata) ++ ++; Function Attrs: nounwind readnone speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) ++ ++!llvm.module.flags = !{!0, !1} ++!llvm.dbg.cu = !{!2} ++ ++!0 = !{i32 2, !"Dwarf Version", i32 4} ++!1 = !{i32 2, !"Debug Info Version", i32 3} ++!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4) ++!3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir") ++!4 = !{} ++!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2) ++!6 = !DISubroutineType(cc: DW_CC_program, types: !7) ++!7 = !{null} ++!8 = !DILocalVariable(name: "arr", scope: !9, file: !3, type: !10) ++!9 = !DILexicalBlock(scope: !5, file: !3, line: 1, column: 1) ++!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !12, dataLocation: !14) ++!11 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) ++!12 = !{!13} ++!13 = !DISubrange(count: 19, lowerBound: 2) ++!14 = distinct !DILocalVariable(scope: !9, file: !3, type: !15, flags: DIFlagArtificial) ++!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32, align: 32) ++!16 = !DILocation(line: 0, scope: !9) ++!17 = !DILocation(line: 6, column: 1, scope: !9) +-- +2.20.1 + diff --git a/patches/0023-Backport-to-15-DebugInfo-Support-translation-of-DISt.patch b/patches/0023-Backport-to-15-DebugInfo-Support-translation-of-DISt.patch new file mode 100644 index 0000000..9c1a41b --- /dev/null +++ b/patches/0023-Backport-to-15-DebugInfo-Support-translation-of-DISt.patch @@ -0,0 +1,359 @@ +From cd7275e23c5841c85f7ada6a8a0c606a4cfa83bc Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 10 Mar 2023 03:19:02 -0800 +Subject: [PATCH 23/79] [Backport to 15][DebugInfo] Support translation of + DIStringType (#1877) + +This type instruction describes a string, mostly for Fortran 90. + +Spec: +KhronosGroup/SPIRV-Registry#186 +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 43 ++++++ + lib/SPIRV/LLVMToSPIRVDbgTran.h | 1 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 47 +++++++ + lib/SPIRV/SPIRVToLLVMDbgTran.h | 2 + + lib/SPIRV/libSPIRV/SPIRV.debug.h | 15 +- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + .../DebugInfoStringType.ll | 133 ++++++++++++++++++ + 7 files changed, 241 insertions(+), 1 deletion(-) + create mode 100644 test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 8aff387b..e7cc00c5 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -283,6 +283,12 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + else + return getDebugInfoNone(); + ++ case dwarf::DW_TAG_string_type: { ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ return transDbgStringType(cast(DIEntry)); ++ return getDebugInfoNone(); ++ } ++ + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_volatile_type: +@@ -731,6 +737,43 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgSubrangeType(const DISubrange *ST) { + return BM->addDebugInfo(SPIRVDebug::TypeSubrange, getVoidTy(), Ops); + } + ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgStringType(const DIStringType *ST) { ++ using namespace SPIRVDebug::Operand::TypeString; ++ SPIRVWordVec Ops(MinOperandCount); ++ Ops[NameIdx] = BM->getString(ST->getName().str())->getId(); ++ ++ Ops[BaseTypeIdx] = ST->getEncoding() ++ ? getDebugInfoNoneId() /*TODO: replace with basetype*/ ++ : getDebugInfoNoneId(); ++ ++ auto TransOperand = [&](llvm::Metadata *DIMD) -> SPIRVWord { ++ if (auto *DIExpr = dyn_cast_or_null(DIMD)) ++ return transDbgExpression(DIExpr)->getId(); ++ if (auto *DIVar = dyn_cast_or_null(DIMD)) { ++ if (const DILocalVariable *LV = dyn_cast(DIVar)) ++ return transDbgLocalVariable(LV)->getId(); ++ if (const DIGlobalVariable *GV = dyn_cast(DIVar)) ++ return transDbgGlobalVariable(GV)->getId(); ++ } ++ return getDebugInfoNoneId(); ++ }; ++ ++ Ops[DataLocationIdx] = TransOperand(ST->getRawStringLocationExp()); ++ ++ ConstantInt *Size = getUInt(M, ST->getSizeInBits()); ++ Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); ++ ++ if (auto *StrLengthExp = ST->getRawStringLengthExp()) { ++ Ops[LengthAddrIdx] = TransOperand(StrLengthExp); ++ } else if (auto *StrLengthVar = ST->getRawStringLength()) { ++ Ops[LengthAddrIdx] = TransOperand(StrLengthVar); ++ } else { ++ Ops[LengthAddrIdx] = getDebugInfoNoneId(); ++ } ++ ++ return BM->addDebugInfo(SPIRVDebug::TypeString, getVoidTy(), Ops); ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTypeDef(const DIDerivedType *DT) { + using namespace SPIRVDebug::Operand::Typedef; + SPIRVWordVec Ops(OperandCount); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index ae673b8c..ec030eda 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -109,6 +109,7 @@ private: + SPIRVEntry *transDbgArrayTypeNonSemantic(const DICompositeType *AT); + SPIRVEntry *transDbgArrayTypeDynamic(const DICompositeType *AT); + SPIRVEntry *transDbgSubrangeType(const DISubrange *ST); ++ SPIRVEntry *transDbgStringType(const DIStringType *ST); + SPIRVEntry *transDbgTypeDef(const DIDerivedType *D); + SPIRVEntry *transDbgSubroutineType(const DISubroutineType *FT); + SPIRVEntry *transDbgEnumType(const DICompositeType *ET); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 9c1cc779..09171bd5 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -451,6 +451,50 @@ SPIRVToLLVMDbgTran::transTypeSubrange(const SPIRVExtInst *DebugInst) { + TranslatedOps[2], TranslatedOps[3]); + } + ++DIStringType * ++SPIRVToLLVMDbgTran::transTypeString(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeString; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ ++ StringRef Name = getString(Ops[NameIdx]); ++ unsigned Encoding = 0; ++ if (!getDbgInst((Ops[BaseTypeIdx]))) { ++ DIBasicType *BaseTy = ++ transTypeBasic(BM->get(Ops[BaseTypeIdx])); ++ Encoding = BaseTy->getEncoding(); ++ } ++ ++ DIExpression *StrLocationExp = nullptr; ++ if (!getDbgInst(Ops[DataLocationIdx])) { ++ if (const auto *DIExpr = ++ getDbgInst(Ops[DataLocationIdx])) ++ StrLocationExp = transDebugInst(DIExpr); ++ } ++ ++ uint64_t SizeInBits = BM->get(Ops[SizeIdx])->getZExtIntValue(); ++ ++ DIExpression *StringLengthExp = nullptr; ++ DIVariable *StringLengthVar = nullptr; ++ if (!getDbgInst(Ops[LengthAddrIdx])) { ++ if (const auto *GV = ++ getDbgInst(Ops[LengthAddrIdx])) ++ StringLengthVar = transDebugInst(GV); ++ if (const auto *LV = ++ getDbgInst(Ops[LengthAddrIdx])) ++ StringLengthVar = transDebugInst(LV); ++ if (const auto *DIExpr = ++ getDbgInst(Ops[LengthAddrIdx])) ++ StringLengthExp = transDebugInst(DIExpr); ++ } ++ ++ return DIStringType::get(M->getContext(), dwarf::DW_TAG_string_type, Name, ++ cast_or_null(StringLengthVar), ++ cast_or_null(StringLengthExp), ++ cast_or_null(StrLocationExp), SizeInBits, ++ 0 /*AlignInBits*/, Encoding); ++} ++ + DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeMember; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +@@ -1009,6 +1053,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::TypeSubrange: + return transTypeSubrange(DebugInst); + ++ case SPIRVDebug::TypeString: ++ return transTypeString(DebugInst); ++ + case SPIRVDebug::TypeVector: + return transTypeVector(DebugInst); + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 8f3c5c70..f18a08c9 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -121,6 +121,8 @@ private: + + DISubrange *transTypeSubrange(const SPIRVExtInst *DebugInst); + ++ DIStringType *transTypeString(const SPIRVExtInst *DebugInst); ++ + DINode *transTypeMember(const SPIRVExtInst *DebugInst); + + DINode *transTypeEnum(const SPIRVExtInst *DebugInst); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index f6bf63a8..54c28658 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -53,7 +53,8 @@ enum Instruction { + ModuleINTEL = 36, + InstCount = 37, + TypeSubrange = 110, +- TypeArrayDynamic = 202 ++ TypeArrayDynamic = 202, ++ TypeString = 203 + }; + + enum Flag { +@@ -355,6 +356,18 @@ enum { + }; + } + ++namespace TypeString { ++enum { ++ NameIdx = 0, ++ BaseTypeIdx = 1, ++ DataLocationIdx = 2, ++ SizeIdx = 3, ++ LengthAddrIdx = 4, ++ LengthSizeIdx = 5, ++ MinOperandCount = 5 ++}; ++} ++ + namespace Typedef { + enum { + NameIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 23576fc6..33e50332 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -241,6 +241,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::TypeTemplate, "DebugTemplate"); + add(SPIRVDebug::TypePtrToMember, "DebugTypePtrToMember,"); + add(SPIRVDebug::TypeSubrange, "DebugTypeSubrange"); ++ add(SPIRVDebug::TypeString, "DebugTypeString"); + add(SPIRVDebug::Inheritance, "DebugInheritance"); + add(SPIRVDebug::Function, "DebugFunction"); + add(SPIRVDebug::FunctionDecl, "DebugFunctionDecl"); +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll b/test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll +new file mode 100644 +index 00000000..6586bf17 +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll +@@ -0,0 +1,133 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -to-binary %t.spt -o %t.spv ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV: String [[#StrGreet:]] ".str.GREETING" ++; CHECK-SPIRV: String [[#StrChar1:]] "CHARACTER_1" ++; CHECK-SPIRV: String [[#StrChar2:]] "CHARACTER_2" ++; CHECK-SPIRV: String [[#StrChar3:]] "CHARACTER_3" ++; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 0 ++; CHECK-SPIRV: Constant [[#TypeInt]] [[#ConstZero:]] 0 ++; CHECK-SPIRV: Constant [[#TypeInt]] [[#Const80:]] 80 ++; CHECK-SPIRV: TypeVoid [[#TypeVoid:]] ++ ++; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone ++; CHECK-SPIRV: [[#DataLocExpr:]] [[#EISId]] DebugExpression [[#]] [[#]] {{$}} ++; CHECK-SPIRV: [[#LengthAddrExpr:]] [[#EISId]] DebugExpression [[#]] [[#]] {{$}} ++ ++; DebugTypeString NameId BaseTyId DataLocId SizeId LengthAddrId ++; CHECK-SPIRV: [[#EISId]] DebugTypeString [[#StrGreet]] [[#DINoneId]] [[#DataLocExpr]] [[#ConstZero]] [[#LengthAddrExpr]] ++; CHECK-SPIRV: [[#EISId]] DebugTypeString [[#StrChar1]] [[#DINoneId]] [[#DINoneId]] [[#Const80]] [[#DINoneId]] ++ ++; CHECK-SPIRV-COUNT-2: [[#LengthAddrVar:]] [[#EISId]] DebugLocalVariable ++; CHECK-SPIRV-NEXT: [[#EISId]] DebugTypeString [[#StrChar2]] [[#DINoneId]] [[#DINoneId]] [[#ConstZero]] [[#LengthAddrVar]] ++; CHECK-SPIRV-COUNT-3: [[#LengthAddrVar1:]] [[#EISId]] DebugLocalVariable ++; CHECK-SPIRV-NEXT: [[#EISId]] DebugTypeString [[#StrChar3]] [[#DINoneId]] [[#DINoneId]] [[#ConstZero]] [[#LengthAddrVar1]] ++; CHECK-SPIRV-COUNT-4: [[#LengthAddrVar2:]] [[#EISId]] DebugLocalVariable ++; CHECK-SPIRV-NEXT: [[#EISId]] DebugTypeString [[#StrChar2]] [[#DINoneId]] [[#DINoneId]] [[#ConstZero]] [[#LengthAddrVar2]] ++ ++; CHECK-LLVM: !DICompileUnit(language: DW_LANG_Fortran95 ++; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_1", size: 80) ++; CHECK-LLVM-DAG: !DIStringType(name: ".str.GREETING", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref)) ++; CHECK-LLVM-DAG: ![[#Scope:]] = distinct !DISubprogram(name: "print_greeting", linkageName: "print_greeting_" ++; CHECK-LLVM-DAG: ![[#StrLenMD:]] = !DILocalVariable(name: "STRING1.len", scope: ![[#Scope]] ++; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_2", stringLength: ![[#StrLenMD]]) ++; CHECK-LLVM-DAG: ![[#StrLenMD1:]] = !DILocalVariable(name: "STRING2.len", scope: ![[#Scope]] ++; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_3", stringLength: ![[#StrLenMD1]]) ++ ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++%"QNCA_a0$i8*$rank0$" = type { ptr, i64, i64, i64, i64, i64 } ++ ++@strlit = internal unnamed_addr constant [5 x i8] c"HELLO" ++@strlit.1 = internal unnamed_addr constant [3 x i8] c"TOM" ++@"hello_world_$GREETING" = internal global %"QNCA_a0$i8*$rank0$" zeroinitializer, !dbg !2 ++@"hello_world_$NAME" = internal global [10 x i8] zeroinitializer, align 1, !dbg !10 ++@0 = internal unnamed_addr constant i32 65536, align 4 ++@1 = internal unnamed_addr constant i32 2, align 4 ++@strlit.2 = internal unnamed_addr constant [2 x i8] c", " ++ ++; Function Attrs: nounwind uwtable ++define void @MAIN__() local_unnamed_addr #0 !dbg !4{ ++ %"hello_world_$GREETING_fetch.16" = load ptr, ptr @"hello_world_$GREETING", align 16, !dbg !20 ++ %fetch.15 = load i64, ptr getelementptr inbounds (%"QNCA_a0$i8*$rank0$", ptr @"hello_world_$GREETING", i64 0, i32 1), align 8, !dbg !20 ++ call void @llvm.dbg.value(metadata i64 %fetch.15, metadata !24, metadata !DIExpression()), !dbg !21 ++ call void @llvm.dbg.value(metadata i64 %fetch.15, metadata !31, metadata !DIExpression()), !dbg !21 ++ call void @llvm.dbg.value(metadata i64 10, metadata !28, metadata !DIExpression()), !dbg !21 ++ call void @llvm.dbg.value(metadata i64 10, metadata !32, metadata !DIExpression()), !dbg !21 ++ call void @llvm.dbg.declare(metadata ptr %"hello_world_$GREETING_fetch.16", metadata !26, metadata !DIExpression()), !dbg !36 ++ call void @llvm.dbg.declare(metadata ptr @"hello_world_$NAME", metadata !29, metadata !DIExpression()), !dbg !37 ++ ret void, !dbg !38 ++} ++ ++; Function Attrs: nofree nounwind uwtable ++define void @print_greeting_(ptr noalias readonly %"print_greeting_$STRING1", ptr noalias readonly %"print_greeting_$STRING2", i64 %"STRING1.len$val", i64 %"STRING2.len$val") local_unnamed_addr #1 !dbg !22 { ++alloca_1: ++ call void @llvm.dbg.value(metadata i64 %"STRING1.len$val", metadata !24, metadata !DIExpression()), !dbg !39 ++ call void @llvm.dbg.value(metadata i64 %"STRING1.len$val", metadata !31, metadata !DIExpression()), !dbg !39 ++ call void @llvm.dbg.value(metadata i64 %"STRING2.len$val", metadata !28, metadata !DIExpression()), !dbg !39 ++ call void @llvm.dbg.value(metadata i64 %"STRING2.len$val", metadata !32, metadata !DIExpression()), !dbg !39 ++ call void @llvm.dbg.declare(metadata ptr %"print_greeting_$STRING1", metadata !26, metadata !DIExpression()), !dbg !40 ++ call void @llvm.dbg.declare(metadata ptr %"print_greeting_$STRING2", metadata !29, metadata !DIExpression()), !dbg !41 ++ ret void, !dbg !42 ++} ++ ++; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn ++declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) #3 ++ ++attributes #0 = { nounwind uwtable } ++attributes #1 = { nofree nounwind uwtable} ++attributes #2 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn } ++attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn } ++ ++!llvm.module.flags = !{!18, !19} ++!llvm.dbg.cu = !{!8} ++ ++!2 = !DIGlobalVariableExpression(var: !3, expr: !DIExpression()) ++!3 = distinct !DIGlobalVariable(name: "greeting", linkageName: "hello_world_$GREETING", scope: !4, file: !5, line: 3, type: !14, isLocal: true, isDefinition: true) ++!4 = distinct !DISubprogram(name: "hello_world", linkageName: "MAIN__", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !8, retainedNodes: !13) ++!5 = !DIFile(filename: "hello.f90", directory: "/dev/null") ++!6 = !DISubroutineType(types: !7) ++!7 = !{null} ++!8 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !5, producer: "fortran", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !9, splitDebugInlining: false, nameTableKind: None) ++!9 = !{!2, !10} ++!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) ++!11 = distinct !DIGlobalVariable(name: "name", linkageName: "hello_world_$NAME", scope: !4, file: !5, line: 2, type: !12, isLocal: true, isDefinition: true) ++!12 = !DIStringType(name: "CHARACTER_1", size: 80) ++!13 = !{} ++!14 = !DIStringType(name: ".str.GREETING", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref)) ++!18 = !{i32 2, !"Debug Info Version", i32 3} ++!19 = !{i32 2, !"Dwarf Version", i32 4} ++!20 = !DILocation(line: 6, column: 23, scope: !4) ++!21 = !DILocation(line: 0, scope: !22, inlinedAt: !33) ++!22 = distinct !DISubprogram(name: "print_greeting", linkageName: "print_greeting_", scope: !5, file: !5, line: 9, type: !6, scopeLine: 9, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !23) ++!23 = !{!24, !26, !28, !29, !31, !32} ++!24 = !DILocalVariable(name: "STRING1.len", scope: !22, type: !25, flags: DIFlagArtificial) ++!25 = !DIBasicType(name: "INTEGER*8", size: 64, encoding: DW_ATE_signed) ++!26 = !DILocalVariable(name: "string1", arg: 1, scope: !22, file: !5, line: 9, type: !27) ++!27 = !DIStringType(name: "CHARACTER_2", stringLength: !24) ++!28 = !DILocalVariable(name: "STRING2.len", scope: !22, type: !25, flags: DIFlagArtificial) ++!29 = !DILocalVariable(name: "string2", arg: 2, scope: !22, file: !5, line: 9, type: !30) ++!30 = !DIStringType(name: "CHARACTER_3", stringLength: !28) ++!31 = !DILocalVariable(name: "_string1", arg: 3, scope: !22, type: !25, flags: DIFlagArtificial) ++!32 = !DILocalVariable(name: "_string2", arg: 4, scope: !22, type: !25, flags: DIFlagArtificial) ++!33 = distinct !DILocation(line: 0, scope: !34, inlinedAt: !35) ++!34 = distinct !DISubprogram(name: "print_greeting_.t60p.t61p.t3v.t3v", linkageName: "print_greeting_.t60p.t61p.t3v.t3v", scope: !5, file: !5, type: !6, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !8, retainedNodes: !13, targetFuncName: "print_greeting_") ++!35 = distinct !DILocation(line: 6, column: 8, scope: !4) ++!36 = !DILocation(line: 9, column: 27, scope: !22, inlinedAt: !33) ++!37 = !DILocation(line: 9, column: 36, scope: !22, inlinedAt: !33) ++!38 = !DILocation(line: 7, column: 1, scope: !4) ++!39 = !DILocation(line: 0, scope: !22) ++!40 = !DILocation(line: 9, column: 27, scope: !22) ++!41 = !DILocation(line: 9, column: 36, scope: !22) ++!42 = !DILocation(line: 12, column: 1, scope: !22) +-- +2.20.1 + diff --git a/patches/0024-Backport-to-15-DebugInfo-Support-translation-of-DIMo.patch b/patches/0024-Backport-to-15-DebugInfo-Support-translation-of-DIMo.patch new file mode 100644 index 0000000..5c638bb --- /dev/null +++ b/patches/0024-Backport-to-15-DebugInfo-Support-translation-of-DIMo.patch @@ -0,0 +1,193 @@ +From e5796efa3853b84e0f4af609c3361ad2d95c88b2 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Mon, 13 Mar 2023 06:15:51 -0700 +Subject: [PATCH 24/79] [Backport to 15][DebugInfo] Support translation of + DIModule (#1878) + +This entity represents a module in the programming language, for example a Fortran module. +Spec: +KhronosGroup/SPIRV-Registry#186 + +The implementation is the same as for SPV_INTEL_debug_module extension. Spec for extension: +https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_debug_module.asciidoc +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 25 +++++++-- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 13 ++++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 1 + + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + .../NonSemanticKernel100/DIModule.ll | 52 +++++++++++++++++++ + 5 files changed, 87 insertions(+), 5 deletions(-) + create mode 100644 test/DebugInfo/NonSemanticKernel100/DIModule.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index e7cc00c5..5ed9749d 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -360,7 +360,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + return transDbgImportedEntry(cast(DIEntry)); + + case dwarf::DW_TAG_module: { +- if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_debug_module)) ++ if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_debug_module) || ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) + return transDbgModule(cast(DIEntry)); + return getDebugInfoNone(); + } +@@ -1257,15 +1258,33 @@ LLVMToSPIRVDbgTran::transDbgImportedEntry(const DIImportedEntity *IE) { + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgModule(const DIModule *Module) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + SPIRVWordVec Ops(OperandCount); ++ // The difference in translation of NonSemantic Debug Info and ++ // SPV_INTEL_debug_module extension is that extension allows Line and IsDecl ++ // operands to be Literals, when the non-OpenCL Debug Info allows only IDs to ++ // the constant values. ++ bool IsNonSemanticDI = ++ (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100); + Ops[NameIdx] = BM->getString(Module->getName().str())->getId(); + Ops[SourceIdx] = getSource(Module->getFile())->getId(); +- Ops[LineIdx] = Module->getLineNo(); ++ if (IsNonSemanticDI) { ++ ConstantInt *Line = getUInt(M, Module->getLineNo()); ++ Ops[LineIdx] = SPIRVWriter->transValue(Line, nullptr)->getId(); ++ } else { ++ Ops[LineIdx] = Module->getLineNo(); ++ } + Ops[ParentIdx] = getScope(Module->getScope())->getId(); + Ops[ConfigMacrosIdx] = + BM->getString(Module->getConfigurationMacros().str())->getId(); + Ops[IncludePathIdx] = BM->getString(Module->getIncludePath().str())->getId(); + Ops[ApiNotesIdx] = BM->getString(Module->getAPINotesFile().str())->getId(); +- Ops[IsDeclIdx] = Module->getIsDecl(); ++ if (IsNonSemanticDI) { ++ ConstantInt *IsDecl = getUInt(M, Module->getIsDecl()); ++ Ops[IsDeclIdx] = SPIRVWriter->transValue(IsDecl, nullptr)->getId(); ++ } else { ++ Ops[IsDeclIdx] = Module->getIsDecl(); ++ } ++ if (IsNonSemanticDI) ++ return BM->addDebugInfo(SPIRVDebug::Module, getVoidTy(), Ops); + BM->addExtension(ExtensionID::SPV_INTEL_debug_module); + BM->addCapability(spv::CapabilityDebugInfoModuleINTEL); + return BM->addDebugInfo(SPIRVDebug::ModuleINTEL, getVoidTy(), Ops); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 09171bd5..d23d49e6 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1001,14 +1001,22 @@ DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); ++ bool IsNonSemanticDI = ++ (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); +- unsigned Line = Ops[LineIdx]; ++ auto GetInt = [&](SPIRVId Id) -> ConstantInt * { ++ auto *V = BM->get(Id); ++ return cast(SPIRVReader->transValue(V, nullptr, nullptr)); ++ }; ++ unsigned Line = ++ IsNonSemanticDI ? GetInt(Ops[LineIdx])->getZExtValue() : Ops[LineIdx]; + DIFile *File = getFile(Ops[SourceIdx]); + StringRef Name = getString(Ops[NameIdx]); + StringRef ConfigMacros = getString(Ops[ConfigMacrosIdx]); + StringRef IncludePath = getString(Ops[IncludePathIdx]); + StringRef ApiNotes = getString(Ops[ApiNotesIdx]); +- bool IsDecl = Ops[IsDeclIdx]; ++ bool IsDecl = ++ IsNonSemanticDI ? GetInt(Ops[IsDeclIdx])->getZExtValue() : Ops[IsDeclIdx]; + + return Builder.createModule(Scope, Name, ConfigMacros, IncludePath, ApiNotes, + File, Line, IsDecl); +@@ -1116,6 +1124,7 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::ImportedEntity: + return transImportedEntry(DebugInst); + ++ case SPIRVDebug::Module: + case SPIRVDebug::ModuleINTEL: + return transModule(DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 54c28658..b6ebb90a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -53,6 +53,7 @@ enum Instruction { + ModuleINTEL = 36, + InstCount = 37, + TypeSubrange = 110, ++ Module = 200, + TypeArrayDynamic = 202, + TypeString = 203 + }; +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 33e50332..2085db6e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -257,6 +257,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::InlinedAt, "DebugInlinedAt"); + add(SPIRVDebug::ImportedEntity, "DebugImportedEntity"); + add(SPIRVDebug::ModuleINTEL, "DebugModuleINTEL"); ++ add(SPIRVDebug::Module, "DebugModule"); + add(SPIRVDebug::Expression, "DebugExpression"); + add(SPIRVDebug::Operation, "DebugOperation"); + } +diff --git a/test/DebugInfo/NonSemanticKernel100/DIModule.ll b/test/DebugInfo/NonSemanticKernel100/DIModule.ll +new file mode 100644 +index 00000000..4aa22daf +--- /dev/null ++++ b/test/DebugInfo/NonSemanticKernel100/DIModule.ll +@@ -0,0 +1,52 @@ ++; ModuleID = '/Volumes/Data/apple-internal/llvm/tools/clang/test/Modules/debug-info-moduleimport.m' ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 %t.bc -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll ++ ++; RUN: llc -mtriple=x86_64-apple-macosx %t.ll -accel-tables=Dwarf -o %t -filetype=obj ++; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ++; RUN: llvm-dwarfdump -verify %t ++ ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 %t.bc -spirv-text -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV ++ ++; CHECK: DW_TAG_compile_unit ++; CHECK-NOT: DW_TAG ++; CHECK: DW_TAG_module ++; CHECK-NEXT: DW_AT_name {{.*}}"DebugModule" ++; CHECK-NEXT: DW_AT_LLVM_config_macros {{.*}}"-DMODULES=0" ++; CHECK-NEXT: DW_AT_LLVM_include_path {{.*}}"/llvm/tools/clang/test/Modules/Inputs" ++; CHECK-NEXT: DW_AT_LLVM_apinotes {{.*}}"m.apinotes" ++ ++target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV: String [[#FileName:]] "/llvm/tools/clang/test/Modules/" ++; CHECK-SPIRV: String [[#EmptyStr:]] "" ++; CHECK-SPIRV: String [[#Name:]] "DebugModule" ++; CHECK-SPIRV: String [[#Defines:]] "-DMODULES=0" ++; CHECK-SPIRV: String [[#IncludePath:]] "/llvm/tools/clang/test/Modules/Inputs" ++; CHECK-SPIRV: String [[#ApiNotes:]] "m.apinotes" ++; CHECK-SPIRV: TypeInt [[#TypeInt32:]] 32 0 ++; CHECK-SPIRV: Constant [[#TypeInt32]] [[#Constant0:]] 0 ++ ++; CHECK-SPIRV: ExtInst [[#]] [[#Source:]] [[#]] DebugSource [[#FileName]] ++; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompileUnit 65536 4 ++; CHECK-SPIRV: ExtInst [[#]] [[#SourceEmpty:]] [[#]] DebugSource [[#EmptyStr]] ++; CHECK-SPIRV: ExtInst [[#]] [[#Module:]] [[#]] DebugModule [[#Name]] [[#SourceEmpty]] [[#Constant0]] [[#Parent]] [[#Defines]] [[#IncludePath]] [[#ApiNotes]] [[#Constant0]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugImportedEntity [[#]] [[#]] [[#]] [[#Source]] [[#Module]] ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!6, !7} ++!llvm.ident = !{!8} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !1, producer: "LLVM version 3.7.0", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !3, sysroot: "/") ++!1 = !DIFile(filename: "/llvm/tools/clang/test/Modules/", directory: "/") ++!2 = !{} ++!3 = !{!4} ++!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !5, file: !1, line: 5) ++!5 = !DIModule(scope: null, name: "DebugModule", configMacros: "-DMODULES=0", includePath: "/llvm/tools/clang/test/Modules/Inputs", apinotes: "m.apinotes") ++!6 = !{i32 2, !"Dwarf Version", i32 4} ++!7 = !{i32 2, !"Debug Info Version", i32 3} ++!8 = !{!"LLVM version 3.7.0"} +-- +2.20.1 + diff --git a/patches/0025-Backport-to-15-DebugInfo-Start-adopting-debug-info-i.patch b/patches/0025-Backport-to-15-DebugInfo-Start-adopting-debug-info-i.patch new file mode 100644 index 0000000..f12598d --- /dev/null +++ b/patches/0025-Backport-to-15-DebugInfo-Start-adopting-debug-info-i.patch @@ -0,0 +1,1366 @@ +From 3fb3881da566bca0749b8302990294b335681932 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 21 Mar 2023 23:20:39 +0100 +Subject: [PATCH 25/79] [Backport to 15][DebugInfo] Start adopting debug info + instructions for NonSemantic set (#1887) + +List of changes: + +All Literal parameters of instructions in OpenCL.DebugInfo.100 +are OpConstants in NonSemantic.Shader.DebugInfo.100 and +NonSemantic.Shader.DebugInfo.200; +SPV_KHR_non_semantic_info is being implicitly added for nonsemantic +debug info; +--- + include/LLVMSPIRVExtensions.inc | 1 + + include/LLVMSPIRVOpts.h | 6 +- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 114 ++++++++--- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 7 +- + lib/SPIRV/SPIRVReader.cpp | 2 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 187 ++++++++++++------ + lib/SPIRV/SPIRVToLLVMDbgTran.h | 5 +- + lib/SPIRV/libSPIRV/SPIRVEnum.h | 6 +- + lib/SPIRV/libSPIRV/SPIRVFunction.cpp | 4 +- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 6 +- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 2 +- + lib/SPIRV/libSPIRV/SPIRVModule.h | 4 +- + .../DebugInfoSubrangeWithOnlyCount.spt | 2 +- + .../DebugInfo/Generic/tu-member-opaque.spvasm | 2 +- + test/DebugInfo/NonSemantic/DebugFunction.cl | 28 +++ + .../Shader200}/DIModule.ll | 12 +- + .../Shader200}/DebugInfoStringType.ll | 4 +- + .../Shader200}/DebugInfoSubrange.ll | 4 +- + .../Shader200}/DebugInfoTargetFunction.ll | 4 +- + .../Shader200}/FortranArray.ll | 4 +- + .../Shader200}/FortranDynamicArrayExpr.ll | 9 +- + .../Shader200}/FortranDynamicArrayVar.ll | 6 +- + .../Shader200}/SourceLanguageLLVMToSPIRV.ll | 22 ++- + tools/llvm-spirv/llvm-spirv.cpp | 14 +- + 24 files changed, 316 insertions(+), 139 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/DebugFunction.cl + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/DIModule.ll (84%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/DebugInfoStringType.ll (98%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/DebugInfoSubrange.ll (98%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/DebugInfoTargetFunction.ll (96%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/FortranArray.ll (98%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/FortranDynamicArrayExpr.ll (95%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/FortranDynamicArrayVar.ll (95%) + rename test/DebugInfo/{NonSemanticKernel100 => NonSemantic/Shader200}/SourceLanguageLLVMToSPIRV.ll (62%) + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index bbb2c201..e8d90048 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -12,6 +12,7 @@ EXT(SPV_KHR_integer_dot_product) + EXT(SPV_KHR_bit_instructions) + EXT(SPV_KHR_uniform_group_instructions) + EXT(SPV_KHR_subgroup_rotate) ++EXT(SPV_KHR_non_semantic_info) + EXT(SPV_INTEL_subgroups) + EXT(SPV_INTEL_media_block_io) + EXT(SPV_INTEL_device_side_avc_motion_estimation) +diff --git a/include/LLVMSPIRVOpts.h b/include/LLVMSPIRVOpts.h +index e821a1fa..7d1f11ff 100644 +--- a/include/LLVMSPIRVOpts.h ++++ b/include/LLVMSPIRVOpts.h +@@ -84,7 +84,7 @@ enum class DebugInfoEIS : uint32_t { + SPIRV_Debug, + OpenCL_DebugInfo_100, + NonSemantic_Shader_DebugInfo_100, +- NonSemantic_Kernel_DebugInfo_100 ++ NonSemantic_Shader_DebugInfo_200 + }; + + /// \brief Helper class to manage SPIR-V translation +@@ -110,6 +110,10 @@ public: + return I->second; + } + ++ void setAllowedToUseExtension(ExtensionID Extension, bool Allow = true) { ++ ExtStatusMap[Extension] = Allow; ++ } ++ + VersionNumber getMaxVersion() const { return MaxVersion; } + + bool isGenArgNameMDEnabled() const { return GenKernelArgNameMD; } +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 5ed9749d..a48be01d 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -262,6 +262,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + if (!MDN) + return BM->addDebugInfo(SPIRVDebug::DebugInfoNone, getVoidTy(), + SPIRVWordVec()); ++ if (isNonSemanticDebugInfo()) ++ BM->addExtension(SPIRV::ExtensionID::SPV_KHR_non_semantic_info); + if (const DINode *DIEntry = dyn_cast(MDN)) { + switch (DIEntry->getTag()) { + // Types +@@ -278,13 +280,13 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + return transDbgArrayType(cast(DIEntry)); + + case dwarf::DW_TAG_subrange_type: +- if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + return transDbgSubrangeType(cast(DIEntry)); + else + return getDebugInfoNone(); + + case dwarf::DW_TAG_string_type: { +- if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + return transDbgStringType(cast(DIEntry)); + return getDebugInfoNone(); + } +@@ -361,7 +363,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + + case dwarf::DW_TAG_module: { + if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_debug_module) || +- BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + return transDbgModule(cast(DIEntry)); + return getDebugInfoNone(); + } +@@ -390,6 +392,15 @@ SPIRVType *LLVMToSPIRVDbgTran::getVoidTy() { + return VoidT; + } + ++SPIRVType *LLVMToSPIRVDbgTran::getInt32Ty() { ++ if (!Int32T) { ++ assert(M && "Pointer to LLVM Module is expected to be initialized!"); ++ // Cache int32 type in a member. ++ Int32T = SPIRVWriter->transType(Type::getInt32Ty(M->getContext())); ++ } ++ return Int32T; ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::getScope(DIScope *S) { + if (S) + return transDbgEntry(S); +@@ -411,6 +422,20 @@ SPIRVEntry *LLVMToSPIRVDbgTran::getGlobalVariable(const DIGlobalVariable *GV) { + return getDebugInfoNone(); + } + ++inline bool LLVMToSPIRVDbgTran::isNonSemanticDebugInfo() { ++ return (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200); ++} ++ ++void LLVMToSPIRVDbgTran::transformToConstant(std::vector &Ops, ++ std::vector Idxs) { ++ for (const auto Idx : Idxs) { ++ SPIRVValue *Const = BM->addIntegerConstant( ++ static_cast(getInt32Ty()), Ops[Idx]); ++ Ops[Idx] = Const->getId(); ++ } ++} ++ + SPIRVWord mapDebugFlags(DINode::DIFlags DFlags) { + SPIRVWord Flags = 0; + if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic) +@@ -490,7 +515,7 @@ SPIRVWord adjustAccessFlags(DIScope *Scope, SPIRVWord Flags) { + + // Fortran dynamic arrays can have following 'dataLocation', 'associated' + // 'allocated' and 'rank' debug metadata. Such arrays are being mapped on +-// DebugTypeArrayDynamic from NonSemantic.Kernel.100 debug spec ++// DebugTypeArrayDynamic from NonSemantic.Shader.200 debug spec + inline bool isFortranArrayDynamic(const DICompositeType *AT) { + return (AT->getRawDataLocation() || AT->getRawAssociated() || + AT->getRawAllocated() || AT->getRawRank()); +@@ -524,9 +549,12 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { + auto DwarfLang = + static_cast(CU->getSourceLanguage()); + Ops[LanguageIdx] = +- BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100 ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200 + ? convertDWARFSourceLangToSPIRVNonSemanticDbgInfo(DwarfLang) + : convertDWARFSourceLangToSPIRV(DwarfLang); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant( ++ Ops, {SPIRVDebugInfoVersionIdx, DWARFVersionIdx, LanguageIdx}); + BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); + // Cache CU in a member. + SPIRVCU = static_cast( +@@ -546,6 +574,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgBaseType(const DIBasicType *BT) { + SPIRVDebug::EncodingTag EncTag = SPIRVDebug::Unspecified; + SPIRV::DbgEncodingMap::find(Encoding, &EncTag); + Ops[EncodingIdx] = EncTag; ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {EncodingIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeBasic, getVoidTy(), Ops); + } + +@@ -561,6 +591,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPointerType(const DIDerivedType *PT) { + Ops[StorageClassIdx] = SPIRSPIRVAddrSpaceMap::map(SPIRAS); + } + Ops[FlagsIdx] = transDebugFlags(PT); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {StorageClassIdx, FlagsIdx}); + SPIRVEntry *Res = BM->addDebugInfo(SPIRVDebug::TypePointer, getVoidTy(), Ops); + return Res; + } +@@ -572,11 +604,13 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgQualifiedType(const DIDerivedType *QT) { + Ops[BaseTypeIdx] = Base->getId(); + Ops[QualifierIdx] = SPIRV::DbgTypeQulifierMap::map( + static_cast(QT->getTag())); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {QualifierIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeQualifier, getVoidTy(), Ops); + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgArrayType(const DICompositeType *AT) { +- if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) { ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { + if (isFortranArrayDynamic(AT)) + return transDbgArrayTypeDynamic(AT); + return transDbgArrayTypeNonSemantic(AT); +@@ -602,6 +636,8 @@ LLVMToSPIRVDbgTran::transDbgArrayTypeOpenCL(const DICompositeType *AT) { + if (AT->isVector()) { + assert(N == 1 && "Multidimensional vector is not expected!"); + Ops[ComponentCountIdx] = static_cast(Count->getZExtValue()); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {ComponentCountIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeVector, getVoidTy(), Ops); + } + if (Count) { +@@ -788,6 +824,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTypeDef(const DIDerivedType *DT) { + SPIRVEntry *Scope = getScope(DT->getScope()); + assert(Scope && "Couldn't translate scope!"); + Ops[ParentIdx] = Scope->getId(); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::Typedef, getVoidTy(), Ops); + } + +@@ -810,6 +848,8 @@ LLVMToSPIRVDbgTran::transDbgSubroutineType(const DISubroutineType *FT) { + Ops[ReturnTypeIdx] = getVoidTy()->getId(); + } + ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeFunction, getVoidTy(), Ops); + } + +@@ -843,6 +883,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEnumType(const DICompositeType *ET) { + SPIRVString *Name = BM->getString(E->getName().str()); + Ops.push_back(Name->getId()); + } ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeEnum, getVoidTy(), Ops); + } + +@@ -875,6 +917,8 @@ LLVMToSPIRVDbgTran::transDbgCompositeType(const DICompositeType *CT) { + Ops.push_back(transDbgEntry(N)->getId()); + } + ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + SPIRVEntry *Res = + BM->addDebugInfo(SPIRVDebug::TypeComposite, getVoidTy(), Ops); + +@@ -916,6 +960,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) { + Ops.push_back(Val->getId()); + } + } ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops); + } + +@@ -929,6 +975,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { + ConstantInt *Size = getUInt(M, DT->getSizeInBits()); + Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); + Ops[FlagsIdx] = transDebugFlags(DT); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::Inheritance, getVoidTy(), Ops); + } + +@@ -968,6 +1016,8 @@ LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { + Ops[SourceIdx] = getDebugInfoNoneId(); + Ops[LineIdx] = 0; // This version of DITemplateParameter has no line number + Ops[ColumnIdx] = 0; // This version of DITemplateParameter has no column info ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeTemplateParameter, getVoidTy(), Ops); + } + +@@ -982,6 +1032,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateTemplateParameter( + Ops[SourceIdx] = getDebugInfoNoneId(); + Ops[LineIdx] = 0; // This version of DITemplateValueParameter has no line info + Ops[ColumnIdx] = 0; // This version of DITemplateValueParameter has no column ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeTemplateTemplateParameter, + getVoidTy(), Ops); + } +@@ -1002,6 +1054,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateParameterPack( + SPIRVEntry *P = transDbgEntry(cast(Op.get())); + Ops.push_back(P->getId()); + } ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeTemplateParameterPack, getVoidTy(), + Ops); + } +@@ -1036,6 +1090,8 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) { + if (DIDerivedType *StaticMember = GV->getStaticDataMemberDeclaration()) + Ops.push_back(transDbgEntry(StaticMember)->getId()); + ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::GlobalVariable, getVoidTy(), Ops); + } + +@@ -1059,6 +1115,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + Ops[ParentIdx] = getScope(Scope)->getId(); + Ops[LinkageNameIdx] = BM->getString(Func->getLinkageName().str())->getId(); + Ops[FlagsIdx] = adjustAccessFlags(Scope, transDebugFlags(Func)); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + + SPIRVEntry *DebugFunc = nullptr; + if (!Func->isDefinition()) { +@@ -1068,6 +1126,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + using namespace SPIRVDebug::Operand::Function; + Ops.resize(MinOperandCount); + Ops[ScopeLineIdx] = Func->getScopeLine(); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {ScopeLineIdx}); + + Ops[FunctionIdIdx] = getDebugInfoNoneId(); + for (const llvm::Function &F : M->functions()) { +@@ -1083,7 +1143,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + Ops.push_back(transDbgEntry(FuncDecl)->getId()); + else { + Ops.push_back(getDebugInfoNoneId()); +- if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) { ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { + // Translate targetFuncName mostly for Fortran trampoline function if it + // is the case + StringRef TargetFunc = Func->getTargetFuncName(); +@@ -1116,6 +1176,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { + Ops[SourceIdx] = getSource(S)->getId(); + Ops[DiscriminatorIdx] = LBF->getDiscriminator(); + Ops[ParentIdx] = getScope(S->getScope())->getId(); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {DiscriminatorIdx}); + return BM->addDebugInfo(SPIRVDebug::LexicalBlockDiscriminator, getVoidTy(), + Ops); + } +@@ -1131,6 +1193,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { + Ops[ColumnIdx] = 0; // This version of DINamespace has no column number + Ops.push_back(BM->getString(NS->getName().str())->getId()); + } ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::LexicalBlock, getVoidTy(), Ops); + } + +@@ -1160,6 +1224,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInlinedAt(const DILocation *Loc) { + Ops[ScopeIdx] = getScope(Loc->getScope())->getId(); + if (DILocation *IA = Loc->getInlinedAt()) + Ops.push_back(transDbgEntry(IA)->getId()); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx}); + return BM->addDebugInfo(SPIRVDebug::InlinedAt, getVoidTy(), Ops); + } + +@@ -1208,6 +1274,8 @@ LLVMToSPIRVDbgTran::transDbgLocalVariable(const DILocalVariable *Var) { + Ops[FlagsIdx] = transDebugFlags(Var); + if (SPIRVWord ArgNumber = Var->getArg()) + Ops.push_back(ArgNumber); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + return BM->addDebugInfo(SPIRVDebug::LocalVariable, getVoidTy(), Ops); + } + +@@ -1230,6 +1298,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) { + unsigned OpCount = OpCountMap[OC]; + SPIRVWordVec Op(OpCount); + Op[OpCodeIdx] = OC; ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Op, {OpCodeIdx}); + for (unsigned J = 1; J < OpCount; ++J) + Op[J] = Expr->getElement(++I); + auto *Operation = BM->addDebugInfo(SPIRVDebug::Operation, getVoidTy(), Op); +@@ -1252,39 +1322,31 @@ LLVMToSPIRVDbgTran::transDbgImportedEntry(const DIImportedEntity *IE) { + Ops[LineIdx] = IE->getLine(); + Ops[ColumnIdx] = 0; // This version of DIImportedEntity has no column number + Ops[ParentIdx] = getScope(IE->getScope())->getId(); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {TagIdx, LineIdx, ColumnIdx}); + return BM->addDebugInfo(SPIRVDebug::ImportedEntity, getVoidTy(), Ops); + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgModule(const DIModule *Module) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + SPIRVWordVec Ops(OperandCount); +- // The difference in translation of NonSemantic Debug Info and +- // SPV_INTEL_debug_module extension is that extension allows Line and IsDecl +- // operands to be Literals, when the non-OpenCL Debug Info allows only IDs to +- // the constant values. +- bool IsNonSemanticDI = +- (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100); + Ops[NameIdx] = BM->getString(Module->getName().str())->getId(); + Ops[SourceIdx] = getSource(Module->getFile())->getId(); +- if (IsNonSemanticDI) { +- ConstantInt *Line = getUInt(M, Module->getLineNo()); +- Ops[LineIdx] = SPIRVWriter->transValue(Line, nullptr)->getId(); +- } else { +- Ops[LineIdx] = Module->getLineNo(); +- } ++ Ops[LineIdx] = Module->getLineNo(); + Ops[ParentIdx] = getScope(Module->getScope())->getId(); + Ops[ConfigMacrosIdx] = + BM->getString(Module->getConfigurationMacros().str())->getId(); + Ops[IncludePathIdx] = BM->getString(Module->getIncludePath().str())->getId(); + Ops[ApiNotesIdx] = BM->getString(Module->getAPINotesFile().str())->getId(); +- if (IsNonSemanticDI) { +- ConstantInt *IsDecl = getUInt(M, Module->getIsDecl()); +- Ops[IsDeclIdx] = SPIRVWriter->transValue(IsDecl, nullptr)->getId(); +- } else { +- Ops[IsDeclIdx] = Module->getIsDecl(); +- } +- if (IsNonSemanticDI) ++ Ops[IsDeclIdx] = Module->getIsDecl(); ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ // The difference in translation of NonSemantic Debug Info and ++ // SPV_INTEL_debug_module extension is that extension allows Line and IsDecl ++ // operands to be Literals, when the non-OpenCL Debug Info allows only IDs ++ // to the constant values. ++ transformToConstant(Ops, {LineIdx, IsDeclIdx}); + return BM->addDebugInfo(SPIRVDebug::Module, getVoidTy(), Ops); ++ } + BM->addExtension(ExtensionID::SPV_INTEL_debug_module); + BM->addCapability(spv::CapabilityDebugInfoModuleINTEL); + return BM->addDebugInfo(SPIRVDebug::ModuleINTEL, getVoidTy(), Ops); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index ec030eda..c17a67d2 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -87,8 +87,12 @@ private: + + // Helper methods + SPIRVType *getVoidTy(); ++ SPIRVType *getInt32Ty(); + SPIRVEntry *getScope(DIScope *SR); + SPIRVEntry *getGlobalVariable(const DIGlobalVariable *GV); ++ inline bool isNonSemanticDebugInfo(); ++ void transformToConstant(std::vector &Ops, ++ std::vector Idxs); + + // No debug info + SPIRVEntry *getDebugInfoNone(); +@@ -157,7 +161,8 @@ private: + std::unordered_map MDMap; + std::unordered_map FileMap; + DebugInfoFinder DIF; +- SPIRVType *VoidT; ++ SPIRVType *VoidT = nullptr; ++ SPIRVType *Int32T = nullptr; + SPIRVEntry *DebugInfoNone; + SPIRVExtInst *SPIRVCU; + std::vector DbgDeclareIntrinsics; +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index b998abcd..22845f05 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -2376,7 +2376,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, + return mapValue(BV, transOCLBuiltinFromExtInst(ExtInst, BB)); + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: +- case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + return mapValue(BV, DbgTran->transDebugIntrinsic(ExtInst, BB)); + default: + llvm_unreachable("Unknown extended instruction set!"); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index d23d49e6..d7986137 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -94,12 +94,37 @@ SPIRVExtInst *SPIRVToLLVMDbgTran::getDbgInst(const SPIRVId Id) { + EI->getExtSetKind() == SPIRV::SPIRVEIS_OpenCL_DebugInfo_100 || + EI->getExtSetKind() == + SPIRV::SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || +- EI->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ EI->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + return EI; + } + return nullptr; + } + ++// Check if module is generated using NonSemantic.Shader.DebugInfo.XXX ++// extended instruction set ++inline bool isNonSemanticDebugInfo(const SPIRVExtInstSetKind Kind) { ++ return (Kind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || ++ Kind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200); ++} ++ ++// Get integer parameter of debug instruction considering whether it's ++// Literal or of OpConstant instruction depending on DebugInfo ++// extended instruction set kind ++SPIRVWord ++SPIRVToLLVMDbgTran::getConstantValueOrLiteral(const std::vector &Ops, ++ const SPIRVWord Idx, ++ const SPIRVExtInstSetKind Kind) { ++ if (!isNonSemanticDebugInfo(Kind)) ++ return Ops[Idx]; ++ ++ SPIRVValue *SPVConst = BM->get(Ops[Idx]); ++ assert(isConstantOpCode(SPVConst->getOpCode()) && ++ "NonSemantic Debug instruction's parameters must be OpConstant"); ++ ConstantInt *Const = ++ cast(SPIRVReader->transValue(SPVConst, nullptr, nullptr)); ++ return Const->getZExtValue(); ++} ++ + const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { + SPIRVString *String = BM->get(Id); + assert(String && "Invalid string"); +@@ -129,11 +154,15 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { + + using namespace SPIRVDebug::Operand::CompilationUnit; + assert(Ops.size() == OperandCount && "Invalid number of operands"); +- M->addModuleFlag(llvm::Module::Max, "Dwarf Version", Ops[DWARFVersionIdx]); +- unsigned SourceLang = +- DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100 +- ? convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(Ops[LanguageIdx]) +- : convertSPIRVSourceLangToDWARF(Ops[LanguageIdx]); ++ SPIRVWord DWARFVersion = getConstantValueOrLiteral( ++ Ops, DWARFVersionIdx, DebugInst->getExtSetKind()); ++ M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion); ++ SPIRVWord SourceLang = ++ getConstantValueOrLiteral(Ops, LanguageIdx, DebugInst->getExtSetKind()); ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ SourceLang = convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(SourceLang); ++ else ++ SourceLang = convertSPIRVSourceLangToDWARF(SourceLang); + auto Producer = findModuleProducer(); + CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, + false, "", 0); +@@ -145,7 +174,8 @@ DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() == OperandCount && "Invalid number of operands"); + StringRef Name = getString(Ops[NameIdx]); +- auto Tag = static_cast(Ops[EncodingIdx]); ++ auto Tag = static_cast( ++ getConstantValueOrLiteral(Ops, EncodingIdx, DebugInst->getExtSetKind())); + unsigned Encoding = SPIRV::DbgEncodingMap::rmap(Tag); + if (Encoding == 0) + return Builder.createUnspecifiedType(Name); +@@ -160,8 +190,9 @@ SPIRVToLLVMDbgTran::transTypeQualifier(const SPIRVExtInst *DebugInst) { + assert(Ops.size() == OperandCount && "Invalid number of operands"); + DIType *BaseTy = + transDebugInst(BM->get(Ops[BaseTypeIdx])); +- unsigned Tag = SPIRV::DbgTypeQulifierMap::rmap( +- static_cast(Ops[QualifierIdx])); ++ SPIRVWord Tag = SPIRV::DbgTypeQulifierMap::rmap( ++ static_cast(getConstantValueOrLiteral( ++ Ops, QualifierIdx, DebugInst->getExtSetKind()))); + return Builder.createQualifiedType(Tag, BaseTy); + } + +@@ -172,13 +203,14 @@ DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { + DIType *PointeeTy = nullptr; + if (BM->getEntry(Ops[BaseTypeIdx])->getOpCode() != OpTypeVoid) + PointeeTy = transDebugInst(BM->get(Ops[BaseTypeIdx])); +- Optional AS; +- if (Ops[StorageClassIdx] != ~0U) { +- auto SC = static_cast(Ops[StorageClassIdx]); +- AS = SPIRSPIRVAddrSpaceMap::rmap(SC); +- } ++ llvm::Optional AS; ++ SPIRVWord SC = getConstantValueOrLiteral(Ops, StorageClassIdx, ++ DebugInst->getExtSetKind()); ++ if (SC != ~0U) // all ones denote no address space ++ AS = SPIRSPIRVAddrSpaceMap::rmap(static_cast(SC)); + DIType *Ty; +- SPIRVWord Flags = Ops[FlagsIdx]; ++ SPIRVWord Flags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + if (Flags & SPIRVDebug::FlagIsLValueReference) + Ty = Builder.createReferenceType(dwarf::DW_TAG_reference_type, PointeeTy, 0, + 0, AS); +@@ -199,9 +231,13 @@ DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { + + DICompositeType * + SPIRVToLLVMDbgTran::transTypeArray(const SPIRVExtInst *DebugInst) { +- if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + return transTypeArrayNonSemantic(DebugInst); + ++ // TODO: figure out better naming for transTypeArrayOpenCL since ++ // it also handles SPIRVEIS_NonSemantic_Shader_DebugInfo_100. ++ // Also to consider separating OpenCL from NonSemantic, as OpenCL has several ++ // workarounds + return transTypeArrayOpenCL(DebugInst); + } + +@@ -331,7 +367,8 @@ SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) { + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + DIType *BaseTy = + transDebugInst(BM->get(Ops[BaseTypeIdx])); +- SPIRVWord Count = Ops[ComponentCountIdx]; ++ SPIRVWord Count = getConstantValueOrLiteral(Ops, ComponentCountIdx, ++ DebugInst->getExtSetKind()); + // FIXME: The current design of SPIR-V Debug Info doesn't provide a field + // for the derived memory size. Meanwhile, OpenCL/SYCL 3-element vectors + // occupy the same amount of memory as 4-element vectors, hence the simple +@@ -357,7 +394,8 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + + StringRef Name = getString(Ops[NameIdx]); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); + + uint64_t Size = 0; +@@ -365,7 +403,7 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + if (!(SizeEntry->isExtInst(SPIRVEIS_Debug, SPIRVDebug::DebugInfoNone) || + SizeEntry->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, + SPIRVDebug::DebugInfoNone) || +- SizeEntry->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ SizeEntry->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, + SPIRVDebug::DebugInfoNone))) { + Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); + } +@@ -378,15 +416,17 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + Identifier = static_cast(UniqId)->getStr(); + + DINode::DIFlags Flags = DINode::FlagZero; +- if (Ops[FlagsIdx] & SPIRVDebug::FlagIsFwdDecl) ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ if (SPIRVFlags & SPIRVDebug::FlagIsFwdDecl) + Flags |= DINode::FlagFwdDecl; +- if (Ops[FlagsIdx] & SPIRVDebug::FlagTypePassByValue) ++ if (SPIRVFlags & SPIRVDebug::FlagTypePassByValue) + Flags |= DINode::FlagTypePassByValue; +- if (Ops[FlagsIdx] & SPIRVDebug::FlagTypePassByReference) ++ if (SPIRVFlags & SPIRVDebug::FlagTypePassByReference) + Flags |= DINode::FlagTypePassByReference; + + DICompositeType *CT = nullptr; +- switch (Ops[TagIdx]) { ++ switch (getConstantValueOrLiteral(Ops, TagIdx, DebugInst->getExtSetKind())) { + case SPIRVDebug::Class: + // TODO: should be replaced with createClassType, when bug with creating + // ClassType with llvm::dwarf::DW_TAG_struct_type tag will be fixed +@@ -501,14 +541,16 @@ DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + StringRef Name = getString(Ops[NameIdx]); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + DIType *BaseType = + transDebugInst(BM->get(Ops[TypeIdx])); + uint64_t OffsetInBits = + BM->get(Ops[OffsetIdx])->getZExtIntValue(); +- unsigned SPIRVFlags = Ops[FlagsIdx]; ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + DINode::DIFlags Flags = DINode::FlagZero; + if ((SPIRVDebug::FlagAccess & SPIRVFlags) == SPIRVDebug::FlagIsPublic) { + Flags |= DINode::FlagPublic; +@@ -542,11 +584,13 @@ DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) { + + StringRef Name = getString(Ops[NameIdx]); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + uint64_t SizeInBits = BM->get(Ops[SizeIdx])->getZExtIntValue(); +- unsigned AlignInBits = 0; +- SPIRVWord Flags = Ops[FlagsIdx]; ++ SPIRVWord AlignInBits = 0; ++ SPIRVWord Flags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + if (Flags & SPIRVDebug::FlagIsFwdDecl) { + return Builder.createForwardDecl(dwarf::DW_TAG_enumeration_type, Name, + Scope, File, LineNo, AlignInBits, +@@ -574,7 +618,8 @@ DINode *SPIRVToLLVMDbgTran::transTypeFunction(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + +- SPIRVWord SPIRVFlags = Ops[FlagsIdx]; ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + DINode::DIFlags Flags = DINode::FlagZero; + if (SPIRVFlags & SPIRVDebug::FlagIsLValueReference) + Flags |= llvm::DINode::FlagLValueReference; +@@ -615,7 +660,8 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + if (Ops.size() > NameIdx) { + StringRef Name = getString(Ops[NameIdx]); + return Builder.createNameSpace(ParentScope, Name, +@@ -630,7 +676,8 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator( + using namespace SPIRVDebug::Operand::LexicalBlockDiscriminator; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned Disc = Ops[DiscriminatorIdx]; ++ SPIRVWord Disc = getConstantValueOrLiteral(Ops, DiscriminatorIdx, ++ DebugInst->getExtSetKind()); + DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); + return Builder.createLexicalBlockFile(ParentScope, File, Disc); + } +@@ -644,11 +691,13 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + DISubroutineType *Ty = + transDebugInst(BM->get(Ops[TypeIdx])); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + StringRef LinkageName = getString(Ops[LinkageNameIdx]); + +- SPIRVWord SPIRVDebugFlags = Ops[FlagsIdx]; ++ SPIRVWord SPIRVDebugFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + DINode::DIFlags Flags = DINode::FlagZero; + if (SPIRVDebugFlags & SPIRVDebug::FlagIsArtificial) + Flags |= llvm::DINode::FlagArtificial; +@@ -676,7 +725,8 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized, + DISubprogram::SPFlagNonvirtual, IsMainSubprogram); + +- unsigned ScopeLine = Ops[ScopeLineIdx]; ++ SPIRVWord ScopeLine = ++ getConstantValueOrLiteral(Ops, ScopeLineIdx, DebugInst->getExtSetKind()); + + // Function declaration descriptor + DISubprogram *FD = nullptr; +@@ -736,11 +786,13 @@ DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { + StringRef Name = getString(Ops[NameIdx]); + StringRef LinkageName = getString(Ops[LinkageNameIdx]); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DISubroutineType *Ty = + transDebugInst(BM->get(Ops[TypeIdx])); + +- SPIRVWord SPIRVDebugFlags = Ops[FlagsIdx]; ++ SPIRVWord SPIRVDebugFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + bool IsDefinition = SPIRVDebugFlags & SPIRVDebug::FlagIsDefinition; + bool IsOptimized = SPIRVDebugFlags & SPIRVDebug::FlagIsOptimized; + bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal; +@@ -799,7 +851,8 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + StringRef Name = getString(Ops[NameIdx]); + DIType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIScope *Parent = getScope(BM->getEntry(Ops[ParentIdx])); + StringRef LinkageName = getString(Ops[LinkageNameIdx]); + +@@ -808,8 +861,10 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + StaticMemberDecl = transDebugInst( + BM->get(Ops[StaticMemberDeclarationIdx])); + } +- bool IsLocal = Ops[FlagsIdx] & SPIRVDebug::FlagIsLocal; +- bool IsDefinition = Ops[FlagsIdx] & SPIRVDebug::FlagIsDefinition; ++ SPIRVWord Flags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ bool IsLocal = Flags & SPIRVDebug::FlagIsLocal; ++ bool IsDefinition = Flags & SPIRVDebug::FlagIsDefinition; + MDNode *VarDecl = nullptr; + if (IsDefinition) { + VarDecl = Builder.createGlobalVariableExpression( +@@ -844,12 +899,15 @@ DINode *SPIRVToLLVMDbgTran::transLocalVariable(const SPIRVExtInst *DebugInst) { + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + StringRef Name = getString(Ops[NameIdx]); + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIType *Ty = transDebugInst(BM->get(Ops[TypeIdx])); + DINode::DIFlags Flags = DINode::FlagZero; +- if (Ops[FlagsIdx] & SPIRVDebug::FlagIsArtificial) ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ if (SPIRVFlags & SPIRVDebug::FlagIsArtificial) + Flags |= DINode::FlagArtificial; +- if (Ops[FlagsIdx] & SPIRVDebug::FlagIsObjectPointer) ++ if (SPIRVFlags & SPIRVDebug::FlagIsObjectPointer) + Flags |= DINode::FlagObjectPointer; + + if (Ops.size() > ArgNumberIdx) +@@ -864,7 +922,8 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + + DIFile *File = getFile(Ops[SourceIdx]); +- unsigned LineNo = Ops[LineIdx]; ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + StringRef Alias = getString(Ops[NameIdx]); + SPIRVEntry *TypeInst = BM->getEntry(Ops[BaseTypeIdx]); + DIType *Ty = transDebugInst(static_cast(TypeInst)); +@@ -881,11 +940,13 @@ DINode *SPIRVToLLVMDbgTran::transInheritance(const SPIRVExtInst *DebugInst) { + transDebugInst(BM->get(Ops[ParentIdx])); + DIType *Child = transDebugInst(BM->get(Ops[ChildIdx])); + DINode::DIFlags Flags = DINode::FlagZero; +- if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) + Flags |= llvm::DINode::FlagPublic; +- if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected) ++ if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected) + Flags |= llvm::DINode::FlagProtected; +- if ((Ops[FlagsIdx] & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) ++ if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) + Flags |= llvm::DINode::FlagPrivate; + uint64_t Offset = BM->get(Ops[OffsetIdx])->getZExtIntValue(); + return Builder.createInheritance(Child, Parent, Offset, 0, Flags); +@@ -972,10 +1033,13 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); +- unsigned Line = Ops[LineIdx]; ++ SPIRVWord Line = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIFile *File = getFile(Ops[SourceIdx]); + auto *Entity = transDebugInst(BM->get(Ops[EntityIdx])); +- if (Ops[TagIdx] == SPIRVDebug::ImportedModule) { ++ SPIRVWord Tag = ++ getConstantValueOrLiteral(Ops, TagIdx, DebugInst->getExtSetKind()); ++ if (Tag == SPIRVDebug::ImportedModule) { + if (!Entity) + return Builder.createImportedModule( + Scope, static_cast(nullptr), File, Line); +@@ -986,7 +1050,7 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { + if (DINamespace *NS = dyn_cast(Entity)) + return Builder.createImportedModule(Scope, NS, File, Line); + } +- if (Ops[TagIdx] == SPIRVDebug::ImportedDeclaration) { ++ if (Tag == SPIRVDebug::ImportedDeclaration) { + StringRef Name = getString(Ops[NameIdx]); + if (DIGlobalVariableExpression *GVE = + dyn_cast(Entity)) +@@ -1001,23 +1065,16 @@ DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::ModuleINTEL; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); +- bool IsNonSemanticDI = +- (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); +- auto GetInt = [&](SPIRVId Id) -> ConstantInt * { +- auto *V = BM->get(Id); +- return cast(SPIRVReader->transValue(V, nullptr, nullptr)); +- }; +- unsigned Line = +- IsNonSemanticDI ? GetInt(Ops[LineIdx])->getZExtValue() : Ops[LineIdx]; ++ SPIRVWord Line = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + DIFile *File = getFile(Ops[SourceIdx]); + StringRef Name = getString(Ops[NameIdx]); + StringRef ConfigMacros = getString(Ops[ConfigMacrosIdx]); + StringRef IncludePath = getString(Ops[IncludePathIdx]); + StringRef ApiNotes = getString(Ops[ApiNotesIdx]); + bool IsDecl = +- IsNonSemanticDI ? GetInt(Ops[IsDeclIdx])->getZExtValue() : Ops[IsDeclIdx]; +- ++ getConstantValueOrLiteral(Ops, IsDeclIdx, DebugInst->getExtSetKind()); + return Builder.createModule(Scope, Name, ConfigMacros, IncludePath, ApiNotes, + File, Line, IsDecl); + } +@@ -1026,9 +1083,12 @@ MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Args = DebugInst->getArguments(); + std::vector Ops; + for (SPIRVId A : Args) { ++ using namespace SPIRVDebug::Operand::Operation; + SPIRVExtInst *O = BM->get(A); + const SPIRVWordVec &Operands = O->getArguments(); +- auto OpCode = static_cast(Operands[0]); ++ auto OpCode = ++ static_cast(getConstantValueOrLiteral( ++ Operands, OpCodeIdx, DebugInst->getExtSetKind())); + Ops.push_back(SPIRV::DbgExpressionOpCodeMap::rmap(OpCode)); + for (unsigned I = 1, E = Operands.size(); I < E; ++I) { + Ops.push_back(Operands[I]); +@@ -1226,11 +1286,12 @@ DebugLoc SPIRVToLLVMDbgTran::transDebugScope(const SPIRVInstruction *Inst) { + return DebugLoc(); + } + +-MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *Inst) { ++MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::InlinedAt; +- SPIRVWordVec Ops = Inst->getArguments(); ++ SPIRVWordVec Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); +- unsigned Line = Ops[LineIdx]; ++ SPIRVWord Line = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + unsigned Col = 0; // DebugInlinedAt instruction has no column operand + DILocalScope *Scope = + cast(getScope(BM->getEntry(Ops[ScopeIdx]))); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index f18a08c9..28a42d37 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -74,7 +74,7 @@ public: + DebugInst->getExtSetKind() == + SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || + DebugInst->getExtSetKind() == +- SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200) && + "Unexpected extended instruction set"); + auto It = DebugInstCache.find(DebugInst); + if (It != DebugInstCache.end()) +@@ -186,6 +186,9 @@ private: + return nullptr; + } + const std::string &getString(const SPIRVId Id); ++ SPIRVWord getConstantValueOrLiteral(const std::vector &, ++ const SPIRVWord, ++ const SPIRVExtInstSetKind); + std::string findModuleProducer(); + Optional> ParseChecksum(StringRef Text); + }; +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 9bb59b6e..3a62429f 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -79,7 +79,7 @@ enum SPIRVExtInstSetKind { + SPIRVEIS_Debug, + SPIRVEIS_OpenCL_DebugInfo_100, + SPIRVEIS_NonSemantic_Shader_DebugInfo_100, +- SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200, + SPIRVEIS_Count, + }; + +@@ -133,8 +133,8 @@ template <> inline void SPIRVMap::init() { + add(SPIRVEIS_OpenCL_DebugInfo_100, "OpenCL.DebugInfo.100"); + add(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, + "NonSemantic.Shader.DebugInfo.100"); +- add(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, +- "NonSemantic.Kernel.DebugInfo.100"); ++ add(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ "NonSemantic.Shader.DebugInfo.200"); + } + typedef SPIRVMap SPIRVBuiltinSetNameMap; + +diff --git a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +index 64aa40f6..8a339297 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +@@ -164,7 +164,7 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope) || + Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, + SPIRVDebug::Scope) || +- Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, + SPIRVDebug::Scope)) { + DebugScope = Inst; + } else if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::NoScope) || +@@ -172,7 +172,7 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + SPIRVDebug::NoScope) || + Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, + SPIRVDebug::NoScope) || +- Inst->isExtInst(SPIRVEIS_NonSemantic_Kernel_DebugInfo_100, ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, + SPIRVDebug::NoScope)) { + DebugScope = nullptr; + } else { +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 568885fb..9a34f610 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -1763,7 +1763,7 @@ public: + assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug || + ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100 || + ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || +- ExtSetKind == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && ++ ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) && + "not supported"); + } + void encode(spv_ostream &O) const override { +@@ -1775,7 +1775,7 @@ public: + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: + case SPIRVEIS_NonSemantic_Shader_DebugInfo_100: +- case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + getEncoder(O) << ExtOpDebug; + break; + default: +@@ -1794,7 +1794,7 @@ public: + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: + case SPIRVEIS_NonSemantic_Shader_DebugInfo_100: +- case SPIRVEIS_NonSemantic_Kernel_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + getDecoder(I) >> ExtOpDebug; + break; + default: +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index 5cbc2a80..0916cebc 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -644,7 +644,7 @@ void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) { + if ((EI->getExtSetKind() == SPIRVEIS_Debug || + EI->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100 || + EI->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || +- EI->getExtSetKind() == SPIRVEIS_NonSemantic_Kernel_DebugInfo_100) && ++ EI->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) && + EI->getExtOp() != SPIRVDebug::Declare && + EI->getExtOp() != SPIRVDebug::Value && + EI->getExtOp() != SPIRVDebug::Scope && +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h +index bd462aa4..0241f914 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.h ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.h +@@ -530,8 +530,8 @@ public: + return SPIRVEIS_OpenCL_DebugInfo_100; + case DebugInfoEIS::NonSemantic_Shader_DebugInfo_100: + return SPIRVEIS_NonSemantic_Shader_DebugInfo_100; +- case DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100: +- return SPIRVEIS_NonSemantic_Kernel_DebugInfo_100; ++ case DebugInfoEIS::NonSemantic_Shader_DebugInfo_200: ++ return SPIRVEIS_NonSemantic_Shader_DebugInfo_200; + } + assert(false && "Unexpected debug info EIS!"); + return SPIRVEIS_Debug; +diff --git a/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt b/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt +index 37bee955..28f90510 100644 +--- a/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt ++++ b/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt +@@ -56,7 +56,7 @@ + + 5 ExtInst 3 27 2 DebugInfoNone + 7 ExtInst 3 30 2 DebugSource 29 27 +-9 ExtInst 3 31 2 DebugCompileUnit 65536 4 30 21 ++9 ExtInst 3 31 2 DebugCompileUnit 65536 4 30 21 + 7 ExtInst 3 32 2 DebugTypeFunction 0 27 + 8 ExtInst 3 35 2 DebugTypeBasic 33 34 3 + 7 ExtInst 3 36 2 DebugTypeArray 35 11 ; Count = 1000 +diff --git a/test/DebugInfo/Generic/tu-member-opaque.spvasm b/test/DebugInfo/Generic/tu-member-opaque.spvasm +index dd24232e..135afcbf 100644 +--- a/test/DebugInfo/Generic/tu-member-opaque.spvasm ++++ b/test/DebugInfo/Generic/tu-member-opaque.spvasm +@@ -71,4 +71,4 @@ + 4 Line 15 6 0 + 1 Return + +-1 FunctionEnd +\ No newline at end of file ++1 FunctionEnd +diff --git a/test/DebugInfo/NonSemantic/DebugFunction.cl b/test/DebugInfo/NonSemantic/DebugFunction.cl +new file mode 100644 +index 00000000..c913fc04 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/DebugFunction.cl +@@ -0,0 +1,28 @@ ++// Check for 2 things: ++// - After round trip translation function definition has !dbg metadata attached ++// specifically if -gline-tables-only was used for Clang ++// - Parent operand of DebugFunction is DebugCompileUnit, not an OpString, even ++// if in LLVM IR it points to a DIFile instead of DICompileUnit. ++ ++// RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o - | llvm-spirv -o %t.spv ++// RUN: llvm-spirv %t.spv --spirv-debug-info-version=nonsemantic-shader-100 -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++// RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++float foo(int i) { ++ return i * 3.14; ++} ++void kernel k() { ++ float a = foo(2); ++} ++ ++// CHECK-SPIRV: String [[foo:[0-9]+]] "foo" ++// CHECK-SPIRV: String [[k:[0-9]+]] "k" ++// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompileUnit ++// CHECK-SPIRV: DebugFunction [[foo]] {{.*}} [[CU]] {{.*}} [[foo_id:[0-9]+]] {{[0-9]+}} {{$}} ++// CHECK-SPIRV: DebugFunction [[k]] {{.*}} [[CU]] {{.*}} [[k_id:[0-9]+]] {{[0-9]+}} {{$}} ++ ++// CHECK-SPIRV: Function {{[0-9]+}} [[foo_id]] ++// CHECK-LLVM: define spir_func float @_Z3fooi(i32 %i) #{{[0-9]+}} !dbg !{{[0-9]+}} { ++ ++// CHECK-SPIRV: Function {{[0-9]+}} [[k_id]] ++// CHECK-LLVM: define spir_kernel void @k() #{{[0-9]+}} !dbg !{{[0-9]+}} +diff --git a/test/DebugInfo/NonSemanticKernel100/DIModule.ll b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +similarity index 84% +rename from test/DebugInfo/NonSemanticKernel100/DIModule.ll +rename to test/DebugInfo/NonSemantic/Shader200/DIModule.ll +index 4aa22daf..8347d010 100644 +--- a/test/DebugInfo/NonSemanticKernel100/DIModule.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +@@ -1,13 +1,13 @@ + ; ModuleID = '/Volumes/Data/apple-internal/llvm/tools/clang/test/Modules/debug-info-moduleimport.m' + ; RUN: llvm-as < %s -o %t.bc +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 %t.bc -o %t.spv ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 %t.bc -o %t.spv + ; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll + + ; RUN: llc -mtriple=x86_64-apple-macosx %t.ll -accel-tables=Dwarf -o %t -filetype=obj + ; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s + ; RUN: llvm-dwarfdump -verify %t + +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 %t.bc -spirv-text -o %t.spt ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 %t.bc -spirv-text -o %t.spt + ; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV + + ; CHECK: DW_TAG_compile_unit +@@ -21,7 +21,7 @@ + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + target triple = "spir64-unknown-unknown" + +-; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Shader.DebugInfo.200" + ; CHECK-SPIRV: String [[#FileName:]] "/llvm/tools/clang/test/Modules/" + ; CHECK-SPIRV: String [[#EmptyStr:]] "" + ; CHECK-SPIRV: String [[#Name:]] "DebugModule" +@@ -29,10 +29,12 @@ target triple = "spir64-unknown-unknown" + ; CHECK-SPIRV: String [[#IncludePath:]] "/llvm/tools/clang/test/Modules/Inputs" + ; CHECK-SPIRV: String [[#ApiNotes:]] "m.apinotes" + ; CHECK-SPIRV: TypeInt [[#TypeInt32:]] 32 0 +-; CHECK-SPIRV: Constant [[#TypeInt32]] [[#Constant0:]] 0 ++; CHECK-SPIRV-DAG: Constant [[#TypeInt32]] [[#Constant0:]] 0 ++; CHECK-SPIRV-DAG: Constant [[#TypeInt32]] [[#Version:]] 65536 ++; CHECK-SPIRV-DAG: Constant [[#TypeInt32]] [[#DWARF:]] 4 + + ; CHECK-SPIRV: ExtInst [[#]] [[#Source:]] [[#]] DebugSource [[#FileName]] +-; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompileUnit 65536 4 ++; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompileUnit [[#Version]] [[#DWARF]] + ; CHECK-SPIRV: ExtInst [[#]] [[#SourceEmpty:]] [[#]] DebugSource [[#EmptyStr]] + ; CHECK-SPIRV: ExtInst [[#]] [[#Module:]] [[#]] DebugModule [[#Name]] [[#SourceEmpty]] [[#Constant0]] [[#Parent]] [[#Defines]] [[#IncludePath]] [[#ApiNotes]] [[#Constant0]] + ; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugImportedEntity [[#]] [[#]] [[#]] [[#Source]] [[#Module]] +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll +similarity index 98% +rename from test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll +rename to test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll +index 6586bf17..7b82c1df 100644 +--- a/test/DebugInfo/NonSemanticKernel100/DebugInfoStringType.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll +@@ -1,5 +1,5 @@ + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV + ; RUN: llvm-spirv -to-binary %t.spt -o %t.spv + +@@ -7,7 +7,7 @@ + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM + +-; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Shader.DebugInfo.200" + ; CHECK-SPIRV: String [[#StrGreet:]] ".str.GREETING" + ; CHECK-SPIRV: String [[#StrChar1:]] "CHARACTER_1" + ; CHECK-SPIRV: String [[#StrChar2:]] "CHARACTER_2" +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +similarity index 98% +rename from test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll +rename to test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +index 0a901ae8..23a729fb 100644 +--- a/test/DebugInfo/NonSemanticKernel100/DebugInfoSubrange.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +@@ -1,5 +1,5 @@ + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV + ; RUN: llvm-spirv -to-binary %t.spt -o %t.spv + +@@ -7,7 +7,7 @@ + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM + +-; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Shader.DebugInfo.200" + + ; CHECK-SPIRV: String [[#LocalVarNameId:]] "A$1$upperbound" + ; CHECK-SPIRV: TypeInt [[#TyInt64Id:]] 64 0 +diff --git a/test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +similarity index 96% +rename from test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll +rename to test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +index 25d5330b..1e6e3f9f 100644 +--- a/test/DebugInfo/NonSemanticKernel100/DebugInfoTargetFunction.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +@@ -1,5 +1,5 @@ + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV + ; RUN: llvm-spirv -to-binary %t.spt -o %t.spv + +@@ -7,7 +7,7 @@ + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM + +-; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV-DAG: ExtInstImport [[#EISId:]] "NonSemantic.Shader.DebugInfo.200" + ; CHECK-SPIRV-DAG: String [[#Func:]] "foo_wrapper" + ; CHECK-SPIRV-DAG: String [[#TargetFunc:]] "_Z3foov" + +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranArray.ll b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +similarity index 98% +rename from test/DebugInfo/NonSemanticKernel100/FortranArray.ll +rename to test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +index 6b5d88a3..10278029 100644 +--- a/test/DebugInfo/NonSemanticKernel100/FortranArray.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +@@ -1,7 +1,7 @@ + ; RUN: llvm-as %s -o %t.bc + ; Translation shouldn't crash: +-; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 +-; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll b/test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayExpr.ll +similarity index 95% +rename from test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll +rename to test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayExpr.ll +index 0aa4c1f7..01137fc9 100644 +--- a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayExpr.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayExpr.ll +@@ -8,18 +8,19 @@ + ;; FortranDynamicArrayVar.ll is for variable representation. + + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 -o - | FileCheck %s --check-prefix=CHECK-SPIRV +-; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +-; CHECK-SPIRV-DAG: ExtInstImport [[#Import:]] "NonSemantic.Kernel.DebugInfo.100" ++; CHECK-SPIRV-DAG: ExtInstImport [[#Import:]] "NonSemantic.Shader.DebugInfo.200" + ; CHECK-SPIRV-DAG: String [[#BasicTName:]] "INTEGER*4" + ; CHECK-SPIRV-DAG: TypeInt [[#Int32T:]] 32 0 + ; CHECK-SPIRV-DAG: Constant [[#Int32T]] [[#IntConst:]] 32 ++; CHECK-SPIRV-DAG: Constant [[#Int32T]] [[#Flag:]] 4 + ; CHECK-SPIRV-DAG: TypeVoid [[#VoidT:]] + ; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgInfoNone:]] [[#Import]] DebugInfoNone +-; CHECK-SPIRV: ExtInst [[#VoidT]] [[#ArrayBasicT:]] [[#Import]] DebugTypeBasic [[#BasicTName]] [[#IntConst]] 4 ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#ArrayBasicT:]] [[#Import]] DebugTypeBasic [[#BasicTName]] [[#IntConst]] [[#Flag]] + ; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprLocation:]] [[#Import]] DebugExpression [[#]] [[#]] {{$}} + ; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprAssociated:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] [[#]] {{$}} + ; CHECK-SPIRV: ExtInst [[#VoidT]] [[#DbgExprLowerBound:]] [[#Import]] DebugExpression [[#]] [[#]] [[#]] {{$}} +diff --git a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll b/test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayVar.ll +similarity index 95% +rename from test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll +rename to test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayVar.ll +index 29f01ffd..bf5aa0ee 100644 +--- a/test/DebugInfo/NonSemanticKernel100/FortranDynamicArrayVar.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranDynamicArrayVar.ll +@@ -9,8 +9,8 @@ + ;; FortranDynamicArrayVar.ll is for expression representation. + + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-kernel-100 -o - | FileCheck %s --check-prefix=CHECK-SPIRV +-; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-kernel-100 ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +@@ -56,7 +56,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) + + !0 = !{i32 2, !"Dwarf Version", i32 4} + !1 = !{i32 2, !"Debug Info Version", i32 3} +-!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4) ++!2 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: " F95 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4) + !3 = !DIFile(filename: "fortsubrange.f90", directory: "/dir") + !4 = !{} + !5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2) +diff --git a/test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +similarity index 62% +rename from test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll +rename to test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +index fd67dcbe..19ab5719 100644 +--- a/test/DebugInfo/NonSemanticKernel100/SourceLanguageLLVMToSPIRV.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +@@ -2,21 +2,25 @@ + ; appropriate SourceLanguages in SPIRV when the extended debug info is enabled. + + ; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C99/' %s | llvm-as - -o %t.bc +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-C99 ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-C99 + + ; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_OpenCL/' %s | llvm-as - -o %t.bc +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-OPENCLC ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-OPENCLC + + ; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus/' %s | llvm-as - -o %t.bc +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP + + ; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus_14/' %s | llvm-as - -o %t.bc +-; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-kernel-100 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP14 +- +-; CHECK-C99: DebugCompileUnit [[#]] [[#]] [[#]] 109 +-; CHECK-OPENCLC: DebugCompileUnit [[#]] [[#]] [[#]] 3 +-; CHECK-CPP: DebugCompileUnit [[#]] [[#]] [[#]] 111 +-; CHECK-CPP14: DebugCompileUnit [[#]] [[#]] [[#]] 114 ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP14 ++ ++; CHECK-C99: Constant [[#]] [[#Constant:]] 109 ++; CHECK-C99: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-OPENCLC: Constant [[#]] [[#Constant:]] 3 ++; CHECK-OPENCLC: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-CPP: Constant [[#]] [[#Constant:]] 111 ++; CHECK-CPP: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-CPP14: Constant [[#]] [[#Constant:]] 114 ++; CHECK-CPP14: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] + + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" + target triple = "spir64-unknown-unknown" +diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp +index 8cb62b6a..e9a7fb45 100644 +--- a/tools/llvm-spirv/llvm-spirv.cpp ++++ b/tools/llvm-spirv/llvm-spirv.cpp +@@ -234,10 +234,10 @@ static cl::opt DebugEIS( + "version of SPIR-V debug info format is compatible with the rules " + "regarding non-semantic instruction sets."), + clEnumValN( +- SPIRV::DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100, +- "nonsemantic-kernel-100", ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200, ++ "nonsemantic-shader-200", + "Emit debug info compliant with the " +- "NonSemantic.Kernel.DebugInfo.100 extended instruction set. This " ++ "NonSemantic.Shader.DebugInfo.200 extended instruction set. This " + "version of SPIR-V debug info format is compatible with the rules " + "regarding non-semantic instruction sets."))); + +@@ -730,8 +730,14 @@ int main(int Ac, char **Av) { + } else { + Opts.setDebugInfoEIS(DebugEIS); + if (DebugEIS.getValue() == +- SPIRV::DebugInfoEIS::NonSemantic_Kernel_DebugInfo_100) ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200) + Opts.setAllowExtraDIExpressionsEnabled(true); ++ if (DebugEIS.getValue() == ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200 || ++ DebugEIS.getValue() == ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200) ++ Opts.setAllowedToUseExtension( ++ SPIRV::ExtensionID::SPV_KHR_non_semantic_info); + } + } + +-- +2.20.1 + diff --git a/patches/0026-Backport-to-15-DebugInfo-Rename-NonSemantic.Kernel.D.patch b/patches/0026-Backport-to-15-DebugInfo-Rename-NonSemantic.Kernel.D.patch new file mode 100644 index 0000000..cbb3f51 --- /dev/null +++ b/patches/0026-Backport-to-15-DebugInfo-Rename-NonSemantic.Kernel.D.patch @@ -0,0 +1,30 @@ +From 24d9f0cb2c7880429f65b4a77a768450e6fbc476 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Mon, 20 Mar 2023 13:42:49 +0100 +Subject: [PATCH 26/79] [Backport to 15][DebugInfo] Rename + NonSemantic.Kernel.DebugInfo.100 (#1891) + +To NonSemantic.Shader.DebugInfo.200 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index b6ebb90a..4d9c30e5 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -52,8 +52,8 @@ enum Instruction { + Source = 35, + ModuleINTEL = 36, + InstCount = 37, +- TypeSubrange = 110, + Module = 200, ++ TypeSubrange = 201, + TypeArrayDynamic = 202, + TypeString = 203 + }; +-- +2.20.1 + diff --git a/patches/0027-Backport-to-15-DebugInfo-Add-more-source-languages-a.patch b/patches/0027-Backport-to-15-DebugInfo-Add-more-source-languages-a.patch new file mode 100644 index 0000000..730448a --- /dev/null +++ b/patches/0027-Backport-to-15-DebugInfo-Add-more-source-languages-a.patch @@ -0,0 +1,137 @@ +From 38a25f06a6fc292c193725f0d241685755c823c6 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Tue, 21 Mar 2023 13:13:51 -0700 +Subject: [PATCH 27/79] [Backport to 15][DebugInfo] Add more source languages + and align to spec changes (#1894) + +Spec: KhronosGroup/SPIRV-Registry#186 +--- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 8 ++++ + lib/SPIRV/libSPIRV/spirv_internal.hpp | 44 ++++++++++++------- + .../Shader200/SourceLanguageLLVMToSPIRV.ll | 6 +-- + 3 files changed, 39 insertions(+), 19 deletions(-) + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 4d9c30e5..dfe2535b 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -900,6 +900,10 @@ inline spv::SourceLanguage convertDWARFSourceLangToSPIRVNonSemanticDbgInfo( + case dwarf::SourceLanguage::DW_LANG_D: + return spv::internal::SourceLanguageD; + ++ case dwarf::SourceLanguage::DW_LANG_Fortran77: ++ return spv::internal::SourceLanguageFortran77; ++ case dwarf::SourceLanguage::DW_LANG_Fortran90: ++ return spv::internal::SourceLanguageFortran90; + case dwarf::SourceLanguage::DW_LANG_Fortran95: + return spv::internal::SourceLanguageFortran95; + case dwarf::SourceLanguage::DW_LANG_Fortran03: +@@ -946,6 +950,10 @@ convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(unsigned SourceLang) { + case spv::internal::SourceLanguageD: + return dwarf::SourceLanguage::DW_LANG_D; + ++ case spv::internal::SourceLanguageFortran77: ++ return dwarf::SourceLanguage::DW_LANG_Fortran77; ++ case spv::internal::SourceLanguageFortran90: ++ return dwarf::SourceLanguage::DW_LANG_Fortran90; + case spv::internal::SourceLanguageFortran95: + return dwarf::SourceLanguage::DW_LANG_Fortran95; + case spv::internal::SourceLanguageFortran2003: +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index def8419c..e495fab3 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -30,22 +30,26 @@ namespace spv { + namespace internal { + + enum InternalSourceLanguageNonSemanticDI { +- ISourceLanguagePython = 101, +- ISourceLanguageJulia = 102, +- ISourceLanguageRust = 103, +- ISourceLanguageD = 104, +- ISourceLanguageFortran95 = 105, +- ISourceLanguageFortran2003 = 106, +- ISourceLanguageFortran2008 = 107, +- ISourceLanguageC = 108, +- ISourceLanguageC99 = 109, +- ISourceLanguageC11 = 110, +- ISourceLanguageCPP = 111, +- ISourceLanguageCPP03 = 112, +- ISourceLanguageCPP11 = 113, +- ISourceLanguageCPP14 = 114, +- ISourceLanguageCPP17 = 115, +- ISourceLanguageCPP20 = 116, ++ ISourceLanguagePython = 200, ++ ISourceLanguageJulia = 201, ++ ISourceLanguageRust = 202, ++ ISourceLanguageD = 203, ++ ISourceLanguageFortran77 = 204, ++ ISourceLanguageFortran90 = 205, ++ ISourceLanguageFortran95 = 206, ++ ISourceLanguageFortran2003 = 207, ++ ISourceLanguageFortran2008 = 208, ++ ISourceLanguageFortran2018 = 209, ++ ISourceLanguageC = 210, ++ ISourceLanguageC99 = 211, ++ ISourceLanguageC11 = 212, ++ ISourceLanguageC17 = 213, ++ ISourceLanguageCPP = 214, ++ ISourceLanguageCPP03 = 215, ++ ISourceLanguageCPP11 = 216, ++ ISourceLanguageCPP14 = 217, ++ ISourceLanguageCPP17 = 218, ++ ISourceLanguageCPP20 = 219, + }; + + enum InternalLinkageType { +@@ -159,18 +163,26 @@ constexpr SourceLanguage SourceLanguageRust = + static_cast(ISourceLanguageRust); + constexpr SourceLanguage SourceLanguageD = + static_cast(ISourceLanguageD); ++constexpr SourceLanguage SourceLanguageFortran77 = ++ static_cast(ISourceLanguageFortran77); ++constexpr SourceLanguage SourceLanguageFortran90 = ++ static_cast(ISourceLanguageFortran90); + constexpr SourceLanguage SourceLanguageFortran95 = + static_cast(ISourceLanguageFortran95); + constexpr SourceLanguage SourceLanguageFortran2003 = + static_cast(ISourceLanguageFortran2003); + constexpr SourceLanguage SourceLanguageFortran2008 = + static_cast(ISourceLanguageFortran2008); ++constexpr SourceLanguage SourceLanguageFortran2018 = ++ static_cast(ISourceLanguageFortran2018); + constexpr SourceLanguage SourceLanguageC = + static_cast(ISourceLanguageC); + constexpr SourceLanguage SourceLanguageC99 = + static_cast(ISourceLanguageC99); + constexpr SourceLanguage SourceLanguageC11 = + static_cast(ISourceLanguageC11); ++constexpr SourceLanguage SourceLanguageC17 = ++ static_cast(ISourceLanguageC17); + constexpr SourceLanguage SourceLanguageCPP = + static_cast(ISourceLanguageCPP); + constexpr SourceLanguage SourceLanguageCPP03 = +diff --git a/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +index 19ab5719..c1b3d8ca 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +@@ -13,13 +13,13 @@ + ; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus_14/' %s | llvm-as - -o %t.bc + ; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP14 + +-; CHECK-C99: Constant [[#]] [[#Constant:]] 109 ++; CHECK-C99: Constant [[#]] [[#Constant:]] 211 + ; CHECK-C99: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] + ; CHECK-OPENCLC: Constant [[#]] [[#Constant:]] 3 + ; CHECK-OPENCLC: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] +-; CHECK-CPP: Constant [[#]] [[#Constant:]] 111 ++; CHECK-CPP: Constant [[#]] [[#Constant:]] 214 + ; CHECK-CPP: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] +-; CHECK-CPP14: Constant [[#]] [[#Constant:]] 114 ++; CHECK-CPP14: Constant [[#]] [[#Constant:]] 217 + ; CHECK-CPP14: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] + + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +-- +2.20.1 + diff --git a/patches/0028-Backport-to-15-DebugInfo-Align-Instruction-names-to-.patch b/patches/0028-Backport-to-15-DebugInfo-Align-Instruction-names-to-.patch new file mode 100644 index 0000000..f00b854 --- /dev/null +++ b/patches/0028-Backport-to-15-DebugInfo-Align-Instruction-names-to-.patch @@ -0,0 +1,567 @@ +From 4a513bfd07f7dd56d1271d90136233ffc70610ba Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Thu, 23 Mar 2023 09:20:23 -0700 +Subject: [PATCH 28/79] [Backport to 15][DebugInfo] Align Instruction names to + the specification (#1896) + +This patch fixes the discovered typos in Debug Instruction names, so we +can generate spec-conformant SPIR-V module. +https://registry.khronos.org/SPIR-V/specs/unified1/DebugInfo.html +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 18 +++--- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 2 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 57 ++++++++++--------- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 12 ++-- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 12 ++-- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 16 +++--- + test/DebugInfo/DebugFunction.cl | 6 +- + .../DebugInfoSubrangeWithOnlyCount.spt | 4 +- + .../DebugInfo/Generic/tu-member-opaque.spvasm | 2 +- + test/DebugInfo/NonSemantic/DebugFunction.cl | 6 +- + .../NonSemantic/Shader200/DIModule.ll | 2 +- + .../Shader200/DebugInfoSubrange.ll | 4 +- + .../Shader200/SourceLanguageLLVMToSPIRV.ll | 8 +-- + test/DebugInfo/OpenCL100/DebugInfoSubrange.ll | 2 +- + test/DebugInfo/SourceLanguageLLVMToSPIRV.ll | 4 +- + 15 files changed, 79 insertions(+), 76 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index a48be01d..4d7caea7 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -344,7 +344,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryImpl(const MDNode *MDN) { + + // Compilation unit + case dwarf::DW_TAG_compile_unit: +- return transDbgCompilationUnit(cast(DIEntry)); ++ return transDbgCompileUnit(cast(DIEntry)); + + // Templates + case dwarf::DW_TAG_template_type_parameter: +@@ -539,8 +539,7 @@ SPIRVId LLVMToSPIRVDbgTran::getDebugInfoNoneId() { + + // Compilation unit + +-SPIRVEntry * +-LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + using namespace SPIRVDebug::Operand::CompilationUnit; + SPIRVWordVec Ops(OperandCount); + Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion; +@@ -977,7 +976,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { + Ops[FlagsIdx] = transDebugFlags(DT); + if (isNonSemanticDebugInfo()) + transformToConstant(Ops, {FlagsIdx}); +- return BM->addDebugInfo(SPIRVDebug::Inheritance, getVoidTy(), Ops); ++ return BM->addDebugInfo(SPIRVDebug::TypeInheritance, getVoidTy(), Ops); + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPtrToMember(const DIDerivedType *DT) { +@@ -992,7 +991,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPtrToMember(const DIDerivedType *DT) { + SPIRVEntry * + LLVMToSPIRVDbgTran::transDbgTemplateParams(DITemplateParameterArray TPA, + const SPIRVEntry *Target) { +- using namespace SPIRVDebug::Operand::Template; ++ using namespace SPIRVDebug::Operand::TypeTemplate; + SPIRVWordVec Ops(MinOperandCount); + Ops[TargetIdx] = Target->getId(); + for (DITemplateParameter *TP : TPA) { +@@ -1003,7 +1002,7 @@ LLVMToSPIRVDbgTran::transDbgTemplateParams(DITemplateParameterArray TPA, + + SPIRVEntry * + LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { +- using namespace SPIRVDebug::Operand::TemplateParameter; ++ using namespace SPIRVDebug::Operand::TypeTemplateParameter; + SPIRVWordVec Ops(OperandCount); + Ops[NameIdx] = BM->getString(TP->getName().str())->getId(); + Ops[TypeIdx] = transDbgEntry(TP->getType())->getId(); +@@ -1023,7 +1022,7 @@ LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateTemplateParameter( + const DITemplateValueParameter *TVP) { +- using namespace SPIRVDebug::Operand::TemplateTemplateParameter; ++ using namespace SPIRVDebug::Operand::TypeTemplateTemplateParameter; + SPIRVWordVec Ops(OperandCount); + assert(isa(TVP->getValue())); + MDString *Val = cast(TVP->getValue()); +@@ -1040,7 +1039,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateTemplateParameter( + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgTemplateParameterPack( + const DITemplateValueParameter *TVP) { +- using namespace SPIRVDebug::Operand::TemplateParameterPack; ++ using namespace SPIRVDebug::Operand::TypeTemplateParameterPack; + SPIRVWordVec Ops(MinOperandCount); + assert(isa(TVP->getValue())); + MDNode *Params = cast(TVP->getValue()); +@@ -1120,7 +1119,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + + SPIRVEntry *DebugFunc = nullptr; + if (!Func->isDefinition()) { +- DebugFunc = BM->addDebugInfo(SPIRVDebug::FunctionDecl, getVoidTy(), Ops); ++ DebugFunc = ++ BM->addDebugInfo(SPIRVDebug::FunctionDeclaration, getVoidTy(), Ops); + } else { + // Here we add operands specific function definition + using namespace SPIRVDebug::Operand::Function; +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index c17a67d2..9e5f711c 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -99,7 +99,7 @@ private: + SPIRVId getDebugInfoNoneId(); + + // Compilation unit +- SPIRVEntry *transDbgCompilationUnit(const DICompileUnit *CU); ++ SPIRVEntry *transDbgCompileUnit(const DICompileUnit *CU); + + /// The following methods (till the end of the file) implement translation + /// of debug instrtuctions described in the spec. +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index d7986137..152683a5 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -149,7 +149,7 @@ DIScope *SPIRVToLLVMDbgTran::getScope(const SPIRVEntry *ScopeInst) { + } + + DICompileUnit * +-SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { ++SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + + using namespace SPIRVDebug::Operand::CompilationUnit; +@@ -337,8 +337,8 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) { + DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); + size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; + +- auto TransOperand = [&](SPIRVWord Idx) -> PointerUnion { ++ auto TransOperand = ++ [&](SPIRVWord Idx) -> PointerUnion { + if (!getDbgInst(Ops[Idx])) { + if (const auto *GV = getDbgInst(Ops[Idx])) + return transDebugInst(GV); +@@ -737,9 +737,10 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + + // Here we create fake array of template parameters. If it was plain nullptr, + // the template parameter operand would be removed in DISubprogram::getImpl. +- // But we want it to be there, because if there is DebugTemplate instruction +- // refering to this function, TransTemplate method must be able to replace the +- // template parameter operand, thus it must be in the operands list. ++ // But we want it to be there, because if there is DebugTypeTemplate ++ // instruction refering to this function, transTypeTemplate method must be ++ // able to replace the template parameter operand, thus it must be in the ++ // operands list. + SmallVector Elts; + DINodeArray TParams = Builder.getOrCreateArray(Elts); + llvm::DITemplateParameterArray TParamsArray = TParams.get(); +@@ -816,9 +817,10 @@ DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { + + // Here we create fake array of template parameters. If it was plain nullptr, + // the template parameter operand would be removed in DISubprogram::getImpl. +- // But we want it to be there, because if there is DebugTemplate instruction +- // refering to this function, TransTemplate method must be able to replace the +- // template parameter operand, thus it must be in the operands list. ++ // But we want it to be there, because if there is DebugTypeTemplate ++ // instruction refering to this function, transTypeTemplate method must be ++ // able to replace the template parameter operand, thus it must be in the ++ // operands list. + SmallVector Elts; + DINodeArray TParams = Builder.getOrCreateArray(Elts); + llvm::DITemplateParameterArray TParamsArray = TParams.get(); +@@ -932,7 +934,8 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { + return Builder.createTypedef(Ty, Alias, File, LineNo, Scope); + } + +-DINode *SPIRVToLLVMDbgTran::transInheritance(const SPIRVExtInst *DebugInst) { ++DINode * ++SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeInheritance; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); +@@ -953,8 +956,8 @@ DINode *SPIRVToLLVMDbgTran::transInheritance(const SPIRVExtInst *DebugInst) { + } + + DINode * +-SPIRVToLLVMDbgTran::transTemplateParameter(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::TemplateParameter; ++SPIRVToLLVMDbgTran::transTypeTemplateParameter(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeTemplateParameter; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + StringRef Name = getString(Ops[NameIdx]); +@@ -972,9 +975,9 @@ SPIRVToLLVMDbgTran::transTemplateParameter(const SPIRVExtInst *DebugInst) { + return Builder.createTemplateTypeParameter(Context, Name, Ty, false); + } + +-DINode *SPIRVToLLVMDbgTran::transTemplateTemplateParameter( ++DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter( + const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::TemplateTemplateParameter; ++ using namespace SPIRVDebug::Operand::TypeTemplateTemplateParameter; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + StringRef Name = getString(Ops[NameIdx]); +@@ -984,9 +987,9 @@ DINode *SPIRVToLLVMDbgTran::transTemplateTemplateParameter( + TemplName); + } + +-DINode * +-SPIRVToLLVMDbgTran::transTemplateParameterPack(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::TemplateParameterPack; ++DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterPack( ++ const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeTemplateParameterPack; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + StringRef Name = getString(Ops[NameIdx]); +@@ -999,8 +1002,8 @@ SPIRVToLLVMDbgTran::transTemplateParameterPack(const SPIRVExtInst *DebugInst) { + return Builder.createTemplateParameterPack(Context, Name, nullptr, Pack); + } + +-MDNode *SPIRVToLLVMDbgTran::transTemplate(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::Template; ++MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeTemplate; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + const size_t NumOps = Ops.size(); + assert(NumOps >= MinOperandCount && "Invalid number of operands"); +@@ -1104,7 +1107,7 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + return nullptr; + + case SPIRVDebug::CompilationUnit: +- return transCompileUnit(DebugInst); ++ return transCompilationUnit(DebugInst); + + case SPIRVDebug::TypeBasic: + return transTypeBasic(DebugInst); +@@ -1151,7 +1154,7 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::Function: + return transFunction(DebugInst); + +- case SPIRVDebug::FunctionDecl: ++ case SPIRVDebug::FunctionDeclaration: + return transFunctionDecl(DebugInst); + + case SPIRVDebug::GlobalVariable: +@@ -1166,20 +1169,20 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::InlinedAt: + return transDebugInlined(DebugInst); + +- case SPIRVDebug::Inheritance: +- return transInheritance(DebugInst); ++ case SPIRVDebug::TypeInheritance: ++ return transTypeInheritance(DebugInst); + + case SPIRVDebug::TypeTemplateParameter: +- return transTemplateParameter(DebugInst); ++ return transTypeTemplateParameter(DebugInst); + + case SPIRVDebug::TypeTemplateTemplateParameter: +- return transTemplateTemplateParameter(DebugInst); ++ return transTypeTemplateTemplateParameter(DebugInst); + + case SPIRVDebug::TypeTemplateParameterPack: +- return transTemplateParameterPack(DebugInst); ++ return transTypeTemplateParameterPack(DebugInst); + + case SPIRVDebug::TypeTemplate: +- return transTemplate(DebugInst); ++ return transTypeTemplate(DebugInst); + + case SPIRVDebug::ImportedEntity: + return transImportedEntry(DebugInst); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 28a42d37..2102f218 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -102,7 +102,7 @@ private: + + MDNode *transDebugInlined(const SPIRVExtInst *Inst); + +- DICompileUnit *transCompileUnit(const SPIRVExtInst *DebugInst); ++ DICompileUnit *transCompilationUnit(const SPIRVExtInst *DebugInst); + + DIBasicType *transTypeBasic(const SPIRVExtInst *DebugInst); + +@@ -127,11 +127,11 @@ private: + + DINode *transTypeEnum(const SPIRVExtInst *DebugInst); + +- DINode *transTemplateParameter(const SPIRVExtInst *DebugInst); +- DINode *transTemplateTemplateParameter(const SPIRVExtInst *DebugInst); +- DINode *transTemplateParameterPack(const SPIRVExtInst *DebugInst); ++ DINode *transTypeTemplateParameter(const SPIRVExtInst *DebugInst); ++ DINode *transTypeTemplateTemplateParameter(const SPIRVExtInst *DebugInst); ++ DINode *transTypeTemplateParameterPack(const SPIRVExtInst *DebugInst); + +- MDNode *transTemplate(const SPIRVExtInst *DebugInst); ++ MDNode *transTypeTemplate(const SPIRVExtInst *DebugInst); + + DINode *transTypeFunction(const SPIRVExtInst *DebugInst); + +@@ -150,7 +150,7 @@ private: + + DINode *transTypedef(const SPIRVExtInst *DebugInst); + +- DINode *transInheritance(const SPIRVExtInst *DebugInst); ++ DINode *transTypeInheritance(const SPIRVExtInst *DebugInst); + + DINode *transImportedEntry(const SPIRVExtInst *DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index dfe2535b..3454d7c7 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -26,14 +26,14 @@ enum Instruction { + TypeEnum = 9, + TypeComposite = 10, + TypeMember = 11, +- Inheritance = 12, ++ TypeInheritance = 12, + TypePtrToMember = 13, + TypeTemplate = 14, + TypeTemplateParameter = 15, + TypeTemplateParameterPack = 16, + TypeTemplateTemplateParameter = 17, + GlobalVariable = 18, +- FunctionDecl = 19, ++ FunctionDeclaration = 19, + Function = 20, + LexicalBlock = 21, + LexicalBlockDiscriminator = 22, +@@ -456,7 +456,7 @@ enum { + }; + } + +-namespace Template { ++namespace TypeTemplate { + enum { + TargetIdx = 0, + FirstParameterIdx = 1, +@@ -464,7 +464,7 @@ enum { + }; + } + +-namespace TemplateParameter { ++namespace TypeTemplateParameter { + enum { + NameIdx = 0, + TypeIdx = 1, +@@ -476,7 +476,7 @@ enum { + }; + } + +-namespace TemplateTemplateParameter { ++namespace TypeTemplateTemplateParameter { + enum { + NameIdx = 0, + TemplateNameIdx = 1, +@@ -487,7 +487,7 @@ enum { + }; + } + +-namespace TemplateParameterPack { ++namespace TypeTemplateParameterPack { + enum { + NameIdx = 0, + SourceIdx = 1, +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 2085db6e..f9d55433 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -221,7 +221,7 @@ SPIRV_DEF_NAMEMAP(OCLExtOpKind, OCLExtOpMap) + typedef SPIRVDebug::Instruction SPIRVDebugExtOpKind; + template <> inline void SPIRVMap::init() { + add(SPIRVDebug::DebugInfoNone, "DebugInfoNone"); +- add(SPIRVDebug::CompilationUnit, "DebugCompileUnit"); ++ add(SPIRVDebug::CompilationUnit, "DebugCompilationUnit"); + add(SPIRVDebug::Source, "DebugSource"); + add(SPIRVDebug::TypeBasic, "DebugTypeBasic"); + add(SPIRVDebug::TypePointer, "DebugTypePointer"); +@@ -234,19 +234,19 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::TypeMember, "DebugTypeMember"); + add(SPIRVDebug::TypeEnum, "DebugTypeEnum"); + add(SPIRVDebug::Typedef, "DebugTypedef"); +- add(SPIRVDebug::TypeTemplateParameter, "DebugTemplateParameter"); +- add(SPIRVDebug::TypeTemplateParameterPack, "DebugTemplateParameterPack"); ++ add(SPIRVDebug::TypeTemplateParameter, "DebugTypeTemplateParameter"); ++ add(SPIRVDebug::TypeTemplateParameterPack, "DebugTypeTemplateParameterPack"); + add(SPIRVDebug::TypeTemplateTemplateParameter, +- "DebugTemplateTemplateParameter"); +- add(SPIRVDebug::TypeTemplate, "DebugTemplate"); ++ "DebugTypeTemplateTemplateParameter"); ++ add(SPIRVDebug::TypeTemplate, "DebugTypeTemplate"); + add(SPIRVDebug::TypePtrToMember, "DebugTypePtrToMember,"); + add(SPIRVDebug::TypeSubrange, "DebugTypeSubrange"); + add(SPIRVDebug::TypeString, "DebugTypeString"); +- add(SPIRVDebug::Inheritance, "DebugInheritance"); ++ add(SPIRVDebug::TypeInheritance, "DebugTypeInheritance"); + add(SPIRVDebug::Function, "DebugFunction"); +- add(SPIRVDebug::FunctionDecl, "DebugFunctionDecl"); ++ add(SPIRVDebug::FunctionDeclaration, "DebugFunctionDeclaration"); + add(SPIRVDebug::LexicalBlock, "DebugLexicalBlock"); +- add(SPIRVDebug::LexicalBlockDiscriminator, "LexicalBlockDiscriminator"); ++ add(SPIRVDebug::LexicalBlockDiscriminator, "DebugLexicalBlockDiscriminator"); + add(SPIRVDebug::LocalVariable, "DebugLocalVariable"); + add(SPIRVDebug::InlinedVariable, "DebugInlinedVariable"); + add(SPIRVDebug::GlobalVariable, "DebugGlobalVariable"); +diff --git a/test/DebugInfo/DebugFunction.cl b/test/DebugInfo/DebugFunction.cl +index a587b93c..c7e5899f 100644 +--- a/test/DebugInfo/DebugFunction.cl ++++ b/test/DebugInfo/DebugFunction.cl +@@ -1,8 +1,8 @@ + // Check for 2 things: + // - After round trip translation function definition has !dbg metadata attached + // specifically if -gline-tables-only was used for Clang +-// - Parent operand of DebugFunction is DebugCompileUnit, not an OpString, even +-// if in LLVM IR it points to a DIFile instead of DICompileUnit. ++// - Parent operand of DebugFunction is DebugCompilationUnit, not an OpString, ++// even if in LLVM IR it points to a DIFile instead of DICompileUnit. + + // RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o - -no-opaque-pointers | llvm-spirv -o %t.spv + // RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV +@@ -17,7 +17,7 @@ void kernel k() { + + // CHECK-SPIRV: String [[foo:[0-9]+]] "foo" + // CHECK-SPIRV: String [[k:[0-9]+]] "k" +-// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompileUnit ++// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompilationUnit + // CHECK-SPIRV: DebugFunction [[foo]] {{.*}} [[CU]] {{.*}} [[foo_id:[0-9]+]] {{[0-9]+}} {{$}} + // CHECK-SPIRV: DebugFunction [[k]] {{.*}} [[CU]] {{.*}} [[k_id:[0-9]+]] {{[0-9]+}} {{$}} + +diff --git a/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt b/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt +index 28f90510..67d2a519 100644 +--- a/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt ++++ b/test/DebugInfo/DebugInfoSubrangeWithOnlyCount.spt +@@ -56,14 +56,14 @@ + + 5 ExtInst 3 27 2 DebugInfoNone + 7 ExtInst 3 30 2 DebugSource 29 27 +-9 ExtInst 3 31 2 DebugCompileUnit 65536 4 30 21 ++9 ExtInst 3 31 2 DebugCompilationUnit 65536 4 30 21 + 7 ExtInst 3 32 2 DebugTypeFunction 0 27 + 8 ExtInst 3 35 2 DebugTypeBasic 33 34 3 + 7 ExtInst 3 36 2 DebugTypeArray 35 11 ; Count = 1000 + 8 ExtInst 3 37 2 DebugTypePointer 36 4294967295 0 + 16 ExtInst 3 40 2 DebugFunction 38 32 30 25 0 31 39 44 25 27 27 + 12 ExtInst 3 42 2 DebugLocalVariable 41 37 30 15 0 40 0 +-6 ExtInst 3 43 2 DebugTemplate 40 ++6 ExtInst 3 43 2 DebugTypeTemplate 40 + 6 ExtInst 3 44 2 DebugOperation 0 + 6 ExtInst 3 45 2 DebugExpression 44 + +diff --git a/test/DebugInfo/Generic/tu-member-opaque.spvasm b/test/DebugInfo/Generic/tu-member-opaque.spvasm +index 135afcbf..bebeb673 100644 +--- a/test/DebugInfo/Generic/tu-member-opaque.spvasm ++++ b/test/DebugInfo/Generic/tu-member-opaque.spvasm +@@ -52,7 +52,7 @@ + + 5 ExtInst 3 7 2 DebugInfoNone + 7 ExtInst 3 10 2 DebugSource 9 7 +-9 ExtInst 3 11 2 DebugCompileUnit 65536 0 10 12 ++9 ExtInst 3 11 2 DebugCompilationUnit 65536 0 10 12 + 7 ExtInst 3 12 2 DebugTypeFunction 0 7 + 7 ExtInst 3 16 2 DebugSource 15 7 + 8 ExtInst 3 21 2 DebugTypeBasic 20 18 4 +diff --git a/test/DebugInfo/NonSemantic/DebugFunction.cl b/test/DebugInfo/NonSemantic/DebugFunction.cl +index c913fc04..da27864f 100644 +--- a/test/DebugInfo/NonSemantic/DebugFunction.cl ++++ b/test/DebugInfo/NonSemantic/DebugFunction.cl +@@ -1,8 +1,8 @@ + // Check for 2 things: + // - After round trip translation function definition has !dbg metadata attached + // specifically if -gline-tables-only was used for Clang +-// - Parent operand of DebugFunction is DebugCompileUnit, not an OpString, even +-// if in LLVM IR it points to a DIFile instead of DICompileUnit. ++// - Parent operand of DebugFunction is DebugCompilationUnit, not an OpString, ++// even if in LLVM IR it points to a DIFile instead of DICompileUnit. + + // RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o - | llvm-spirv -o %t.spv + // RUN: llvm-spirv %t.spv --spirv-debug-info-version=nonsemantic-shader-100 -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV +@@ -17,7 +17,7 @@ void kernel k() { + + // CHECK-SPIRV: String [[foo:[0-9]+]] "foo" + // CHECK-SPIRV: String [[k:[0-9]+]] "k" +-// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompileUnit ++// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompilationUnit + // CHECK-SPIRV: DebugFunction [[foo]] {{.*}} [[CU]] {{.*}} [[foo_id:[0-9]+]] {{[0-9]+}} {{$}} + // CHECK-SPIRV: DebugFunction [[k]] {{.*}} [[CU]] {{.*}} [[k_id:[0-9]+]] {{[0-9]+}} {{$}} + +diff --git a/test/DebugInfo/NonSemantic/Shader200/DIModule.ll b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +index 8347d010..fb83dfca 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DIModule.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +@@ -34,7 +34,7 @@ target triple = "spir64-unknown-unknown" + ; CHECK-SPIRV-DAG: Constant [[#TypeInt32]] [[#DWARF:]] 4 + + ; CHECK-SPIRV: ExtInst [[#]] [[#Source:]] [[#]] DebugSource [[#FileName]] +-; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompileUnit [[#Version]] [[#DWARF]] ++; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompilationUnit [[#Version]] [[#DWARF]] + ; CHECK-SPIRV: ExtInst [[#]] [[#SourceEmpty:]] [[#]] DebugSource [[#EmptyStr]] + ; CHECK-SPIRV: ExtInst [[#]] [[#Module:]] [[#]] DebugModule [[#Name]] [[#SourceEmpty]] [[#Constant0]] [[#Parent]] [[#Defines]] [[#IncludePath]] [[#ApiNotes]] [[#Constant0]] + ; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugImportedEntity [[#]] [[#]] [[#]] [[#Source]] [[#Module]] +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +index 23a729fb..d83e170a 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +@@ -16,8 +16,8 @@ + ; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone + + ; CHECK-SPIRV: [[#DebugFuncId:]] [[#EISId]] DebugFunction +-; CHECK-SPIRV: [[#DebugTemplate:]] [[#EISId]] DebugTemplate [[#DebugFuncId]] +-; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugTemplate]] ++; CHECK-SPIRV: [[#DebugTypeTemplate:]] [[#EISId]] DebugTypeTemplate [[#DebugFuncId]] ++; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugTypeTemplate]] + ; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#DINoneId]] [[#Constant1Id]] [[#LocalVarId]] [[#DINoneId]] + + ; CHECK-SPIRV: [[#DIExprId:]] [[#EISId]] DebugExpression +diff --git a/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +index c1b3d8ca..e27e0f7d 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/SourceLanguageLLVMToSPIRV.ll +@@ -14,13 +14,13 @@ + ; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP14 + + ; CHECK-C99: Constant [[#]] [[#Constant:]] 211 +-; CHECK-C99: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-C99: DebugCompilationUnit [[#]] [[#]] [[#]] [[#Constant]] + ; CHECK-OPENCLC: Constant [[#]] [[#Constant:]] 3 +-; CHECK-OPENCLC: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-OPENCLC: DebugCompilationUnit [[#]] [[#]] [[#]] [[#Constant]] + ; CHECK-CPP: Constant [[#]] [[#Constant:]] 214 +-; CHECK-CPP: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-CPP: DebugCompilationUnit [[#]] [[#]] [[#]] [[#Constant]] + ; CHECK-CPP14: Constant [[#]] [[#Constant:]] 217 +-; CHECK-CPP14: DebugCompileUnit [[#]] [[#]] [[#]] [[#Constant]] ++; CHECK-CPP14: DebugCompilationUnit [[#]] [[#]] [[#]] [[#Constant]] + + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" + target triple = "spir64-unknown-unknown" +diff --git a/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll b/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +index 27c81083..fcc11485 100644 +--- a/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll ++++ b/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +@@ -14,7 +14,7 @@ + ; CHECK-SPIRV: Constant [[#TypeInt64Id]] [[#NegativeCount:]] 4294967295 4294967295 + + ; CHECK-SPIRV: [[#DbgFuncId:]] [[#]] DebugFunction [[#FuncNameId]] +-; CHECK-SPIRV: [[#DbgTemplateId:]] [[#]] DebugTemplate [[#DbgFuncId]] ++; CHECK-SPIRV: [[#DbgTemplateId:]] [[#]] DebugTypeTemplate [[#DbgFuncId]] + ; CHECK-SPIRV: [[#]] [[#DbgLocVarId:]] [[#]] DebugLocalVariable [[#VarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DbgTemplateId]] + ; CHECK-SPIRV: DebugTypeArray [[#]] [[#DbgLocVarId]] [[#LowerBoundId]] + +diff --git a/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll b/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll +index f6c381c5..51b4376e 100644 +--- a/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll ++++ b/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll +@@ -39,5 +39,5 @@ entry: + !7 = distinct !DISubprogram(name: "func", scope: !8, file: !8, line: 1, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) + !8 = !DIFile(filename: "test.cl", directory: "/tmp", checksumkind: CSK_MD5, checksum: "18aa9ce738eaafc7b7b7181c19092815") + +-; CHECK-OPENCLC: DebugCompileUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 3 +-; CHECK-CPP4OPENCL: DebugCompileUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 6 ++; CHECK-OPENCLC: DebugCompilationUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 3 ++; CHECK-CPP4OPENCL: DebugCompilationUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 6 +-- +2.20.1 + diff --git a/patches/0029-Rename-ConvertFToTF32INTEL-to-RoundFToTF32INTEL.patch b/patches/0029-Rename-ConvertFToTF32INTEL-to-RoundFToTF32INTEL.patch new file mode 100644 index 0000000..1e016a2 --- /dev/null +++ b/patches/0029-Rename-ConvertFToTF32INTEL-to-RoundFToTF32INTEL.patch @@ -0,0 +1,284 @@ +From 331578fd1be6c36622855b65fa06ea895fb55119 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 4 Apr 2023 10:49:01 +0200 +Subject: [PATCH 29/79] Rename ConvertFToTF32INTEL to RoundFToTF32INTEL + +Extension name will be preserved for a while for binary compatibility. + +Signed-off-by: Sidorov, Dmitry +--- + include/LLVMSPIRVExtensions.inc | 3 +- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 116 +++++++++--------- + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 4 +- + lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h | 4 +- + lib/SPIRV/libSPIRV/spirv_internal.hpp | 10 +- + .../convert_tensor_float32.ll | 24 ++-- + 6 files changed, 81 insertions(+), 80 deletions(-) + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index e8d90048..5e966a5f 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -54,6 +54,7 @@ EXT(SPV_INTEL_hw_thread_queries) + EXT(SPV_INTEL_global_variable_decorations) + EXT(SPV_INTEL_complex_float_mul_div) + EXT(SPV_INTEL_split_barrier) +-EXT(SPV_INTEL_tensor_float32_conversion) + EXT(SPV_INTEL_masked_gather_scatter) ++EXT(SPV_INTEL_tensor_float32_conversion) // TODO: to remove old extension ++EXT(SPV_INTEL_tensor_float32_rounding) + EXT(SPV_EXT_relaxed_printf_string_address_space) +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 9a34f610..8ee9aaf0 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3420,64 +3420,6 @@ _SPIRV_OP(ComplexFMulINTEL) + _SPIRV_OP(ComplexFDivINTEL) + #undef _SPIRV_OP + +-template +-class SPIRVTensorFloat32ConversionINTELInstBase : public SPIRVUnaryInst { +-protected: +- SPIRVCapVec getRequiredCapability() const override { +- return getVec(internal::CapabilityTensorFloat32ConversionINTEL); +- } +- +- llvm::Optional getRequiredExtension() const override { +- return ExtensionID::SPV_INTEL_tensor_float32_conversion; +- } +- +- void validate() const override { +- SPIRVUnaryInst::validate(); +- +- SPIRVType *ResCompTy = this->getType(); +- SPIRVWord ResCompCount = 1; +- if (ResCompTy->isTypeVector()) { +- ResCompCount = ResCompTy->getVectorComponentCount(); +- ResCompTy = ResCompTy->getVectorComponentType(); +- } +- +- // validate is a const method, whilst getOperand is non-const method +- // because it may call a method of class Module that may modify LiteralMap +- // of Module field. That modification is not impacting validate method for +- // these instructions, so const_cast is safe here. +- using SPVTF32ConvTy = SPIRVTensorFloat32ConversionINTELInstBase; +- SPIRVValue *Input = const_cast(this)->getOperand(0); +- +- SPIRVType *InCompTy = Input->getType(); +- SPIRVWord InCompCount = 1; +- if (InCompTy->isTypeVector()) { +- InCompCount = InCompTy->getVectorComponentCount(); +- InCompTy = InCompTy->getVectorComponentType(); +- } +- +- auto InstName = OpCodeNameMap::map(OC); +- SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); +- +- SPVErrLog.checkError( +- ResCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, +- InstName + "\nResult value must be a scalar or vector of floating-point" +- " 32-bit type\n"); +- SPVErrLog.checkError(InCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, +- InstName + +- "\nInput value must be a scalar or vector of " +- "floating-point 32-bit type\n"); +- SPVErrLog.checkError( +- ResCompCount == InCompCount, SPIRVEC_InvalidInstruction, +- InstName + "\nInput type must have the same number of components as " +- "result type\n"); +- } +-}; +- +-#define _SPIRV_OP(x) \ +- typedef SPIRVTensorFloat32ConversionINTELInstBase SPIRV##x; +-_SPIRV_OP(ConvertFToTF32INTEL) +-#undef _SPIRV_OP +- + class SPIRVMaskedGatherScatterINTELInstBase : public SPIRVInstTemplateBase { + protected: + SPIRVCapVec getRequiredCapability() const override { +@@ -3625,6 +3567,64 @@ class SPIRVMaskedScatterINTELInst + _SPIRV_OP(MaskedGather, true, 7) + _SPIRV_OP(MaskedScatter, false, 5) + #undef _SPIRV_OP ++ ++template ++class SPIRVTensorFloat32RoundingINTELInstBase : public SPIRVUnaryInst { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(internal::CapabilityTensorFloat32RoundingINTEL); ++ } ++ ++ llvm::Optional getRequiredExtension() const override { ++ return ExtensionID::SPV_INTEL_tensor_float32_conversion; ++ } ++ ++ void validate() const override { ++ SPIRVUnaryInst::validate(); ++ ++ SPIRVType *ResCompTy = this->getType(); ++ SPIRVWord ResCompCount = 1; ++ if (ResCompTy->isTypeVector()) { ++ ResCompCount = ResCompTy->getVectorComponentCount(); ++ ResCompTy = ResCompTy->getVectorComponentType(); ++ } ++ ++ // validate is a const method, whilst getOperand is non-const method ++ // because it may call a method of class Module that may modify LiteralMap ++ // of Module field. That modification is not impacting validate method for ++ // these instructions, so const_cast is safe here. ++ using SPVTF32RoundTy = SPIRVTensorFloat32RoundingINTELInstBase; ++ SPIRVValue *Input = const_cast(this)->getOperand(0); ++ ++ SPIRVType *InCompTy = Input->getType(); ++ SPIRVWord InCompCount = 1; ++ if (InCompTy->isTypeVector()) { ++ InCompCount = InCompTy->getVectorComponentCount(); ++ InCompTy = InCompTy->getVectorComponentType(); ++ } ++ ++ auto InstName = OpCodeNameMap::map(OC); ++ SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); ++ ++ SPVErrLog.checkError( ++ ResCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, ++ InstName + "\nResult value must be a scalar or vector of floating-point" ++ " 32-bit type\n"); ++ SPVErrLog.checkError(InCompTy->isTypeFloat(32), SPIRVEC_InvalidInstruction, ++ InstName + ++ "\nInput value must be a scalar or vector of " ++ "floating-point 32-bit type\n"); ++ SPVErrLog.checkError( ++ ResCompCount == InCompCount, SPIRVEC_InvalidInstruction, ++ InstName + "\nInput type must have the same number of components as " ++ "result type\n"); ++ } ++}; ++ ++#define _SPIRV_OP(x) \ ++ typedef SPIRVTensorFloat32RoundingINTELInstBase SPIRV##x; ++_SPIRV_OP(RoundFToTF32INTEL) ++#undef _SPIRV_OP + } // namespace SPIRV + + #endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index 0d94b0fa..4fbdc618 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -615,9 +615,9 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityGlobalVariableDecorationsINTEL, + "GlobalVariableDecorationsINTEL"); + add(internal::CapabilityComplexFloatMulDivINTEL, "ComplexFloatMulDivINTEL"); +- add(internal::CapabilityTensorFloat32ConversionINTEL, +- "TensorFloat32ConversionINTEL"); + add(internal::CapabilityMaskedGatherScatterINTEL, "MaskedGatherScatterINTEL"); ++ add(internal::CapabilityTensorFloat32RoundingINTEL, ++ "TensorFloat32RoundingINTEL"); + } + SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +index b5e4cefd..ea888d8a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +@@ -13,6 +13,6 @@ _SPIRV_OP_INTERNAL(JointMatrixWorkItemLengthINTEL, + internal::OpJointMatrixWorkItemLengthINTEL) + _SPIRV_OP_INTERNAL(ComplexFMulINTEL, internal::ComplexFMulINTEL) + _SPIRV_OP_INTERNAL(ComplexFDivINTEL, internal::ComplexFDivINTEL) +-_SPIRV_OP_INTERNAL(ConvertFToTF32INTEL, internal::ConvertFToTF32INTEL) + _SPIRV_OP_INTERNAL(MaskedGatherINTEL, internal::OpMaskedGatherINTEL) +-_SPIRV_OP_INTERNAL(MaskedScatterINTEL, internal::OpMaskedScatterINTEL) +\ No newline at end of file ++_SPIRV_OP_INTERNAL(MaskedScatterINTEL, internal::OpMaskedScatterINTEL) ++_SPIRV_OP_INTERNAL(RoundFToTF32INTEL, internal::RoundFToTF32INTEL) +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index e495fab3..e03a3e25 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -69,7 +69,7 @@ enum InternalOp { + IOpJointMatrixWorkItemLengthINTEL = 6410, + IOpComplexFMulINTEL = 6415, + IOpComplexFDivINTEL = 6416, +- IOpConvertFToTF32INTEL = 6426, ++ IOpRoundFToTF32INTEL = 6426, + IOpMaskedGatherINTEL = 6428, + IOpMaskedScatterINTEL = 6429, + IOpPrev = OpMax - 2, +@@ -102,7 +102,7 @@ enum InternalCapability { + ICapFPArithmeticFenceINTEL = 6144, + ICapGlobalVariableDecorationsINTEL = 6146, + ICapabilityComplexFloatMulDivINTEL = 6414, +- ICapabilityTensorFloat32ConversionINTEL = 6425, ++ ICapabilityTensorFloat32RoundingINTEL = 6425, + ICapabilityMaskedGatherScatterINTEL = 6427 + }; + +@@ -147,12 +147,12 @@ _SPIRV_OP(Capability, ComplexFloatMulDivINTEL) + _SPIRV_OP(Op, ComplexFMulINTEL) + _SPIRV_OP(Op, ComplexFDivINTEL) + +-_SPIRV_OP(Capability, TensorFloat32ConversionINTEL) +-_SPIRV_OP(Op, ConvertFToTF32INTEL) +- + _SPIRV_OP(Capability, MaskedGatherScatterINTEL) + _SPIRV_OP(Op, MaskedGatherINTEL) + _SPIRV_OP(Op, MaskedScatterINTEL) ++ ++_SPIRV_OP(Capability, TensorFloat32RoundingINTEL) ++_SPIRV_OP(Op, RoundFToTF32INTEL) + #undef _SPIRV_OP + + constexpr SourceLanguage SourceLanguagePython = +diff --git a/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll b/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll +index 1f027069..140df662 100644 +--- a/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll ++++ b/test/transcoding/SPV_INTEL_tensor_float32_conversion/convert_tensor_float32.ll +@@ -13,7 +13,7 @@ + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" + target triple = "spir64-unknown-unknown" + +-; CHECK-SPIRV: Capability TensorFloat32ConversionINTEL ++; CHECK-SPIRV: Capability TensorFloat32RoundingINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_tensor_float32_conversion" + ; CHECK-SPIRV: TypeFloat [[#FP32Ty:]] 32 + ; CHECK-SPIRV: TypeVector [[#FP32v8Ty:]] [[#FP32Ty]] 8 +@@ -22,24 +22,24 @@ target triple = "spir64-unknown-unknown" + ; CHECK-SPIRV: FunctionParameter [[#FP32Ty]] [[FP32ValId:.*]] + ; CHECK-SPIRV: FunctionParameter [[#FP32v8Ty]] [[FP32v8ValId:.*]] + +-; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32Ty]] [[#]] [[FP32ValId]] +-; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32v8Ty]] [[#]] [[FP32v8ValId]] +-; CHECK-SPIRV: ConvertFToTF32INTEL [[#FP32Ty]] [[#]] [[#CONST]] ++; CHECK-SPIRV: RoundFToTF32INTEL [[#FP32Ty]] [[#]] [[FP32ValId]] ++; CHECK-SPIRV: RoundFToTF32INTEL [[#FP32v8Ty]] [[#]] [[FP32v8ValId]] ++; CHECK-SPIRV: RoundFToTF32INTEL [[#FP32Ty]] [[#]] [[#CONST]] + +-; CHECK-LLVM: call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float +-; CHECK-LLVM: call spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float> +-; CHECK-LLVM: call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float 1.000000e+00) ++; CHECK-LLVM: call spir_func float @_Z25__spirv_RoundFToTF32INTELf(float ++; CHECK-LLVM: call spir_func <8 x float> @_Z25__spirv_RoundFToTF32INTELDv8_f(<8 x float> ++; CHECK-LLVM: call spir_func float @_Z25__spirv_RoundFToTF32INTELf(float 1.000000e+00) + + define spir_func void @_Z2opffv8(float %a, <8 x float> %in) { +- %1 = tail call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float %a) +- %2 = tail call spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float> %in) +- %3 = tail call spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float 1.000000e+00) ++ %1 = tail call spir_func float @_Z25__spirv_RoundFToTF32INTELf(float %a) ++ %2 = tail call spir_func <8 x float> @_Z25__spirv_RoundFToTF32INTELDv8_f(<8 x float> %in) ++ %3 = tail call spir_func float @_Z25__spirv_RoundFToTF32INTELf(float 1.000000e+00) + ret void + } + +-declare spir_func float @_Z27__spirv_ConvertFToTF32INTELf(float) ++declare spir_func float @_Z25__spirv_RoundFToTF32INTELf(float) + +-declare spir_func <8 x float> @_Z27__spirv_ConvertFToTF32INTELDv8_f(<8 x float>) ++declare spir_func <8 x float> @_Z25__spirv_RoundFToTF32INTELDv8_f(<8 x float>) + + !opencl.spir.version = !{!0} + !spirv.Source = !{!1} +-- +2.20.1 + diff --git a/patches/0030-Backport-to-15-Preserve-invalid-SPIRV-source-lang-li.patch b/patches/0030-Backport-to-15-Preserve-invalid-SPIRV-source-lang-li.patch new file mode 100644 index 0000000..ccab9d6 --- /dev/null +++ b/patches/0030-Backport-to-15-Preserve-invalid-SPIRV-source-lang-li.patch @@ -0,0 +1,122 @@ +From 376f08c9259eb89506b0e424d628a48662ae28e9 Mon Sep 17 00:00:00 2001 +From: Mateusz Chudyk +Date: Thu, 4 May 2023 13:32:55 +0200 +Subject: [PATCH 30/79] [Backport to 15] Preserve invalid SPIRV source lang + literal in module metadata (#1951) (#1980) + +Some SPIR-V producers generate invalid source language value (invalid = +other than the enum values defined in spv::SourceLanguage). While in +many cases this is rightly translated to DW_LANG_OpenCL, the original +source language value should be preserved in LLVM module metadata for +later use by LLVM IR consumers. + +Co-authored-by: Michal Paszkowski +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 12 +++++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 17 ++++++++ + .../InvalidSourceLanguageSPIRVtoLLVM.spvasm | 40 +++++++++++++++++++ + 3 files changed, 67 insertions(+), 2 deletions(-) + create mode 100644 test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 152683a5..28b2170e 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -159,10 +159,18 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion); + SPIRVWord SourceLang = + getConstantValueOrLiteral(Ops, LanguageIdx, DebugInst->getExtSetKind()); +- if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { + SourceLang = convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(SourceLang); +- else ++ } else if (isSPIRVSourceLangValid(SourceLang)) { + SourceLang = convertSPIRVSourceLangToDWARF(SourceLang); ++ } else { ++ // Some SPIR-V producers generate invalid source language value. In such ++ // case the original value should be preserved in "Source Lang Literal" ++ // module flag for later use by LLVM IR consumers. ++ M->addModuleFlag(llvm::Module::Warning, "Source Lang Literal", SourceLang); ++ SourceLang = dwarf::DW_LANG_OpenCL; ++ } ++ + auto Producer = findModuleProducer(); + CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, + false, "", 0); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 3454d7c7..0c17595e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -849,6 +849,23 @@ inline spv::SourceLanguage convertDWARFSourceLangToSPIRV(dwarf::SourceLanguage D + } + } + ++inline bool isSPIRVSourceLangValid(unsigned SourceLang) { ++ switch (SourceLang) { ++ // When updating this function, make sure to also ++ // update convertSPIRVSourceLangToDWARF() ++ case spv::SourceLanguage::SourceLanguageOpenCL_CPP: ++ case spv::SourceLanguage::SourceLanguageCPP_for_OpenCL: ++ case spv::SourceLanguage::SourceLanguageOpenCL_C: ++ case spv::SourceLanguage::SourceLanguageESSL: ++ case spv::SourceLanguage::SourceLanguageGLSL: ++ case spv::SourceLanguage::SourceLanguageHLSL: ++ case spv::SourceLanguage::SourceLanguageUnknown: ++ return true; ++ default: ++ return false; ++ } ++} ++ + inline dwarf::SourceLanguage convertSPIRVSourceLangToDWARF(unsigned SourceLang) { + switch (SourceLang) { + // When updating this function, make sure to also +diff --git a/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm b/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm +new file mode 100644 +index 00000000..82f1f4e5 +--- /dev/null ++++ b/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm +@@ -0,0 +1,40 @@ ++; This test checks that any invalid source language in the Compilation Unit instruction is mapped to ++; DW_LANG_OpenCL and the original literal value is retained in the "Source Lang Literal" LLVM module flag metadata. ++ ++; REQUIRES: spirv-as ++ ++; RUN: spirv-as --target-env spv1.3 %s -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis | FileCheck %s ++ ++; SPIR-V ++; Version: 1.1 ++; Generator: Khronos LLVM/SPIR-V Translator; 14 ++; Bound: 16 ++; Schema: 0 ++ OpCapability Addresses ++ OpCapability Kernel ++ %1 = OpExtInstImport "OpenCL.std" ++ %2 = OpExtInstImport "OpenCL.DebugInfo.100" ++ OpMemoryModel Physical64 OpenCL ++ OpEntryPoint Kernel %5 "func" ++ %7 = OpString "kernel_arg_type.func." ++ %8 = OpString "/tmp/test.cl" ++ %9 = OpString "//__CSK_MD5:18aa9ce738eaafc7b7b7181c19092815" ++ %12 = OpString "func" ++ %14 = OpString "" ++ OpSource Unknown 0 ++ OpName %entry "entry" ++ OpModuleProcessed "Debug info producer: " ++ %void = OpTypeVoid ++ %4 = OpTypeFunction %void ++ %10 = OpExtInst %void %2 DebugSource %8 %9 ++ %11 = OpExtInst %void %2 DebugCompilationUnit 65536 5 %10 !0x0000002A ++ %13 = OpExtInst %void %2 DebugInfoNone ++ %15 = OpExtInst %void %2 DebugFunction %12 %13 %10 1 0 %11 %14 FlagIsDefinition|FlagPrototyped|FlagIsOptimized 2 %5 %13 ++ %5 = OpFunction %void None %4 ++ %entry = OpLabel ++ OpReturn ++ OpFunctionEnd ++ ++; CHECK: !{i32 2, !"Source Lang Literal", i32 42} ++; CHECK: !DICompileUnit(language: DW_LANG_OpenCL, +-- +2.20.1 + diff --git a/patches/0031-Backport-to-15-Check-for-nullptr-from-getDbgInst-191.patch b/patches/0031-Backport-to-15-Check-for-nullptr-from-getDbgInst-191.patch new file mode 100644 index 0000000..84da858 --- /dev/null +++ b/patches/0031-Backport-to-15-Check-for-nullptr-from-getDbgInst-191.patch @@ -0,0 +1,35 @@ +From e8008badff7efd4f545deff9564988460140ebf6 Mon Sep 17 00:00:00 2001 +From: LU-JOHN <111294400+LU-JOHN@users.noreply.github.com> +Date: Fri, 31 Mar 2023 11:53:15 -0500 +Subject: [PATCH 31/79] [Backport to 15] Check for nullptr from getDbgInst + (#1919) + +Ensure that ExprLB is non-NULL before using it. + +Signed-off-by: Lu, John +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 28b2170e..54339fbc 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -271,10 +271,11 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { + UpperBound, nullptr)); + continue; + } +- if (auto *ExprUB = getDbgInst(Ops[I])) { ++ const SPIRVExtInst *ExprUB, *ExprLB; ++ if ((ExprUB = getDbgInst(Ops[I])) && ++ (ExprLB = ++ getDbgInst(Ops[Ops.size() / 2 + I]))) { + auto *UpperBound = transDebugInst(ExprUB); +- auto *ExprLB = +- getDbgInst(Ops[Ops.size() / 2 + I]); + auto *LowerBound = transDebugInst(ExprLB); + Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound, + UpperBound, nullptr)); +-- +2.20.1 + diff --git a/patches/0032-DebugInfo-Add-DW_ATE_complex_float-translation-1946.patch b/patches/0032-DebugInfo-Add-DW_ATE_complex_float-translation-1946.patch new file mode 100644 index 0000000..e709817 --- /dev/null +++ b/patches/0032-DebugInfo-Add-DW_ATE_complex_float-translation-1946.patch @@ -0,0 +1,202 @@ +From 23be07fd36b02a9a2283d21838e4e56f220ed576 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 12 Apr 2023 16:24:16 +0200 +Subject: [PATCH 32/79] [DebugInfo] Add DW_ATE_complex_float translation + (#1946) + +It's mapped on new Encoding value for DebugBasicType in NonSemantic.Shader.DebugInfo.200 spec. +If another DebugInfo instruction set is specified - it's mapped to DW_TAG_unspecified_type + +Spec: +KhronosGroup/SPIRV-Registry#186 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 5 + + lib/SPIRV/SPIRVReader.cpp | 1 + + lib/SPIRV/libSPIRV/SPIRV.debug.h | 4 +- + .../NonSemantic/Shader200/FortranComplex.ll | 108 ++++++++++++++++++ + tools/llvm-spirv/llvm-spirv.cpp | 2 +- + 5 files changed, 118 insertions(+), 2 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 4d7caea7..3c54d60b 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -572,6 +572,11 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgBaseType(const DIBasicType *BT) { + auto Encoding = static_cast(BT->getEncoding()); + SPIRVDebug::EncodingTag EncTag = SPIRVDebug::Unspecified; + SPIRV::DbgEncodingMap::find(Encoding, &EncTag); ++ // Unset encoding if it's complex and NonSemantic.Shader.DebugInfo.200 is not ++ // enabled ++ if (EncTag == SPIRVDebug::Complex && ++ BM->getDebugInfoEIS() != SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ EncTag = SPIRVDebug::Unspecified; + Ops[EncodingIdx] = EncTag; + if (isNonSemanticDebugInfo()) + transformToConstant(Ops, {EncodingIdx}); +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 22845f05..6293e443 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -2376,6 +2376,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F, + return mapValue(BV, transOCLBuiltinFromExtInst(ExtInst, BB)); + case SPIRVEIS_Debug: + case SPIRVEIS_OpenCL_DebugInfo_100: ++ case SPIRVEIS_NonSemantic_Shader_DebugInfo_100: + case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + return mapValue(BV, DbgTran->transDebugIntrinsic(ExtInst, BB)); + default: +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 0c17595e..f1e6abac 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -88,7 +88,8 @@ enum EncodingTag { + Signed = 4, + SignedChar = 5, + Unsigned = 6, +- UnsignedChar = 7 ++ UnsignedChar = 7, ++ Complex = 8 + }; + + enum CompositeTypeTag { +@@ -1000,6 +1001,7 @@ inline void DbgEncodingMap::init() { + add(dwarf::DW_ATE_signed_char, SPIRVDebug::SignedChar); + add(dwarf::DW_ATE_unsigned, SPIRVDebug::Unsigned); + add(dwarf::DW_ATE_unsigned_char, SPIRVDebug::UnsignedChar); ++ add(dwarf::DW_ATE_complex_float, SPIRVDebug::Complex); + } + + typedef SPIRVMap DbgTypeQulifierMap; +diff --git a/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll b/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll +new file mode 100644 +index 00000000..8a1032c3 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll +@@ -0,0 +1,108 @@ ++;; Tests for Fortran's complex type encoding in debug info ++;; Compiled from the following Fortran source ++;; ++;; program complex_numbers ++;; implicit none ++;; complex :: a, b, c ++;; ++;; a = (1.0, 2.0) ++;; b = (2.0, -1.0) ++;; ++;; c = a + b ++;; ++;; end program complex_numbers ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 -o - | FileCheck %s --check-prefix=CHECK-SPIRV-200 ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM-200 ++ ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-100 -o - | FileCheck %s --check-prefix=CHECK-SPIRV-100 ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-100 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM-100 ++ ++; CHECK-SPIRV-200-DAG: ExtInstImport [[#Import:]] "NonSemantic.Shader.DebugInfo.200 ++; CHECK-SPIRV-200-DAG: String [[#Name:]] "COMPLEX*8" ++; CHECK-SPIRV-200-DAG: Constant [[#]] [[#Size:]] 64 ++; CHECK-SPIRV-200-DAG: Constant [[#]] [[#Encoding:]] 8 ++; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#Type:]] [[#Import]] DebugTypeBasic [[#Name]] [[#Size]] [[#Encoding]] ++; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++ ++; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) ++; CHECK-LLVM-200: ![[#Type]] = !DIBasicType(name: "COMPLEX*8", size: 64, encoding: DW_ATE_complex_float) ++; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++ ++; CHECK-SPIRV-100-DAG: ExtInstImport [[#Import:]] "NonSemantic.Shader.DebugInfo.100 ++; CHECK-SPIRV-100-DAG: String [[#Name:]] "COMPLEX*8" ++; CHECK-SPIRV-100-DAG: Constant [[#]] [[#Size:]] 64 ++; CHECK-SPIRV-100-DAG: Constant [[#]] [[#Encoding:]] 0 ++; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#Type:]] [[#Import]] DebugTypeBasic [[#Name]] [[#Size]] [[#Encoding]] ++; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] ++ ++; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) ++; CHECK-LLVM-100: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "COMPLEX*8") ++; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++ ++; ModuleID = 'test.f90' ++source_filename = "test.f90" ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++@0 = internal unnamed_addr constant i32 65536, align 4 ++@1 = internal unnamed_addr constant i32 2, align 4 ++ ++; Function Attrs: nounwind uwtable ++define void @MAIN__() local_unnamed_addr !dbg !4 !llfort.type_idx !12 { ++alloca_0: ++ %func_result = tail call i32 @for_set_fpe_(ptr nonnull @0), !dbg !13, !llfort.type_idx !14 ++ %func_result2 = tail call i32 @for_set_reentrancy(ptr nonnull @1), !dbg !13, !llfort.type_idx !14 ++ call void @llvm.dbg.value(metadata float 1.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !15 ++ call void @llvm.dbg.value(metadata float 2.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32)), !dbg !15 ++ call void @llvm.dbg.value(metadata float 2.000000e+00, metadata !10, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !15 ++ call void @llvm.dbg.value(metadata float -1.000000e+00, metadata !10, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32)), !dbg !15 ++ call void @llvm.dbg.value(metadata float poison, metadata !8, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !15 ++ call void @llvm.dbg.value(metadata float poison, metadata !8, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32)), !dbg !15 ++ ret void, !dbg !16 ++} ++ ++declare !llfort.intrin_id !17 !llfort.type_idx !18 i32 @for_set_fpe_(ptr nocapture readonly) local_unnamed_addr ++ ++; Function Attrs: nofree ++declare !llfort.intrin_id !19 !llfort.type_idx !20 i32 @for_set_reentrancy(ptr nocapture readonly) local_unnamed_addr ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ++declare void @llvm.dbg.value(metadata, metadata, metadata) ++ ++!llvm.module.flags = !{!0, !1} ++!llvm.dbg.cu = !{!2} ++!omp_offload.info = !{} ++ ++!0 = !{i32 2, !"Debug Info Version", i32 3} ++!1 = !{i32 2, !"Dwarf Version", i32 4} ++!2 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!3 = !DIFile(filename: "test.f90", directory: "complex") ++!4 = distinct !DISubprogram(name: "complex_numbers", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !5, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2, retainedNodes: !7) ++!5 = !DISubroutineType(types: !6) ++!6 = !{null} ++!7 = !{!8, !10, !11} ++!8 = !DILocalVariable(name: "c", scope: !4, file: !3, line: 3, type: !9) ++!9 = !DIBasicType(name: "COMPLEX*8", size: 64, encoding: DW_ATE_complex_float) ++!10 = !DILocalVariable(name: "b", scope: !4, file: !3, line: 3, type: !9) ++!11 = !DILocalVariable(name: "a", scope: !4, file: !3, line: 3, type: !9) ++!12 = !{i64 23} ++!13 = !DILocation(line: 1, column: 9, scope: !4) ++!14 = !{i64 2} ++!15 = !DILocation(line: 0, scope: !4) ++!16 = !DILocation(line: 9, column: 1, scope: !4) ++!17 = !{i32 97} ++!18 = !{i64 27} ++!19 = !{i32 98} ++!20 = !{i64 29} +diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp +index e9a7fb45..85d4e61d 100644 +--- a/tools/llvm-spirv/llvm-spirv.cpp ++++ b/tools/llvm-spirv/llvm-spirv.cpp +@@ -733,7 +733,7 @@ int main(int Ac, char **Av) { + SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200) + Opts.setAllowExtraDIExpressionsEnabled(true); + if (DebugEIS.getValue() == +- SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200 || ++ SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_100 || + DebugEIS.getValue() == + SPIRV::DebugInfoEIS::NonSemantic_Shader_DebugInfo_200) + Opts.setAllowedToUseExtension( +-- +2.20.1 + diff --git a/patches/0033-Backport-to-15-DebugInfo-Handle-null-value-of-DW_TAG.patch b/patches/0033-Backport-to-15-DebugInfo-Handle-null-value-of-DW_TAG.patch new file mode 100644 index 0000000..8032876 --- /dev/null +++ b/patches/0033-Backport-to-15-DebugInfo-Handle-null-value-of-DW_TAG.patch @@ -0,0 +1,270 @@ +From ed11c7559f9c9fd2bbfb31bb43e4a0f0f66bec1d Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 14 Apr 2023 17:03:07 +0200 +Subject: [PATCH 33/79] [Backport to 15][DebugInfo] Handle null value of + DW_TAG_template_value_parameter (#1956) + +It might be set as null in case if a function pointer is passed as auto +template parameter. + +The patch also adds a test for a 'good' DW_TAG_template_value_parameter +value for function pointers, just because this case was untested. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 10 +- + .../Generic/function-ptr-templ-null.ll | 107 ++++++++++++++++++ + test/DebugInfo/Generic/function-ptr-templ.ll | 106 +++++++++++++++++ + 3 files changed, 221 insertions(+), 2 deletions(-) + create mode 100644 test/DebugInfo/Generic/function-ptr-templ-null.ll + create mode 100644 test/DebugInfo/Generic/function-ptr-templ.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 3c54d60b..6a1e948e 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1014,8 +1014,14 @@ LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { + Ops[ValueIdx] = getDebugInfoNoneId(); + if (TP->getTag() == dwarf::DW_TAG_template_value_parameter) { + const DITemplateValueParameter *TVP = cast(TP); +- Constant *C = cast(TVP->getValue())->getValue(); +- Ops[ValueIdx] = SPIRVWriter->transValue(C, nullptr)->getId(); ++ if (auto *TVVal = TVP->getValue()) { ++ Constant *C = cast(TVVal)->getValue(); ++ Ops[ValueIdx] = SPIRVWriter->transValue(C, nullptr)->getId(); ++ } else { ++ SPIRVType *TyPtr = ++ SPIRVWriter->transType(PointerType::get(M->getContext(), 0)); ++ Ops[ValueIdx] = BM->addNullConstant(TyPtr)->getId(); ++ } + } + Ops[SourceIdx] = getDebugInfoNoneId(); + Ops[LineIdx] = 0; // This version of DITemplateParameter has no line number +diff --git a/test/DebugInfo/Generic/function-ptr-templ-null.ll b/test/DebugInfo/Generic/function-ptr-templ-null.ll +new file mode 100644 +index 00000000..85ee2fd8 +--- /dev/null ++++ b/test/DebugInfo/Generic/function-ptr-templ-null.ll +@@ -0,0 +1,107 @@ ++;; compiled from (null added manually): ++;; template ++;; int foo() { ++;; int result = Func(); ++;; return result; ++;; }; ++;; ++;; long get() { return 42; } ++;; ++;; void boo() { ++;; int val = foo(); ++;; } ++ ++; REQUIRES: object-emission ++ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll ++; RUN: FileCheck < %t.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s --check-prefix=CHECK-DWARF ++ ++; CHECK-LLVM: ![[#]] = !DITemplateValueParameter(name: "Func", type: ![[#Type:]], value: ptr null) ++; CHECK-LLVM: ![[#Type]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: 64) ++ ++; CHECK-DWARF: DW_TAG_subprogram ++; CHECK-DWARF: DW_AT_name{{.*}}"foo<&get>" ++ ++; CHECK-DWARF: DW_TAG_template_value_parameter ++; CHECK-DWARF: DW_AT_type {{.*}} "int (*)()" ++; CHECK-DWARF: DW_AT_name {{.*}} "Func" ++ ++; ModuleID = '/app/example.cpp' ++source_filename = "/app/example.cpp" ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++$_Z3fooIXadL_Z3getvEEEiv = comdat any ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define dso_local noundef i32 @_Z3getv() #0 !dbg !10 { ++ ret i32 42, !dbg !16 ++} ++ ++; Function Attrs: mustprogress noinline optnone uwtable ++define dso_local void @_Z3boov() #1 !dbg !17 { ++ %1 = alloca i32, align 4 ++ call void @llvm.dbg.declare(metadata ptr %1, metadata !20, metadata !DIExpression()), !dbg !21 ++ %2 = call noundef i32 @_Z3fooIXadL_Z3getvEEEiv(), !dbg !22 ++ store i32 %2, ptr %1, align 4, !dbg !21 ++ ret void, !dbg !23 ++} ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn ++declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define linkonce_odr dso_local noundef i32 @_Z3fooIXadL_Z3getvEEEiv() #0 comdat !dbg !24 { ++ %1 = alloca i32, align 4 ++ call void @llvm.dbg.declare(metadata ptr %1, metadata !28, metadata !DIExpression()), !dbg !29 ++ %2 = call noundef i32 @_Z3getv(), !dbg !30 ++ store i32 %2, ptr %1, align 4, !dbg !29 ++ %3 = load i32, ptr %1, align 4, !dbg !31 ++ ret i32 %3, !dbg !32 ++} ++ ++attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } ++attributes #1 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } ++attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} ++!llvm.ident = !{!9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git ef38880ce03bc1f1fb3606c5a629151f3d0e975e)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "/app/example.cpp", directory: "/app") ++!2 = !{i32 7, !"Dwarf Version", i32 4} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 8, !"PIC Level", i32 2} ++!6 = !{i32 7, !"PIE Level", i32 2} ++!7 = !{i32 7, !"uwtable", i32 2} ++!8 = !{i32 7, !"frame-pointer", i32 2} ++!9 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git ef38880ce03bc1f1fb3606c5a629151f3d0e975e)"} ++!10 = distinct !DISubprogram(name: "get", linkageName: "_Z3getv", scope: !11, file: !11, line: 7, type: !12, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!11 = !DIFile(filename: "example.cpp", directory: "/app") ++!12 = !DISubroutineType(types: !13) ++!13 = !{!14} ++!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!15 = !{} ++!16 = !DILocation(line: 7, column: 13, scope: !10) ++!17 = distinct !DISubprogram(name: "boo", linkageName: "_Z3boov", scope: !11, file: !11, line: 9, type: !18, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!18 = !DISubroutineType(types: !19) ++!19 = !{null} ++!20 = !DILocalVariable(name: "val", scope: !17, file: !11, line: 10, type: !14) ++!21 = !DILocation(line: 10, column: 9, scope: !17) ++!22 = !DILocation(line: 10, column: 15, scope: !17) ++!23 = !DILocation(line: 11, column: 1, scope: !17) ++!24 = distinct !DISubprogram(name: "foo<&get>", linkageName: "_Z3fooIXadL_Z3getvEEEiv", scope: !11, file: !11, line: 2, type: !12, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, templateParams: !25, retainedNodes: !15) ++!25 = !{!26} ++!26 = !DITemplateValueParameter(name: "Func", type: !27, value: null) ++!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) ++!28 = !DILocalVariable(name: "result", scope: !24, file: !11, line: 3, type: !14) ++!29 = !DILocation(line: 3, column: 9, scope: !24) ++!30 = !DILocation(line: 3, column: 18, scope: !24) ++!31 = !DILocation(line: 4, column: 12, scope: !24) ++!32 = !DILocation(line: 4, column: 5, scope: !24) +diff --git a/test/DebugInfo/Generic/function-ptr-templ.ll b/test/DebugInfo/Generic/function-ptr-templ.ll +new file mode 100644 +index 00000000..daf231b4 +--- /dev/null ++++ b/test/DebugInfo/Generic/function-ptr-templ.ll +@@ -0,0 +1,106 @@ ++;; compiled from: ++;; template ++;; int foo() { ++;; int result = Func(); ++;; return result; ++;; }; ++;; ++;; long get() { return 42; } ++;; ++;; void boo() { ++;; int val = foo(); ++;; } ++ ++; REQUIRES: object-emission ++ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll ++; RUN: FileCheck < %t.ll %s --check-prefix=CHECK-LLVM ++; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %t.ll | llvm-dwarfdump -v -debug-info - | FileCheck %s --check-prefix=CHECK-DWARF ++ ++; CHECK-LLVM: ![[#]] = !DITemplateValueParameter(name: "Func", type: ![[#Type:]], value: ptr @_Z3getv) ++; CHECK-LLVM: ![[#Type]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: 64) ++ ++; CHECK-DWARF: DW_TAG_subprogram ++; CHECK-DWARF: DW_AT_name{{.*}}"foo<&get>" ++ ++; CHECK-DWARF: DW_TAG_template_value_parameter ++; CHECK-DWARF: DW_AT_type {{.*}} "int (*)()" ++; CHECK-DWARF: DW_AT_name {{.*}} "Func" ++ ++; ModuleID = '/app/example.cpp' ++source_filename = "/app/example.cpp" ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++$_Z3fooIXadL_Z3getvEEEiv = comdat any ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define dso_local noundef i32 @_Z3getv() #0 !dbg !10 { ++ ret i32 42, !dbg !16 ++} ++ ++; Function Attrs: mustprogress noinline optnone uwtable ++define dso_local void @_Z3boov() #1 !dbg !17 { ++ %1 = alloca i32, align 4 ++ call void @llvm.dbg.declare(metadata ptr %1, metadata !20, metadata !DIExpression()), !dbg !21 ++ %2 = call noundef i32 @_Z3fooIXadL_Z3getvEEEiv(), !dbg !22 ++ store i32 %2, ptr %1, align 4, !dbg !21 ++ ret void, !dbg !23 ++} ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn ++declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define linkonce_odr dso_local noundef i32 @_Z3fooIXadL_Z3getvEEEiv() #0 comdat !dbg !24 { ++ %1 = alloca i32, align 4 ++ call void @llvm.dbg.declare(metadata ptr %1, metadata !28, metadata !DIExpression()), !dbg !29 ++ %2 = call noundef i32 @_Z3getv(), !dbg !30 ++ store i32 %2, ptr %1, align 4, !dbg !29 ++ %3 = load i32, ptr %1, align 4, !dbg !31 ++ ret i32 %3, !dbg !32 ++} ++ ++attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } ++attributes #1 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } ++attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} ++!llvm.ident = !{!9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git ef38880ce03bc1f1fb3606c5a629151f3d0e975e)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "/app/example.cpp", directory: "/app") ++!2 = !{i32 7, !"Dwarf Version", i32 4} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 8, !"PIC Level", i32 2} ++!6 = !{i32 7, !"PIE Level", i32 2} ++!7 = !{i32 7, !"uwtable", i32 2} ++!8 = !{i32 7, !"frame-pointer", i32 2} ++!9 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git ef38880ce03bc1f1fb3606c5a629151f3d0e975e)"} ++!10 = distinct !DISubprogram(name: "get", linkageName: "_Z3getv", scope: !11, file: !11, line: 7, type: !12, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!11 = !DIFile(filename: "example.cpp", directory: "/app") ++!12 = !DISubroutineType(types: !13) ++!13 = !{!14} ++!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!15 = !{} ++!16 = !DILocation(line: 7, column: 13, scope: !10) ++!17 = distinct !DISubprogram(name: "boo", linkageName: "_Z3boov", scope: !11, file: !11, line: 9, type: !18, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!18 = !DISubroutineType(types: !19) ++!19 = !{null} ++!20 = !DILocalVariable(name: "val", scope: !17, file: !11, line: 10, type: !14) ++!21 = !DILocation(line: 10, column: 9, scope: !17) ++!22 = !DILocation(line: 10, column: 15, scope: !17) ++!23 = !DILocation(line: 11, column: 1, scope: !17) ++!24 = distinct !DISubprogram(name: "foo<&get>", linkageName: "_Z3fooIXadL_Z3getvEEEiv", scope: !11, file: !11, line: 2, type: !12, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, templateParams: !25, retainedNodes: !15) ++!25 = !{!26} ++!26 = !DITemplateValueParameter(name: "Func", type: !27, value: ptr @_Z3getv) ++!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) ++!28 = !DILocalVariable(name: "result", scope: !24, file: !11, line: 3, type: !14) ++!29 = !DILocation(line: 3, column: 9, scope: !24) ++!30 = !DILocation(line: 3, column: 18, scope: !24) ++!31 = !DILocation(line: 4, column: 12, scope: !24) ++!32 = !DILocation(line: 4, column: 5, scope: !24) +-- +2.20.1 + diff --git a/patches/0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch b/patches/0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch new file mode 100644 index 0000000..7d323e1 --- /dev/null +++ b/patches/0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch @@ -0,0 +1,1073 @@ +From 31361b29ba298044304b390f77235c9b56868253 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 19 Apr 2023 15:34:06 +0200 +Subject: [PATCH 34/79] [Backport to 15][DebugInfo] Support multiple + CompileUnits (#1950) + +It's possible for LLVM IR module to contain multiple CU in case if this module is a result +of llvm-link between two modules compiled for different languages and or compiled with +different options. + +This patch introduces handling of such modules. +std::unordered_map BuilderMap was introduced +to SPIR-V consumption part and +std::unordered_map SPIRVCUMap was introduced +to SPIR-V generation part to preserve Scope relations between DI metadata in SPIR-V and vice versa. + +Note, that DIBuilder has a single CU field and this class is not trivially copiable. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 36 ++- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 2 +- + lib/SPIRV/SPIRVReader.cpp | 8 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 290 +++++++++++-------- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 4 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 56 +++- + test/DebugInfo/Generic/c-and-cpp-mixed.ll | 120 ++++++++ + test/DebugInfo/X86/mixed-nodebug-cu.ll | 2 +- + test/DebugInfo/X86/split-dwarf-omit-empty.ll | 2 +- + 9 files changed, 377 insertions(+), 143 deletions(-) + create mode 100644 test/DebugInfo/Generic/c-and-cpp-mixed.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 6a1e948e..e36658b4 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -52,11 +52,11 @@ void LLVMToSPIRVDbgTran::transDebugMetadata() { + if (DIF.compile_unit_count() == 0) + return; + +- DICompileUnit *CU = *DIF.compile_units().begin(); +- transDbgEntry(CU); +- +- for (DIImportedEntity *IE : CU->getImportedEntities()) +- transDbgEntry(IE); ++ for (DICompileUnit *CU : DIF.compile_units()) { ++ transDbgEntry(CU); ++ for (DIImportedEntity *IE : CU->getImportedEntities()) ++ transDbgEntry(IE); ++ } + + for (const DIType *T : DIF.types()) + transDbgEntry(T); +@@ -404,10 +404,9 @@ SPIRVType *LLVMToSPIRVDbgTran::getInt32Ty() { + SPIRVEntry *LLVMToSPIRVDbgTran::getScope(DIScope *S) { + if (S) + return transDbgEntry(S); +- else { +- assert(SPIRVCU && "Compile unit is expected to be already translated"); +- return SPIRVCU; +- } ++ assert(!SPIRVCUMap.empty() && ++ "Compile units are expected to be already translated"); ++ return SPIRVCUMap.begin()->second; + } + + SPIRVEntry *LLVMToSPIRVDbgTran::getGlobalVariable(const DIGlobalVariable *GV) { +@@ -556,9 +555,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + Ops, {SPIRVDebugInfoVersionIdx, DWARFVersionIdx, LanguageIdx}); + BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); + // Cache CU in a member. +- SPIRVCU = static_cast( ++ SPIRVCUMap[CU] = static_cast( + BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops)); +- return SPIRVCU; ++ return SPIRVCUMap[CU]; + } + + // Types +@@ -985,7 +984,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPtrToMember(const DIDerivedType *DT) { +- using namespace SPIRVDebug::Operand::PtrToMember; ++ using namespace SPIRVDebug::Operand::TypePtrToMember; + SPIRVWordVec Ops(OperandCount); + Ops[MemberTypeIdx] = transDbgEntry(DT->getBaseType())->getId(); + Ops[ParentIdx] = transDbgEntry(DT->getClassType())->getId(); +@@ -1084,7 +1083,7 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) { + + // Parent scope + DIScope *Context = GV->getScope(); +- SPIRVEntry *Parent = SPIRVCU; ++ SPIRVEntry *Parent = SPIRVCUMap.begin()->second; + // Global variable may be declared in scope of a namespace or imported module, + // it may also be a static variable declared in scope of a function. + if (Context && (isa(Context) || isa(Context) || +@@ -1119,10 +1118,15 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + Ops[LineIdx] = Func->getLine(); + Ops[ColumnIdx] = 0; // This version of DISubprogram has no column number + auto Scope = Func->getScope(); +- if (Scope && isa(Scope)) +- Ops[ParentIdx] = SPIRVCU->getId(); +- else ++ if (Scope && !isa(Scope)) { + Ops[ParentIdx] = getScope(Scope)->getId(); ++ } else { ++ if (auto *Unit = Func->getUnit()) ++ Ops[ParentIdx] = SPIRVCUMap[Unit]->getId(); ++ else ++ // it might so happen, that DISubprogram is missing Unit parameter ++ Ops[ParentIdx] = SPIRVCUMap.begin()->second->getId(); ++ } + Ops[LinkageNameIdx] = BM->getString(Func->getLinkageName().str())->getId(); + Ops[FlagsIdx] = adjustAccessFlags(Scope, transDebugFlags(Func)); + if (isNonSemanticDebugInfo()) +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 9e5f711c..d43040d7 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -164,7 +164,7 @@ private: + SPIRVType *VoidT = nullptr; + SPIRVType *Int32T = nullptr; + SPIRVEntry *DebugInfoNone; +- SPIRVExtInst *SPIRVCU; ++ std::unordered_map SPIRVCUMap; + std::vector DbgDeclareIntrinsics; + std::vector DbgValueIntrinsics; + }; // class LLVMToSPIRVDbgTran +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 6293e443..85731c3d 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3333,13 +3333,9 @@ bool SPIRVToLLVM::translate() { + + // Compile unit might be needed during translation of debug intrinsics. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { +- // Translate Compile Unit first. +- // It shuldn't be far from the beginig of the vector +- if (EI->getExtOp() == SPIRVDebug::CompilationUnit) { ++ // Translate Compile Units first. ++ if (EI->getExtOp() == SPIRVDebug::CompilationUnit) + DbgTran->transDebugInst(EI); +- // Fixme: there might be more then one Compile Unit. +- break; +- } + } + // Then translate all debug instructions. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 54339fbc..2ad7b4a9 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -64,7 +64,7 @@ static uint64_t getDerivedSizeInBits(const DIType *Ty) { + } + SPIRVToLLVMDbgTran::SPIRVToLLVMDbgTran(SPIRVModule *TBM, Module *TM, + SPIRVToLLVM *Reader) +- : BM(TBM), M(TM), Builder(*M), SPIRVReader(Reader) { ++ : BM(TBM), M(TM), SPIRVReader(Reader) { + Enable = BM->hasDebugInfo(); + } + +@@ -80,8 +80,11 @@ SPIRVToLLVMDbgTran::getDIFile(const std::string &FileName, + Optional> CS) { + return getOrInsert(FileMap, FileName, [=]() { + SplitFileName Split(FileName); ++ // Use the first builder from the map to crete DIFile since it's ++ // relations with other debug metadata is not going through DICompileUnit + if (!Split.BaseName.empty()) +- return Builder.createFile(Split.BaseName, Split.Path, CS); ++ return BuilderMap.begin()->second->createFile(Split.BaseName, Split.Path, ++ CS); + return static_cast(nullptr); + }); + } +@@ -154,9 +157,15 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + + using namespace SPIRVDebug::Operand::CompilationUnit; + assert(Ops.size() == OperandCount && "Invalid number of operands"); +- SPIRVWord DWARFVersion = getConstantValueOrLiteral( +- Ops, DWARFVersionIdx, DebugInst->getExtSetKind()); +- M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion); ++ // We must preserve only one Dwarf version module level metadata ++ // UpgradeDebugInfo from llvm/lib/IR/AutoUpgrade.cpp has already done all ++ // work for us during linking stage leaving a single Dwarf version in the ++ // module ++ if (!M->getModuleFlag("Dwarf Version")) { ++ SPIRVWord DWARFVersion = getConstantValueOrLiteral( ++ Ops, DWARFVersionIdx, DebugInst->getExtSetKind()); ++ M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion); ++ } + SPIRVWord SourceLang = + getConstantValueOrLiteral(Ops, LanguageIdx, DebugInst->getExtSetKind()); + if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { +@@ -172,9 +181,9 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + } + + auto Producer = findModuleProducer(); +- CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, +- false, "", 0); +- return CU; ++ BuilderMap[DebugInst->getId()] = std::make_unique(*M); ++ return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); + } + + DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { +@@ -186,9 +195,9 @@ DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { + getConstantValueOrLiteral(Ops, EncodingIdx, DebugInst->getExtSetKind())); + unsigned Encoding = SPIRV::DbgEncodingMap::rmap(Tag); + if (Encoding == 0) +- return Builder.createUnspecifiedType(Name); ++ return getDIBuilder(DebugInst).createUnspecifiedType(Name); + uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); +- return Builder.createBasicType(Name, Size, Encoding); ++ return getDIBuilder(DebugInst).createBasicType(Name, Size, Encoding); + } + + DIDerivedType * +@@ -201,7 +210,7 @@ SPIRVToLLVMDbgTran::transTypeQualifier(const SPIRVExtInst *DebugInst) { + SPIRVWord Tag = SPIRV::DbgTypeQulifierMap::rmap( + static_cast(getConstantValueOrLiteral( + Ops, QualifierIdx, DebugInst->getExtSetKind()))); +- return Builder.createQualifiedType(Tag, BaseTy); ++ return getDIBuilder(DebugInst).createQualifiedType(Tag, BaseTy); + } + + DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { +@@ -220,19 +229,19 @@ DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) { + SPIRVWord Flags = + getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + if (Flags & SPIRVDebug::FlagIsLValueReference) +- Ty = Builder.createReferenceType(dwarf::DW_TAG_reference_type, PointeeTy, 0, +- 0, AS); ++ Ty = getDIBuilder(DebugInst).createReferenceType( ++ dwarf::DW_TAG_reference_type, PointeeTy, 0, 0, AS); + else if (Flags & SPIRVDebug::FlagIsRValueReference) +- Ty = Builder.createReferenceType(dwarf::DW_TAG_rvalue_reference_type, +- PointeeTy, 0, 0, AS); ++ Ty = getDIBuilder(DebugInst).createReferenceType( ++ dwarf::DW_TAG_rvalue_reference_type, PointeeTy, 0, 0, AS); + else +- Ty = Builder.createPointerType(PointeeTy, BM->getAddressingModel() * 32, 0, +- AS); ++ Ty = getDIBuilder(DebugInst).createPointerType( ++ PointeeTy, BM->getAddressingModel() * 32, 0, AS); + + if (Flags & SPIRVDebug::FlagIsObjectPointer) +- Ty = Builder.createObjectPointerType(Ty); ++ Ty = getDIBuilder(DebugInst).createObjectPointerType(Ty); + else if (Flags & SPIRVDebug::FlagIsArtificial) +- Ty = Builder.createArtificialType(Ty); ++ Ty = getDIBuilder(DebugInst).createArtificialType(Ty); + + return Ty; + } +@@ -267,8 +276,8 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { + int64_t ConstantAsInt = static_cast(C->getZExtIntValue()); + auto *LowerBound = ConstantAsMetadata::get( + ConstantInt::get(M->getContext(), APInt(64, ConstantAsInt))); +- Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound, +- UpperBound, nullptr)); ++ Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange( ++ nullptr, LowerBound, UpperBound, nullptr)); + continue; + } + const SPIRVExtInst *ExprUB, *ExprLB; +@@ -277,8 +286,8 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { + getDbgInst(Ops[Ops.size() / 2 + I]))) { + auto *UpperBound = transDebugInst(ExprUB); + auto *LowerBound = transDebugInst(ExprLB); +- Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound, +- UpperBound, nullptr)); ++ Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange( ++ nullptr, LowerBound, UpperBound, nullptr)); + continue; + } + if (!getDbgInst(Ops[I])) { +@@ -289,21 +298,24 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { + if (Ops.size() / 2 + I < Ops.size()) { + C = BM->get(Ops[Ops.size() / 2 + I]); + int64_t LowerBound = static_cast(C->getZExtIntValue()); +- Subscripts.push_back(Builder.getOrCreateSubrange(LowerBound, Count)); ++ Subscripts.push_back( ++ getDIBuilder(DebugInst).getOrCreateSubrange(LowerBound, Count)); + } else { + auto *CountAsMD = ConstantAsMetadata::get( + ConstantInt::get(M->getContext(), APInt(64, Count))); +- Subscripts.push_back( +- Builder.getOrCreateSubrange(CountAsMD, nullptr, nullptr, nullptr)); ++ Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange( ++ CountAsMD, nullptr, nullptr, nullptr)); + } + // Count = -1 means that the array is empty + TotalCount *= Count > 0 ? static_cast(Count) : 0; + continue; + } + } +- DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ DINodeArray SubscriptArray = ++ getDIBuilder(DebugInst).getOrCreateArray(Subscripts); + size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; +- return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); ++ return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy, ++ SubscriptArray); + } + + DICompositeType * +@@ -323,9 +335,11 @@ SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) { + Subscripts.push_back(SR); + } + } +- DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ DINodeArray SubscriptArray = ++ getDIBuilder(DebugInst).getOrCreateArray(Subscripts); + size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; +- return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray); ++ return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy, ++ SubscriptArray); + } + + DICompositeType * +@@ -343,7 +357,8 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) { + TotalCount *= Count->getSExtValue() > 0 ? Count->getSExtValue() : 0; + Subscripts.push_back(SR); + } +- DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ DINodeArray SubscriptArray = ++ getDIBuilder(DebugInst).getOrCreateArray(Subscripts); + size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount; + + auto TransOperand = +@@ -365,8 +380,9 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) { + PointerUnion Allocated = + TransOperand(AllocatedIdx); + PointerUnion Rank = TransOperand(RankIdx); +- return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray, +- DataLocation, Associated, Allocated, Rank); ++ return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy, ++ SubscriptArray, DataLocation, ++ Associated, Allocated, Rank); + } + + DICompositeType * +@@ -389,10 +405,12 @@ SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) { + uint64_t Size = getDerivedSizeInBits(BaseTy) * SizeCount; + + SmallVector Subscripts; +- Subscripts.push_back(Builder.getOrCreateSubrange(0, Count)); +- DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts); ++ Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange(0, Count)); ++ DINodeArray SubscriptArray = ++ getDIBuilder(DebugInst).getOrCreateArray(Subscripts); + +- return Builder.createVectorType(Size, 0 /*align*/, BaseTy, SubscriptArray); ++ return getDIBuilder(DebugInst).createVectorType(Size, 0 /*align*/, BaseTy, ++ SubscriptArray); + } + + DICompositeType * +@@ -439,21 +457,21 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::Class: + // TODO: should be replaced with createClassType, when bug with creating + // ClassType with llvm::dwarf::DW_TAG_struct_type tag will be fixed +- CT = Builder.createReplaceableCompositeType( ++ CT = getDIBuilder(DebugInst).createReplaceableCompositeType( + llvm::dwarf::DW_TAG_class_type, Name, ParentScope, File, LineNo, 0, + Size, Align, Flags, Identifier); + CT = llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(CT)); + break; + case SPIRVDebug::Structure: +- CT = Builder.createStructType(ParentScope, Name, File, LineNo, Size, Align, +- Flags, DerivedFrom, +- DINodeArray() /*elements*/, 0 /*RunTimeLang*/, +- nullptr /*VTableHolder*/, Identifier); ++ CT = getDIBuilder(DebugInst).createStructType( ++ ParentScope, Name, File, LineNo, Size, Align, Flags, DerivedFrom, ++ DINodeArray() /*elements*/, 0 /*RunTimeLang*/, nullptr /*VTableHolder*/, ++ Identifier); + break; + case SPIRVDebug::Union: +- CT = Builder.createUnionType(ParentScope, Name, File, LineNo, Size, Align, +- Flags, DINodeArray(), 0 /*RuntimrLang*/, +- Identifier); ++ CT = getDIBuilder(DebugInst).createUnionType( ++ ParentScope, Name, File, LineNo, Size, Align, Flags, DINodeArray(), ++ 0 /*RuntimrLang*/, Identifier); + break; + default: + llvm_unreachable("Unexpected composite type"); +@@ -464,8 +482,8 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + for (size_t I = FirstMemberIdx; I < Ops.size(); ++I) { + EltTys.push_back(transDebugInst(BM->get(Ops[I]))); + } +- DINodeArray Elements = Builder.getOrCreateArray(EltTys); +- Builder.replaceArrays(CT, Elements); ++ DINodeArray Elements = getDIBuilder(DebugInst).getOrCreateArray(EltTys); ++ getDIBuilder(DebugInst).replaceArrays(CT, Elements); + assert(CT && "Composite type translation failed."); + return CT; + } +@@ -496,8 +514,8 @@ SPIRVToLLVMDbgTran::transTypeSubrange(const SPIRVExtInst *DebugInst) { + }; + for (int Idx = CountIdx; Idx < OperandCount; ++Idx) + TransOperand(Idx); +- return Builder.getOrCreateSubrange(TranslatedOps[0], TranslatedOps[1], +- TranslatedOps[2], TranslatedOps[3]); ++ return getDIBuilder(DebugInst).getOrCreateSubrange( ++ TranslatedOps[0], TranslatedOps[1], TranslatedOps[2], TranslatedOps[3]); + } + + DIStringType * +@@ -576,14 +594,15 @@ DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { + assert(isConstantOpCode(ConstVal->getOpCode()) && + "Static member must be a constant"); + llvm::Value *Val = SPIRVReader->transValue(ConstVal, nullptr, nullptr); +- return Builder.createStaticMemberType(Scope, Name, File, LineNo, BaseType, +- Flags, cast(Val)); ++ return getDIBuilder(DebugInst).createStaticMemberType( ++ Scope, Name, File, LineNo, BaseType, Flags, cast(Val)); + } + uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); + uint64_t Alignment = 0; + +- return Builder.createMemberType(Scope, Name, File, LineNo, Size, Alignment, +- OffsetInBits, Flags, BaseType); ++ return getDIBuilder(DebugInst).createMemberType(Scope, Name, File, LineNo, ++ Size, Alignment, OffsetInBits, ++ Flags, BaseType); + } + + DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) { +@@ -601,24 +620,24 @@ DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) { + SPIRVWord Flags = + getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + if (Flags & SPIRVDebug::FlagIsFwdDecl) { +- return Builder.createForwardDecl(dwarf::DW_TAG_enumeration_type, Name, +- Scope, File, LineNo, AlignInBits, +- SizeInBits); ++ return getDIBuilder(DebugInst).createForwardDecl( ++ dwarf::DW_TAG_enumeration_type, Name, Scope, File, LineNo, AlignInBits, ++ SizeInBits); + } else { + SmallVector Elts; + for (size_t I = FirstEnumeratorIdx, E = Ops.size(); I < E; I += 2) { + uint64_t Val = BM->get(Ops[I])->getZExtIntValue(); + StringRef Name = getString(Ops[I + 1]); +- Elts.push_back(Builder.createEnumerator(Name, Val)); ++ Elts.push_back(getDIBuilder(DebugInst).createEnumerator(Name, Val)); + } +- DINodeArray Enumerators = Builder.getOrCreateArray(Elts); ++ DINodeArray Enumerators = getDIBuilder(DebugInst).getOrCreateArray(Elts); + DIType *UnderlyingType = nullptr; + SPIRVEntry *E = BM->getEntry(Ops[UnderlyingTypeIdx]); + if (!isa(E)) + UnderlyingType = transDebugInst(static_cast(E)); +- return Builder.createEnumerationType(Scope, Name, File, LineNo, SizeInBits, +- AlignInBits, Enumerators, +- UnderlyingType, "", UnderlyingType); ++ return getDIBuilder(DebugInst).createEnumerationType( ++ Scope, Name, File, LineNo, SizeInBits, AlignInBits, Enumerators, ++ UnderlyingType, "", UnderlyingType); + } + } + +@@ -648,20 +667,21 @@ DINode *SPIRVToLLVMDbgTran::transTypeFunction(const SPIRVExtInst *DebugInst) { + + Elements.push_back(Param); + } +- DITypeRefArray ArgTypes = Builder.getOrCreateTypeArray(Elements); +- return Builder.createSubroutineType(ArgTypes, Flags); ++ DITypeRefArray ArgTypes = ++ getDIBuilder(DebugInst).getOrCreateTypeArray(Elements); ++ return getDIBuilder(DebugInst).createSubroutineType(ArgTypes, Flags); + } + + DINode * + SPIRVToLLVMDbgTran::transTypePtrToMember(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::PtrToMember; ++ using namespace SPIRVDebug::Operand::TypePtrToMember; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= OperandCount && "Invalid number of operands"); + SPIRVExtInst *Member = BM->get(Ops[MemberTypeIdx]); + DIType *PointeeTy = transDebugInst(Member); + SPIRVExtInst *ContainingTy = BM->get(Ops[ParentIdx]); + DIType *BaseTy = transDebugInst(ContainingTy); +- return Builder.createMemberPointerType(PointeeTy, BaseTy, 0); ++ return getDIBuilder(DebugInst).createMemberPointerType(PointeeTy, BaseTy, 0); + } + + DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) { +@@ -673,11 +693,12 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) { + getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); + if (Ops.size() > NameIdx) { + StringRef Name = getString(Ops[NameIdx]); +- return Builder.createNameSpace(ParentScope, Name, +- false /*inlined namespace*/); ++ return getDIBuilder(DebugInst).createNameSpace(ParentScope, Name, ++ false /*inlined namespace*/); + } + unsigned Column = Ops[ColumnIdx]; +- return Builder.createLexicalBlock(ParentScope, File, LineNo, Column); ++ return getDIBuilder(DebugInst).createLexicalBlock(ParentScope, File, LineNo, ++ Column); + } + + DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator( +@@ -688,7 +709,8 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator( + SPIRVWord Disc = getConstantValueOrLiteral(Ops, DiscriminatorIdx, + DebugInst->getExtSetKind()); + DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx])); +- return Builder.createLexicalBlockFile(ParentScope, File, Disc); ++ return getDIBuilder(DebugInst).createLexicalBlockFile(ParentScope, File, ++ Disc); + } + + DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { +@@ -751,14 +773,15 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + // able to replace the template parameter operand, thus it must be in the + // operands list. + SmallVector Elts; +- DINodeArray TParams = Builder.getOrCreateArray(Elts); ++ DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts); + llvm::DITemplateParameterArray TParamsArray = TParams.get(); + + DISubprogram *DIS = nullptr; + if (Scope && (isa(Scope) || isa(Scope)) && + !IsDefinition) +- DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, +- nullptr, Flags, SPFlags, TParamsArray); ++ DIS = getDIBuilder(DebugInst).createMethod(Scope, Name, LinkageName, File, ++ LineNo, Ty, 0, 0, nullptr, Flags, ++ SPFlags, TParamsArray); + else { + // Create targetFuncName mostly for Fortran trampoline function if it is + // the case +@@ -766,10 +789,11 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + if (Ops.size() > TargetFunctionNameIdx) { + TargetFunction = getString(Ops[TargetFunctionNameIdx]); + } +- DIS = Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty, +- ScopeLine, Flags, SPFlags, TParamsArray, FD, +- /*ThrownTypes*/ nullptr, +- /*Annotations*/ nullptr, TargetFunction); ++ DIS = getDIBuilder(DebugInst).createFunction( ++ Scope, Name, LinkageName, File, LineNo, Ty, ScopeLine, Flags, SPFlags, ++ TParamsArray, FD, ++ /*ThrownTypes*/ nullptr, ++ /*Annotations*/ nullptr, TargetFunction); + } + DebugInstCache[DebugInst] = DIS; + SPIRVId RealFuncId = Ops[FunctionIdIdx]; +@@ -831,23 +855,24 @@ DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { + // able to replace the template parameter operand, thus it must be in the + // operands list. + SmallVector Elts; +- DINodeArray TParams = Builder.getOrCreateArray(Elts); ++ DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts); + llvm::DITemplateParameterArray TParamsArray = TParams.get(); + + DISubprogram *DIS = nullptr; + DISubprogram::DISPFlags SPFlags = + DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized); + if (isa(Scope) || isa(Scope)) +- DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0, +- nullptr, Flags, SPFlags, TParamsArray); ++ DIS = getDIBuilder(DebugInst).createMethod(Scope, Name, LinkageName, File, ++ LineNo, Ty, 0, 0, nullptr, Flags, ++ SPFlags, TParamsArray); + else { + // Since a function declaration doesn't have any retained nodes, resolve + // the temporary placeholder for them immediately. +- DIS = Builder.createTempFunctionFwdDecl(Scope, Name, LinkageName, File, +- LineNo, Ty, 0, Flags, SPFlags, +- TParamsArray); ++ DIS = getDIBuilder(DebugInst).createTempFunctionFwdDecl( ++ Scope, Name, LinkageName, File, LineNo, Ty, 0, Flags, SPFlags, ++ TParamsArray); + llvm::TempMDNode FwdDecl(cast(DIS)); +- DIS = Builder.replaceTemporary(std::move(FwdDecl), DIS); ++ DIS = getDIBuilder(DebugInst).replaceTemporary(std::move(FwdDecl), DIS); + } + DebugInstCache[DebugInst] = DIS; + +@@ -878,16 +903,16 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + bool IsDefinition = Flags & SPIRVDebug::FlagIsDefinition; + MDNode *VarDecl = nullptr; + if (IsDefinition) { +- VarDecl = Builder.createGlobalVariableExpression( ++ VarDecl = getDIBuilder(DebugInst).createGlobalVariableExpression( + Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition, + nullptr, StaticMemberDecl); + } else { +- VarDecl = Builder.createTempGlobalVariableFwdDecl( ++ VarDecl = getDIBuilder(DebugInst).createTempGlobalVariableFwdDecl( + Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, StaticMemberDecl); + // replaceAllUsesWith call makes VarDecl non-temp. + // Otherwise DIBuilder will crash at finalization. + llvm::TempMDNode TMP(VarDecl); +- VarDecl = Builder.replaceTemporary(std::move(TMP), VarDecl); ++ VarDecl = getDIBuilder(DebugInst).replaceTemporary(std::move(TMP), VarDecl); + } + // If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone. + // Otherwise Ops[VariableIdx] may be a global variable or a constant(C++ +@@ -922,9 +947,10 @@ DINode *SPIRVToLLVMDbgTran::transLocalVariable(const SPIRVExtInst *DebugInst) { + Flags |= DINode::FlagObjectPointer; + + if (Ops.size() > ArgNumberIdx) +- return Builder.createParameterVariable(Scope, Name, Ops[ArgNumberIdx], File, +- LineNo, Ty, true, Flags); +- return Builder.createAutoVariable(Scope, Name, File, LineNo, Ty, true, Flags); ++ return getDIBuilder(DebugInst).createParameterVariable( ++ Scope, Name, Ops[ArgNumberIdx], File, LineNo, Ty, true, Flags); ++ return getDIBuilder(DebugInst).createAutoVariable(Scope, Name, File, LineNo, ++ Ty, true, Flags); + } + + DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { +@@ -940,7 +966,7 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { + DIType *Ty = transDebugInst(static_cast(TypeInst)); + DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); + assert(Scope && "Typedef should have a parent scope"); +- return Builder.createTypedef(Ty, Alias, File, LineNo, Scope); ++ return getDIBuilder(DebugInst).createTypedef(Ty, Alias, File, LineNo, Scope); + } + + DINode * +@@ -961,7 +987,8 @@ SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst) { + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) + Flags |= llvm::DINode::FlagPrivate; + uint64_t Offset = BM->get(Ops[OffsetIdx])->getZExtIntValue(); +- return Builder.createInheritance(Child, Parent, Offset, 0, Flags); ++ return getDIBuilder(DebugInst).createInheritance(Child, Parent, Offset, 0, ++ Flags); + } + + DINode * +@@ -978,10 +1005,11 @@ SPIRVToLLVMDbgTran::transTypeTemplateParameter(const SPIRVExtInst *DebugInst) { + if (!getDbgInst(Ops[ValueIdx])) { + SPIRVValue *Val = BM->get(Ops[ValueIdx]); + Value *V = SPIRVReader->transValue(Val, nullptr, nullptr); +- return Builder.createTemplateValueParameter(Context, Name, Ty, false, +- cast(V)); ++ return getDIBuilder(DebugInst).createTemplateValueParameter( ++ Context, Name, Ty, false, cast(V)); + } +- return Builder.createTemplateTypeParameter(Context, Name, Ty, false); ++ return getDIBuilder(DebugInst).createTemplateTypeParameter(Context, Name, Ty, ++ false); + } + + DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter( +@@ -992,8 +1020,8 @@ DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter( + StringRef Name = getString(Ops[NameIdx]); + StringRef TemplName = getString(Ops[TemplateNameIdx]); + DIScope *Context = nullptr; +- return Builder.createTemplateTemplateParameter(Context, Name, nullptr, +- TemplName); ++ return getDIBuilder(DebugInst).createTemplateTemplateParameter( ++ Context, Name, nullptr, TemplName); + } + + DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterPack( +@@ -1006,9 +1034,10 @@ DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterPack( + for (size_t I = FirstParameterIdx, E = Ops.size(); I < E; ++I) { + Elts.push_back(transDebugInst(BM->get(Ops[I]))); + } +- DINodeArray Pack = Builder.getOrCreateArray(Elts); ++ DINodeArray Pack = getDIBuilder(DebugInst).getOrCreateArray(Elts); + DIScope *Context = nullptr; +- return Builder.createTemplateParameterPack(Context, Name, nullptr, Pack); ++ return getDIBuilder(DebugInst).createTemplateParameterPack(Context, Name, ++ nullptr, Pack); + } + + MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) { +@@ -1024,10 +1053,10 @@ MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) { + for (size_t I = FirstParameterIdx; I < NumOps; ++I) { + Elts.push_back(transDebugInst(BM->get(Ops[I]))); + } +- DINodeArray TParams = Builder.getOrCreateArray(Elts); ++ DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts); + + if (DICompositeType *Comp = dyn_cast(D)) { +- Builder.replaceArrays(Comp, Comp->getElements(), TParams); ++ getDIBuilder(DebugInst).replaceArrays(Comp, Comp->getElements(), TParams); + return Comp; + } + if (isa(D)) { +@@ -1053,24 +1082,32 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { + getConstantValueOrLiteral(Ops, TagIdx, DebugInst->getExtSetKind()); + if (Tag == SPIRVDebug::ImportedModule) { + if (!Entity) +- return Builder.createImportedModule( ++ return getDIBuilder(DebugInst).createImportedModule( + Scope, static_cast(nullptr), File, Line); + if (DIModule *DM = dyn_cast(Entity)) +- return Builder.createImportedModule(Scope, DM, File, Line); ++ return getDIBuilder(DebugInst).createImportedModule(Scope, DM, File, ++ Line); + if (DIImportedEntity *IE = dyn_cast(Entity)) +- return Builder.createImportedModule(Scope, IE, File, Line); ++ return getDIBuilder(DebugInst).createImportedModule(Scope, IE, File, ++ Line); + if (DINamespace *NS = dyn_cast(Entity)) +- return Builder.createImportedModule(Scope, NS, File, Line); ++ return getDIBuilder(DebugInst).createImportedModule(Scope, NS, File, ++ Line); + } + if (Tag == SPIRVDebug::ImportedDeclaration) { + StringRef Name = getString(Ops[NameIdx]); + if (DIGlobalVariableExpression *GVE = + dyn_cast(Entity)) +- return Builder.createImportedDeclaration(Scope, GVE->getVariable(), File, +- Line, Name); +- return Builder.createImportedDeclaration(Scope, Entity, File, Line, Name); ++ return getDIBuilder(DebugInst).createImportedDeclaration( ++ Scope, GVE->getVariable(), File, Line, Name); ++ return getDIBuilder(DebugInst).createImportedDeclaration(Scope, Entity, ++ File, Line, Name); + } +- llvm_unreachable("Unexpected kind of imported entity!"); ++ // FIXME: uncomment and fix following line, with existing bugs it's reachable. ++ // llvm_unreachable("Unexpected kind of imported entity!"); ++ // Imported entity translation is broken. For example ImportedEntity is ++ // missing 2nd parameter. ++ return nullptr; + } + + DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { +@@ -1087,8 +1124,8 @@ DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { + StringRef ApiNotes = getString(Ops[ApiNotesIdx]); + bool IsDecl = + getConstantValueOrLiteral(Ops, IsDeclIdx, DebugInst->getExtSetKind()); +- return Builder.createModule(Scope, Name, ConfigMacros, IncludePath, ApiNotes, +- File, Line, IsDecl); ++ return getDIBuilder(DebugInst).createModule( ++ Scope, Name, ConfigMacros, IncludePath, ApiNotes, File, Line, IsDecl); + } + + MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { +@@ -1107,7 +1144,7 @@ MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { + } + } + ArrayRef Addr(Ops.data(), Ops.size()); +- return Builder.createExpression(Addr); ++ return getDIBuilder(DebugInst).createExpression(Addr); + } + + MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { +@@ -1248,22 +1285,22 @@ SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst, + // parameter. To work around this limitation we create a dummy temp + // alloca, use it to create llvm.dbg.declare, and then remove the alloca. + auto *AI = new AllocaInst(Type::getInt8Ty(M->getContext()), 0, "tmp", BB); +- auto *DbgDeclare = Builder.insertDeclare( ++ auto *DbgDeclare = getDIBuilder(DebugInst).insertDeclare( + AI, LocalVar.first, GetExpression(Ops[ExpressionIdx]), + LocalVar.second, BB); + AI->eraseFromParent(); + return DbgDeclare; + } +- return Builder.insertDeclare(GetValue(Ops[VariableIdx]), LocalVar.first, +- GetExpression(Ops[ExpressionIdx]), +- LocalVar.second, BB); ++ return getDIBuilder(DebugInst).insertDeclare( ++ GetValue(Ops[VariableIdx]), LocalVar.first, ++ GetExpression(Ops[ExpressionIdx]), LocalVar.second, BB); + } + case SPIRVDebug::Value: { + using namespace SPIRVDebug::Operand::DebugValue; + auto LocalVar = GetLocalVar(Ops[DebugLocalVarIdx]); + Value *Val = GetValue(Ops[ValueIdx]); + DIExpression *Expr = GetExpression(Ops[ExpressionIdx]); +- auto *DbgValIntr = Builder.insertDbgValueIntrinsic( ++ auto *DbgValIntr = getDIBuilder(DebugInst).insertDbgValueIntrinsic( + Val, LocalVar.first, Expr, LocalVar.second, BB); + if (Expr->getNumLocationOperands() == 1) { + SmallVector MDs = {ValueAsMetadata::get(Val)}; +@@ -1318,7 +1355,8 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *DebugInst) { + void SPIRVToLLVMDbgTran::finalize() { + if (!Enable) + return; +- Builder.finalize(); ++ for (const auto &Builder : BuilderMap) ++ Builder.second->finalize(); + } + + DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { +@@ -1335,6 +1373,26 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + return getDIFile(getString(SourceArgs[FileIdx]), ParseChecksum(ChecksumStr)); + } + ++DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) { ++ assert(BuilderMap.size() != 0 && "No debug compile units"); ++ if (BuilderMap.size() == 1) ++ return *BuilderMap.begin()->second; ++ while (DebugInst->getExtOp() != SPIRVDebug::CompilationUnit) { ++ if (DebugInst->getExtOp() == SPIRVDebug::DebugInfoNone) ++ return *BuilderMap.begin()->second; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ SPIRVWord ParentScopeIdx = 0; ++ if (!hasDbgInstParentScopeIdx(DebugInst->getExtOp(), ParentScopeIdx)) ++ return *BuilderMap.begin()->second; ++ if (SPIRVEntry *Scope = BM->getEntry(Ops[ParentScopeIdx])) { ++ DebugInst = static_cast(Scope); ++ continue; ++ } ++ return *BuilderMap.begin()->second; ++ } ++ return *BuilderMap[DebugInst->getId()]; ++} ++ + SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) { + auto Loc = FileName.find_last_of("/\\"); + if (Loc != std::string::npos) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 2102f218..f6b31686 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -160,7 +160,7 @@ private: + + SPIRVModule *BM; + Module *M; +- DIBuilder Builder; ++ std::unordered_map> BuilderMap; + SPIRVToLLVM *SPIRVReader; + DICompileUnit *CU; + bool Enable; +@@ -177,6 +177,8 @@ private: + DIScope *getScope(const SPIRVEntry *ScopeInst); + SPIRVExtInst *getDbgInst(const SPIRVId Id); + ++ DIBuilder &getDIBuilder(const SPIRVExtInst *DebugInst); ++ + template SPIRVExtInst *getDbgInst(const SPIRVId Id) { + if (SPIRVExtInst *DI = getDbgInst(Id)) { + if (DI->getExtOp() == OpCode) { +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index f1e6abac..19170e1d 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -13,6 +13,8 @@ static const std::string ChecksumKindPrefx = {"//__CSK_"}; + + // clang-format off + ++// Need to update hasDbgInstParentScopeIdx each time we add new instruction ++// with ParentScopeIdx + enum Instruction { + DebugInfoNone = 0, + CompilationUnit = 1, +@@ -449,7 +451,7 @@ enum { + }; + } + +-namespace PtrToMember { ++namespace TypePtrToMember { + enum { + MemberTypeIdx = 0, + ParentIdx = 1, +@@ -830,6 +832,58 @@ enum { + }; + } + ++// helper function to get parent scope of debug instruction, to be used ++// to determine with which compile unit the particular instruction relates ++inline bool hasDbgInstParentScopeIdx(const uint32_t Kind, ++ uint32_t &ParentScopeIdx) { ++ switch (Kind) { ++ case SPIRVDebug::Typedef: ++ ParentScopeIdx = Typedef::ParentIdx; ++ return true; ++ case SPIRVDebug::TypeEnum: ++ ParentScopeIdx = TypeEnum::ParentIdx; ++ return true; ++ case SPIRVDebug::TypeComposite: ++ ParentScopeIdx = TypeMember::ParentIdx; ++ return true; ++ case SPIRVDebug::TypeInheritance: ++ ParentScopeIdx = TypeInheritance::ParentIdx; ++ return true; ++ case SPIRVDebug::TypePtrToMember: ++ ParentScopeIdx = TypePtrToMember::ParentIdx; ++ return true; ++ case SPIRVDebug::Function: ++ ParentScopeIdx = Function::ParentIdx; ++ return true; ++ case SPIRVDebug::LexicalBlock: ++ ParentScopeIdx = LexicalBlock::ParentIdx; ++ return true; ++ case SPIRVDebug::LexicalBlockDiscriminator: ++ ParentScopeIdx = LexicalBlockDiscriminator::ParentIdx; ++ return true; ++ case SPIRVDebug::Scope: ++ ParentScopeIdx = Scope::ScopeIdx; ++ return true; ++ case SPIRVDebug::InlinedAt: ++ ParentScopeIdx = InlinedAt::ScopeIdx; ++ return true; ++ case SPIRVDebug::LocalVariable: ++ ParentScopeIdx = LocalVariable::ParentIdx; ++ return true; ++ case SPIRVDebug::ImportedEntity: ++ ParentScopeIdx = ImportedEntity::ParentIdx; ++ return true; ++ case SPIRVDebug::ModuleINTEL: ++ ParentScopeIdx = ModuleINTEL::ParentIdx; ++ return true; ++ case SPIRVDebug::Module: ++ ParentScopeIdx = ModuleINTEL::ParentIdx; ++ return true; ++ default: ++ return false; ++ } ++} ++ + } // namespace Operand + } // namespace SPIRVDebug + +diff --git a/test/DebugInfo/Generic/c-and-cpp-mixed.ll b/test/DebugInfo/Generic/c-and-cpp-mixed.ll +new file mode 100644 +index 00000000..b1427b05 +--- /dev/null ++++ b/test/DebugInfo/Generic/c-and-cpp-mixed.ll +@@ -0,0 +1,120 @@ ++;; This test checks that two DICompileUnits resulted in a link of C and C++ ++;; object files are being translated correctly ++ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv --to-text %t.spv -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll ++; RUN: FileCheck < %t.ll %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV: String [[#Foo:]] "foo" ++; CHECK-SPIRV: String [[#Main:]] "main" ++; CHECK-SPIRV: ExtInst [[#]] [[#CU1:]] [[#]] DebugCompilationUnit ++; CHECK-SPIRV: ExtInst [[#]] [[#CU2:]] [[#]] DebugCompilationUnit ++; CHECK-SPIRV: ExtInst [[#]] [[#Func1:]] [[#]] DebugFunction [[#Foo]] [[#]] [[#]] [[#]] [[#]] [[#CU1]] ++; CHECK-SPIRV: ExtInst [[#]] [[#Func2:]] [[#]] DebugFunction [[#Main]] [[#]] [[#]] [[#]] [[#]] [[#CU2]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#Func1]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#Func2]] ++ ++; CHECK-LLVM: define spir_func void @foo() #0 !dbg ![[#Func1:]] { ++; CHECK-LLVM: entry: ++; CHECK-LLVM: %[[#VALUE:]] = getelementptr inbounds [4 x i8], ptr @str, i32 0, i32 0 ++; CHECK-LLVM: %puts = call spir_func i32 @puts(ptr nocapture %[[#VALUE]]) #0, !dbg ![[#Puts1Loc:]] ++; CHECK-LLVM: ret void, !dbg ![[#Ret1:]] ++; CHECK-LLVM: } ++ ++; CHECK-LLVM: define spir_func i32 @main(i32 %argc, ptr nocapture %argv) #0 !dbg ![[#Func2:]] { ++; CHECK-LLVM: entry: ++; CHECK-LLVM: call void @llvm.dbg.value(metadata i32 %argc, metadata ![[#Fun2Param1:]], metadata !DIExpression()), !dbg ![[#Fun2Param1Loc:]] ++; CHECK-LLVM: call void @llvm.dbg.value(metadata ptr %argv, metadata ![[#Fun2Param2:]], metadata !DIExpression(DW_OP_deref, DW_OP_deref)), !dbg ![[#Fun2Param2Loc:]] ++; CHECK-LLVM: %[[#VALUE1:]] = getelementptr inbounds [6 x i8], ptr @str1, i32 0, i32 0 ++; CHECK-LLVM: %puts = call spir_func i32 @puts(ptr nocapture %[[#VALUE1]]) #0, !dbg ![[#Puts2Loc:]] ++; CHECK-LLVM: call spir_func void @foo() #0, !dbg ![[#CallFoo:]] ++; CHECK-LLVM: ret i32 0, !dbg ![[#Ret2:]] ++; CHECK-LLVM: } ++ ++; CHECK-LLVM: !llvm.dbg.cu = !{![[#CU1:]], ![[#CU2:]]} ++; CHECK-LLVM: ![[#CU1]] = distinct !DICompileUnit(language: DW_LANG_OpenCL, file: ![[#File:]], producer: "clang version 14", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) ++; CHECK-LLVM: ![[#File]] = !DIFile(filename: "foo.c", directory: "/tmp") ++; CHECK-LLVM: ![[#CU2]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: ![[#File]], producer: "clang version 14", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) ++; CHECK-LLVM: ![[#Empty:]] = !{} ++; CHECK-LLVM: ![[#Func1]] = distinct !DISubprogram(name: "foo", scope: null, file: ![[#File]], line: 5, type: ![[#Func1T:]], scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[#CU1]], templateParams: ![[#Empty]], retainedNodes: ![[#Empty]]) ++; CHECK-LLVM: ![[#Func1T]] = !DISubroutineType(types: ![[#Func1TP:]]) ++; CHECK-LLVM: ![[#Func1TP]] = !{null} ++; CHECK-LLVM: ![[#Puts1Loc]] = !DILocation(line: 6, column: 3, scope: ![[#Puts1Scope:]]) ++; CHECK-LLVM: ![[#Puts1Scope]] = distinct !DILexicalBlock(scope: ![[#Func1]], file: ![[#File]], line: 5, column: 16) ++; CHECK-LLVM: ![[#Ret1]] = !DILocation(line: 7, column: 1, scope: ![[#Puts1Scope]]) ++; CHECK-LLVM: ![[#Func2]] = distinct !DISubprogram(name: "main", scope: null, file: ![[#File]], line: 11, type: ![[#Func2T:]], scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[#CU2]], templateParams: ![[#Empty]], retainedNodes: ![[#Fun2Params:]]) ++; CHECK-LLVM: ![[#Func2T]] = !DISubroutineType(types: ![[#Func2TP:]]) ++; CHECK-LLVM: ![[#Func2TP]] = !{![[#Func2TP1:]], ++; CHECK-LLVM-SAME: ![[#Func2TP1]], ![[#Func2TP2:]] ++; CHECK-LLVM: ![[#Func2TP1]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++; CHECK-LLVM: ![[#Func2TP2]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) ++; CHECK-LLVM: ![[#Fun2Params]] = !{![[#Fun2Param1]], ![[#Fun2Param2]]} ++; CHECK-LLVM: ![[#Fun2Param1]] = !DILocalVariable(name: "argc", arg: 1, scope: ![[#Func2]], file: ![[#File]], line: 11, type: ![[#Func2TP1]]) ++; CHECK-LLVM: ![[#Fun2Param2]] = !DILocalVariable(name: "argv", arg: 2, scope: ![[#Func2]], file: ![[#File]], line: 11, type: ![[#Func2TP2]]) ++; CHECK-LLVM: ![[#Fun2Param1Loc:]] = !DILocation(line: 11, column: 14, scope: ![[#Func2]]) ++; CHECK-LLVM: ![[#Fun2Param2Loc:]] = !DILocation(line: 11, column: 26, scope: ![[#Func2]]) ++; CHECK-LLVM: ![[#Puts2Loc]] = !DILocation(line: 12, column: 3, scope: ![[#Puts2Scope:]] ++; CHECK-LLVM: ![[#Puts2Scope]] = distinct !DILexicalBlock(scope: ![[#Func2]], file: ![[#File]], line: 11, column: 34) ++; CHECK-LLVM: ![[#CallFoo]] = !DILocation(line: 13, column: 3, scope: ![[#Puts2Scope]]) ++; CHECK-LLVM: ![[#Ret2]] = !DILocation(line: 14, column: 3, scope: ![[#Puts2Scope]]) ++ ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++; ModuleID = 'test.bc' ++ ++@str = private unnamed_addr constant [4 x i8] c"FOO\00" ++@str1 = private unnamed_addr constant [6 x i8] c"Main!\00" ++ ++define void @foo() nounwind !dbg !5 { ++entry: ++ %puts = tail call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str, i32 0, i32 0)), !dbg !23 ++ ret void, !dbg !25 ++} ++ ++declare i32 @puts(i8* nocapture) nounwind ++ ++define i32 @main(i32 %argc, i8** nocapture %argv) nounwind !dbg !12 { ++entry: ++ tail call void @llvm.dbg.value(metadata i32 %argc, metadata !21, metadata !DIExpression()), !dbg !26 ++ ; Avoid talking about the pointer size in debug info because that's target dependent ++ tail call void @llvm.dbg.value(metadata i8** %argv, metadata !22, metadata !DIExpression(DW_OP_deref, DW_OP_deref)), !dbg !27 ++ %puts = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str1, i32 0, i32 0)), !dbg !28 ++ tail call void @foo() nounwind, !dbg !30 ++ ret i32 0, !dbg !31 ++} ++ ++declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ++ ++!llvm.dbg.cu = !{!0, !9} ++!llvm.module.flags = !{!33} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 14", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1) ++!1 = !{} ++!5 = distinct !DISubprogram(name: "foo", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !32, scope: !6, type: !7, retainedNodes: !1) ++!6 = !DIFile(filename: "foo.c", directory: "/tmp") ++!7 = !DISubroutineType(types: !8) ++!8 = !{null} ++!9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, producer: "clang version 14", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1) ++!12 = distinct !DISubprogram(name: "main", line: 11, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !9, scopeLine: 11, file: !32, scope: !6, type: !13, retainedNodes: !19) ++!13 = !DISubroutineType(types: !14) ++!14 = !{!15, !15, !18} ++!15 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) ++!18 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) ++!19 = !{!21, !22} ++!21 = !DILocalVariable(name: "argc", line: 11, arg: 1, scope: !12, file: !6, type: !15) ++!22 = !DILocalVariable(name: "argv", line: 11, arg: 2, scope: !12, file: !6, type: !18) ++!23 = !DILocation(line: 6, column: 3, scope: !24) ++!24 = distinct !DILexicalBlock(line: 5, column: 16, file: !32, scope: !5) ++!25 = !DILocation(line: 7, column: 1, scope: !24) ++!26 = !DILocation(line: 11, column: 14, scope: !12) ++!27 = !DILocation(line: 11, column: 26, scope: !12) ++!28 = !DILocation(line: 12, column: 3, scope: !29) ++!29 = distinct !DILexicalBlock(line: 11, column: 34, file: !32, scope: !12) ++!30 = !DILocation(line: 13, column: 3, scope: !29) ++!31 = !DILocation(line: 14, column: 3, scope: !29) ++!32 = !DIFile(filename: "foo.c", directory: "/tmp") ++!33 = !{i32 1, !"Debug Info Version", i32 3} +diff --git a/test/DebugInfo/X86/mixed-nodebug-cu.ll b/test/DebugInfo/X86/mixed-nodebug-cu.ll +index 0ec0f2f2..27d80af1 100644 +--- a/test/DebugInfo/X86/mixed-nodebug-cu.ll ++++ b/test/DebugInfo/X86/mixed-nodebug-cu.ll +@@ -7,7 +7,7 @@ + ; CHECK: DW_TAG_compile_unit + ; CHECK: DW_TAG_subprogram + ; CHECK: DW_AT_name{{.*}}"f" +-; CHECK-NOT: DW_TAG_compile_unit ++; CHECK: DW_TAG_compile_unit + ; + ; created from + ; void f() {} // compile with -g +diff --git a/test/DebugInfo/X86/split-dwarf-omit-empty.ll b/test/DebugInfo/X86/split-dwarf-omit-empty.ll +index b4afeed3..03e57cb6 100644 +--- a/test/DebugInfo/X86/split-dwarf-omit-empty.ll ++++ b/test/DebugInfo/X86/split-dwarf-omit-empty.ll +@@ -24,7 +24,7 @@ target triple = "spir64-unknown-unknown" + + ; CHECK: .debug_info contents: + ; CHECK: Compile Unit +-; CHECK-NOT: Compile Unit ++; CHECK: Compile Unit + ; CHECK: .debug_info.dwo contents: + + +-- +2.20.1 + diff --git a/patches/0035-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch b/patches/0035-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch new file mode 100644 index 0000000..6565192 --- /dev/null +++ b/patches/0035-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch @@ -0,0 +1,368 @@ +From 44033b501bec8654aa9dcd086155dd8aecf41dc8 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Thu, 20 Apr 2023 14:22:52 -0700 +Subject: [PATCH 35/79] [Backport to 15][DebugInfo] Support translation of + DebugFunctionDefinition instruction (#1961) + +DebugFunction does not have an Function Id operand in NonSemantic.Shader debug info specification. It's been replaced by the whole new DebugFunctionDefinition instruction to avoid forward references. + +This instruction must appear in the entry basic block of an OpFunction. + +Specification: +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugFunctionDefinition +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 27 ++++++++++++ + lib/SPIRV/LLVMToSPIRVDbgTran.h | 2 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 43 ++++++++++++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 2 + + lib/SPIRV/libSPIRV/SPIRV.debug.h | 13 +++++- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 14 +++++- + test/DebugInfo/NonSemantic/DebugFunction.cl | 29 +++++++++---- + .../Shader200/DebugInfoTargetFunction.ll | 2 +- + .../NonSemantic/Shader200/FortranComplex.ll | 16 +++---- + 10 files changed, 123 insertions(+), 26 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index e36658b4..3a717232 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1133,6 +1133,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); + + SPIRVEntry *DebugFunc = nullptr; ++ SPIRVValue *FuncDef = nullptr; + if (!Func->isDefinition()) { + DebugFunc = + BM->addDebugInfo(SPIRVDebug::FunctionDeclaration, getVoidTy(), Ops); +@@ -1150,9 +1151,14 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + SPIRVValue *SPIRVFunc = SPIRVWriter->getTranslatedValue(&F); + assert(SPIRVFunc && "All function must be already translated"); + Ops[FunctionIdIdx] = SPIRVFunc->getId(); ++ FuncDef = SPIRVFunc; + break; + } + } ++ // For NonSemantic.Shader.DebugInfo we store Function Id index as a ++ // separate DebugFunctionDefinition instruction. ++ if (isNonSemanticDebugInfo()) ++ Ops.pop_back(); + + if (DISubprogram *FuncDecl = Func->getDeclaration()) + Ops.push_back(transDbgEntry(FuncDecl)->getId()); +@@ -1179,9 +1185,30 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + if (DITemplateParameterArray TPA = Func->getTemplateParams()) { + DebugFunc = transDbgTemplateParams(TPA, DebugFunc); + } ++ ++ if (isNonSemanticDebugInfo()) ++ transDbgFuncDefinition(FuncDef, DebugFunc); ++ + return DebugFunc; + } + ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFuncDefinition(SPIRVValue *FuncDef, ++ SPIRVEntry *DbgFunc) { ++ if (!isNonSemanticDebugInfo() || !FuncDef) ++ return nullptr; ++ ++ using namespace SPIRVDebug::Operand::FunctionDefinition; ++ SPIRVWordVec Ops(OperandCount); ++ Ops[FunctionIdx] = DbgFunc->getId(); ++ Ops[DefinitionIdx] = FuncDef->getId(); ++ SPIRVFunction *F = static_cast(FuncDef); ++ SPIRVBasicBlock *BB = F->getNumBasicBlock() ? F->getBasicBlock(0) : nullptr; ++ SPIRVId ExtSetId = BM->getExtInstSetId(BM->getDebugInfoEIS()); ++ ++ return BM->addExtInst(getVoidTy(), ExtSetId, SPIRVDebug::FunctionDefinition, ++ Ops, BB, BB->getInst(0)); ++} ++ + // Location information + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index d43040d7..984de156 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -134,6 +134,8 @@ private: + SPIRVEntry *transDbgGlobalVariable(const DIGlobalVariable *GV); + SPIRVEntry *transDbgFunction(const DISubprogram *Func); + ++ SPIRVEntry *transDbgFuncDefinition(SPIRVValue *SPVFunc, SPIRVEntry *DbgFunc); ++ + // Location information + SPIRVEntry *transDbgScope(const DIScope *S); + SPIRVEntry *transDebugLoc(const DebugLoc &Loc, SPIRVBasicBlock *BB, +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 2ad7b4a9..42e637ca 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -761,7 +761,11 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + + // Function declaration descriptor + DISubprogram *FD = nullptr; +- if (Ops.size() > DeclarationIdx) { ++ if (isNonSemanticDebugInfo(DebugInst->getExtSetKind()) && ++ Ops.size() > DeclarationNonSemIdx) { ++ FD = transDebugInst( ++ BM->get(Ops[DeclarationNonSemIdx])); ++ } else if (Ops.size() > DeclarationIdx) { + FD = transDebugInst( + BM->get(Ops[DeclarationIdx])); + } +@@ -786,7 +790,7 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + // Create targetFuncName mostly for Fortran trampoline function if it is + // the case + StringRef TargetFunction; +- if (Ops.size() > TargetFunctionNameIdx) { ++ if (Ops.size() > MinOperandCount) { + TargetFunction = getString(Ops[TargetFunctionNameIdx]); + } + DIS = getDIBuilder(DebugInst).createFunction( +@@ -796,11 +800,21 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + /*Annotations*/ nullptr, TargetFunction); + } + DebugInstCache[DebugInst] = DIS; +- SPIRVId RealFuncId = Ops[FunctionIdIdx]; +- FuncMap[RealFuncId] = DIS; + +- // Function. +- SPIRVEntry *E = BM->getEntry(Ops[FunctionIdIdx]); ++ // At this point, we don't have info about the function definition for ++ // NonSemantic.Shader debug info. If function definition is present, it'll be ++ // translated later within the function scope. ++ // For "default" debug info we do translate function body here. ++ if (!isNonSemanticDebugInfo(DebugInst->getExtSetKind())) ++ transFunctionBody(DIS, Ops[FunctionIdIdx]); ++ ++ return DIS; ++} ++ ++void SPIRVToLLVMDbgTran::transFunctionBody(DISubprogram *DIS, SPIRVId FuncId) { ++ FuncMap[FuncId] = DIS; ++ ++ SPIRVEntry *E = BM->getEntry(FuncId); + if (E->getOpCode() == OpFunction) { + SPIRVFunction *BF = static_cast(E); + llvm::Function *F = SPIRVReader->transFunction(BF); +@@ -808,7 +822,18 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + if (!F->hasMetadata("dbg")) + F->setMetadata("dbg", DIS); + } +- return DIS; ++} ++ ++DINode * ++SPIRVToLLVMDbgTran::transFunctionDefinition(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::FunctionDefinition; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ ++ SPIRVExtInst *Func = BM->get(Ops[FunctionIdx]); ++ DISubprogram *LLVMFunc = cast(DebugInstCache[Func]); ++ ++ transFunctionBody(LLVMFunc, Ops[DefinitionIdx]); ++ return nullptr; + } + + DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { +@@ -1203,6 +1228,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::FunctionDeclaration: + return transFunctionDecl(DebugInst); + ++ case SPIRVDebug::FunctionDefinition: ++ return transFunctionDefinition(DebugInst); ++ + case SPIRVDebug::GlobalVariable: + return transGlobalVariable(DebugInst); + +@@ -1272,6 +1300,7 @@ SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst, + switch (DebugInst->getExtOp()) { + case SPIRVDebug::Scope: + case SPIRVDebug::NoScope: ++ case SPIRVDebug::FunctionDefinition: + return nullptr; + case SPIRVDebug::Declare: { + using namespace SPIRVDebug::Operand::DebugDeclare; +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index f6b31686..b1ded375 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -141,6 +141,8 @@ private: + DINode *transLexicalBlockDiscriminator(const SPIRVExtInst *DebugInst); + + DINode *transFunction(const SPIRVExtInst *DebugInst); ++ DINode *transFunctionDefinition(const SPIRVExtInst *DebugInst); ++ void transFunctionBody(DISubprogram *DIS, SPIRVId FuncId); + + DINode *transFunctionDecl(const SPIRVExtInst *DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 19170e1d..677f1cba 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -54,6 +54,7 @@ enum Instruction { + Source = 35, + ModuleINTEL = 36, + InstCount = 37, ++ FunctionDefinition = 101, + Module = 200, + TypeSubrange = 201, + TypeArrayDynamic = 202, +@@ -543,12 +544,22 @@ enum { + FlagsIdx = 7, + ScopeLineIdx = 8, + FunctionIdIdx = 9, ++ DeclarationNonSemIdx = 9, + DeclarationIdx = 10, +- TargetFunctionNameIdx = 11, ++ // Only for NonSemantic.Schader.DebugInfo.200 ++ TargetFunctionNameIdx = 10, + MinOperandCount = 10 + }; + } + ++namespace FunctionDefinition { ++enum { ++ FunctionIdx = 0, ++ DefinitionIdx = 1, ++ OperandCount = 2 ++}; ++} ++ + namespace LexicalBlock { + enum { + SourceIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index f9d55433..2fe7b096 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -260,6 +260,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::Module, "DebugModule"); + add(SPIRVDebug::Expression, "DebugExpression"); + add(SPIRVDebug::Operation, "DebugOperation"); ++ add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition"); + } + SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index 0916cebc..5733254e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -1883,7 +1883,19 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { + O << SPIRVNL() << MI.AsmTargetVec << MI.AsmVec; + } + +- O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() << MI.FuncVec; ++ // At this point we know that FunctionDefinition could have been included both ++ // into DebugInstVec and into basick block of function from FuncVec. ++ // By spec we should only have this instruction to be present inside the ++ // function body, so removing it from the DebugInstVec to avoid duplication. ++ MI.DebugInstVec.erase( ++ std::remove_if(MI.DebugInstVec.begin(), MI.DebugInstVec.end(), ++ [](SPIRVExtInst *I) { ++ return I->getExtOp() == SPIRVDebug::FunctionDefinition; ++ }), ++ MI.DebugInstVec.end()); ++ ++ O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() ++ << MI.FuncVec; + return O; + } + +diff --git a/test/DebugInfo/NonSemantic/DebugFunction.cl b/test/DebugInfo/NonSemantic/DebugFunction.cl +index da27864f..74603e17 100644 +--- a/test/DebugInfo/NonSemantic/DebugFunction.cl ++++ b/test/DebugInfo/NonSemantic/DebugFunction.cl +@@ -4,8 +4,15 @@ + // - Parent operand of DebugFunction is DebugCompilationUnit, not an OpString, + // even if in LLVM IR it points to a DIFile instead of DICompileUnit. + +-// RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o - | llvm-spirv -o %t.spv +-// RUN: llvm-spirv %t.spv --spirv-debug-info-version=nonsemantic-shader-100 -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++// RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm-bc -triple spir -debug-info-kind=line-tables-only -O0 -o %t.bc ++// RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv ++// RUN: llvm-spirv %t.spv -to-text -o %t.spt ++// RUN: FileCheck %s --input-file %t.spt --check-prefix=CHECK-SPIRV ++ ++// RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++// RUN: llvm-spirv %t.spv -to-text -o %t.spt ++// RUN: FileCheck %s --input-file %t.spt --check-prefix=CHECK-SPIRV ++ + // RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM + + float foo(int i) { +@@ -18,11 +25,17 @@ void kernel k() { + // CHECK-SPIRV: String [[foo:[0-9]+]] "foo" + // CHECK-SPIRV: String [[k:[0-9]+]] "k" + // CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompilationUnit +-// CHECK-SPIRV: DebugFunction [[foo]] {{.*}} [[CU]] {{.*}} [[foo_id:[0-9]+]] {{[0-9]+}} {{$}} +-// CHECK-SPIRV: DebugFunction [[k]] {{.*}} [[CU]] {{.*}} [[k_id:[0-9]+]] {{[0-9]+}} {{$}} ++// CHECK-SPIRV: [[#FuncFoo:]] [[#]] DebugFunction [[foo]] {{.*}} [[CU]] ++// CHECK-SPIRV: [[#FuncK:]] [[#]] DebugFunction [[k]] {{.*}} [[CU]] ++// CHECK-SPIRV-NOT: DebugFunctionDefinition ++ ++// CHECK-SPIRV: Function {{[0-9]+}} [[#foo_id:]] ++// CHECK-SPIRV: DebugFunctionDefinition [[#FuncFoo]] [[#foo_id]] ++// CHECK-LLVM: define spir_func float @_Z3fooi(i32 %i) #{{[0-9]+}} !dbg ![[#foo_id:]] { + +-// CHECK-SPIRV: Function {{[0-9]+}} [[foo_id]] +-// CHECK-LLVM: define spir_func float @_Z3fooi(i32 %i) #{{[0-9]+}} !dbg !{{[0-9]+}} { ++// CHECK-SPIRV: Function {{[0-9]+}} [[#k_id:]] ++// CHECK-SPIRV: DebugFunctionDefinition [[#FuncK]] [[#k_id]] ++// CHECK-LLVM: define spir_kernel void @k() #{{[0-9]+}} !dbg ![[#k_id:]] + +-// CHECK-SPIRV: Function {{[0-9]+}} [[k_id]] +-// CHECK-LLVM: define spir_kernel void @k() #{{[0-9]+}} !dbg !{{[0-9]+}} ++// CHECK-LLVM: ![[#foo_id]] = distinct !DISubprogram(name: "foo" ++// CHECK-LLVM: ![[#k_id]] = distinct !DISubprogram(name: "k" +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +index 1e6e3f9f..074305af 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +@@ -12,7 +12,7 @@ + ; CHECK-SPIRV-DAG: String [[#TargetFunc:]] "_Z3foov" + + ; CHECK-SPIRV-DAG: ExtInst [[#]] [[#DebugNone:]] [[#]] DebugInfoNone +-; CHECK-SPIRV-DAG: ExtInst [[#]] [[#]] [[#]] DebugFunction [[#Func]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#DebugNone]] [[#TargetFunc]] ++; CHECK-SPIRV-DAG: ExtInst [[#]] [[#]] [[#]] DebugFunction [[#Func]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#DebugNone]] [[#TargetFunc]] + + ; CHECK-LLVM: define spir_func void @_Z11foo_wrapperv() {{.*}} !dbg ![[#DbgSubProg:]] { + ; CHECK-LLVM: ![[#DbgSubProg]] = distinct !DISubprogram(name: "foo_wrapper", linkageName: "_Z11foo_wrapperv", scope: null, file: ![[#]], line: 3, type: ![[#]], scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], templateParams: ![[#]], retainedNodes: ![[#]], targetFuncName: "_Z3foov") +diff --git a/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll b/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll +index 8a1032c3..daca3c4a 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranComplex.ll +@@ -32,10 +32,10 @@ + ; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] + ; CHECK-SPIRV-200-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] + +-; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) +-; CHECK-LLVM-200: ![[#Type]] = !DIBasicType(name: "COMPLEX*8", size: 64, encoding: DW_ATE_complex_float) +-; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) +-; CHECK-LLVM-200: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-200-DAG: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) ++; CHECK-LLVM-200-DAG: ![[#Type]] = !DIBasicType(name: "COMPLEX*8", size: 64, encoding: DW_ATE_complex_float) ++; CHECK-LLVM-200-DAG: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-200-DAG: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) + + ; CHECK-SPIRV-100-DAG: ExtInstImport [[#Import:]] "NonSemantic.Shader.DebugInfo.100 + ; CHECK-SPIRV-100-DAG: String [[#Name:]] "COMPLEX*8" +@@ -46,10 +46,10 @@ + ; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] + ; CHECK-SPIRV-100-DAG: ExtInst [[#]] [[#]] [[#Import]] DebugLocalVariable [[#]] [[#Type]] + +-; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) +-; CHECK-LLVM-100: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "COMPLEX*8") +-; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) +-; CHECK-LLVM-100: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-100-DAG: ![[#]] = !DILocalVariable(name: "a", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type:]]) ++; CHECK-LLVM-100-DAG: ![[#Type]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "COMPLEX*8") ++; CHECK-LLVM-100-DAG: ![[#]] = !DILocalVariable(name: "b", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) ++; CHECK-LLVM-100-DAG: ![[#]] = !DILocalVariable(name: "c", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#Type]]) + + ; ModuleID = 'test.f90' + source_filename = "test.f90" +-- +2.20.1 + diff --git a/patches/0036-Backport-to-15-DebugInfo-Add-module-producer-info-fo.patch b/patches/0036-Backport-to-15-DebugInfo-Add-module-producer-info-fo.patch new file mode 100644 index 0000000..4d26ef3 --- /dev/null +++ b/patches/0036-Backport-to-15-DebugInfo-Add-module-producer-info-fo.patch @@ -0,0 +1,183 @@ +From e73ad0215898a4857cc1a5595a0d394e22292662 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 21 Apr 2023 08:18:00 -0700 +Subject: [PATCH 36/79] [Backport to 15][DebugInfo] Add module producer info + for NonSemantic.Shader.DebugInfo.200 (#1968) + +Keep existing W/A for other debug info specs, except +NonSemantic.Shader.DebugInfo.100 +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 14 +++- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 16 +++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 4 +- + .../NonSemantic/DebugInfoProducer.ll | 76 +++++++++++++++++++ + 4 files changed, 105 insertions(+), 5 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/DebugInfoProducer.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 3a717232..7ff8b9a1 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -540,7 +540,7 @@ SPIRVId LLVMToSPIRVDbgTran::getDebugInfoNoneId() { + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + using namespace SPIRVDebug::Operand::CompilationUnit; +- SPIRVWordVec Ops(OperandCount); ++ SPIRVWordVec Ops(MinOperandCount); + Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion; + Ops[DWARFVersionIdx] = M->getDwarfVersion(); + Ops[SourceIdx] = getSource(CU)->getId(); +@@ -553,7 +553,17 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + if (isNonSemanticDebugInfo()) + transformToConstant( + Ops, {SPIRVDebugInfoVersionIdx, DWARFVersionIdx, LanguageIdx}); +- BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); ++ ++ if (isNonSemanticDebugInfo()) { ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ Ops.push_back(BM->getString(CU->getProducer().str())->getId()); ++ } ++ } else { ++ // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug ++ // info by default ++ BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + ++ CU->getProducer().str()); ++ } + // Cache CU in a member. + SPIRVCUMap[CU] = static_cast( + BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops)); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 42e637ca..0e00f7b0 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -156,7 +156,7 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + const SPIRVWordVec &Ops = DebugInst->getArguments(); + + using namespace SPIRVDebug::Operand::CompilationUnit; +- assert(Ops.size() == OperandCount && "Invalid number of operands"); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + // We must preserve only one Dwarf version module level metadata + // UpgradeDebugInfo from llvm/lib/IR/AutoUpgrade.cpp has already done all + // work for us during linking stage leaving a single Dwarf version in the +@@ -180,8 +180,20 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + SourceLang = dwarf::DW_LANG_OpenCL; + } + +- auto Producer = findModuleProducer(); + BuilderMap[DebugInst->getId()] = std::make_unique(*M); ++ ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100) { ++ return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ SourceLang, getFile(Ops[SourceIdx]), "spirv", false, "", 0); ++ } ++ if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ StringRef Producer = getString(Ops[ProducerIdx]); ++ return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); ++ } ++ // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug ++ // info by default ++ auto Producer = findModuleProducer(); + return BuilderMap[DebugInst->getId()]->createCompileUnit( + SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); + } +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 677f1cba..06c5af0a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -290,7 +290,9 @@ enum { + DWARFVersionIdx = 1, + SourceIdx = 2, + LanguageIdx = 3, +- OperandCount = 4 ++ // For NonSemantic.Shader.DebugInfo.200 ++ ProducerIdx = 4, ++ MinOperandCount = 4 + }; + } + +diff --git a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +new file mode 100644 +index 00000000..4bc59dc3 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +@@ -0,0 +1,76 @@ ++; Test checks debug info of producer is preserved from LLVM IR to spirv ++; and spirv to LLVM IR translation. ++ ++; Original .cpp source: ++; ++; int main() { ++; return 0; ++; } ++ ++; Command line: ++; ./clang -cc1 -debug-info-kind=standalone -v s.cpp -S -emit-llvm -triple spir ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV-200 ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM-200 ++ ++; Check that we don't produce "producer" info for NonSemantic.Shader.DebugInfo.100 as it's not specification conformant ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV-100 ++; RUN: llvm-spirv -spirv-text -r -emit-opaque-pointers %t.spt -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix CHECK-LLVM-100 ++ ++; ModuleID = 's.bc' ++source_filename = "s.cpp" ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir" ++ ++; Function Attrs: noinline norecurse nounwind optnone ++define i32 @main() #0 !dbg !8 { ++entry: ++ %retval = alloca i32, align 4 ++ store i32 0, i32* %retval, align 4 ++ ret i32 0, !dbg !13 ++} ++ ++attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!3, !4, !5, !6} ++!opencl.used.extensions = !{!2} ++!opencl.used.optional.core.features = !{!2} ++!opencl.compiler.options = !{!2} ++!llvm.ident = !{!7} ++ ++; CHECK-LLVM-200: !DICompileUnit ++; CHECK-LLVM-200-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-LLVM-200-NOT: producer: "spirv" ++ ++; CHECK-LLVM-100: !DICompileUnit ++; CHECK-LLVM-100-SAME: producer: "spirv" ++; CHECK-LLVM-100-NOT: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++ ++; CHECK-SPIRV-200: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-200: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#ProducerId]] ++ ++; CHECK-SPIRV-100-NOT: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-100-NOT: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++ ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) ++!1 = !DIFile(filename: "", directory: "oneAPI") ++!2 = !{} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 1, !"ThinLTO", i32 0} ++!6 = !{i32 1, !"EnableSplitLTOUnit", i32 1} ++!7 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"} ++!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) ++!9 = !DIFile(filename: "s.cpp", directory: "C:\\") ++!10 = !DISubroutineType(types: !11) ++!11 = !{!12} ++!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!13 = !DILocation(line: 2, column: 2, scope: !8) +-- +2.20.1 + diff --git a/patches/0037-NFC-Use-typed-pointers-for-null-function-pointers-de.patch b/patches/0037-NFC-Use-typed-pointers-for-null-function-pointers-de.patch new file mode 100644 index 0000000..b1ecb6a --- /dev/null +++ b/patches/0037-NFC-Use-typed-pointers-for-null-function-pointers-de.patch @@ -0,0 +1,36 @@ +From 93b493e4d53339dbf4b27f1684d0756ec7a5fbd1 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Sat, 22 Apr 2023 00:02:48 +0200 +Subject: [PATCH 37/79] [NFC] Use typed pointers for null function pointers + debug info (#1969) + +`PointerType::get(Context` will return typeless/opaque pointer. While it +is OK for KHR translator since it's being built on top of LLVM trunk, +where opaque pointers are enabled by default - it won't work for +intel/llvm, where their generation is disabled. + +Upstream of https://github.com/intel/llvm/pull/9118 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 7ff8b9a1..49f1cfba 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1027,8 +1027,8 @@ LLVMToSPIRVDbgTran::transDbgTemplateParameter(const DITemplateParameter *TP) { + Constant *C = cast(TVVal)->getValue(); + Ops[ValueIdx] = SPIRVWriter->transValue(C, nullptr)->getId(); + } else { +- SPIRVType *TyPtr = +- SPIRVWriter->transType(PointerType::get(M->getContext(), 0)); ++ SPIRVType *TyPtr = SPIRVWriter->transType( ++ PointerType::get(Type::getInt8Ty(M->getContext()), 0)); + Ops[ValueIdx] = BM->addNullConstant(TyPtr)->getId(); + } + } +-- +2.20.1 + diff --git a/patches/0038-DebugInfo-Fix-Composite-type-translation-for-NonSema.patch b/patches/0038-DebugInfo-Fix-Composite-type-translation-for-NonSema.patch new file mode 100644 index 0000000..de4f17a --- /dev/null +++ b/patches/0038-DebugInfo-Fix-Composite-type-translation-for-NonSema.patch @@ -0,0 +1,45 @@ +From 5dc6a23d5cbb4d84e2082297de3356eb90ece1dc Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 25 Apr 2023 22:17:50 +0200 +Subject: [PATCH 38/79] [DebugInfo] Fix Composite type translation for + NonSemantic spec (#1975) + +Tag should be OpConstant, not Literal. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 2 +- + test/DebugInfo/TransTypeCompositeCaseClass_.ll | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 49f1cfba..ee6b6687 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -931,7 +931,7 @@ LLVMToSPIRVDbgTran::transDbgCompositeType(const DICompositeType *CT) { + } + + if (isNonSemanticDebugInfo()) +- transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); ++ transformToConstant(Ops, {TagIdx, LineIdx, ColumnIdx, FlagsIdx}); + SPIRVEntry *Res = + BM->addDebugInfo(SPIRVDebug::TypeComposite, getVoidTy(), Ops); + +diff --git a/test/DebugInfo/TransTypeCompositeCaseClass_.ll b/test/DebugInfo/TransTypeCompositeCaseClass_.ll +index 1b06cef4..3dcea445 100644 +--- a/test/DebugInfo/TransTypeCompositeCaseClass_.ll ++++ b/test/DebugInfo/TransTypeCompositeCaseClass_.ll +@@ -13,6 +13,10 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-100 %t.bc -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ + ; ModuleID = 'main.cpp' + source_filename = "main.cpp" + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +-- +2.20.1 + diff --git a/patches/0039-DebugInfo-Add-Flag-parameter-to-DebugTypeBasic-1965.patch b/patches/0039-DebugInfo-Add-Flag-parameter-to-DebugTypeBasic-1965.patch new file mode 100644 index 0000000..025d109 --- /dev/null +++ b/patches/0039-DebugInfo-Add-Flag-parameter-to-DebugTypeBasic-1965.patch @@ -0,0 +1,227 @@ +From 0f2e44ee92e0c71f4666f0413a251d721250f5fd Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 26 Apr 2023 12:20:30 +0200 +Subject: [PATCH 39/79] [DebugInfo] Add Flag parameter to DebugTypeBasic + (#1965) + +It can only be FlagUnknownPhysicalLayout. There is no way we can +generate it LLVM environment and get use of it, hence the patch just +ignores it if it come from another SPIR-V generator. + +In general, there are following possible debug flags for DIBasicType: +BigEndian, LittleEndian and Artificial. There is not way that clang will +ever generate them, but that can be produced by manually writing +assembly and transforming it to LLVM IR. While it can be potential +improvement for the future - I don't see it useful to add to the spec +and implementation right now. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 2 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 4 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 50 +++++----- + .../NonSemantic/basic-type-with-flag.spt | 96 +++++++++++++++++++ + 4 files changed, 127 insertions(+), 25 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/basic-type-with-flag.spt + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index ee6b6687..e849b435 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -574,7 +574,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgBaseType(const DIBasicType *BT) { + using namespace SPIRVDebug::Operand::TypeBasic; +- SPIRVWordVec Ops(OperandCount); ++ SPIRVWordVec Ops(OperandCountOCL); + Ops[NameIdx] = BM->getString(BT->getName().str())->getId(); + ConstantInt *Size = getUInt(M, BT->getSizeInBits()); + Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 0e00f7b0..5917fc0c 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -201,7 +201,9 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeBasic; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +- assert(Ops.size() == OperandCount && "Invalid number of operands"); ++ assert((Ops.size() == OperandCountOCL || ++ Ops.size() == OperandCountNonSemantic) && ++ "Invalid number of operands"); + StringRef Name = getString(Ops[NameIdx]); + auto Tag = static_cast( + getConstantValueOrLiteral(Ops, EncodingIdx, DebugInst->getExtSetKind())); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 06c5af0a..86e347e9 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -62,25 +62,26 @@ enum Instruction { + }; + + enum Flag { +- FlagIsProtected = 1 << 0, +- FlagIsPrivate = 1 << 1, +- FlagIsPublic = FlagIsPrivate | FlagIsProtected, +- FlagAccess = FlagIsPublic, +- FlagIsLocal = 1 << 2, +- FlagIsDefinition = 1 << 3, +- FlagIsFwdDecl = 1 << 4, +- FlagIsArtificial = 1 << 5, +- FlagIsExplicit = 1 << 6, +- FlagIsPrototyped = 1 << 7, +- FlagIsObjectPointer = 1 << 8, +- FlagIsStaticMember = 1 << 9, +- FlagIsIndirectVariable = 1 << 10, +- FlagIsLValueReference = 1 << 11, +- FlagIsRValueReference = 1 << 12, +- FlagIsOptimized = 1 << 13, +- FlagIsEnumClass = 1 << 14, +- FlagTypePassByValue = 1 << 15, +- FlagTypePassByReference = 1 << 16, ++ FlagIsProtected = 1 << 0, ++ FlagIsPrivate = 1 << 1, ++ FlagIsPublic = FlagIsPrivate | FlagIsProtected, ++ FlagAccess = FlagIsPublic, ++ FlagIsLocal = 1 << 2, ++ FlagIsDefinition = 1 << 3, ++ FlagIsFwdDecl = 1 << 4, ++ FlagIsArtificial = 1 << 5, ++ FlagIsExplicit = 1 << 6, ++ FlagIsPrototyped = 1 << 7, ++ FlagIsObjectPointer = 1 << 8, ++ FlagIsStaticMember = 1 << 9, ++ FlagIsIndirectVariable = 1 << 10, ++ FlagIsLValueReference = 1 << 11, ++ FlagIsRValueReference = 1 << 12, ++ FlagIsOptimized = 1 << 13, ++ FlagIsEnumClass = 1 << 14, ++ FlagTypePassByValue = 1 << 15, ++ FlagTypePassByReference = 1 << 16, ++ FlagUnknownPhysicalLayout = 1 << 17, + }; + + enum EncodingTag { +@@ -306,10 +307,13 @@ enum { + + namespace TypeBasic { + enum { +- NameIdx = 0, +- SizeIdx = 1, +- EncodingIdx = 2, +- OperandCount = 3 ++ NameIdx = 0, ++ SizeIdx = 1, ++ EncodingIdx = 2, ++ // For NonSemantic Specs ++ FlagsIdx = 3, ++ OperandCountOCL = 3, ++ OperandCountNonSemantic = 4 + }; + } + +diff --git a/test/DebugInfo/NonSemantic/basic-type-with-flag.spt b/test/DebugInfo/NonSemantic/basic-type-with-flag.spt +new file mode 100644 +index 00000000..ebad020e +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/basic-type-with-flag.spt +@@ -0,0 +1,96 @@ ++;; This test checks, that SPIR-V module generated by another SPIR-V producer ++;; containing FlagUnknownPhysicalLayout flag of DebugTypeBasic can be ++;; consumed without issues ++ ++; RUN: llvm-spirv %s -to-binary -o %t.spv ++; RUN: llvm-spirv -r %t.spv ++; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-LLVM: DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++ ++119734787 65792 393230 56 0 ++2 Capability Addresses ++2 Capability Linkage ++2 Capability Kernel ++2 Capability Int8 ++8 Extension "SPV_KHR_non_semantic_info" ++5 ExtInstImport 1 "OpenCL.std" ++11 ExtInstImport 2 "NonSemantic.Shader.DebugInfo.100" ++3 MemoryModel 2 2 ++8 String 25 "foo.cpp" ++4 String 30 "int" ++3 String 35 "A" ++3 String 36 "b" ++3 String 44 "foo" ++5 String 45 "_Z3fooP1A" ++3 String 51 "a" ++3 Source 0 0 ++5 Name 7 "_Z3fooP1A" ++3 Name 8 "a" ++4 Name 9 "entry" ++4 Name 11 "a.addr" ++5 Name 16 "struct.A" ++3 Name 23 "b" ++ ++15 ModuleProcessed "Debug info producer: clang version 3.1 (trunk 150996)" ++7 Decorate 7 LinkageAttributes "_Z3fooP1A" Export ++4 Decorate 11 Alignment 8 ++4 TypeInt 3 32 0 ++4 TypeInt 4 8 0 ++4 Constant 3 21 0 ++4 Constant 3 27 65536 ++4 Constant 3 28 6 ++4 Constant 3 31 32 ++4 Constant 3 32 4 ++4 Constant 3 37 1 ++4 Constant 3 38 2 ++4 Constant 3 41 4294967295 ++4 Constant 3 46 3 ++4 Constant 3 47 136 ++4 Constant 3 49 16 ++4 Constant 3 56 131072 ;; FlagUnknownPhysicalLayout ++4 TypePointer 5 7 4 ++4 TypeFunction 6 3 5 ++4 TypePointer 10 7 5 ++2 TypeVoid 13 ++3 TypeStruct 16 3 ++ ++4 TypePointer 17 7 16 ++4 TypePointer 18 7 17 ++4 TypePointer 22 7 3 ++ ++ ++5 ExtInst 13 14 2 DebugInfoNone ++7 ExtInst 13 26 2 DebugSource 25 14 ++9 ExtInst 13 29 2 DebugCompilationUnit 27 21 26 28 ++9 ExtInst 13 33 2 DebugTypeBasic 30 31 32 56 ++14 ExtInst 13 39 2 DebugTypeMember 36 33 26 37 21 34 21 31 38 ++15 ExtInst 13 34 2 DebugTypeComposite 35 21 26 37 21 29 14 31 21 39 ++8 ExtInst 13 42 2 DebugTypePointer 34 41 21 ++8 ExtInst 13 43 2 DebugTypeFunction 21 33 42 ++15 ExtInst 13 48 2 DebugFunction 44 43 26 46 21 29 45 47 46 14 ++9 ExtInst 13 50 2 DebugLexicalBlock 26 46 49 48 ++13 ExtInst 13 52 2 DebugLocalVariable 51 42 26 46 21 48 21 1 ++5 ExtInst 13 53 2 DebugExpression ++ ++5 Function 3 7 0 6 ++3 FunctionParameter 5 8 ++ ++2 Label 9 ++7 ExtInst 13 57 2 DebugFunctionDefinition 48 7 ++4 Variable 10 11 7 ++4 Bitcast 10 12 11 ++5 Store 12 8 2 8 ++6 ExtInst 13 54 2 DebugScope 48 ++4 Line 25 3 13 ++8 ExtInst 13 15 2 DebugDeclare 52 11 53 ++6 ExtInst 13 55 2 DebugScope 50 ++4 Line 25 4 3 ++4 Bitcast 18 19 11 ++6 Load 17 20 19 2 8 ++6 InBoundsPtrAccessChain 22 23 20 21 21 ++6 Load 3 24 23 2 4 ++2 ReturnValue 24 ++ ++1 FunctionEnd ++ +-- +2.20.1 + diff --git a/patches/0040-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch b/patches/0040-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch new file mode 100644 index 0000000..a7fa13f --- /dev/null +++ b/patches/0040-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch @@ -0,0 +1,458 @@ +From b2045d29bb6c540081aea0f4ba3918a93c63bbe2 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Wed, 26 Apr 2023 04:25:30 -0700 +Subject: [PATCH 40/79] [Backport to 15][DebugInfo] Support translation of + DebugEntryPoint instruction (#1973) + +This instruction is generated for DWARF `DISPFlagMainSubprogram` flag of +function as well as for `spir_kernel` functions. + +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugEntryPoint +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 58 +++++++++++++++++-- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 1 + + lib/SPIRV/SPIRVReader.cpp | 7 +++ + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 47 ++++++++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 9 ++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 16 ++++- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + test/DebugInfo/NonSemantic/DebugFunction.cl | 16 +++-- + .../NonSemantic/DebugInfoProducer.ll | 15 +++-- + .../NonSemantic/Shader200/FortranArray.ll | 12 +++- + 10 files changed, 152 insertions(+), 30 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index e849b435..38a4502c 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1144,6 +1144,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + + SPIRVEntry *DebugFunc = nullptr; + SPIRVValue *FuncDef = nullptr; ++ bool IsEntryPointKernel = false; + if (!Func->isDefinition()) { + DebugFunc = + BM->addDebugInfo(SPIRVDebug::FunctionDeclaration, getVoidTy(), Ops); +@@ -1158,11 +1159,30 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + Ops[FunctionIdIdx] = getDebugInfoNoneId(); + for (const llvm::Function &F : M->functions()) { + if (Func->describes(&F)) { ++ // Function definition of spir_kernel can have no "spir_kernel" calling ++ // convention because SPIRVRegularizeLLVMBase::addKernelEntryPoint pass ++ // could have turned it to spir_func. The "true" entry point is a ++ // wrapper kernel function, which can be found further in the module. ++ if (FuncDef) { ++ if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { ++ IsEntryPointKernel = true; ++ break; ++ } ++ continue; ++ } ++ + SPIRVValue *SPIRVFunc = SPIRVWriter->getTranslatedValue(&F); + assert(SPIRVFunc && "All function must be already translated"); + Ops[FunctionIdIdx] = SPIRVFunc->getId(); + FuncDef = SPIRVFunc; +- break; ++ if (!isNonSemanticDebugInfo()) ++ break; ++ ++ // Most likely unreachable because of Regularise LLVM pass ++ if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { ++ IsEntryPointKernel = true; ++ break; ++ } + } + } + // For NonSemantic.Shader.DebugInfo we store Function Id index as a +@@ -1196,17 +1216,18 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) { + DebugFunc = transDbgTemplateParams(TPA, DebugFunc); + } + +- if (isNonSemanticDebugInfo()) +- transDbgFuncDefinition(FuncDef, DebugFunc); ++ if (isNonSemanticDebugInfo() && ++ (Func->isMainSubprogram() || IsEntryPointKernel)) [[maybe_unused]] ++ SPIRVEntry *Inst = transDbgEntryPoint(Func, DebugFunc); ++ ++ if (isNonSemanticDebugInfo() && FuncDef) [[maybe_unused]] ++ SPIRVEntry *Inst = transDbgFuncDefinition(FuncDef, DebugFunc); + + return DebugFunc; + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFuncDefinition(SPIRVValue *FuncDef, + SPIRVEntry *DbgFunc) { +- if (!isNonSemanticDebugInfo() || !FuncDef) +- return nullptr; +- + using namespace SPIRVDebug::Operand::FunctionDefinition; + SPIRVWordVec Ops(OperandCount); + Ops[FunctionIdx] = DbgFunc->getId(); +@@ -1219,6 +1240,31 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFuncDefinition(SPIRVValue *FuncDef, + Ops, BB, BB->getInst(0)); + } + ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntryPoint(const DISubprogram *Func, ++ SPIRVEntry *DbgFunc) { ++ using namespace SPIRVDebug::Operand::EntryPoint; ++ SPIRVWordVec Ops(OperandCount); ++ Ops[EntryPointIdx] = DbgFunc->getId(); ++ ++ DICompileUnit *CU = Func->getUnit(); ++ if (!CU) { ++ Ops[CompilationUnitIdx] = SPIRVCUMap.begin()->second->getId(); ++ SPIRVWord EmptyStrIdx = BM->getString("")->getId(); ++ Ops[CompilerSignatureIdx] = EmptyStrIdx; ++ Ops[CommandLineArgsIdx] = EmptyStrIdx; ++ return BM->addDebugInfo(SPIRVDebug::EntryPoint, getVoidTy(), Ops); ++ } ++ ++ StringRef Producer = CU->getProducer(); ++ StringRef Flags = CU->getFlags(); ++ SPIRVEntry *CUVal = SPIRVCUMap[CU] ? SPIRVCUMap[CU] : getDebugInfoNone(); ++ ++ Ops[CompilationUnitIdx] = CUVal->getId(); ++ Ops[CompilerSignatureIdx] = BM->getString(Producer.str())->getId(); ++ Ops[CommandLineArgsIdx] = BM->getString(Flags.str())->getId(); ++ return BM->addDebugInfo(SPIRVDebug::EntryPoint, getVoidTy(), Ops); ++} ++ + // Location information + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 984de156..da6685c6 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -135,6 +135,7 @@ private: + SPIRVEntry *transDbgFunction(const DISubprogram *Func); + + SPIRVEntry *transDbgFuncDefinition(SPIRVValue *SPVFunc, SPIRVEntry *DbgFunc); ++ SPIRVEntry *transDbgEntryPoint(const DISubprogram *Func, SPIRVEntry *DbgFunc); + + // Location information + SPIRVEntry *transDbgScope(const DIScope *S); +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 85731c3d..6dd1bfdf 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3331,12 +3331,19 @@ bool SPIRVToLLVM::translate() { + transGlobalCtorDtors(BV); + } + ++ // Entry Points should be translated before all debug intrinsics. ++ for (SPIRVExtInst *EI : BM->getDebugInstVec()) { ++ if (EI->getExtOp() == SPIRVDebug::EntryPoint) ++ DbgTran->transDebugInst(EI); ++ } ++ + // Compile unit might be needed during translation of debug intrinsics. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { + // Translate Compile Units first. + if (EI->getExtOp() == SPIRVDebug::CompilationUnit) + DbgTran->transDebugInst(EI); + } ++ + // Then translate all debug instructions. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { + DbgTran->transDebugInst(EI); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 5917fc0c..327c2b47 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -152,7 +152,14 @@ DIScope *SPIRVToLLVMDbgTran::getScope(const SPIRVEntry *ScopeInst) { + } + + DICompileUnit * +-SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { ++SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, ++ const std::string CompilerVersion, ++ const std::string Flags) { ++ // Do nothing in case we have already translated the CU (e.g. during ++ // DebugEntryPoint translation) ++ if (BuilderMap[DebugInst->getId()]) ++ return nullptr; ++ + const SPIRVWordVec &Ops = DebugInst->getArguments(); + + using namespace SPIRVDebug::Operand::CompilationUnit; +@@ -184,18 +191,18 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) { + + if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100) { + return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), "spirv", false, "", 0); ++ SourceLang, getFile(Ops[SourceIdx]), CompilerVersion, false, Flags, 0); + } + if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { + StringRef Producer = getString(Ops[ProducerIdx]); + return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); ++ SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); + } + // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug + // info by default + auto Producer = findModuleProducer(); + return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); ++ SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); + } + + DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { +@@ -727,7 +734,8 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator( + Disc); + } + +-DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { ++DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst, ++ bool IsMainSubprogram) { + using namespace SPIRVDebug::Operand::Function; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); +@@ -764,11 +772,13 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) { + bool IsDefinition = SPIRVDebugFlags & SPIRVDebug::FlagIsDefinition; + bool IsOptimized = SPIRVDebugFlags & SPIRVDebug::FlagIsOptimized; + bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal; +- bool IsMainSubprogram = ++ bool IsMainSubprogramFlag = ++ IsMainSubprogram || + BM->isEntryPoint(spv::ExecutionModelKernel, Ops[FunctionIdIdx]); +- DISubprogram::DISPFlags SPFlags = +- DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized, +- DISubprogram::SPFlagNonvirtual, IsMainSubprogram); ++ ++ DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags( ++ IsLocal, IsDefinition, IsOptimized, DISubprogram::SPFlagNonvirtual, ++ IsMainSubprogramFlag); + + SPIRVWord ScopeLine = + getConstantValueOrLiteral(Ops, ScopeLineIdx, DebugInst->getExtSetKind()); +@@ -918,6 +928,22 @@ DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) { + return DIS; + } + ++MDNode *SPIRVToLLVMDbgTran::transEntryPoint(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::EntryPoint; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() == OperandCount && "Invalid number of operands"); ++ ++ SPIRVExtInst *EP = BM->get(Ops[EntryPointIdx]); ++ SPIRVExtInst *CU = BM->get(Ops[CompilationUnitIdx]); ++ std::string Producer = getString(Ops[CompilerSignatureIdx]); ++ std::string CLArgs = getString(Ops[CommandLineArgsIdx]); ++ ++ [[maybe_unused]] DICompileUnit *C = ++ transCompilationUnit(CU, Producer, CLArgs); ++ ++ return transFunction(EP, true /*IsMainSubprogram*/); ++} ++ + MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::GlobalVariable; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +@@ -1245,6 +1271,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::FunctionDefinition: + return transFunctionDefinition(DebugInst); + ++ case SPIRVDebug::EntryPoint: ++ return transEntryPoint(DebugInst); ++ + case SPIRVDebug::GlobalVariable: + return transGlobalVariable(DebugInst); + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index b1ded375..c8929300 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -102,7 +102,9 @@ private: + + MDNode *transDebugInlined(const SPIRVExtInst *Inst); + +- DICompileUnit *transCompilationUnit(const SPIRVExtInst *DebugInst); ++ DICompileUnit *transCompilationUnit(const SPIRVExtInst *DebugInst, ++ const std::string CompilerVersion = "", ++ const std::string Flags = ""); + + DIBasicType *transTypeBasic(const SPIRVExtInst *DebugInst); + +@@ -140,12 +142,15 @@ private: + DINode *transLexicalBlock(const SPIRVExtInst *DebugInst); + DINode *transLexicalBlockDiscriminator(const SPIRVExtInst *DebugInst); + +- DINode *transFunction(const SPIRVExtInst *DebugInst); ++ DINode *transFunction(const SPIRVExtInst *DebugInst, ++ bool IsMainSubprogram = false); + DINode *transFunctionDefinition(const SPIRVExtInst *DebugInst); + void transFunctionBody(DISubprogram *DIS, SPIRVId FuncId); + + DINode *transFunctionDecl(const SPIRVExtInst *DebugInst); + ++ MDNode *transEntryPoint(const SPIRVExtInst *DebugInst); ++ + MDNode *transGlobalVariable(const SPIRVExtInst *DebugInst); + + DINode *transLocalVariable(const SPIRVExtInst *DebugInst); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 86e347e9..1fc6875a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -55,6 +55,7 @@ enum Instruction { + ModuleINTEL = 36, + InstCount = 37, + FunctionDefinition = 101, ++ EntryPoint = 107, + Module = 200, + TypeSubrange = 201, + TypeArrayDynamic = 202, +@@ -552,7 +553,7 @@ enum { + FunctionIdIdx = 9, + DeclarationNonSemIdx = 9, + DeclarationIdx = 10, +- // Only for NonSemantic.Schader.DebugInfo.200 ++ // Only for NonSemantic.Shader.DebugInfo.200 + TargetFunctionNameIdx = 10, + MinOperandCount = 10 + }; +@@ -566,6 +567,16 @@ enum { + }; + } + ++namespace EntryPoint { ++enum { ++ EntryPointIdx = 0, ++ CompilationUnitIdx = 1, ++ CompilerSignatureIdx = 2, ++ CommandLineArgsIdx = 3, ++ OperandCount = 4 ++}; ++} ++ + namespace LexicalBlock { + enum { + SourceIdx = 0, +@@ -872,6 +883,9 @@ inline bool hasDbgInstParentScopeIdx(const uint32_t Kind, + case SPIRVDebug::Function: + ParentScopeIdx = Function::ParentIdx; + return true; ++ case SPIRVDebug::EntryPoint: ++ ParentScopeIdx = EntryPoint::CompilationUnitIdx; ++ return true; + case SPIRVDebug::LexicalBlock: + ParentScopeIdx = LexicalBlock::ParentIdx; + return true; +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 2fe7b096..b4dd9027 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -261,6 +261,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::Expression, "DebugExpression"); + add(SPIRVDebug::Operation, "DebugOperation"); + add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition"); ++ add(SPIRVDebug::EntryPoint, "DebugEntryPoint"); + } + SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) + +diff --git a/test/DebugInfo/NonSemantic/DebugFunction.cl b/test/DebugInfo/NonSemantic/DebugFunction.cl +index 74603e17..9f84a896 100644 +--- a/test/DebugInfo/NonSemantic/DebugFunction.cl ++++ b/test/DebugInfo/NonSemantic/DebugFunction.cl +@@ -22,11 +22,15 @@ void kernel k() { + float a = foo(2); + } + +-// CHECK-SPIRV: String [[foo:[0-9]+]] "foo" +-// CHECK-SPIRV: String [[k:[0-9]+]] "k" +-// CHECK-SPIRV: [[CU:[0-9]+]] {{[0-9]+}} DebugCompilationUnit +-// CHECK-SPIRV: [[#FuncFoo:]] [[#]] DebugFunction [[foo]] {{.*}} [[CU]] +-// CHECK-SPIRV: [[#FuncK:]] [[#]] DebugFunction [[k]] {{.*}} [[CU]] ++// CHECK-SPIRV-DAG: String [[foo:[0-9]+]] "foo" ++// CHECK-SPIRV-DAG: String [[#EmptyStr:]] "" ++// CHECK-SPIRV-DAG: String [[k:[0-9]+]] "k" ++// CHECK-SPIRV-DAG: String [[#CV:]] {{.*}}clang version [[#]].[[#]].[[#]] ++// CHECK-SPIRV: [[#CU:]] [[#]] DebugCompilationUnit ++// CHECK-SPIRV: [[#FuncFoo:]] [[#]] DebugFunction [[foo]] {{.*}} [[#CU]] ++// CHECK-SPIRV: [[#FuncK:]] [[#]] DebugFunction [[k]] {{.*}} [[#CU]] ++// CHECK-SPIRV: DebugEntryPoint [[#FuncK]] [[#CU]] [[#CV]] [[#EmptyStr]] {{$}} ++// CHECK-SPIRV-NOT: DebugEntryPoint + // CHECK-SPIRV-NOT: DebugFunctionDefinition + + // CHECK-SPIRV: Function {{[0-9]+}} [[#foo_id:]] +@@ -38,4 +42,6 @@ void kernel k() { + // CHECK-LLVM: define spir_kernel void @k() #{{[0-9]+}} !dbg ![[#k_id:]] + + // CHECK-LLVM: ![[#foo_id]] = distinct !DISubprogram(name: "foo" ++// CHECK-LLVM-SAME: spFlags: DISPFlagDefinition, + // CHECK-LLVM: ![[#k_id]] = distinct !DISubprogram(name: "k" ++// CHECK-LLVM-SAME: spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, +diff --git a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +index 4bc59dc3..9de3cc59 100644 +--- a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll ++++ b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +@@ -47,20 +47,23 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + + ; CHECK-LLVM-200: !DICompileUnit + ; CHECK-LLVM-200-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-LLVM-200-SAME: flags: "-O2" + ; CHECK-LLVM-200-NOT: producer: "spirv" + + ; CHECK-LLVM-100: !DICompileUnit +-; CHECK-LLVM-100-SAME: producer: "spirv" +-; CHECK-LLVM-100-NOT: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-LLVM-100-SAME: producer: "clang{{.*}}version{{.*}}13.0.0{{.*}}(https://github.com/llvm/llvm-project.git{{.*}}16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-LLVM-100-SAME: flags: "-O2" + + ; CHECK-SPIRV-200: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" + ; CHECK-SPIRV-200: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#ProducerId]] ++; CHECK-SPIRV-200: DebugEntryPoint [[#]] [[#]] [[#ProducerId]] [[#]] {{$}} + +-; CHECK-SPIRV-100-NOT: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" +-; CHECK-SPIRV-100-NOT: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV-100: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-100-NOT: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#ProducerId]] {{$}} ++; CHECK-SPIRV-100: DebugEntryPoint [[#]] [[#]] [[#ProducerId]] [[#]] {{$}} + + +-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None, flags: "-O2") + !1 = !DIFile(filename: "", directory: "oneAPI") + !2 = !{} + !3 = !{i32 2, !"Debug Info Version", i32 3} +@@ -68,7 +71,7 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + !5 = !{i32 1, !"ThinLTO", i32 0} + !6 = !{i32 1, !"EnableSplitLTOUnit", i32 1} + !7 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)"} +-!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) ++!8 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !0, retainedNodes: !2) + !9 = !DIFile(filename: "s.cpp", directory: "C:\\") + !10 = !DISubroutineType(types: !11) + !11 = !{!12} +diff --git a/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +index 10278029..bf3a7b96 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +@@ -1,10 +1,20 @@ + ; RUN: llvm-as %s -o %t.bc + ; Translation shouldn't crash: +-; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spt ++; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV + ; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 + ; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + ++ ++; CHECK-SPIRV: [[#None:]] [[#]] DebugInfoNone ++; CHECK-SPIRV: [[#CompUnit:]] [[#]] DebugCompilationUnit ++; CHECK-SPIRV: [[#EntryFunc:]] [[#]] DebugFunction ++; CHECK-SPIRV: [[#BaseTy:]] [[#]] DebugTypeBasic ++; CHECK-SPIRV: [[#Subrange:]] [[#]] DebugTypeSubrange ++; CHECK-SPIRV: DebugTypeArrayDynamic [[#BaseTy]] [[#]] [[#]] [[#None]] [[#None]] [[#Subrange]] ++; CHECK-SPIRV: DebugEntryPoint [[#EntryFunc]] [[#CompUnit]] [[#]] [[#]] {{$}} ++ + ; CHECK-LLVM: !DICompileUnit(language: DW_LANG_Fortran95 + ; CHECK-LLVM: !DICompositeType(tag: DW_TAG_array_type, baseType: ![[#BaseT:]], size: 32, elements: ![[#Elements:]], dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref, DW_OP_constu, 0, DW_OP_or)) + ; CHECK-LLVM: ![[#BaseT:]] = !DIBasicType(name: "INTEGER*4", size: 32, encoding: DW_ATE_signed) +-- +2.20.1 + diff --git a/patches/0041-Backport-to-15-DebugInfo-Add-NonSemantic.Shader.200-.patch b/patches/0041-Backport-to-15-DebugInfo-Add-NonSemantic.Shader.200-.patch new file mode 100644 index 0000000..7a19357 --- /dev/null +++ b/patches/0041-Backport-to-15-DebugInfo-Add-NonSemantic.Shader.200-.patch @@ -0,0 +1,325 @@ +From 6ac8a508527a705551190b3955ca355328481d0b Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 26 Apr 2023 20:34:10 +0200 +Subject: [PATCH 41/79] [Backport to 15][DebugInfo] Add NonSemantic.Shader.200 + debug operations (#1976) + +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/pull/186 + +The patch also adds Constantness requirement for operands + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 9 ++- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 3 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 126 ++++++++++++++++++----------- + test/DebugInfo/DebugInfoLLVMArg.ll | 22 +++-- + test/DebugInfo/expr-opcode.ll | 7 ++ + 5 files changed, 113 insertions(+), 54 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 38a4502c..a992d373 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1389,7 +1389,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) { + SPIRV::DbgExpressionOpCodeMap::map(DWARFOpCode); + if (OpCountMap.find(OC) == OpCountMap.end()) + report_fatal_error(llvm::Twine("unknown opcode found in DIExpression")); +- if (OC > SPIRVDebug::Fragment && !BM->allowExtraDIExpressions()) ++ if (OC > SPIRVDebug::Fragment && ++ !(BM->allowExtraDIExpressions() || ++ BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200)) + report_fatal_error( + llvm::Twine("unsupported opcode found in DIExpression")); + +@@ -1398,8 +1400,11 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) { + Op[OpCodeIdx] = OC; + if (isNonSemanticDebugInfo()) + transformToConstant(Op, {OpCodeIdx}); +- for (unsigned J = 1; J < OpCount; ++J) ++ for (unsigned J = 1; J < OpCount; ++J) { + Op[J] = Expr->getElement(++I); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Op, {J}); ++ } + auto *Operation = BM->addDebugInfo(SPIRVDebug::Operation, getVoidTy(), Op); + Operations.push_back(Operation->getId()); + } +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 327c2b47..1215886e 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1205,7 +1205,8 @@ MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) { + Operands, OpCodeIdx, DebugInst->getExtSetKind())); + Ops.push_back(SPIRV::DbgExpressionOpCodeMap::rmap(OpCode)); + for (unsigned I = 1, E = Operands.size(); I < E; ++I) { +- Ops.push_back(Operands[I]); ++ Ops.push_back( ++ getConstantValueOrLiteral(Operands, I, DebugInst->getExtSetKind())); + } + } + ArrayRef Addr(Ops.data(), Ops.size()); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 1fc6875a..7809aecf 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -260,23 +260,25 @@ enum ExpressionOpCode { + DerefSize = 146, + XderefSize = 147, + Nop = 148, +- PushObjectAddress = 149, +- Call2 = 150, +- Call4 = 151, +- CallRef = 152, +- FormTlsAddress = 153, +- CallFrameCfa = 154, +- ImplicitValue = 155, +- ImplicitPointer = 156, +- Addrx = 157, +- Constx = 158, +- EntryValue = 159, +- ConstTypeOp = 160, +- RegvalType = 161, +- DerefType = 162, +- XderefType = 163, +- Reinterpret = 164, +- LLVMArg = 165, ++ PushObjectAddress = 149, ++ Call2 = 150, ++ Call4 = 151, ++ CallRef = 152, ++ FormTlsAddress = 153, ++ CallFrameCfa = 154, ++ ImplicitValue = 155, ++ ImplicitPointer = 156, ++ Addrx = 157, ++ Constx = 158, ++ EntryValue = 159, ++ ConstTypeOp = 160, ++ RegvalType = 161, ++ DerefType = 162, ++ XderefType = 163, ++ Reinterpret = 164, ++ LLVMArg = 165, ++ ImplicitPointerTag = 166, ++ TagOffset = 167, + }; + + enum ImportedEntityTag { +@@ -675,15 +677,15 @@ static std::map OpCountMap { + { Constu, 2 }, + { Fragment, 3 }, + { Convert, 3 }, +- // { Addr, 2 }, /* not implemented */ +- // { Const1u, 2 }, +- // { Const1s, 2 }, +- // { Const2u, 2 }, +- // { Const2s, 2 }, +- // { Const4u, 2 }, +- // { Const4s, 2 }, +- // { Const8u, 2 }, +- // { Const8s, 2 }, ++ { Addr, 2 }, ++ { Const1u, 2 }, ++ { Const1s, 2 }, ++ { Const2u, 2 }, ++ { Const2s, 2 }, ++ { Const4u, 2 }, ++ { Const4s, 2 }, ++ { Const8u, 2 }, ++ { Const8s, 2 }, + { Consts, 2 }, + { Dup, 1 }, + { Drop, 1 }, +@@ -702,14 +704,14 @@ static std::map OpCountMap { + { Shr, 1 }, + { Shra, 1 }, + { Xor, 1 }, +- // { Bra, 2 }, /* not implemented */ ++ { Bra, 2 }, + { Eq, 1 }, + { Ge, 1 }, + { Gt, 1 }, + { Le, 1 }, + { Lt, 1 }, + { Ne, 1 }, +- // { Skip, 2 }, /* not implemented */ ++ { Skip, 2 }, + { Lit0, 1 }, + { Lit1, 1 }, + { Lit2, 1 }, +@@ -807,29 +809,31 @@ static std::map OpCountMap { + { Breg30, 2 }, + { Breg31, 2 }, + { Regx, 2 }, +- // { Fbreg, 1 }, /* not implemented */ ++ { Fbreg, 1 }, + { Bregx, 3 }, +- // { Piece, 2 }, /* not implemented */ ++ { Piece, 2 }, + { DerefSize, 2 }, + { XderefSize, 2 }, + { Nop, 1 }, + { PushObjectAddress, 1 }, +- // { Call2, 2 }, /* not implemented */ +- // { Call4, 2 }, +- // { CallRef, 2 }, +- // { FormTlsAddress, 1 }, +- // { CallFrameCfa, 1 }, +- // { ImplicitValue, 3 }, +- // { ImplicitPointer, 3 }, +- // { Addrx, 2 }, +- // { Constx, 2 }, +- // { EntryValue, 3 }, +- // { ConstTypeOp, 4 }, +- // { RegvalType, 3 }, +- // { DerefType, 3 }, +- // { XderefType, 3 }, +- // { Reinterpret, 2 }, ++ { Call2, 2 }, ++ { Call4, 2 }, ++ { CallRef, 2 }, ++ { FormTlsAddress, 1 }, ++ { CallFrameCfa, 1 }, ++ { ImplicitValue, 3 }, ++ { ImplicitPointer, 3 }, ++ { Addrx, 2 }, ++ { Constx, 2 }, ++ { EntryValue, 3 }, ++ { ConstTypeOp, 4 }, ++ { RegvalType, 3 }, ++ { DerefType, 3 }, ++ { XderefType, 3 }, ++ { Reinterpret, 2 }, + { LLVMArg, 2 }, ++ { ImplicitPointerTag, 2 }, ++ { TagOffset, 2 }, + }; + } + +@@ -1121,6 +1125,15 @@ inline void DbgExpressionOpCodeMap::init() { + add(dwarf::DW_OP_constu, SPIRVDebug::Constu); + add(dwarf::DW_OP_LLVM_fragment, SPIRVDebug::Fragment); + add(dwarf::DW_OP_LLVM_convert, SPIRVDebug::Convert); ++ add(dwarf::DW_OP_addr, SPIRVDebug::Addr); ++ add(dwarf::DW_OP_const1u, SPIRVDebug::Const1u); ++ add(dwarf::DW_OP_const1s, SPIRVDebug::Const1s); ++ add(dwarf::DW_OP_const2u, SPIRVDebug::Const2u); ++ add(dwarf::DW_OP_const2s, SPIRVDebug::Const2s); ++ add(dwarf::DW_OP_const4u, SPIRVDebug::Const4u); ++ add(dwarf::DW_OP_const4s, SPIRVDebug::Const4s); ++ add(dwarf::DW_OP_const8u, SPIRVDebug::Const8u); ++ add(dwarf::DW_OP_const8s, SPIRVDebug::Const8s); + add(dwarf::DW_OP_consts, SPIRVDebug::Consts); + add(dwarf::DW_OP_dup, SPIRVDebug::Dup); + add(dwarf::DW_OP_drop, SPIRVDebug::Drop); +@@ -1146,6 +1159,7 @@ inline void DbgExpressionOpCodeMap::init() { + add(dwarf::DW_OP_le, SPIRVDebug::Le); + add(dwarf::DW_OP_lt, SPIRVDebug::Lt); + add(dwarf::DW_OP_ne, SPIRVDebug::Ne); ++ add(dwarf::DW_OP_skip, SPIRVDebug::Skip); + add(dwarf::DW_OP_lit0, SPIRVDebug::Lit0); + add(dwarf::DW_OP_lit1, SPIRVDebug::Lit1); + add(dwarf::DW_OP_lit2, SPIRVDebug::Lit2); +@@ -1244,11 +1258,31 @@ inline void DbgExpressionOpCodeMap::init() { + add(dwarf::DW_OP_breg31, SPIRVDebug::Breg31); + add(dwarf::DW_OP_regx, SPIRVDebug::Regx); + add(dwarf::DW_OP_bregx, SPIRVDebug::Bregx); ++ add(dwarf::DW_OP_piece, SPIRVDebug::Piece); + add(dwarf::DW_OP_deref_size, SPIRVDebug::DerefSize ); + add(dwarf::DW_OP_xderef_size, SPIRVDebug::XderefSize ); + add(dwarf::DW_OP_nop, SPIRVDebug::Nop); + add(dwarf::DW_OP_push_object_address, SPIRVDebug::PushObjectAddress ); +- add(dwarf::DW_OP_LLVM_arg, SPIRVDebug::LLVMArg); ++ ++ ++ add(dwarf::DW_OP_call2, SPIRVDebug::Call2); ++ add(dwarf::DW_OP_call4, SPIRVDebug::Call4); ++ add(dwarf::DW_OP_call_ref, SPIRVDebug::CallRef); ++ add(dwarf::DW_OP_form_tls_address, SPIRVDebug::FormTlsAddress); ++ add(dwarf::DW_OP_call_frame_cfa, SPIRVDebug::CallFrameCfa); ++ add(dwarf::DW_OP_implicit_value, SPIRVDebug::ImplicitValue); ++ add(dwarf::DW_OP_implicit_pointer, SPIRVDebug::ImplicitPointer); ++ add(dwarf::DW_OP_addrx, SPIRVDebug::Addrx); ++ add(dwarf::DW_OP_constx, SPIRVDebug::Constx); ++ add(dwarf::DW_OP_entry_value, SPIRVDebug::EntryValue); ++ add(dwarf::DW_OP_const_type, SPIRVDebug::ConstTypeOp); ++ add(dwarf::DW_OP_regval_type, SPIRVDebug::RegvalType); ++ add(dwarf::DW_OP_deref_type, SPIRVDebug::DerefType); ++ add(dwarf::DW_OP_xderef_type, SPIRVDebug::XderefType); ++ add(dwarf::DW_OP_reinterpret, SPIRVDebug::Reinterpret); ++ add(dwarf::DW_OP_LLVM_arg, SPIRVDebug::LLVMArg); ++ add(dwarf::DW_OP_LLVM_implicit_pointer, SPIRVDebug::ImplicitPointerTag); ++ add(dwarf::DW_OP_LLVM_tag_offset, SPIRVDebug::TagOffset); + } + + typedef SPIRVMap +diff --git a/test/DebugInfo/DebugInfoLLVMArg.ll b/test/DebugInfo/DebugInfoLLVMArg.ll +index a78a04d8..47c7485d 100644 +--- a/test/DebugInfo/DebugInfoLLVMArg.ll ++++ b/test/DebugInfo/DebugInfoLLVMArg.ll +@@ -1,15 +1,27 @@ + ; This test checks that DW_OP_LLVM_arg operation goes through round trip translation correctly. ++; DW_OP_LLVM_arg is mapped on 165 in SPIR-V + + ; RUN: llvm-as %s -o %t.bc + ; RUN: llvm-spirv %t.bc -o %t.spv --spirv-allow-extra-diexpressions + ; RUN: llvm-spirv %t.spv -to-text -o %t.spt +-; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV +-; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: FileCheck < %t.spt %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-OCL ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv %t.spv -to-text -o %t.spt ++; RUN: FileCheck < %t.spt %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-200 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV-200-DAG: TypeInt [[#INT32:]] 32 0 ++; CHECK-SPIRV-200-DAG: Constant [[#INT32]] [[#CONST0:]] 0 ++; CHECK-SPIRV-200-DAG: Constant [[#INT32]] [[#CONST165:]] 165 + ; CHECK-SPIRV: Undef [[#]] [[#UNDEF:]] + ; CHECK-SPIRV: [[#DEBUG_LOC_VAR:]] [[#]] DebugLocalVariable +-; CHECK-SPIRV: [[#EXPR_ARG_0:]] [[#]] DebugOperation 165 0 ++; CHECK-SPIRV-OCL: [[#EXPR_ARG_0:]] [[#]] DebugOperation 165 0 ++; CHECK-SPIRV-200: [[#EXPR_ARG_0:]] [[#]] DebugOperation [[#CONST165]] [[#CONST0]] + ; CHECK-SPIRV: [[#EXPRESSION:]] [[#]] DebugExpression [[#EXPR_ARG_0]] + ; CHECK-SPIRV: [[#EXPR_EMPTY:]] [[#]] DebugExpression{{ *$}} + ; CHECK-SPIRV: Variable [[#]] [[#VAL:]] +@@ -24,9 +36,9 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone spe + define void @DbgIntrinsics() sanitize_memtag { + entry: + %x = alloca i32, align 4 +-; CHECK-LLVM: call void @llvm.dbg.value(metadata !DIArgList(i32* %x), metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_arg, 0)) ++; CHECK-LLVM: call void @llvm.dbg.value(metadata !DIArgList(ptr %x), metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_arg, 0)) + call void @llvm.dbg.value(metadata !DIArgList(i32* %x), metadata !6, metadata !DIExpression(DW_OP_LLVM_arg, 0)), !dbg !10 +-; CHECK-LLVM: call void @llvm.dbg.value(metadata i32* undef, metadata ![[#]], metadata !DIExpression()) ++; CHECK-LLVM: call void @llvm.dbg.value(metadata ptr undef, metadata ![[#]], metadata !DIExpression()) + call void @llvm.dbg.value(metadata !DIArgList(i32* %x, i32* %x), metadata !6, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)), !dbg !10 + store i32 42, i32* %x, align 4 + ret void +diff --git a/test/DebugInfo/expr-opcode.ll b/test/DebugInfo/expr-opcode.ll +index 482d7af8..f9219ba0 100644 +--- a/test/DebugInfo/expr-opcode.ll ++++ b/test/DebugInfo/expr-opcode.ll +@@ -6,6 +6,13 @@ + ; RUN: llc -mtriple=%triple -dwarf-version=5 -filetype=obj -O0 < %t.rev.ll + ; RUN: llc -mtriple=%triple -dwarf-version=4 -filetype=obj -O0 < %t.rev.ll + ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll ++ ++; RUN: llc -mtriple=%triple -dwarf-version=5 -filetype=obj -O0 < %t.rev.ll ++; RUN: llc -mtriple=%triple -dwarf-version=4 -filetype=obj -O0 < %t.rev.ll ++ + ; CHECK: DW_OP_constu, 42 + ; CHECK: DW_OP_plus_uconst, 42 + ; CHECK: DW_OP_plus +-- +2.20.1 + diff --git a/patches/0042-DebugInfo-Translate-inline-namespace-debug-info-1978.patch b/patches/0042-DebugInfo-Translate-inline-namespace-debug-info-1978.patch new file mode 100644 index 0000000..ca4aaa3 --- /dev/null +++ b/patches/0042-DebugInfo-Translate-inline-namespace-debug-info-1978.patch @@ -0,0 +1,163 @@ +From be0f76a6d5287b978cc9d69b2abf8eef720a8bf4 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Thu, 27 Apr 2023 03:00:08 -0700 +Subject: [PATCH 42/79] [DebugInfo] Translate inline namespace debug info + (#1978) + +In NonSemantic.Shader.DebugInfo.200 DebugLexicalBlock has Inline +namespace parameter, which specifies if C/C++ namespace is inline or not. +It allows us to save `exportSymbols` field of `DINamespace` metadata. + +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/pull/186/ +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 6 ++ + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 11 ++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 13 ++-- + .../NonSemantic/Shader200/InlineNamespace.ll | 69 +++++++++++++++++++ + 4 files changed, 91 insertions(+), 8 deletions(-) + create mode 100755 test/DebugInfo/NonSemantic/Shader200/InlineNamespace.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index a992d373..6e5b81dc 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1290,6 +1290,12 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgScope(const DIScope *S) { + Ops[LineIdx] = 0; // This version of DINamespace has no line number + Ops[ColumnIdx] = 0; // This version of DINamespace has no column number + Ops.push_back(BM->getString(NS->getName().str())->getId()); ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ SPIRVValue *ExpConst = BM->addConstant( ++ SPIRVWriter->transType(Type::getInt1Ty(M->getContext())), ++ NS->getExportSymbols() /*Is inlined namespace*/); ++ Ops.push_back(ExpConst->getId()); ++ } + } + if (isNonSemanticDebugInfo()) + transformToConstant(Ops, {LineIdx, ColumnIdx}); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 1215886e..037cb1ab 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -712,10 +712,17 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) { + DIFile *File = getFile(Ops[SourceIdx]); + SPIRVWord LineNo = + getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); +- if (Ops.size() > NameIdx) { ++ if (Ops.size() > MinOperandCount) { + StringRef Name = getString(Ops[NameIdx]); ++ bool InlinedNamespace = false; ++ if (DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ SPIRVValue *V = BM->get(Ops[InlineNamespaceIdx]); ++ Value *Var = SPIRVReader->transValue(V, nullptr, nullptr); ++ InlinedNamespace = cast(Var)->isOne(); ++ } + return getDIBuilder(DebugInst).createNameSpace(ParentScope, Name, +- false /*inlined namespace*/); ++ InlinedNamespace); + } + unsigned Column = Ops[ColumnIdx]; + return getDIBuilder(DebugInst).createLexicalBlock(ParentScope, File, LineNo, +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 7809aecf..dd08563b 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -581,12 +581,13 @@ enum { + + namespace LexicalBlock { + enum { +- SourceIdx = 0, +- LineIdx = 1, +- ColumnIdx = 2, +- ParentIdx = 3, +- NameIdx = 4, +- MinOperandCount = 4 ++ SourceIdx = 0, ++ LineIdx = 1, ++ ColumnIdx = 2, ++ ParentIdx = 3, ++ MinOperandCount = 4, ++ NameIdx = 4, ++ InlineNamespaceIdx = 5, + }; + } + +diff --git a/test/DebugInfo/NonSemantic/Shader200/InlineNamespace.ll b/test/DebugInfo/NonSemantic/Shader200/InlineNamespace.ll +new file mode 100755 +index 00000000..cf1977a6 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/Shader200/InlineNamespace.ll +@@ -0,0 +1,69 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv -spirv-text %t.bc -o %t.spt --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: FileCheck < %t.spt %s -check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -to-binary %t.spt -o %t.spv ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM ++ ++; Source: ++; -- inline-namespace.cxx ----------------------------------------------------- ++; 1 inline namespace Outer { ++; 2 namespace Inner { ++; 3 int global; ++; 4 } ++; 5 } ++; 6 ++; 7 void foo() { ++; 8 Inner::global++; ++; 9 } ++; -- inline-namespace.cxx ----------------------------------------------------- ++ ++; CHECK-SPIRV: String [[#StrOuter:]] "Outer" ++; CHECK-SPIRV: String [[#StrInner:]] "Inner" ++; CHECK-SPIRV: TypeBool [[#TypeBool:]] ++; CHECK-SPIRV: ConstantTrue [[#TypeBool]] [[#ConstTrue:]] ++; CHECK-SPIRV: ConstantFalse [[#TypeBool]] [[#ConstFalse:]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#]] [[#StrOuter]] [[#ConstTrue]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#]] [[#StrInner]] [[#ConstFalse]] ++ ++; CHECK-LLVM: !DINamespace(name: "Inner", scope: ![[#OuterSpace:]]) ++; CHECK-LLVM: ![[#OuterSpace]] = !DINamespace(name: "Outer", scope: null, exportSymbols: true) ++ ++; ModuleID = 'inline-namespace.cxx' ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++@_ZN5Outer5Inner6globalE = dso_local global i32 0, align 4, !dbg !0 ++ ++; Function Attrs: noinline nounwind optnone uwtable mustprogress ++define dso_local void @_Z3foov() #0 !dbg !11 { ++entry: ++ %0 = load i32, i32* @_ZN5Outer5Inner6globalE, align 4, !dbg !14 ++ %inc = add nsw i32 %0, 1, !dbg !14 ++ store i32 %inc, i32* @_ZN5Outer5Inner6globalE, align 4, !dbg !14 ++ ret void, !dbg !15 ++} ++ ++attributes #0 = { noinline nounwind optnone uwtable mustprogress } ++ ++!llvm.dbg.cu = !{!6} ++!llvm.module.flags = !{!9, !10} ++ ++!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) ++!1 = distinct !DIGlobalVariable(name: "global", linkageName: "_ZN5Outer5Inner6globalE", scope: !2, file: !4, line: 3, type: !5, isLocal: false, isDefinition: true) ++!2 = !DINamespace(name: "Inner", scope: !3) ++!3 = !DINamespace(name: "Outer", scope: null, exportSymbols: true) ++!4 = !DIFile(filename: "inlined-namespace.cxx", directory: "/path/to") ++!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !4, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None) ++!7 = !{} ++!8 = !{!0} ++!9 = !{i32 7, !"Dwarf Version", i32 4} ++!10 = !{i32 2, !"Debug Info Version", i32 3} ++!11 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !4, file: !4, line: 7, type: !12, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !7) ++!12 = !DISubroutineType(types: !13) ++!13 = !{null} ++!14 = !DILocation(line: 8, column: 16, scope: !11) ++!15 = !DILocation(line: 9, column: 1, scope: !11) +-- +2.20.1 + diff --git a/patches/0043-DebugInfo-Fix-translation-of-Target-Function-operand.patch b/patches/0043-DebugInfo-Fix-translation-of-Target-Function-operand.patch new file mode 100644 index 0000000..692fbee --- /dev/null +++ b/patches/0043-DebugInfo-Fix-translation-of-Target-Function-operand.patch @@ -0,0 +1,100 @@ +From d0773fa007b057a5dd83762b69c1d85b2e679b3d Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Thu, 27 Apr 2023 11:36:13 -0700 +Subject: [PATCH 43/79] [DebugInfo] Fix translation of Target Function operand + (#1982) + +Before reading Target function name operand of `DebugFunction` we need +to make sure it's the translation of appropriate debug extension. +Otherwise, we can get in a situation, where we do have 11 operands, but +the last one is not a `String` with name, but the `DebugFunctionDeclaration`. +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 13 +++++++++---- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 32 ++++++++++++++++++-------------- + 2 files changed, 27 insertions(+), 18 deletions(-) + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 037cb1ab..46e0daf1 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -745,7 +745,9 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst, + bool IsMainSubprogram) { + using namespace SPIRVDebug::Operand::Function; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +- assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ assert(Ops.size() >= MinOperandCountNonSem && "Invalid number of operands"); ++ if (!isNonSemanticDebugInfo(DebugInst->getExtSetKind())) ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + + StringRef Name = getString(Ops[NameIdx]); + DISubroutineType *Ty = +@@ -781,7 +783,8 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst, + bool IsLocal = SPIRVDebugFlags & SPIRVDebug::FlagIsLocal; + bool IsMainSubprogramFlag = + IsMainSubprogram || +- BM->isEntryPoint(spv::ExecutionModelKernel, Ops[FunctionIdIdx]); ++ (!isNonSemanticDebugInfo(DebugInst->getExtSetKind()) && ++ BM->isEntryPoint(spv::ExecutionModelKernel, Ops[FunctionIdIdx])); + + DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags( + IsLocal, IsDefinition, IsOptimized, DISubprogram::SPFlagNonvirtual, +@@ -820,8 +823,10 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst, + else { + // Create targetFuncName mostly for Fortran trampoline function if it is + // the case +- StringRef TargetFunction; +- if (Ops.size() > MinOperandCount) { ++ StringRef TargetFunction = ""; ++ if (DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200 && ++ Ops.size() > TargetFunctionNameIdx) { + TargetFunction = getString(Ops[TargetFunctionNameIdx]); + } + DIS = getDIBuilder(DebugInst).createFunction( +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index dd08563b..cd181faa 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -543,21 +543,25 @@ enum { + + namespace Function { + enum { +- NameIdx = 0, +- TypeIdx = 1, +- SourceIdx = 2, +- LineIdx = 3, +- ColumnIdx = 4, +- ParentIdx = 5, +- LinkageNameIdx = 6, +- FlagsIdx = 7, +- ScopeLineIdx = 8, +- FunctionIdIdx = 9, +- DeclarationNonSemIdx = 9, +- DeclarationIdx = 10, ++ NameIdx = 0, ++ TypeIdx = 1, ++ SourceIdx = 2, ++ LineIdx = 3, ++ ColumnIdx = 4, ++ ParentIdx = 5, ++ LinkageNameIdx = 6, ++ FlagsIdx = 7, ++ ScopeLineIdx = 8, ++ FunctionIdIdx = 9, ++ DeclarationIdx = 10, ++ MinOperandCount = 10, ++ ++// Only for NonSemantic.Shader.DebugInfo.* ++// No operand FunctionId ++ DeclarationNonSemIdx = 9, ++ MinOperandCountNonSem = 9, + // Only for NonSemantic.Shader.DebugInfo.200 +- TargetFunctionNameIdx = 10, +- MinOperandCount = 10 ++ TargetFunctionNameIdx = 10, + }; + } + +-- +2.20.1 + diff --git a/patches/0044-NFC-DebugInfo-Rewrite-NonSemantic-DebugInfoProducer-.patch b/patches/0044-NFC-DebugInfo-Rewrite-NonSemantic-DebugInfoProducer-.patch new file mode 100644 index 0000000..4a4de88 --- /dev/null +++ b/patches/0044-NFC-DebugInfo-Rewrite-NonSemantic-DebugInfoProducer-.patch @@ -0,0 +1,29 @@ +From 464e30e2c61654a9423a6bebc061a13bfa6a4d91 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 28 Apr 2023 07:29:16 -0700 +Subject: [PATCH 44/79] [NFC][DebugInfo] Rewrite NonSemantic/DebugInfoProducer + test + +There is a bug in -r -spirv-text mode in translation of Strings with spaces. +Temporary avoid running such pipeline until proper fix is delivered. +--- + test/DebugInfo/NonSemantic/DebugInfoProducer.ll | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +index 9de3cc59..49a894f6 100644 +--- a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll ++++ b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +@@ -20,7 +20,8 @@ + ; Check that we don't produce "producer" info for NonSemantic.Shader.DebugInfo.100 as it's not specification conformant + ; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text -o %t.spt + ; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV-100 +-; RUN: llvm-spirv -spirv-text -r -emit-opaque-pointers %t.spt -o %t.rev.bc ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix CHECK-LLVM-100 + + ; ModuleID = 's.bc' +-- +2.20.1 + diff --git a/patches/0045-DebugInfo-Fix-missing-2nd-operand-for-DebugImportedE.patch b/patches/0045-DebugInfo-Fix-missing-2nd-operand-for-DebugImportedE.patch new file mode 100644 index 0000000..f78c217 --- /dev/null +++ b/patches/0045-DebugInfo-Fix-missing-2nd-operand-for-DebugImportedE.patch @@ -0,0 +1,162 @@ +From e7e51bdf150a86bd599af447c3d790493f3f52e7 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Tue, 2 May 2023 14:39:37 +0200 +Subject: [PATCH 45/79] [DebugInfo] Fix missing 2nd operand for + DebugImportedEntity (#1983) + +It will be still missing for OpenCL debug info, but for +NonSemantic the correct behavior is preserved. + +Signed-off-by: Sidorov, Dmitry dmitry.sidorov@intel.com +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 20 +++++++++----- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 26 +++++++++++-------- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 18 ++++++++++++- + .../NonSemantic/Shader200/DIModule.ll | 2 +- + test/DebugInfo/omit-empty.ll | 2 +- + 5 files changed, 47 insertions(+), 21 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 6e5b81dc..946aa71d 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1422,17 +1422,23 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgExpression(const DIExpression *Expr) { + SPIRVEntry * + LLVMToSPIRVDbgTran::transDbgImportedEntry(const DIImportedEntity *IE) { + using namespace SPIRVDebug::Operand::ImportedEntity; +- SPIRVWordVec Ops(OperandCount); + auto Tag = static_cast(IE->getTag()); ++ // FIXME: 'OpenCL/bugged' version is kept because it's hard to remove it ++ // It's W/A for missing 2nd index in OpenCL's implementation ++ const SPIRVWord OffsetIdx = ++ isNonSemanticDebugInfo() ? OperandCount - NonSemantic::OperandCount : 0; ++ SPIRVWordVec Ops(OperandCount - OffsetIdx); + Ops[NameIdx] = BM->getString(IE->getName().str())->getId(); + Ops[TagIdx] = SPIRV::DbgImportedEntityMap::map(Tag); +- Ops[SourceIdx] = getSource(IE->getFile())->getId(); +- Ops[EntityIdx] = transDbgEntry(IE->getEntity())->getId(); +- Ops[LineIdx] = IE->getLine(); +- Ops[ColumnIdx] = 0; // This version of DIImportedEntity has no column number +- Ops[ParentIdx] = getScope(IE->getScope())->getId(); ++ Ops[SourceIdx - OffsetIdx] = getSource(IE->getFile())->getId(); ++ Ops[EntityIdx - OffsetIdx] = transDbgEntry(IE->getEntity())->getId(); ++ Ops[LineIdx - OffsetIdx] = IE->getLine(); ++ // This version of DIImportedEntity has no column number ++ Ops[ColumnIdx - OffsetIdx] = 0; ++ Ops[ParentIdx - OffsetIdx] = getScope(IE->getScope())->getId(); + if (isNonSemanticDebugInfo()) +- transformToConstant(Ops, {TagIdx, LineIdx, ColumnIdx}); ++ transformToConstant(Ops, ++ {TagIdx, LineIdx - OffsetIdx, ColumnIdx - OffsetIdx}); + return BM->addDebugInfo(SPIRVDebug::ImportedEntity, getVoidTy(), Ops); + } + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 46e0daf1..32790095 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1149,12 +1149,20 @@ MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) { + DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::ImportedEntity; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +- assert(Ops.size() >= OperandCount && "Invalid number of operands"); +- DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx])); +- SPIRVWord Line = +- getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); +- DIFile *File = getFile(Ops[SourceIdx]); +- auto *Entity = transDebugInst(BM->get(Ops[EntityIdx])); ++ // FIXME: 'OpenCL/bugged' version is kept because it's hard to remove it ++ // It's W/A for missing 2nd index in OpenCL's implementation ++ const SPIRVWord OffsetIdx = isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ++ ? OperandCount - NonSemantic::OperandCount ++ : 0; ++ ++ assert(Ops.size() == (OperandCount - OffsetIdx) && ++ "Invalid number of operands"); ++ DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx - OffsetIdx])); ++ SPIRVWord Line = getConstantValueOrLiteral(Ops, LineIdx - OffsetIdx, ++ DebugInst->getExtSetKind()); ++ DIFile *File = getFile(Ops[SourceIdx - OffsetIdx]); ++ auto *Entity = ++ transDebugInst(BM->get(Ops[EntityIdx - OffsetIdx])); + SPIRVWord Tag = + getConstantValueOrLiteral(Ops, TagIdx, DebugInst->getExtSetKind()); + if (Tag == SPIRVDebug::ImportedModule) { +@@ -1180,11 +1188,7 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) { + return getDIBuilder(DebugInst).createImportedDeclaration(Scope, Entity, + File, Line, Name); + } +- // FIXME: uncomment and fix following line, with existing bugs it's reachable. +- // llvm_unreachable("Unexpected kind of imported entity!"); +- // Imported entity translation is broken. For example ImportedEntity is +- // missing 2nd parameter. +- return nullptr; ++ llvm_unreachable("Unexpected kind of imported entity!"); + } + + DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) { +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index cd181faa..7ddba0a1 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -843,6 +843,9 @@ static std::map OpCountMap { + } + + namespace ImportedEntity { ++inline namespace OpenCL { ++// it's bugged version, note 2nd index is missing ++// FIXME: need to remove it after some graceful period + enum { + NameIdx = 0, + TagIdx = 1, +@@ -853,7 +856,20 @@ enum { + ParentIdx = 7, + OperandCount = 8 + }; +-} ++} // namespace OpenCL ++namespace NonSemantic { ++enum { ++ NameIdx = 0, ++ TagIdx = 1, ++ SourceIdx = 2, ++ EntityIdx = 3, ++ LineIdx = 4, ++ ColumnIdx = 5, ++ ParentIdx = 6, ++ OperandCount = 7 ++}; ++} // namespace NonSemantic ++} // namespace ImportedEntity + + namespace ModuleINTEL { + enum { +diff --git a/test/DebugInfo/NonSemantic/Shader200/DIModule.ll b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +index fb83dfca..e413c42e 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DIModule.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DIModule.ll +@@ -37,7 +37,7 @@ target triple = "spir64-unknown-unknown" + ; CHECK-SPIRV: ExtInst [[#]] [[#Parent:]] [[#]] DebugCompilationUnit [[#Version]] [[#DWARF]] + ; CHECK-SPIRV: ExtInst [[#]] [[#SourceEmpty:]] [[#]] DebugSource [[#EmptyStr]] + ; CHECK-SPIRV: ExtInst [[#]] [[#Module:]] [[#]] DebugModule [[#Name]] [[#SourceEmpty]] [[#Constant0]] [[#Parent]] [[#Defines]] [[#IncludePath]] [[#ApiNotes]] [[#Constant0]] +-; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugImportedEntity [[#]] [[#]] [[#]] [[#Source]] [[#Module]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugImportedEntity [[#]] [[#]] [[#Source]] [[#Module]] + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!6, !7} +diff --git a/test/DebugInfo/omit-empty.ll b/test/DebugInfo/omit-empty.ll +index 42d0a1ce..edb7dd8f 100644 +--- a/test/DebugInfo/omit-empty.ll ++++ b/test/DebugInfo/omit-empty.ll +@@ -20,7 +20,7 @@ target triple = "spir64-unknown-unknown" + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !6) + !6 = !{!7} +-!7 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !8, entity: !8, file: !1, line: 3) ++!7 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !8, entity: !11, file: !1, line: 3) + !8 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !5, retainedNodes: !2) + !9 = !DISubroutineType(types: !10) + !10 = !{null} +-- +2.20.1 + diff --git a/patches/0046-Restore-DebugInfoProducer.ll-test-to-original-state.patch b/patches/0046-Restore-DebugInfoProducer.ll-test-to-original-state.patch new file mode 100644 index 0000000..5df634e --- /dev/null +++ b/patches/0046-Restore-DebugInfoProducer.ll-test-to-original-state.patch @@ -0,0 +1,91 @@ +From e82ecc2bd7295604fcf1824e47c95fa6a09c6e63 Mon Sep 17 00:00:00 2001 +From: Stanley Gambarin +Date: Fri, 5 May 2023 16:09:13 -0700 +Subject: [PATCH 46/79] Restore DebugInfoProducer.ll test to original state + +--- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 25 +++++++++++-------- + .../NonSemantic/DebugInfoProducer.ll | 2 +- + 2 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index 5733254e..dbfcd9f2 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -1632,8 +1632,9 @@ SPIRVInstruction *SPIRVModuleImpl::addExpectKHRInst(SPIRVType *ResultTy, + // Create AliasDomainDeclINTEL/AliasScopeDeclINTEL/AliasScopeListDeclINTEL + // instructions + template +-SPIRVEntry *SPIRVModuleImpl::getOrAddMemAliasingINTELInst( +- std::vector Args, llvm::MDNode *MD) { ++SPIRVEntry * ++SPIRVModuleImpl::getOrAddMemAliasingINTELInst(std::vector Args, ++ llvm::MDNode *MD) { + assert(MD && "noalias/alias.scope metadata can't be null"); + // Don't duplicate aliasing instruction. For that use a map with a MDNode key + if (AliasInstMDMap.find(MD) != AliasInstMDMap.end()) +@@ -1644,20 +1645,23 @@ SPIRVEntry *SPIRVModuleImpl::getOrAddMemAliasingINTELInst( + } + + // Create AliasDomainDeclINTEL instruction +-SPIRVEntry *SPIRVModuleImpl::getOrAddAliasDomainDeclINTELInst( +- std::vector Args, llvm::MDNode *MD) { ++SPIRVEntry * ++SPIRVModuleImpl::getOrAddAliasDomainDeclINTELInst(std::vector Args, ++ llvm::MDNode *MD) { + return getOrAddMemAliasingINTELInst(Args, MD); + } + + // Create AliasScopeDeclINTEL instruction +-SPIRVEntry *SPIRVModuleImpl::getOrAddAliasScopeDeclINTELInst( +- std::vector Args, llvm::MDNode *MD) { ++SPIRVEntry * ++SPIRVModuleImpl::getOrAddAliasScopeDeclINTELInst(std::vector Args, ++ llvm::MDNode *MD) { + return getOrAddMemAliasingINTELInst(Args, MD); + } + + // Create AliasScopeListDeclINTEL instruction +-SPIRVEntry *SPIRVModuleImpl::getOrAddAliasScopeListDeclINTELInst( +- std::vector Args, llvm::MDNode *MD) { ++SPIRVEntry * ++SPIRVModuleImpl::getOrAddAliasScopeListDeclINTELInst(std::vector Args, ++ llvm::MDNode *MD) { + return getOrAddMemAliasingINTELInst(Args, MD); + } + +@@ -1869,7 +1873,7 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { + } + + if (M.isAllowedToUseExtension( +- ExtensionID::SPV_INTEL_memory_access_aliasing)) { ++ ExtensionID::SPV_INTEL_memory_access_aliasing)) { + O << SPIRVNL() << MI.AliasInstMDVec; + } + +@@ -1894,8 +1898,7 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { + }), + MI.DebugInstVec.end()); + +- O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() +- << MI.FuncVec; ++ O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() << MI.FuncVec; + return O; + } + +diff --git a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +index 49a894f6..dfe1c8ce 100644 +--- a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll ++++ b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +@@ -52,7 +52,7 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + ; CHECK-LLVM-200-NOT: producer: "spirv" + + ; CHECK-LLVM-100: !DICompileUnit +-; CHECK-LLVM-100-SAME: producer: "clang{{.*}}version{{.*}}13.0.0{{.*}}(https://github.com/llvm/llvm-project.git{{.*}}16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-LLVM-100-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" + ; CHECK-LLVM-100-SAME: flags: "-O2" + + ; CHECK-SPIRV-200: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" +-- +2.20.1 + diff --git a/patches/0047-Backport-to-15-Fix-SPIRV-Friendly-IR-mangling-for-op.patch b/patches/0047-Backport-to-15-Fix-SPIRV-Friendly-IR-mangling-for-op.patch new file mode 100644 index 0000000..a6610dd --- /dev/null +++ b/patches/0047-Backport-to-15-Fix-SPIRV-Friendly-IR-mangling-for-op.patch @@ -0,0 +1,188 @@ +From 5be08b8bb91fc6ca62857792c177bc7479e5e3db Mon Sep 17 00:00:00 2001 +From: Mateusz Chudyk +Date: Sun, 4 Jun 2023 20:45:28 +0200 +Subject: [PATCH 47/79] [Backport to 15] Fix SPIRV Friendly IR mangling for + opcodes from cl_khr_integer_do_product (#2014) (#2015) + +--- + lib/SPIRV/SPIRVUtil.cpp | 8 ++++ + .../SPV_KHR_integer_dot_product-nonsat.ll | 45 +++++++++++++++++++ + .../SPV_KHR_integer_dot_product-sat.ll | 45 +++++++++++++++++++ + 3 files changed, 98 insertions(+) + +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 44c03848..1ac4eb62 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -2331,6 +2331,14 @@ public: + case OpSubgroupAvcSicConfigureSkcINTEL: + addUnsignedArgs(0, 4); + break; ++ case OpUDotKHR: ++ case OpUDotAccSatKHR: ++ addUnsignedArg(-1); ++ break; ++ case OpSUDotKHR: ++ case OpSUDotAccSatKHR: ++ addUnsignedArg(1); ++ break; + default:; + // No special handling is needed + } +diff --git a/test/transcoding/SPV_KHR_integer_dot_product-nonsat.ll b/test/transcoding/SPV_KHR_integer_dot_product-nonsat.ll +index a1caf3b4..9a5cc764 100644 +--- a/test/transcoding/SPV_KHR_integer_dot_product-nonsat.ll ++++ b/test/transcoding/SPV_KHR_integer_dot_product-nonsat.ll +@@ -6,6 +6,9 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + ++; RUN: llvm-spirv -r -emit-opaque-pointers --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc.spvir ++; RUN: llvm-dis < %t.rev.bc.spvir | FileCheck %s --check-prefix=CHECK-SPV-IR ++ + ; CHECK-ERROR: Feature requires the following SPIR-V extension: + ; CHECK-ERROR-NEXT: SPV_KHR_integer_dot_product + +@@ -42,6 +45,21 @@ target triple = "spir-unknown-unknown" + ; CHECK-LLVM: call spir_func i32 @_Z21__spirv_SUDotKHR_Rintiii + ; CHECK-LLVM: call spir_func i64 @_Z22__spirv_SUDotKHR_Rlongiii + ++; CHECK-SPV-IR: call spir_func i8 @_Z21__spirv_SDotKHR_Rchariii( ++; CHECK-SPV-IR: call spir_func i16 @_Z22__spirv_SDotKHR_Rshortiii( ++; CHECK-SPV-IR: call spir_func i32 @_Z20__spirv_SDotKHR_Rintiii( ++; CHECK-SPV-IR: call spir_func i64 @_Z21__spirv_SDotKHR_Rlongiii( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z22__spirv_UDotKHR_Rucharjjj( ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_UDotKHR_Rushortjjj( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_UDotKHR_Ruintjjj( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_UDotKHR_Rulongjjj( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z22__spirv_SUDotKHR_Rchariji( ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_SUDotKHR_Rshortiji( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_SUDotKHR_Rintiji( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_SUDotKHR_Rlongiji( ++ + ; CHECK-SPIRV: 6 SDotKHR [[#I8]] [[#]] [[#]] [[#]] 0 + ; CHECK-SPIRV: 6 SDotKHR [[#I16]] [[#]] [[#]] [[#]] 0 + ; CHECK-SPIRV: 6 SDotKHR [[#I32]] [[#]] [[#]] [[#]] 0 +@@ -95,6 +113,21 @@ define spir_kernel void @TestNonSatPacked(i32 %0, i32 %1) #0 !kernel_arg_addr_sp + ; CHECK-LLVM: call spir_func i32 @_Z21__spirv_SUDotKHR_RintDv4_cS_ + ; CHECK-LLVM: call spir_func i64 @_Z22__spirv_SUDotKHR_RlongDv4_cS_ + ++; CHECK-SPV-IR: call spir_func i8 @_Z21__spirv_SDotKHR_RcharDv4_cS_( ++; CHECK-SPV-IR: call spir_func i16 @_Z22__spirv_SDotKHR_RshortDv4_cS_( ++; CHECK-SPV-IR: call spir_func i32 @_Z20__spirv_SDotKHR_RintDv4_cS_( ++; CHECK-SPV-IR: call spir_func i64 @_Z21__spirv_SDotKHR_RlongDv4_cS_( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z22__spirv_UDotKHR_RucharDv4_hS_( ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_UDotKHR_RushortDv4_hS_( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_UDotKHR_RuintDv4_hS_( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_UDotKHR_RulongDv4_hS_( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z22__spirv_SUDotKHR_RcharDv4_cDv4_h( ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_SUDotKHR_RshortDv4_cDv4_h( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_SUDotKHR_RintDv4_cDv4_h( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_SUDotKHR_RlongDv4_cDv4_h( ++ + ; CHECK-SPIRV: 5 SDotKHR [[#I8]] + ; CHECK-SPIRV: 5 SDotKHR [[#I16]] + ; CHECK-SPIRV: 5 SDotKHR [[#I32]] +@@ -145,6 +178,18 @@ define spir_kernel void @TestNonSatVec(<4 x i8> %0, <4 x i8> %1) #0 !kernel_arg_ + ; CHECK-LLVM: call spir_func i32 @_Z21__spirv_SUDotKHR_RintDv2_sS_ + ; CHECK-LLVM: call spir_func i64 @_Z22__spirv_SUDotKHR_RlongDv2_sS_ + ++; CHECK-SPV-IR: call spir_func i16 @_Z22__spirv_SDotKHR_RshortDv2_sS_( ++; CHECK-SPV-IR: call spir_func i32 @_Z20__spirv_SDotKHR_RintDv2_sS_( ++; CHECK-SPV-IR: call spir_func i64 @_Z21__spirv_SDotKHR_RlongDv2_sS_( ++ ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_UDotKHR_RushortDv2_tS_( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_UDotKHR_RuintDv2_tS_( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_UDotKHR_RulongDv2_tS_( ++ ++; CHECK-SPV-IR: call spir_func i16 @_Z23__spirv_SUDotKHR_RshortDv2_sDv2_t( ++; CHECK-SPV-IR: call spir_func i32 @_Z21__spirv_SUDotKHR_RintDv2_sDv2_t( ++; CHECK-SPV-IR: call spir_func i64 @_Z22__spirv_SUDotKHR_RlongDv2_sDv2_t( ++ + ; CHECK-SPIRV: 5 SDotKHR [[#I16]] + ; CHECK-SPIRV: 5 SDotKHR [[#I32]] + ; CHECK-SPIRV: 5 SDotKHR [[#I64]] +diff --git a/test/transcoding/SPV_KHR_integer_dot_product-sat.ll b/test/transcoding/SPV_KHR_integer_dot_product-sat.ll +index 3ba7c94e..e0350b1c 100644 +--- a/test/transcoding/SPV_KHR_integer_dot_product-sat.ll ++++ b/test/transcoding/SPV_KHR_integer_dot_product-sat.ll +@@ -6,6 +6,9 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + ++; RUN: llvm-spirv -r -emit-opaque-pointers --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc.spvir ++; RUN: llvm-dis < %t.rev.bc.spvir | FileCheck %s --check-prefix=CHECK-SPV-IR ++ + ; CHECK-ERROR: Feature requires the following SPIR-V extension: + ; CHECK-ERROR-NEXT: SPV_KHR_integer_dot_product + +@@ -42,6 +45,21 @@ target triple = "spir-unknown-unknown" + ; CHECK-LLVM: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_Rintiiii + ; CHECK-LLVM: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_Rlongiili + ++; CHECK-SPV-IR: call spir_func i8 @_Z27__spirv_SDotAccSatKHR_Rchariici( ++; CHECK-SPV-IR: call spir_func i16 @_Z28__spirv_SDotAccSatKHR_Rshortiisi( ++; CHECK-SPV-IR: call spir_func i32 @_Z26__spirv_SDotAccSatKHR_Rintiiii( ++; CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_SDotAccSatKHR_Rlongiili( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z28__spirv_UDotAccSatKHR_Rucharjjhj( ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_UDotAccSatKHR_Rushortjjtj( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_UDotAccSatKHR_Ruintjjjj( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_UDotAccSatKHR_Rulongjjmj( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z28__spirv_SUDotAccSatKHR_Rcharijci( ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_SUDotAccSatKHR_Rshortijsi( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_Rintijii( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_Rlongijli( ++ + ; CHECK-SPIRV: 7 SDotAccSatKHR [[#I8]] [[#]] [[#]] [[#]] [[#]] 0 + ; CHECK-SPIRV: 7 SDotAccSatKHR [[#I16]] [[#]] [[#]] [[#]] [[#]] 0 + ; CHECK-SPIRV: 7 SDotAccSatKHR [[#I32]] [[#]] [[#]] [[#]] [[#]] 0 +@@ -95,6 +113,21 @@ define spir_kernel void @TestSatPacked(i32 %0, i32 %1, i8 %acc8, i16 %acc16, i32 + ; CHECK-LLVM: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_RintDv4_cS_ + ; CHECK-LLVM: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_RlongDv4_cS_ + ++; CHECK-SPV-IR: call spir_func i8 @_Z27__spirv_SDotAccSatKHR_RcharDv4_cS_c( ++; CHECK-SPV-IR: call spir_func i16 @_Z28__spirv_SDotAccSatKHR_RshortDv4_cS_s( ++; CHECK-SPV-IR: call spir_func i32 @_Z26__spirv_SDotAccSatKHR_RintDv4_cS_i( ++; CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_SDotAccSatKHR_RlongDv4_cS_l( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z28__spirv_UDotAccSatKHR_RucharDv4_hS_h( ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_UDotAccSatKHR_RushortDv4_hS_t( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_UDotAccSatKHR_RuintDv4_hS_j( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_UDotAccSatKHR_RulongDv4_hS_m( ++ ++; CHECK-SPV-IR: call spir_func i8 @_Z28__spirv_SUDotAccSatKHR_RcharDv4_cDv4_hc( ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_SUDotAccSatKHR_RshortDv4_cDv4_hs( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_RintDv4_cDv4_hi( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_RlongDv4_cDv4_hl( ++ + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I8]] + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I16]] + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I32]] +@@ -145,6 +178,18 @@ define spir_kernel void @TestSatVec(<4 x i8> %0, <4 x i8> %1, i8 %acc8, i16 %acc + ; CHECK-LLVM: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_RintDv2_sS_ + ; CHECK-LLVM: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_RlongDv2_sS_ + ++; CHECK-SPV-IR: call spir_func i16 @_Z28__spirv_SDotAccSatKHR_RshortDv2_sS_s( ++; CHECK-SPV-IR: call spir_func i32 @_Z26__spirv_SDotAccSatKHR_RintDv2_sS_i( ++; CHECK-SPV-IR: call spir_func i64 @_Z27__spirv_SDotAccSatKHR_RlongDv2_sS_l( ++ ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_UDotAccSatKHR_RushortDv2_tS_t( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_UDotAccSatKHR_RuintDv2_tS_j( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_UDotAccSatKHR_RulongDv2_tS_m( ++ ++; CHECK-SPV-IR: call spir_func i16 @_Z29__spirv_SUDotAccSatKHR_RshortDv2_sDv2_ts( ++; CHECK-SPV-IR: call spir_func i32 @_Z27__spirv_SUDotAccSatKHR_RintDv2_sDv2_ti( ++; CHECK-SPV-IR: call spir_func i64 @_Z28__spirv_SUDotAccSatKHR_RlongDv2_sDv2_tl( ++ + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I16]] + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I32]] + ; CHECK-SPIRV: 6 SDotAccSatKHR [[#I64]] +-- +2.20.1 + diff --git a/patches/0048-Backport-to-15-NFC-Remove-JointMatrixINTEL-W-S-1658.patch b/patches/0048-Backport-to-15-NFC-Remove-JointMatrixINTEL-W-S-1658.patch new file mode 100644 index 0000000..5222e0e --- /dev/null +++ b/patches/0048-Backport-to-15-NFC-Remove-JointMatrixINTEL-W-S-1658.patch @@ -0,0 +1,591 @@ +From 12dd7b4b0c51373df8d0805201c6d415ad993f3b Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Mon, 24 Oct 2022 22:35:59 +0200 +Subject: [PATCH 48/79] [Backport to 15] [NFC] Remove JointMatrixINTEL W/S + (#1658) + +It's not longer needed after https://github.com/intel/llvm/pull/6535 + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVRegularizeLLVM.cpp | 115 ------------------ + lib/SPIRV/SPIRVRegularizeLLVM.h | 1 - + .../SPV_INTEL_joint_matrix/joint_matrix.ll | 40 +++--- + .../joint_matrix_bfloat16.ll | 25 ++-- + .../joint_matrix_element.ll | 24 ++-- + ...rix_extract_insert_element_of_sycl_half.ll | 16 +-- + .../joint_matrix_half.ll | 34 +++--- + 7 files changed, 63 insertions(+), 192 deletions(-) + +diff --git a/lib/SPIRV/SPIRVRegularizeLLVM.cpp b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +index e1e2f707..443272a0 100644 +--- a/lib/SPIRV/SPIRVRegularizeLLVM.cpp ++++ b/lib/SPIRV/SPIRVRegularizeLLVM.cpp +@@ -347,118 +347,6 @@ Value *SPIRVRegularizeLLVMBase::extendBitInstBoolArg(Instruction *II) { + } + } + +-void SPIRVRegularizeLLVMBase::adaptStructTypes(StructType *ST) { +- if (!ST->hasName()) +- return; +- StringRef STName = ST->getName(); +- STName.consume_front("struct."); +- STName.consume_front("__spv::"); +- StringRef MangledName = STName.substr(0, STName.find('.')); +- +- // Representation in LLVM IR before the translator is a pointer array wrapped +- // in a structure: +- // %struct.__spirv_JointMatrixINTEL = type { [R x [C x [L x [S x type]]]]* } +- // where R = Rows, C = Columnts, L = Layout + 1, S = Scope + 1 +- // this '+1' for the Layout and Scope is required because both of them can +- // be '0', but array size can not be '0'. +- // The result should look like SPIR-V friendly LLVM IR: +- // %spirv.JointMatrixINTEL._char_2_2_0_3 +- // Here we check the structure name yet again. Another option would be to +- // check SPIR-V friendly function calls (by their name) and obtain return +- // or their parameter types, assuming, that the appropriate types are Matrix +- // structure type. But in the near future, we will reuse Composite +- // instructions to do, for example, matrix initialization directly on AMX +- // register by OpCompositeConstruct. And we can't claim, that the Result type +- // of OpCompositeConstruct instruction is always the joint matrix type, it's +- // simply not true. +- if (MangledName == "__spirv_JointMatrixINTEL" && !ST->isOpaquePointerTy()) { +- auto *PtrTy = dyn_cast(ST->getElementType(0)); +- assert(PtrTy && +- "Expected a pointer to an array to represent joint matrix type"); +- std::vector TypeLayout; +- ArrayType *ArrayTy = +- dyn_cast(PtrTy->getNonOpaquePointerElementType()); +- assert(ArrayTy && "Expected a pointer element type of an array type to " +- "represent joint matrix type"); +- TypeLayout.push_back(ArrayTy->getNumElements()); +- for (size_t I = 1; I != 4; ++I) { +- ArrayTy = dyn_cast(ArrayTy->getElementType()); +- assert(ArrayTy && +- "Expected a element type to represent joint matrix type"); +- TypeLayout.push_back(ArrayTy->getNumElements()); +- } +- // JointMatrixINTEL type can have optional 'Use' parameter, which is encoded +- // as another array dimention. In case if it has default 'Unnecessary' (4) +- // parameter - ignore it. +- if (isa(ArrayTy->getElementType())) { +- ArrayTy = cast(ArrayTy->getElementType()); +- uint32_t UseInt = ArrayTy->getNumElements(); +- assert(UseInt <= 4 && "Use parameter encoded in the array must be < 5 "); +- if (UseInt != 4) +- TypeLayout.push_back(UseInt); +- } +- +- auto *ElemTy = ArrayTy->getElementType(); +- std::string ElemTyStr; +- if (ElemTy->isIntegerTy()) { +- auto *IntElemTy = cast(ElemTy); +- switch (IntElemTy->getBitWidth()) { +- case 8: +- ElemTyStr = "char"; +- break; +- case 16: +- ElemTyStr = "short"; +- break; +- case 32: +- ElemTyStr = "int"; +- break; +- case 64: +- ElemTyStr = "long"; +- break; +- default: +- ElemTyStr = "i" + std::to_string(IntElemTy->getBitWidth()); +- } +- } +- // Check half type like this as well, but in DPC++ it most likelly will +- // be a class +- else if (ElemTy->isHalfTy()) +- ElemTyStr = "half"; +- else if (ElemTy->isFloatTy()) +- ElemTyStr = "float"; +- else if (ElemTy->isDoubleTy()) +- ElemTyStr = "double"; +- else { +- // Half type is special: in DPC++ we use `class half` instead of `half` +- // type natively supported by Clang. +- auto *STElemTy = dyn_cast(ElemTy); +- if (!STElemTy && !STElemTy->hasName()) +- llvm_unreachable("Unexpected type for matrix!"); +- if (isSYCLHalfType(ElemTy)) +- ElemTyStr = "half"; +- if (isSYCLBfloat16Type(ElemTy)) +- ElemTyStr = "bfloat16"; +- if (ElemTyStr.size() == 0) +- llvm_unreachable("Unexpected type for matrix!"); +- } +- std::stringstream SPVName; +- SPVName << kSPIRVTypeName::PrefixAndDelim +- << kSPIRVTypeName::JointMatrixINTEL << kSPIRVTypeName::Delimiter +- << kSPIRVTypeName::PostfixDelim << ElemTyStr +- << kSPIRVTypeName::PostfixDelim << std::to_string(TypeLayout[0]) +- << kSPIRVTypeName::PostfixDelim << std::to_string(TypeLayout[1]) +- << kSPIRVTypeName::PostfixDelim << std::to_string(TypeLayout[2] - 1) +- << kSPIRVTypeName::PostfixDelim +- << std::to_string(TypeLayout[3] - 1); +- if (TypeLayout.size() == 5) +- SPVName << kSPIRVTypeName::PostfixDelim +- << std::to_string(TypeLayout[4] - 1); +- // Note, that this structure is not opaque and there is no way to make it +- // opaque but to recreate it entirely and replace it everywhere. Lets +- // keep the structure as is, dealing with it during SPIR-V generation. +- ST->setName(SPVName.str()); +- } +-} +- + bool SPIRVRegularizeLLVMBase::runRegularizeLLVM(Module &Module) { + M = &Module; + Ctx = &M->getContext(); +@@ -623,9 +511,6 @@ bool SPIRVRegularizeLLVMBase::regularize() { + } + } + +- for (StructType *ST : M->getIdentifiedStructTypes()) +- adaptStructTypes(ST); +- + if (SPIRVDbgSaveRegularizedModule) + saveLLVMModule(M, RegularizedModuleTmpFile); + return true; +diff --git a/lib/SPIRV/SPIRVRegularizeLLVM.h b/lib/SPIRV/SPIRVRegularizeLLVM.h +index f8b3d082..1bcb5f07 100644 +--- a/lib/SPIRV/SPIRVRegularizeLLVM.h ++++ b/lib/SPIRV/SPIRVRegularizeLLVM.h +@@ -105,7 +105,6 @@ public: + Value *extendBitInstBoolArg(llvm::Instruction *OldInst); + + static std::string lowerLLVMIntrinsicName(llvm::IntrinsicInst *II); +- void adaptStructTypes(llvm::StructType *ST); + static char ID; + + private: +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll +index 959ea8eb..89c3e217 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll +@@ -1,16 +1,10 @@ + ; RUN: llvm-as < %s -o %t.bc +-; RUN: llvm-spirv %t.bc -s -o %t.pre.bc +-; RUN: llvm-dis %t.pre.bc -o - | FileCheck %s --check-prefix=CHECK-PRE + ; RUN: llvm-spirv %t.bc -spirv-ext=+SPV_INTEL_joint_matrix -o %t.spv + ; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV + + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +-; CHECK-PRE: %spirv.JointMatrixINTEL._short_2_2_0_3 +-; CHECK-PRE: %spirv.JointMatrixINTEL._char_2_16_0_3_0 +-; CHECK-PRE: %spirv.JointMatrixINTEL._char_16_2_3_3 +- + ; CHECK-SPIRV: Capability JointMatrixINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_joint_matrix" + ; CHECK-SPIRV: Name [[#Kernel:]] "_ZTSZ4mainE11matrix_test" +@@ -67,9 +61,9 @@ source_filename = "./joint_matrix_test.cpp" + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" + target triple = "spir64-unknown-unknown" + +-%"struct.__spv::__spirv_JointMatrixINTEL" = type { [2 x [2 x [1 x [4 x [4 x i16]]]]]* } +-%"struct.__spv::__spirv_JointMatrixINTEL.0" = type { [2 x [16 x [1 x [4 x [1 x i8]]]]]* } +-%"struct.__spv::__spirv_JointMatrixINTEL.2" = type { [16 x [2 x [4 x [4 x i8]]]]* } ++%spirv.JointMatrixINTEL._short_2_2_0_3 = type { [2 x [2 x [1 x [4 x [4 x i16]]]]]* } ++%spirv.JointMatrixINTEL._char_2_16_0_3_0 = type { [2 x [16 x [1 x [4 x [1 x i8]]]]]* } ++%spirv.JointMatrixINTEL._char_16_2_3_3 = type { [16 x [2 x [4 x [4 x i8]]]]* } + + $_ZTSZ4mainE11matrix_test = comdat any + +@@ -99,14 +93,14 @@ entry: + %add.ptr.i51 = getelementptr inbounds i16, i16 addrspace(1)* %_arg_, i64 %mul6.i + %add.ptr7.i52 = getelementptr inbounds i16, i16 addrspace(1)* %add.ptr.i51, i64 %sub5.i + %add.ptr7.i = addrspacecast i16 addrspace(1)* %add.ptr7.i52 to i16 addrspace(4)* +- %call8.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i16 addrspace(4)* %add.ptr7.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call8.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i16 addrspace(4)* %add.ptr7.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + %add.ptr11.i53 = getelementptr inbounds i8, i8 addrspace(1)* %_arg_3, i64 %mul6.i + %add.ptr16.i55 = getelementptr inbounds i8, i8 addrspace(1)* %_arg_5, i64 %sub5.i + br label %for.cond.i + + for.cond.i: ; preds = %for.body.i, %entry + %k.0.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] +- %C.0.i = phi %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* [ %call8.i, %entry ], [ %call19.i, %for.body.i ] ++ %C.0.i = phi %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* [ %call8.i, %entry ], [ %call19.i, %for.body.i ] + %cmp.i = icmp ult i32 %k.0.i, 32 + br i1 %cmp.i, label %for.body.i, label %_ZZ4mainENKUlN2cl4sycl7nd_itemILi2EEEE_clES2_.exit + +@@ -114,45 +108,45 @@ for.body.i: ; preds = %for.cond.i + %idx.ext.i = zext i32 %k.0.i to i64 + %add.ptr12.i54 = getelementptr inbounds i8, i8 addrspace(1)* %add.ptr11.i53, i64 %idx.ext.i + %add.ptr12.i = addrspacecast i8 addrspace(1)* %add.ptr12.i54 to i8 addrspace(4)* +- %call13.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm2ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)* %add.ptr12.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call13.i = tail call spir_func %spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm2ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)* %add.ptr12.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + %mul14.i = shl nuw nsw i32 %k.0.i, 5 + %idx.ext15.i = zext i32 %mul14.i to i64 + %add.ptr17.i56 = getelementptr inbounds i8, i8 addrspace(1)* %add.ptr16.i55, i64 %idx.ext15.i + %add.ptr17.i = addrspacecast i8 addrspace(1)* %add.ptr17.i56 to i8 addrspace(4)* +- %call18.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL.2" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm16ELm2ELN5__spv12MatrixLayoutE3ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)* %add.ptr17.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 +- %call19.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* %call13.i, %"struct.__spv::__spirv_JointMatrixINTEL.2" addrspace(4)* %call18.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %C.0.i, i32 3) #3 ++ %call18.i = tail call spir_func %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm16ELm2ELN5__spv12MatrixLayoutE3ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)* %add.ptr17.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call19.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 + %add.i = add nuw nsw i32 %k.0.i, 16 + br label %for.cond.i, !llvm.loop !19 + + _ZZ4mainENKUlN2cl4sycl7nd_itemILi2EEEE_clES2_.exit: ; preds = %for.cond.i +- tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(i16 addrspace(4)* %add.ptr7.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %C.0.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 +- %C.0.i.new = call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z26__spirv_CompositeConstructi(i32 42) #1 ++ tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(i16 addrspace(4)* %add.ptr7.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %C.0.i.new = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z26__spirv_CompositeConstructi(i32 42) #1 + %ref.tmp = alloca i32, align 4 + %ref.tmp.ascast = addrspacecast i32* %ref.tmp to i32 addrspace(4)* + store i32 0, i32 addrspace(4)* %ref.tmp.ascast, align 4 + %zero = load i32, i32 addrspace(4)* %ref.tmp.ascast, align 8 +- %C.0.i.new.load = call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z26__spirv_CompositeConstructi(i32 %zero) #1 ++ %C.0.i.new.load = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z26__spirv_CompositeConstructi(i32 %zero) #1 + + ret void + } + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i16 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i16 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm2ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm2ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL.2" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm16ELm2ELN5__spv12MatrixLayoutE3ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm16ELm2ELN5__spv12MatrixLayoutE3ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL.2" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)*, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(i16 addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(i16 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z26__spirv_CompositeConstructi(i32) #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z26__spirv_CompositeConstructi(i32) #1 + + ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn + declare void @llvm.assume(i1 noundef) #2 +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_bfloat16.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_bfloat16.ll +index 0cf2dd07..a7cd188b 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_bfloat16.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_bfloat16.ll +@@ -11,7 +11,6 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +-; CHECK-REGULARIZED: %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 + ; CHECK-REGULARIZED: %[[Alloca:.*]] = alloca %"class.cl::sycl::ext::intel::experimental::bfloat16", align 2 + ; CHECK-REGULARIZED: %[[ASCast:.*]] = addrspacecast %"class.cl::sycl::ext::intel::experimental::bfloat16"* %[[Alloca]] to %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* + ; CHECK-REGULARIZED: %[[GEP1:.*]] = getelementptr inbounds %"class.cl::sycl::ext::intel::experimental::bfloat16", %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* %[[ASCast]], i64 0, i32 0 +@@ -65,7 +64,7 @@ target triple = "spir64-unknown-unknown" + %"class.cl::sycl::item.0" = type { %"struct.cl::sycl::detail::ItemBase.1" } + %"struct.cl::sycl::detail::ItemBase.1" = type { %"class.cl::sycl::range", %"class.cl::sycl::id" } + %"class.cl::sycl::group" = type { %"class.cl::sycl::range", %"class.cl::sycl::range", %"class.cl::sycl::range", %"class.cl::sycl::id" } +-%"struct.__spv::__spirv_JointMatrixINTEL" = type { [8 x [16 x [1 x [4 x %"class.cl::sycl::ext::intel::experimental::bfloat16"]]]] addrspace(4)* } ++%spirv.JointMatrixINTEL._bfloat16_8_16_0_3 = type opaque + + $_ZZZ17matrix_verify_addIN2cl4sycl3ext5intel12experimental8bfloat16ELm16ELm16EEvNS1_5queueER10big_matrixIT_XT0_EXT1_EERNS1_8nd_rangeILi2EEEfENKUlRNS1_7handlerEE_clESF_ENKUlNS1_7nd_itemILi2EEEE_clESI_ = comdat any + +@@ -101,7 +100,7 @@ entry: + %call.i.i.i = tail call spir_func noundef zeroext i16 @_Z27__spirv_ConvertFToBF16INTELf(float noundef 5.000000e+00) #6 + %value.i.i = getelementptr inbounds %"class.cl::sycl::ext::intel::experimental::bfloat16", %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* %agg.tmp.ascast.i, i64 0, i32 0 + store i16 %call.i.i.i, i16 addrspace(4)* %value.i.i, align 2, !tbaa !9 +- %call.i = tail call spir_func noundef %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z26__spirv_CompositeConstructIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESB_(%"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef nonnull byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %agg.tmp.i) #7 ++ %call.i = tail call spir_func noundef %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* @_Z26__spirv_CompositeConstructIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESB_(%"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef nonnull byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %agg.tmp.i) #7 + call void @llvm.lifetime.end.p0i8(i64 2, i8* nonnull %4) + %ref.tmp.ascast.i = addrspacecast %"class.cl::sycl::ext::intel::experimental::bfloat16"* %ref.tmp.i to %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* + %5 = bitcast %"class.cl::sycl::ext::intel::experimental::bfloat16"* %ref.tmp.i to i8* +@@ -112,10 +111,10 @@ entry: + br label %for.cond + + for.cond: ; preds = %for.body, %entry +- %sub_a.sroa.0.0 = phi %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* [ %call.i, %entry ], [ %call.i58, %for.body ] ++ %sub_a.sroa.0.0 = phi %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* [ %call.i, %entry ], [ %call.i58, %for.body ] + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %conv = zext i32 %i.0 to i64 +- %call.i41 = call spir_func noundef i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEmPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef %sub_a.sroa.0.0) #7 ++ %call.i41 = call spir_func noundef i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEmPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef %sub_a.sroa.0.0) #7 + %cmp = icmp ugt i64 %call.i41, %conv + br i1 %cmp, label %for.body, label %for.cond.cleanup + +@@ -129,13 +128,13 @@ for.cond.cleanup: ; preds = %for.cond + %div = and i64 %sub5, -8 + %add.ptr.i45 = getelementptr inbounds %"class.cl::sycl::ext::intel::experimental::bfloat16", %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(1)* %add.ptr.i, i64 %div + %call.ascast.i = addrspacecast %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(1)* %add.ptr.i45 to %"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* +- call spir_func void @_Z29__spirv_JointMatrixStoreINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEvPT_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEmS7_S9_i(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* noundef %call.ascast.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef %sub_a.sroa.0.0, i64 noundef 16, i32 noundef 0, i32 noundef 3, i32 noundef 0) #7 ++ call spir_func void @_Z29__spirv_JointMatrixStoreINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEvPT_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEmS7_S9_i(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* noundef %call.ascast.i, %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef %sub_a.sroa.0.0, i64 noundef 16, i32 noundef 0, i32 noundef 3, i32 noundef 0) #7 + ret void + + for.body: ; preds = %for.cond + %call.i.i = call spir_func noundef zeroext i16 @_Z27__spirv_ConvertFToBF16INTELf(float noundef 2.000000e+00) #6 + call void @llvm.lifetime.start.p0i8(i64 2, i8* nonnull %5) #8, !noalias !16 +- call spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EET_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* sret(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %ref.tmp.ascast.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef %sub_a.sroa.0.0, i64 noundef %conv) #7, !noalias !16 ++ call spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EET_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* sret(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %ref.tmp.ascast.i, %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef %sub_a.sroa.0.0, i64 noundef %conv) #7, !noalias !16 + %10 = load i16, i16 addrspace(4)* %value.i.i.i, align 2, !tbaa !19, !noalias !20 + %call.i.i.i.i = call spir_func noundef float @_Z27__spirv_ConvertBF16ToFINTELt(i16 noundef zeroext %10) #6, !noalias !20 + %call.i.i3.i.i = call spir_func noundef float @_Z27__spirv_ConvertBF16ToFINTELt(i16 noundef zeroext %call.i.i) #6, !noalias !20 +@@ -144,7 +143,7 @@ for.body: ; preds = %for.cond + call void @llvm.lifetime.end.p0i8(i64 2, i8* nonnull %5) #8, !noalias !16 + call void @llvm.lifetime.start.p0i8(i64 2, i8* nonnull %6) + store i16 %call.i.i4.i.i, i16 addrspace(4)* %8, align 2, !tbaa !19 +- %call.i58 = call spir_func noundef %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESD_SB_m(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef %sub_a.sroa.0.0, %"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef nonnull byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %agg.tmp.i54, i64 noundef %conv) #7 ++ %call.i58 = call spir_func noundef %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESD_SB_m(%spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef %sub_a.sroa.0.0, %"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef nonnull byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2 %agg.tmp.i54, i64 noundef %conv) #7 + call void @llvm.lifetime.end.p0i8(i64 2, i8* nonnull %6) + %inc = add nuw nsw i32 %i.0, 1 + br label %for.cond, !llvm.loop !23 +@@ -157,13 +156,13 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #0 + declare void @llvm.assume(i1 noundef) #3 + + ; Function Attrs: convergent +-declare dso_local spir_func noundef %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z26__spirv_CompositeConstructIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESB_(%"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2) local_unnamed_addr #4 ++declare dso_local spir_func noundef %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* @_Z26__spirv_CompositeConstructIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESB_(%"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2) local_unnamed_addr #4 + + ; Function Attrs: convergent +-declare dso_local spir_func noundef i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEmPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef) local_unnamed_addr #4 ++declare dso_local spir_func noundef i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEmPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef) local_unnamed_addr #4 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EET_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* sret(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef, i64 noundef) local_unnamed_addr #4 ++declare dso_local spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EET_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* sret(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2, %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef, i64 noundef) local_unnamed_addr #4 + + ; Function Attrs: convergent nounwind + declare dso_local spir_func noundef float @_Z27__spirv_ConvertBF16ToFINTELt(i16 noundef zeroext) local_unnamed_addr #5 +@@ -172,10 +171,10 @@ declare dso_local spir_func noundef float @_Z27__spirv_ConvertBF16ToFINTELt(i16 + declare dso_local spir_func noundef zeroext i16 @_Z27__spirv_ConvertFToBF16INTELf(float noundef) local_unnamed_addr #5 + + ; Function Attrs: convergent +-declare dso_local spir_func noundef %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESD_SB_m(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef, %"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2, i64 noundef) local_unnamed_addr #4 ++declare dso_local spir_func noundef %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEPNS6_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESD_SB_m(%spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef, %"class.cl::sycl::ext::intel::experimental::bfloat16"* noundef byval(%"class.cl::sycl::ext::intel::experimental::bfloat16") align 2, i64 noundef) local_unnamed_addr #4 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEvPT_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEmS7_S9_i(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* noundef, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* noundef, i64 noundef, i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #4 ++declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIN2cl4sycl3ext5intel12experimental8bfloat16ELm8ELm16ELN5__spv12MatrixLayoutE0ELNS6_5Scope4FlagE3EEvPT_PNS6_24__spirv_JointMatrixINTELISA_XT0_EXT1_EXT2_EXT3_EEEmS7_S9_i(%"class.cl::sycl::ext::intel::experimental::bfloat16" addrspace(4)* noundef, %spirv.JointMatrixINTEL._bfloat16_8_16_0_3 addrspace(4)* noundef, i64 noundef, i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #4 + + attributes #0 = { argmemonly nofree nosync nounwind willreturn } + attributes #1 = { convergent inlinehint norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll +index 11db9a06..f6519cfd 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll +@@ -29,7 +29,7 @@ target triple = "spir64-unknown-unknown" + %"class.cl::sycl::range" = type { %"class.cl::sycl::detail::array" } + %"class.cl::sycl::detail::array" = type { [1 x i64] } + %"class.cl::sycl::id" = type { %"class.cl::sycl::detail::array" } +-%"struct.__spv::__spirv_JointMatrixINTEL" = type { [16 x [16 x [1 x [4 x float]]]] addrspace(4)* } ++%spirv.JointMatrixINTEL._float_16_16_0_3 = type opaque + + $_ZTSN2cl4sycl6detail23__sycl_service_kernel__16AssertInfoCopierE = comdat any + +@@ -54,43 +54,43 @@ declare extern_weak dso_local spir_func void @__devicelib_assert_read(i8 addrspa + ; Function Attrs: convergent norecurse + define weak_odr dso_local spir_kernel void @_ZTSZZ4mainENKUlRN2cl4sycl7handlerEE_clES2_E6matrix() local_unnamed_addr #0 comdat !kernel_arg_buffer_location !6 { + entry: +- %call9.i.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)* addrspacecast (float addrspace(1)* null to float addrspace(4)*), i64 1, i32 0, i32 3, i32 0) #2 ++ %call9.i.i = tail call spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)* addrspacecast (float addrspace(1)* null to float addrspace(4)*), i64 1, i32 0, i32 3, i32 0) #2 + br label %for.cond.i + + for.cond.i: ; preds = %for.body.i, %entry +- %A.sroa.0.0.i = phi %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* [ %call9.i.i, %entry ], [ %call5.i.i, %for.body.i ] ++ %A.sroa.0.0.i = phi %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* [ %call9.i.i, %entry ], [ %call5.i.i, %for.body.i ] + %i.0.i = phi i32 [ 0, %entry ], [ %inc.i, %for.body.i ] + %conv.i = zext i32 %i.0.i to i64 +- %call.i12.i = tail call spir_func i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEmPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %A.sroa.0.0.i) #2 ++ %call.i12.i = tail call spir_func i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEmPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i) #2 + %cmp.i = icmp ugt i64 %call.i12.i, %conv.i + br i1 %cmp.i, label %for.body.i, label %_ZZZ4mainENKUlRN2cl4sycl7handlerEE_clES2_ENKUlNS0_7nd_itemILi2EEEE_clES5_.exit + + for.body.i: ; preds = %for.cond.i +- %call.i.i = tail call spir_func float @_Z28__spirv_VectorExtractDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmET_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEET4_(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %A.sroa.0.0.i, i64 %conv.i) #2 ++ %call.i.i = tail call spir_func float @_Z28__spirv_VectorExtractDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmET_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEET4_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, i64 %conv.i) #2 + %mul.i.i = fmul float %call.i.i, 5.000000e+00 +- %call5.i.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEES7_T4_S5_(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %A.sroa.0.0.i, float %mul.i.i, i64 %conv.i) #2 ++ %call5.i.i = tail call spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEES7_T4_S5_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, float %mul.i.i, i64 %conv.i) #2 + %inc.i = add nuw nsw i32 %i.0.i, 1 + br label %for.cond.i, !llvm.loop !7 + + _ZZZ4mainENKUlRN2cl4sycl7handlerEE_clES2_ENKUlNS0_7nd_itemILi2EEEE_clES5_.exit: ; preds = %for.cond.i +- tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)* addrspacecast (float addrspace(1)* null to float addrspace(4)*), %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %A.sroa.0.0.i, i64 1, i32 0, i32 3, i32 0) #2 ++ tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)* addrspacecast (float addrspace(1)* null to float addrspace(4)*), %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, i64 1, i32 0, i32 3, i32 0) #2 + ret void + } + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEmPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*) local_unnamed_addr #1 ++declare dso_local spir_func i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEmPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEE(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func float @_Z28__spirv_VectorExtractDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmET_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEET4_(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i64) local_unnamed_addr #1 ++declare dso_local spir_func float @_Z28__spirv_VectorExtractDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmET_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEET4_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*, i64) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEES7_T4_S5_(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, float, i64) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEES7_T4_S5_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*, float, i64) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)*, %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + attributes #0 = { convergent norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="/work/tmp/matrix-slice.cpp" "uniform-work-group-size"="true" } + attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_extract_insert_element_of_sycl_half.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_extract_insert_element_of_sycl_half.ll +index a105dffd..1192be60 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_extract_insert_element_of_sycl_half.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_extract_insert_element_of_sycl_half.ll +@@ -44,8 +44,8 @@ target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256: + target triple = "spir64-unknown-unknown" + + %"class.cl::sycl::detail::half_impl::half" = type { half } +-%"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" = type { %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* } +-%"struct.__spv::__spirv_JointMatrixINTEL" = type { [8 x [16 x [1 x [4 x %"class.cl::sycl::detail::half_impl::half"]]]] addrspace(4)* } ++%"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" = type { %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* } ++%spirv.JointMatrixINTEL._half_8_16_0_3 = type opaque + %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" = type { %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)*, i64 } + + $_ZN2cl4sycl3ext6oneapi12experimental6matrixplERKNS4_10wi_elementINS0_6detail9half_impl4halfELm8ELm16ELNS4_13matrix_layoutE0ENS2_9sub_groupEEERKS8_ = comdat any +@@ -63,11 +63,11 @@ entry: + %M = getelementptr inbounds %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element", %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* %0, i32 0, i32 0 + %1 = load %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)*, %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)* addrspace(4)* %M, align 8, !tbaa !15 + %spvm = getelementptr inbounds %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix", %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)* %1, i32 0, i32 0 +- %2 = load %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* addrspace(4)* %spvm, align 8, !tbaa !13 ++ %2 = load %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)*, %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* addrspace(4)* %spvm, align 8, !tbaa !13 + %3 = load %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)*, %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* addrspace(4)* %lhs.addr.ascast, align 8, !tbaa !8 + %idx = getelementptr inbounds %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element", %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* %3, i32 0, i32 1 + %4 = load i64, i64 addrspace(4)* %idx, align 8, !tbaa !17 +- call spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EET_PNS5_24__spirv_JointMatrixINTELIS9_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* sret(%"class.cl::sycl::detail::half_impl::half") align 2 %ref.tmp1.ascast, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %2, i64 %4) #2 ++ call spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EET_PNS5_24__spirv_JointMatrixINTELIS9_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* sret(%"class.cl::sycl::detail::half_impl::half") align 2 %ref.tmp1.ascast, %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* %2, i64 %4) #2 + ret void + } + +@@ -82,19 +82,19 @@ entry: + %M = getelementptr inbounds %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element", %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* %this1, i32 0, i32 0 + %0 = load %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)*, %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)* addrspace(4)* %M, align 8, !tbaa !15 + %spvm = getelementptr inbounds %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix", %"struct.cl::sycl::ext::oneapi::experimental::matrix::joint_matrix" addrspace(4)* %0, i32 0, i32 0 +- %1 = load %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* addrspace(4)* %spvm, align 8, !tbaa !13 ++ %1 = load %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)*, %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* addrspace(4)* %spvm, align 8, !tbaa !13 + %idx = getelementptr inbounds %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element", %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* %this1, i32 0, i32 1 + %2 = load i64, i64 addrspace(4)* %idx, align 8, !tbaa !17 + %agg.tmp.ascast.ascast = addrspacecast %"class.cl::sycl::detail::half_impl::half" addrspace(4)* %agg.tmp.ascast to %"class.cl::sycl::detail::half_impl::half"* +- %call = call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESC_SA_m(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %1, %"class.cl::sycl::detail::half_impl::half"* byval(%"class.cl::sycl::detail::half_impl::half") align 2 %agg.tmp.ascast.ascast, i64 %2) #2 ++ %call = call spir_func %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESC_SA_m(%spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* %1, %"class.cl::sycl::detail::half_impl::half"* byval(%"class.cl::sycl::detail::half_impl::half") align 2 %agg.tmp.ascast.ascast, i64 %2) #2 + ret %"class.cl::sycl::ext::oneapi::experimental::matrix::wi_element" addrspace(4)* %this1 + } + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESC_SA_m(%"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, %"class.cl::sycl::detail::half_impl::half"* byval(%"class.cl::sycl::detail::half_impl::half") align 2, i64) #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEESC_SA_m(%spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)*, %"class.cl::sycl::detail::half_impl::half"* byval(%"class.cl::sycl::detail::half_impl::half") align 2, i64) #1 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EET_PNS5_24__spirv_JointMatrixINTELIS9_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* sret(%"class.cl::sycl::detail::half_impl::half") align 2, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i64) #1 ++declare dso_local spir_func void @_Z28__spirv_VectorExtractDynamicIN2cl4sycl6detail9half_impl4halfELm8ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EET_PNS5_24__spirv_JointMatrixINTELIS9_XT0_EXT1_EXT2_EXT3_EEEm(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* sret(%"class.cl::sycl::detail::half_impl::half") align 2, %spirv.JointMatrixINTEL._half_8_16_0_3 addrspace(4)*, i64) #1 + + attributes #0 = { convergent mustprogress norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } + attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_half.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_half.ll +index 94aa124c..0b2b5dd0 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_half.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_half.ll +@@ -1,16 +1,10 @@ + ; RUN: llvm-as < %s -o %t.bc +-; RUN: llvm-spirv %t.bc -s -o %t.pre.bc +-; RUN: llvm-dis %t.pre.bc -o - | FileCheck %s --check-prefix=CHECK-PRE + ; RUN: llvm-spirv %t.bc -spirv-ext=+SPV_INTEL_joint_matrix -o %t.spv + ; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV + + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +-; CHECK-PRE: %spirv.JointMatrixINTEL._float_2_2_0_3 +-; CHECK-PRE: %spirv.JointMatrixINTEL._half_2_16_0_3 +-; CHECK-PRE: %spirv.JointMatrixINTEL._half_16_2_3_3 +- + ; CHECK-SPIRV-DAG: TypeFloat [[#FloatTy:]] 32 + ; CHECK-SPIRV-DAG: TypeFloat [[#HalfTy:]] 16 + ; CHECK-SPIRV-DAG: TypeInt [[#IntTy:]] 32 0 +@@ -36,9 +30,9 @@ target triple = "spir64-unknown-unknown" + %"class._ZTSN2cl4sycl6detail5arrayILi1EEE.cl::sycl::detail::array" = type { [1 x i64] } + %"class._ZTSN2cl4sycl2idILi1EEE.cl::sycl::id" = type { %"class._ZTSN2cl4sycl6detail5arrayILi1EEE.cl::sycl::detail::array" } + %"class.cl::sycl::detail::half_impl::half" = type { half } +-%"struct.__spv::__spirv_JointMatrixINTEL" = type { [2 x [2 x [1 x [4 x float]]]]* } +-%"struct.__spv::__spirv_JointMatrixINTEL.0" = type { [2 x [16 x [1 x [4 x %"class.cl::sycl::detail::half_impl::half"]]]]* } +-%"struct.__spv::__spirv_JointMatrixINTEL.1" = type { [16 x [2 x [4 x [4 x %"class.cl::sycl::detail::half_impl::half"]]]]* } ++%spirv.JointMatrixINTEL._float_2_2_0_3 = type opaque ++%spirv.JointMatrixINTEL._half_2_16_0_3 = type opaque ++%spirv.JointMatrixINTEL._half_16_2_3_3 = type opaque + + $_ZTSN2cl4sycl6detail16AssertInfoCopierE = comdat any + +@@ -86,14 +80,14 @@ entry: + %add.ptr.i51 = getelementptr inbounds float, float addrspace(1)* %_arg_, i64 %mul6.i + %add.ptr7.i52 = getelementptr inbounds float, float addrspace(1)* %add.ptr.i51, i64 %sub5.i + %add.ptr7.i = addrspacecast float addrspace(1)* %add.ptr7.i52 to float addrspace(4)* +- %call8.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)* %add.ptr7.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call8.i = tail call spir_func %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)* %add.ptr7.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + %add.ptr11.i53 = getelementptr inbounds %"class.cl::sycl::detail::half_impl::half", %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %_arg_3, i64 %mul6.i + %add.ptr16.i55 = getelementptr inbounds %"class.cl::sycl::detail::half_impl::half", %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %_arg_5, i64 %sub5.i + br label %for.cond.i + + for.cond.i: ; preds = %for.body.i, %entry + %k.0.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] +- %C.0.i = phi %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* [ %call8.i, %entry ], [ %call19.i, %for.body.i ] ++ %C.0.i = phi %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* [ %call8.i, %entry ], [ %call19.i, %for.body.i ] + %cmp.i = icmp ult i32 %k.0.i, 32 + br i1 %cmp.i, label %for.body.i, label %_ZZ4mainENKUlN2cl4sycl7nd_itemILi2EEEE_clES2_.exit + +@@ -101,35 +95,35 @@ for.body.i: ; preds = %for.cond.i + %idx.ext46.i = zext i32 %k.0.i to i64 + %add.ptr12.i54 = getelementptr inbounds %"class.cl::sycl::detail::half_impl::half", %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %add.ptr11.i53, i64 %idx.ext46.i + %add.ptr12.i = addrspacecast %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %add.ptr12.i54 to %"class.cl::sycl::detail::half_impl::half" addrspace(4)* +- %call13.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm2ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* %add.ptr12.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call13.i = tail call spir_func %spirv.JointMatrixINTEL._half_2_16_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm2ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* %add.ptr12.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + %mul14.i = shl nuw nsw i32 %k.0.i, 5 + %idx.ext1547.i = zext i32 %mul14.i to i64 + %add.ptr17.i56 = getelementptr inbounds %"class.cl::sycl::detail::half_impl::half", %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %add.ptr16.i55, i64 %idx.ext1547.i + %add.ptr17.i = addrspacecast %"class.cl::sycl::detail::half_impl::half" addrspace(1)* %add.ptr17.i56 to %"class.cl::sycl::detail::half_impl::half" addrspace(4)* +- %call18.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL.1" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm16ELm2ELN5__spv12MatrixLayoutE3ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* %add.ptr17.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 +- %call19.i = tail call spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIN2cl4sycl6detail9half_impl4halfEfLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS6_3ELS6_0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS9_IT_XT1_EXT2_EXT4_EXT7_EEEPNS9_ISD_XT2_EXT3_EXT5_EXT7_EEESC_S8_(%"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* %call13.i, %"struct.__spv::__spirv_JointMatrixINTEL.1" addrspace(4)* %call18.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %C.0.i, i32 3) #3 ++ %call18.i = tail call spir_func %spirv.JointMatrixINTEL._half_16_2_3_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm16ELm2ELN5__spv12MatrixLayoutE3ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)* %add.ptr17.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ %call19.i = tail call spir_func %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIN2cl4sycl6detail9half_impl4halfEfLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS6_3ELS6_0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS9_IT_XT1_EXT2_EXT4_EXT7_EEEPNS9_ISD_XT2_EXT3_EXT5_EXT7_EEESC_S8_(%spirv.JointMatrixINTEL._half_2_16_0_3 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._half_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 + %add.i = add nuw nsw i32 %k.0.i, 16 + br label %for.cond.i, !llvm.loop !20 + + _ZZ4mainENKUlN2cl4sycl7nd_itemILi2EEEE_clES2_.exit: ; preds = %for.cond.i +- tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)* %add.ptr7.i, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* %C.0.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 ++ tail call spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)* %add.ptr7.i, %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* %C.0.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + ret void + } + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(float addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm2ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._half_2_16_0_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm2ELm16ELN5__spv12MatrixLayoutE0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL.1" addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm16ELm2ELN5__spv12MatrixLayoutE3ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._half_16_2_3_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIN2cl4sycl6detail9half_impl4halfELm16ELm2ELN5__spv12MatrixLayoutE3ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPSA_mS6_S8_i(%"class.cl::sycl::detail::half_impl::half" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIN2cl4sycl6detail9half_impl4halfEfLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS6_3ELS6_0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS9_IT_XT1_EXT2_EXT4_EXT7_EEEPNS9_ISD_XT2_EXT3_EXT5_EXT7_EEESC_S8_(%"struct.__spv::__spirv_JointMatrixINTEL.0" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL.1" addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i32) local_unnamed_addr #1 ++declare dso_local spir_func %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIN2cl4sycl6detail9half_impl4halfEfLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS6_3ELS6_0ELNS5_5Scope4FlagE3EEPNS5_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS9_IT_XT1_EXT2_EXT4_EXT7_EEEPNS9_ISD_XT2_EXT3_EXT5_EXT7_EEESC_S8_(%spirv.JointMatrixINTEL._half_2_16_0_3 addrspace(4)*, %spirv.JointMatrixINTEL._half_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 + + ; Function Attrs: convergent +-declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)*, %"struct.__spv::__spirv_JointMatrixINTEL" addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 ++declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)*, %spirv.JointMatrixINTEL._float_2_2_0_3 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + + ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn + declare void @llvm.assume(i1 noundef) #2 +-- +2.20.1 + diff --git a/patches/0049-Backport-to-15-Split-JointMatrixMadINTEL-instruction.patch b/patches/0049-Backport-to-15-Split-JointMatrixMadINTEL-instruction.patch new file mode 100644 index 0000000..a8e7644 --- /dev/null +++ b/patches/0049-Backport-to-15-Split-JointMatrixMadINTEL-instruction.patch @@ -0,0 +1,154 @@ +From 67f12d5a0ea61a8b577b2bc7ad80dcd99a8eb41c Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Wed, 15 Feb 2023 19:49:45 +0100 +Subject: [PATCH 49/79] [Backport to 15] Split JointMatrixMadINTEL instruction + into 4 (#1833) + +JointMatrixMadINTEL will stand for signed/signed Matrix type +JointMatrixSUMadINTEL will stand for signed/signed Matrix type +JointMatrixUSMadINTEL will stand for unsigned/signed Matrix type +JointMatrixUUMadINTEL will stand for unsigned/unsigned Matrix type + +Spec update: +intel/llvm#8175 + +Signed-off-by: Dmitry Sidorov dmitry.sidorov@intel.com +--- + lib/SPIRV/SPIRVWriter.cpp | 11 +++------- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 3 +++ + lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h | 3 +++ + lib/SPIRV/libSPIRV/spirv_internal.hpp | 6 +++++ + .../SPV_INTEL_joint_matrix/joint_matrix.ll | 22 ++++++++++++++++++- + 5 files changed, 36 insertions(+), 9 deletions(-) + +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index c923642b..cf1482e2 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -606,14 +606,9 @@ SPIRVType *LLVMToSPIRVBase::transPointerType(SPIRVType *ET, unsigned AddrSpc) { + return TranslatedTy; + } + +-// Representation in LLVM IR before the translator is a pointer array wrapped +-// in a structure: +-// %struct.__spirv_JointMatrixINTEL = type { [R x [C x [L x [S x type]]]]* } +-// where R = Rows, C = Columnts, L = Layout + 1, S = Scope + 1 +-// this '+1' for the Layout and Scope is required because both of them can +-// be '0', but array size can not be '0'. +-// The result should look like SPIR-V friendly LLVM IR: +-// %spirv.JointMatrixINTEL._char_2_2_0_3 ++// Representation in LLVM IR before the translator is a pointer to an opaque ++// structure: ++// %spirv.JointMatrixINTEL._%element_type%_%rows%_%cols%_%scope%_%use% + // Here we check the structure name yet again. Another option would be to + // check SPIR-V friendly function calls (by their name) and obtain return + // or their parameter types, assuming, that the appropriate types are Matrix +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 8ee9aaf0..8127717e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3330,6 +3330,9 @@ class SPIRVJointMatrixINTELInst : public SPIRVJointMatrixINTELInstBase { + _SPIRV_OP(JointMatrixLoad, true, 6, true) + _SPIRV_OP(JointMatrixStore, false, 5, true) + _SPIRV_OP(JointMatrixMad, true, 7) ++_SPIRV_OP(JointMatrixSUMad, true, 7) ++_SPIRV_OP(JointMatrixUSMad, true, 7) ++_SPIRV_OP(JointMatrixUUMad, true, 7) + _SPIRV_OP(JointMatrixWorkItemLength, true, 4) + #undef _SPIRV_OP + +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +index ea888d8a..2682f869 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +@@ -9,6 +9,9 @@ _SPIRV_OP_INTERNAL(TypeJointMatrixINTEL, internal::OpTypeJointMatrixINTEL) + _SPIRV_OP_INTERNAL(JointMatrixLoadINTEL, internal::OpJointMatrixLoadINTEL) + _SPIRV_OP_INTERNAL(JointMatrixStoreINTEL, internal::OpJointMatrixStoreINTEL) + _SPIRV_OP_INTERNAL(JointMatrixMadINTEL, internal::OpJointMatrixMadINTEL) ++_SPIRV_OP_INTERNAL(JointMatrixSUMadINTEL, internal::OpJointMatrixSUMadINTEL) ++_SPIRV_OP_INTERNAL(JointMatrixUSMadINTEL, internal::OpJointMatrixUSMadINTEL) ++_SPIRV_OP_INTERNAL(JointMatrixUUMadINTEL, internal::OpJointMatrixUUMadINTEL) + _SPIRV_OP_INTERNAL(JointMatrixWorkItemLengthINTEL, + internal::OpJointMatrixWorkItemLengthINTEL) + _SPIRV_OP_INTERNAL(ComplexFMulINTEL, internal::ComplexFMulINTEL) +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index e03a3e25..c4524196 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -65,6 +65,9 @@ enum InternalOp { + IOpJointMatrixLoadINTEL = 6120, + IOpJointMatrixStoreINTEL = 6121, + IOpJointMatrixMadINTEL = 6122, ++ IOpJointMatrixSUMadINTEL = 6128, ++ IOpJointMatrixUSMadINTEL = 6129, ++ IOpJointMatrixUUMadINTEL = 6130, + IOpArithmeticFenceINTEL = 6145, + IOpJointMatrixWorkItemLengthINTEL = 6410, + IOpComplexFMulINTEL = 6415, +@@ -138,6 +141,9 @@ _SPIRV_OP(Op, TypeJointMatrixINTEL) + _SPIRV_OP(Op, JointMatrixLoadINTEL) + _SPIRV_OP(Op, JointMatrixStoreINTEL) + _SPIRV_OP(Op, JointMatrixMadINTEL) ++_SPIRV_OP(Op, JointMatrixSUMadINTEL) ++_SPIRV_OP(Op, JointMatrixUSMadINTEL) ++_SPIRV_OP(Op, JointMatrixUUMadINTEL) + _SPIRV_OP(Op, JointMatrixWorkItemLengthINTEL) + _SPIRV_OP(Capability, HWThreadQueryINTEL) + _SPIRV_OP(BuiltIn, SubDeviceIDINTEL) +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll +index 89c3e217..9088d739 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix.ll +@@ -34,6 +34,10 @@ + ; CHECK-SPIRV: JointMatrixLoadINTEL [[#ATy]] [[#A:]] [[#Aptr:]] [[#Stride]] [[#Zero]] [[#Three]] [[#Zero]] + ; CHECK-SPIRV: JointMatrixLoadINTEL [[#BTy]] [[#B:]] [[#Bptr:]] [[#Stride]] [[#Zero]] [[#Three]] [[#Zero]] + ; CHECK-SPIRV: JointMatrixMadINTEL [[#CTy]] [[#CMad]] [[#A]] [[#B]] [[#C]] [[#Three]] ++; CHECK-SPIRV: JointMatrixSUMadINTEL [[#CTy]] [[#UnusedMad1:]] [[#A]] [[#B]] [[#C]] [[#Three]] ++; CHECK-SPIRV: JointMatrixUSMadINTEL [[#CTy]] [[#UnusedMad2:]] [[#A]] [[#B]] [[#C]] [[#Three]] ++; CHECK-SPIRV: JointMatrixUUMadINTEL [[#CTy]] [[#UnusedMad3:]] [[#A]] [[#B]] [[#C]] [[#Three]] ++ + ; CHECK-SPIRV: JointMatrixStoreINTEL [[#Cptr:]] [[#C]] [[#Stride]] [[#Zero]] [[#Three]] [[#Zero]] + ; CHECK-SPIRV: CompositeConstruct [[#CTy]] [[#Cnew:]] [[#FortyTwo]] + ; CHECK-SPIRV: Store [[#PtrToZero:]] [[#Zero]] +@@ -49,7 +53,11 @@ + ; CHECK-LLVM: [[C:%.*]] = phi %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [ [[CLoaded]], %entry ], [ [[CMad:%.*]], %for.body.i ] + ; CHECK-LLVM: [[A:%.*]] = call spir_func %spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* @_Z79__spirv_JointMatrixLoadINTEL_RPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS4cliii(i8 addrspace(4)* [[APtr:%.*]], i64 [[Stride]], i32 0, i32 3, i32 0) + ; CHECK-LLVM: [[B:%.*]] = call spir_func %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* @_Z77__spirv_JointMatrixLoadINTEL_RPU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS4cliii(i8 addrspace(4)* [[BPtr:%.*]], i64 [[Stride]], i32 0, i32 3, i32 0) +-; CHECK-LLVM: [[CMad:%.*]] = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z27__spirv_JointMatrixMadINTELPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3i(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* [[A]], %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* [[B]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i32 3) ++; CHECK-LLVM: [[CMad1:%.*]] = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z27__spirv_JointMatrixMadINTELPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3i(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* [[A]], %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* [[B]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i32 3) ++; CHECK-LLVM: [[CMad2:%.*]] = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z29__spirv_JointMatrixSUMadINTELPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3i(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* [[A]], %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* [[B]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i32 3) ++; CHECK-LLVM: [[CMad3:%.*]] = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z29__spirv_JointMatrixUSMadINTELPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3i(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* [[A]], %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* [[B]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i32 3) ++; CHECK-LLVM: [[CMad4:%.*]] = call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z29__spirv_JointMatrixUUMadINTELPU3AS141__spirv_JointMatrixINTEL__char_2_16_0_3_0PU3AS139__spirv_JointMatrixINTEL__char_16_2_3_3PU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3i(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(1)* [[A]], %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(1)* [[B]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i32 3) ++ + ; CHECK-LLVM: call spir_func void @_Z29__spirv_JointMatrixStoreINTELPU3AS4sPU3AS139__spirv_JointMatrixINTEL__short_2_2_0_3liii(i16 addrspace(4)* [[CPtr]], %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* [[C]], i64 [[Stride]], i32 0, i32 3, i32 0) + ; CHECK-LLVM: call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(1)* @_Z26__spirv_CompositeConstructi(i32 42) + ; CHECK-LLVM: store i32 0, i32 addrspace(4)* [[StoredZero:%.*]], align 4 +@@ -115,6 +123,9 @@ for.body.i: ; preds = %for.cond.i + %add.ptr17.i = addrspacecast i8 addrspace(1)* %add.ptr17.i56 to i8 addrspace(4)* + %call18.i = tail call spir_func %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* @_Z28__spirv_JointMatrixLoadINTELIaLm16ELm2ELN5__spv12MatrixLayoutE3ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEEPS5_mS1_S3_i(i8 addrspace(4)* %add.ptr17.i, i64 %_arg_1, i32 0, i32 3, i32 0) #3 + %call19.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 ++ %call20.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixSUMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 ++ %call21.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixUSMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 ++ %call22.i = tail call spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixUUMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)* %call13.i, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* %call18.i, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* %C.0.i, i32 3) #3 + %add.i = add nuw nsw i32 %k.0.i, 16 + br label %for.cond.i, !llvm.loop !19 + +@@ -142,6 +153,15 @@ declare dso_local spir_func %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)* + ; Function Attrs: convergent + declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z27__spirv_JointMatrixMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)*, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 + ++; Function Attrs: convergent ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixSUMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)*, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixUSMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)*, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 ++ ++; Function Attrs: convergent ++declare dso_local spir_func %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)* @_Z29__spirv_JointMatrixUUMadINTELIasLm2ELm16ELm2ELN5__spv12MatrixLayoutE0ELS1_3ELS1_0ELNS0_5Scope4FlagE3EEPNS0_24__spirv_JointMatrixINTELIT0_XT1_EXT3_EXT6_EXT7_EEEPNS4_IT_XT1_EXT2_EXT4_EXT7_EEEPNS4_IS8_XT2_EXT3_EXT5_EXT7_EEES7_S3_(%spirv.JointMatrixINTEL._char_2_16_0_3_0 addrspace(4)*, %spirv.JointMatrixINTEL._char_16_2_3_3 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i32) local_unnamed_addr #1 ++ + ; Function Attrs: convergent + declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIsLm2ELm2ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(i16 addrspace(4)*, %spirv.JointMatrixINTEL._short_2_2_0_3 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + +-- +2.20.1 + diff --git a/patches/0050-DebugInfo-Support-translation-of-DebugSourceContinue.patch b/patches/0050-DebugInfo-Support-translation-of-DebugSourceContinue.patch new file mode 100644 index 0000000..29aa181 --- /dev/null +++ b/patches/0050-DebugInfo-Support-translation-of-DebugSourceContinue.patch @@ -0,0 +1,413 @@ +From b587d7eec52a0772b77c39a0aee685ec76ce0491 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 5 May 2023 02:29:41 -0700 +Subject: [PATCH 50/79] [DebugInfo] Support translation of DebugSourceContinued + (#1993) + +Max length of SPIRV instruction is 65535 words by specification. +DebugSourceContinued helps to overcome the limitation and specify full source code text by continuing the string from the previous DebugSource(Continued)instruction. + +Spec: +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugSourceContinued +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 41 ++++++++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 46 +++++++++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 8 ++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 14 +++-- + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 1 + + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 21 +++++++- + lib/SPIRV/libSPIRV/SPIRVStream.cpp | 22 ++++++++ + lib/SPIRV/libSPIRV/SPIRVStream.h | 1 + + .../NonSemantic/DebugSourceContinued.ll | 52 +++++++++++++++++++ + .../NonSemantic/Shader200/FortranArray.ll | 2 +- + 10 files changed, 186 insertions(+), 22 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/DebugSourceContinued.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 946aa71d..7b4ce6c5 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1341,17 +1341,44 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + return It->second; + + using namespace SPIRVDebug::Operand::Source; +- SPIRVWordVec Ops(OperandCount); ++ SPIRVWordVec Ops(MinOperandCount); + Ops[FileIdx] = BM->getString(FileName)->getId(); + DIFile *F = DIEntry ? DIEntry->getFile() : nullptr; +- if (F && F->getRawChecksum()) { ++ ++ if (F && F->getRawChecksum() && !isNonSemanticDebugInfo()) { + auto CheckSum = F->getChecksum().getValue(); +- Ops[TextIdx] = BM->getString("//__" + CheckSum.getKindAsString().str() + +- ":" + CheckSum.Value.str()) +- ->getId(); +- } else { +- Ops[TextIdx] = getDebugInfoNone()->getId(); ++ Ops.push_back(BM->getString("//__" + CheckSum.getKindAsString().str() + ++ ":" + CheckSum.Value.str()) ++ ->getId()); + } ++ ++ if (F && F->getRawSource() && isNonSemanticDebugInfo()) { ++ std::string Str = F->getSource().getValue().str(); ++ constexpr size_t MaxNumWords = ++ MaxWordCount - 2 /*Fixed WC for SPIRVString*/; ++ constexpr size_t MaxStrSize = MaxNumWords * 4 - 1; ++ const size_t NumWords = getSizeInWords(Str); ++ ++ Ops.push_back(BM->getString(Str.substr(0, MaxStrSize))->getId()); ++ SPIRVExtInst *Source = static_cast( ++ BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops)); ++ FileMap[FileName] = Source; ++ Str.erase(0, MaxStrSize); ++ ++ // No need to generate source continued instructions ++ if (NumWords < MaxNumWords) ++ return Source; ++ ++ uint64_t NumOfContinuedInstructions = ++ NumWords / MaxNumWords - 1 + (NumWords % MaxNumWords ? 1 : 0); ++ for (uint64_t J = 0; J < NumOfContinuedInstructions; J++) { ++ SPIRVWord Op = BM->getString(Str.substr(0, MaxStrSize))->getId(); ++ BM->addDebugInfo(SPIRVDebug::SourceContinued, getVoidTy(), {Op}); ++ Str.erase(0, MaxStrSize); ++ } ++ return Source; ++ } ++ + SPIRVExtInst *Source = static_cast( + BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops)); + FileMap[FileName] = Source; +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 32790095..5d58e81e 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -77,14 +77,21 @@ void SPIRVToLLVMDbgTran::addDbgInfoVersion() { + + DIFile * + SPIRVToLLVMDbgTran::getDIFile(const std::string &FileName, +- Optional> CS) { ++ Optional> CS, ++ Optional Source) { + return getOrInsert(FileMap, FileName, [=]() { + SplitFileName Split(FileName); + // Use the first builder from the map to crete DIFile since it's + // relations with other debug metadata is not going through DICompileUnit +- if (!Split.BaseName.empty()) ++ if (!Split.BaseName.empty()) { ++ if (Source.hasValue()) { ++ StringRef SourceRef = StringRef(Source.getValue()); ++ return BuilderMap.begin()->second->createFile( ++ Split.BaseName, Split.Path, CS, SourceRef); ++ } + return BuilderMap.begin()->second->createFile(Split.BaseName, Split.Path, + CS); ++ } + return static_cast(nullptr); + }); + } +@@ -134,6 +141,19 @@ const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { + return String->getStr(); + } + ++Optional ++SPIRVToLLVMDbgTran::getStringContinued(const SPIRVId Id, ++ SPIRVExtInst *DebugInst) { ++ std::string Str = BM->get(Id)->getStr(); ++ using namespace SPIRVDebug::Operand::SourceContinued; ++ for (auto *I : DebugInst->getContinuedInstructions()) { ++ std::string TmpStr = ++ BM->get(I->getArguments()[TextIdx])->getStr(); ++ Str.append(TmpStr); ++ } ++ return Str; ++} ++ + void SPIRVToLLVMDbgTran::transDbgInfo(const SPIRVValue *SV, Value *V) { + // A constant sampler does not have a corresponding SPIRVInstruction. + if (SV->getOpCode() == OpConstantSampler) +@@ -1327,6 +1347,7 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + + case SPIRVDebug::Operation: // To be translated with transExpression + case SPIRVDebug::Source: // To be used by other instructions ++ case SPIRVDebug::SourceContinued: + return nullptr; + + case SPIRVDebug::Expression: +@@ -1454,12 +1475,21 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + assert(Source->getExtOp() == SPIRVDebug::Source && + "DebugSource instruction is expected"); + SPIRVWordVec SourceArgs = Source->getArguments(); +- assert(SourceArgs.size() == OperandCount && "Invalid number of operands"); +- std::string ChecksumStr = +- getDbgInst(SourceArgs[TextIdx]) +- ? "" +- : getString(SourceArgs[TextIdx]); +- return getDIFile(getString(SourceArgs[FileIdx]), ParseChecksum(ChecksumStr)); ++ assert(SourceArgs.size() >= MinOperandCount && "Invalid number of operands"); ++ if (SourceArgs.size() == MinOperandCount) ++ return getDIFile(getString(SourceArgs[FileIdx])); ++ ++ if (!isNonSemanticDebugInfo(Source->getExtSetKind())) { ++ std::string ChecksumStr = ++ getDbgInst(SourceArgs[TextIdx]) ++ ? "" ++ : getString(SourceArgs[TextIdx]); ++ return getDIFile(getString(SourceArgs[FileIdx]), ++ ParseChecksum(ChecksumStr)); ++ } ++ ++ return getDIFile(getString(SourceArgs[FileIdx]), None, ++ getStringContinued(SourceArgs[TextIdx], Source)); + } + + DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index c8929300..14acaf48 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -89,8 +89,10 @@ public: + + private: + DIFile *getFile(const SPIRVId SourceId); +- DIFile *getDIFile(const std::string &FileName, +- Optional> CS = None); ++ DIFile * ++ getDIFile(const std::string &FileName, ++ Optional> CS = None, ++ Optional Source = None); + DIFile *getDIFile(const SPIRVEntry *E); + unsigned getLineNo(const SPIRVEntry *E); + +@@ -195,6 +197,8 @@ private: + return nullptr; + } + const std::string &getString(const SPIRVId Id); ++ Optional getStringContinued(const SPIRVId Id, ++ SPIRVExtInst *DebugInst); + SPIRVWord getConstantValueOrLiteral(const std::vector &, + const SPIRVWord, + const SPIRVExtInstSetKind); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 7ddba0a1..1ca7ee07 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -55,6 +55,7 @@ enum Instruction { + ModuleINTEL = 36, + InstCount = 37, + FunctionDefinition = 101, ++ SourceContinued = 102, + EntryPoint = 107, + Module = 200, + TypeSubrange = 201, +@@ -302,9 +303,9 @@ enum { + + namespace Source { + enum { +- FileIdx = 0, +- TextIdx = 1, +- OperandCount = 2 ++ FileIdx = 0, ++ TextIdx = 1, ++ MinOperandCount = 1 + }; + } + +@@ -573,6 +574,13 @@ enum { + }; + } + ++namespace SourceContinued { ++enum { ++ TextIdx = 0, ++ OperandCount = 1 ++}; ++} ++ + namespace EntryPoint { + enum { + EntryPointIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index b4dd9027..fc16a994 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -261,6 +261,7 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::Expression, "DebugExpression"); + add(SPIRVDebug::Operation, "DebugOperation"); + add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition"); ++ add(SPIRVDebug::SourceContinued, "DebugSourceContinued"); + add(SPIRVDebug::EntryPoint, "DebugEntryPoint"); + } + SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 8127717e..f7b57d08 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -1757,6 +1757,14 @@ public: + + SPIRVExtInstSetKind getExtSetKind() const { return ExtSetKind; } + ++ void addContinuedInstruction(SPIRVExtInst *Inst) { ++ ContinuedInstructions.push_back(Inst); ++ } ++ ++ std::vector getContinuedInstructions() { ++ return ContinuedInstructions; ++ } ++ + void setExtSetKindById() { + assert(Module && "Invalid module"); + ExtSetKind = Module->getBuiltinSet(ExtSetId); +@@ -1801,7 +1809,17 @@ public: + assert(0 && "not supported"); + getDecoder(I) >> ExtOp; + } +- getDecoder(I) >> Args; ++ SPIRVDecoder Decoder = getDecoder(I); ++ Decoder >> Args; ++ ++ if (ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || ++ ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ if (getExtOp() == SPIRVDebug::Instruction::Source) { ++ for (SPIRVEntry *E : Decoder.getSourceContinuedInstructions()) { ++ addContinuedInstruction(static_cast(E)); ++ } ++ } ++ } + } + void validate() const override { + SPIRVFunctionCallGeneric::validate(); +@@ -1850,6 +1868,7 @@ protected: + OCLExtOpKind ExtOpOCL; + SPIRVDebugExtOpKind ExtOpDebug; + }; ++ std::vector ContinuedInstructions; + }; + + class SPIRVCompositeConstruct : public SPIRVInstruction { +diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.cpp b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +index 8a9e0a48..18fef3da 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVStream.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +@@ -39,6 +39,7 @@ + #include "SPIRVStream.h" + #include "SPIRVDebug.h" + #include "SPIRVFunction.h" ++#include "SPIRVInstruction.h" + #include "SPIRVNameMapEnum.h" + #include "SPIRVOpCode.h" + +@@ -331,4 +332,25 @@ SPIRVDecoder::getContinuedInstructions(const spv::Op ContinuedOpCode) { + return ContinuedInst; + } + ++std::vector SPIRVDecoder::getSourceContinuedInstructions() { ++ std::vector ContinuedInst; ++ std::streampos Pos = IS.tellg(); // remember position ++ getWordCountAndOpCode(); ++ while (OpCode == OpExtInst) { ++ SPIRVEntry *Entry = getEntry(); ++ assert(Entry && "Failed to decode entry! Invalid instruction!"); ++ SPIRVExtInst *Inst = static_cast(Entry); ++ if (Inst->getExtOp() != SPIRVDebug::Instruction::SourceContinued) { ++ IS.seekg(Pos); // restore position ++ return ContinuedInst; ++ } ++ M.add(Entry); ++ ContinuedInst.push_back(Entry); ++ Pos = IS.tellg(); ++ getWordCountAndOpCode(); ++ } ++ IS.seekg(Pos); // restore position ++ return ContinuedInst; ++} ++ + } // namespace SPIRV +diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.h b/lib/SPIRV/libSPIRV/SPIRVStream.h +index 0577db14..9f746284 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVStream.h ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.h +@@ -78,6 +78,7 @@ public: + void ignoreInstruction(); + std::vector + getContinuedInstructions(const spv::Op ContinuedOpCode); ++ std::vector getSourceContinuedInstructions(); + + std::istream &IS; + SPIRVModule &M; +diff --git a/test/DebugInfo/NonSemantic/DebugSourceContinued.ll b/test/DebugInfo/NonSemantic/DebugSourceContinued.ll +new file mode 100644 +index 00000000..732b6c0c +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/DebugSourceContinued.ll +@@ -0,0 +1,52 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; CHECK-LLVM: !DIFile(filename: "t.c", directory: "/test", source: "A ++; CHECK-LLVM-SAME-COUNT-200000: A ++; CHECK-LLVM-SAME: MayThe4thBeWithYou ++; CHECK-LLVM-SAME-COUNT-330000: A ++ ++; CHECK-SPIRV: String [[#Str:]] "A ++; CHECK-SPIRV-SAME-COUNT-19999: A ++; CHECK-SPIRV-SAME: MayThe4thBeWithYou ++; CHECK-SPIRV-SAME-COUNT-62113: A ++; CHECK-SPIRV: String [[#Str2:]] "A ++; CHECK-SPIRV-SAME-COUNT-262130: A ++; CHECK-SPIRV: String [[#Str3:]] "A ++; CHECK-SPIRV-SAME-COUNT-5755: A ++; CHECK-SPIRV: DebugSource [[#]] [[#Str]] ++; CHECK-SPIRV: DebugSourceContinued [[#Str2]] ++; CHECK-SPIRV: DebugSourceContinued [[#Str3]] ++ ++; ModuleID = 't.c' ++source_filename = "t.c" ++;target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64" ++ ++@t1 = global i32 1, align 4, !dbg !0 ++@t2 = global i32 0, align 4, !dbg !6 ++ ++!llvm.dbg.cu = !{!2} ++!llvm.module.flags = !{!11, !12, !13} ++!llvm.ident = !{!14} ++ ++!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) ++!1 = distinct !DIGlobalVariable(name: "t1", scope: !2, file: !10, line: 1, type: !9, isLocal: false, isDefinition: true) ++!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 322159)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) ++!3 = !DIFile(filename: "t.c", directory: "/test", source: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMayThe4thBeWithYouAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") ++!4 = !{} ++!5 = !{!0, !6} ++!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) ++!7 = distinct !DIGlobalVariable(name: "t2", scope: !2, file: !8, line: 1, type: !9, isLocal: false, isDefinition: true) ++!8 = !DIFile(filename: "t2.h", directory: "/test", source: "22222222222222222222222222222222") ++!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!10 = !DIFile(filename: "t1.h", directory: "/test", source: "11111111111111111111111111111111") ++!11 = !{i32 2, !"Dwarf Version", i32 4} ++!12 = !{i32 2, !"Debug Info Version", i32 3} ++!13 = !{i32 1, !"wchar_size", i32 4} ++!14 = !{!"clang version 7.0.0 (trunk 322159)"} +diff --git a/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +index bf3a7b96..9aed141b 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/FortranArray.ll +@@ -7,8 +7,8 @@ + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + + +-; CHECK-SPIRV: [[#None:]] [[#]] DebugInfoNone + ; CHECK-SPIRV: [[#CompUnit:]] [[#]] DebugCompilationUnit ++; CHECK-SPIRV: [[#None:]] [[#]] DebugInfoNone + ; CHECK-SPIRV: [[#EntryFunc:]] [[#]] DebugFunction + ; CHECK-SPIRV: [[#BaseTy:]] [[#]] DebugTypeBasic + ; CHECK-SPIRV: [[#Subrange:]] [[#]] DebugTypeSubrange +-- +2.20.1 + diff --git a/patches/0051-DebugInfo-Fix-translation-of-DebugSource-Text-argume.patch b/patches/0051-DebugInfo-Fix-translation-of-DebugSource-Text-argume.patch new file mode 100644 index 0000000..2e937fb --- /dev/null +++ b/patches/0051-DebugInfo-Fix-translation-of-DebugSource-Text-argume.patch @@ -0,0 +1,28 @@ +From 09942e855533e55630c2991f2a2964c8b04d13f1 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Tue, 9 May 2023 10:40:14 -0700 +Subject: [PATCH 51/79] [DebugInfo] Fix translation of DebugSource Text + argument (#2003) + +Handle the case when we have `DebugInfoNone` for the Text argument +which is usually expected to be `OpString`. +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 5d58e81e..fcbf47e0 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -144,6 +144,8 @@ const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { + Optional + SPIRVToLLVMDbgTran::getStringContinued(const SPIRVId Id, + SPIRVExtInst *DebugInst) { ++ if (getDbgInst(Id)) ++ return std::string(); + std::string Str = BM->get(Id)->getStr(); + using namespace SPIRVDebug::Operand::SourceContinued; + for (auto *I : DebugInst->getContinuedInstructions()) { +-- +2.20.1 + diff --git a/patches/0052-DebugInfo-Translate-checksum-info-inside-DebugSource.patch b/patches/0052-DebugInfo-Translate-checksum-info-inside-DebugSource.patch new file mode 100644 index 0000000..5acabf6 --- /dev/null +++ b/patches/0052-DebugInfo-Translate-checksum-info-inside-DebugSource.patch @@ -0,0 +1,321 @@ +From d9b00f00195f2dd53da16962790f25d6fcdfd6ac Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 19 May 2023 06:16:07 -0700 +Subject: [PATCH 52/79] [DebugInfo] Translate checksum info inside DebugSource + instruction (#1996) + +It's done in scope of NonSemantic.Shader.200.DebugInfo spec to have a +proper solution for translation of checksum info (instead of the W/A +done for OpenCL DebugInfo spec in #936) +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 26 +++++++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 34 +++++++++++++++---- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 4 +-- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 23 ++++++++++++- + test/DebugInfo/DebugInfoChecksum.ll | 22 +++++++++--- + .../DebugInfo/DebugInfoChecksumCompileUnit.ll | 25 +++++++++++--- + .../NonSemantic/DebugSourceContinued.ll | 13 +++++-- + 7 files changed, 121 insertions(+), 26 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 7b4ce6c5..753b1a22 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1345,11 +1345,24 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + Ops[FileIdx] = BM->getString(FileName)->getId(); + DIFile *F = DIEntry ? DIEntry->getFile() : nullptr; + +- if (F && F->getRawChecksum() && !isNonSemanticDebugInfo()) { ++ if (F && F->getRawChecksum()) { + auto CheckSum = F->getChecksum().getValue(); +- Ops.push_back(BM->getString("//__" + CheckSum.getKindAsString().str() + +- ":" + CheckSum.Value.str()) +- ->getId()); ++ ++ if (!isNonSemanticDebugInfo()) ++ Ops.push_back(BM->getString("//__" + CheckSum.getKindAsString().str() + ++ ":" + CheckSum.Value.str()) ++ ->getId()); ++ else if (BM->getDebugInfoEIS() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ SPIRVDebug::FileChecksumKind ChecksumKind = ++ SPIRV::DbgChecksumKindMap::map(CheckSum.Kind); ++ ++ Ops.push_back( ++ BM->addIntegerConstant(static_cast(getInt32Ty()), ++ ChecksumKind) ++ ->getId()); ++ Ops.push_back(BM->getString(CheckSum.Value.str())->getId()); ++ } + } + + if (F && F->getRawSource() && isNonSemanticDebugInfo()) { +@@ -1359,6 +1372,11 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + constexpr size_t MaxStrSize = MaxNumWords * 4 - 1; + const size_t NumWords = getSizeInWords(Str); + ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200 && ++ Ops.size() == MinOperandCount) { ++ Ops.push_back(getDebugInfoNoneId()); ++ Ops.push_back(getDebugInfoNoneId()); ++ } + Ops.push_back(BM->getString(Str.substr(0, MaxStrSize))->getId()); + SPIRVExtInst *Source = static_cast( + BM->addDebugInfo(SPIRVDebug::Source, getVoidTy(), Ops)); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index fcbf47e0..40ad90d0 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -141,11 +141,11 @@ const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { + return String->getStr(); + } + +-Optional +-SPIRVToLLVMDbgTran::getStringContinued(const SPIRVId Id, +- SPIRVExtInst *DebugInst) { +- if (getDbgInst(Id)) +- return std::string(); ++const std::string ++SPIRVToLLVMDbgTran::getStringSourceContinued(const SPIRVId Id, ++ SPIRVExtInst *DebugInst) { ++ if (!isValidId(Id) || getDbgInst(Id)) ++ return ""; + std::string Str = BM->get(Id)->getStr(); + using namespace SPIRVDebug::Operand::SourceContinued; + for (auto *I : DebugInst->getContinuedInstructions()) { +@@ -1490,8 +1490,28 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + ParseChecksum(ChecksumStr)); + } + +- return getDIFile(getString(SourceArgs[FileIdx]), None, +- getStringContinued(SourceArgs[TextIdx], Source)); ++ Optional> CS; ++ SPIRVWord StrIdx = SourceArgs[TextIdx]; ++ if (Source->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { ++ if (!getDbgInst(SourceArgs[ChecksumKind]) && ++ !getDbgInst(SourceArgs[ChecksumValue])) { ++ llvm::DIFile::ChecksumKind Kind = SPIRV::DbgChecksumKindMap::rmap( ++ static_cast( ++ BM->get(SourceArgs[ChecksumKind]) ++ ->getZExtIntValue())); ++ StringRef Checksum = getString(SourceArgs[ChecksumValue]); ++ size_t ChecksumEndPos = Checksum.find_if_not(llvm::isHexDigit); ++ CS.emplace(Kind, Checksum.substr(0, ChecksumEndPos)); ++ } ++ ++ if (SourceArgs.size() == MaxOperandCount) ++ StrIdx = SourceArgs[TextNonSemIdx]; ++ else ++ StrIdx = SPIRVID_INVALID; ++ } ++ ++ return getDIFile(getString(SourceArgs[FileIdx]), CS, ++ getStringSourceContinued(StrIdx, Source)); + } + + DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 14acaf48..9e9dbc4c 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -197,8 +197,8 @@ private: + return nullptr; + } + const std::string &getString(const SPIRVId Id); +- Optional getStringContinued(const SPIRVId Id, +- SPIRVExtInst *DebugInst); ++ const std::string getStringSourceContinued(const SPIRVId Id, ++ SPIRVExtInst *DebugInst); + SPIRVWord getConstantValueOrLiteral(const std::vector &, + const SPIRVWord, + const SPIRVExtInstSetKind); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 1ca7ee07..2d52fc9a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -4,6 +4,7 @@ + #include "spirv/unified1/spirv.hpp" + #include "spirv_internal.hpp" + #include "llvm/BinaryFormat/Dwarf.h" ++#include "llvm/IR/DebugInfoMetadata.h" + + namespace SPIRVDebug { + +@@ -287,6 +288,12 @@ enum ImportedEntityTag { + ImportedDeclaration = 1, + }; + ++enum FileChecksumKind { ++ MD5 = 0, ++ SHA1 = 1, ++ SHA256 = 2, ++}; ++ + namespace Operand { + + namespace CompilationUnit { +@@ -305,7 +312,12 @@ namespace Source { + enum { + FileIdx = 0, + TextIdx = 1, +- MinOperandCount = 1 ++ // For NonSemantic.Shader.DebugInfo.200 ++ ChecksumKind = 1, ++ ChecksumValue = 2, ++ TextNonSemIdx = 3, ++ MinOperandCount = 1, ++ MaxOperandCount = 4 + }; + } + +@@ -1322,6 +1334,15 @@ inline void DbgImportedEntityMap::init() { + add(dwarf::DW_TAG_imported_declaration, SPIRVDebug::ImportedDeclaration); + } + ++typedef SPIRVMap ++ DbgChecksumKindMap; ++template <> ++inline void DbgChecksumKindMap::init() { ++ add(llvm::DIFile::CSK_MD5, SPIRVDebug::MD5); ++ add(llvm::DIFile::CSK_SHA1, SPIRVDebug::SHA1); ++ add(llvm::DIFile::CSK_SHA256, SPIRVDebug::SHA256); ++} ++ + } // namespace SPIRV + + #endif // SPIRV_DEBUG_H +diff --git a/test/DebugInfo/DebugInfoChecksum.ll b/test/DebugInfo/DebugInfoChecksum.ll +index df951369..b38d9228 100644 +--- a/test/DebugInfo/DebugInfoChecksum.ll ++++ b/test/DebugInfo/DebugInfoChecksum.ll +@@ -11,12 +11,18 @@ + ; ./clang -cc1 -debug-info-kind=standalone -S -emit-llvm -triple spir -gcodeview -gcodeview-ghash main.cpp + + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV-OCL + ; RUN: llvm-spirv %t.bc -o %t.spv + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM + ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-200 -o - | FileCheck %s --check-prefix CHECK-SPIRV-200 ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ + ; ModuleID = 'source.bc' + source_filename = "main.cpp" + target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +@@ -41,9 +47,15 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + + ; CHECK-LLVM: !DIFile(filename: "main.cpp" + ; CHECK-LLVM-SAME: checksumkind: CSK_MD5, checksum: "7bb56387968a9caa6e9e35fff94eaf7b" +-; CHECK-SPIRV: String [[#REG:]] "//__CSK_MD5:7bb56387968a9caa6e9e35fff94eaf7b" +-; CHECK-SPIRV: DebugSource +-; CHECK-SPIRV-SAME: [[#REG]] ++ ++; CHECK-SPIRV-OCL: String [[#REG:]] "//__CSK_MD5:7bb56387968a9caa6e9e35fff94eaf7b" ++; CHECK-SPIRV-OCL: DebugSource [[#]] [[#REG]] ++ ++; 0 means MD5 ++; CHECK-SPIRV-200: String [[#Val:]] "7bb56387968a9caa6e9e35fff94eaf7b" ++; CHECK-SPIRV-200: TypeInt [[#TypeInt32:]] 32 ++; CHECK-SPIRV-200: Constant [[#TypeInt32]] [[#Kind:]] 0 ++; CHECK-SPIRV-200: DebugSource [[#]] [[#Kind]] [[#Val]] + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 7d09e1d7cf27ce781e83f9d388a7a3e1e6487ead)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) + !1 = !DIFile(filename: "", directory: "oneAPI", checksumkind: CSK_MD5, checksum: "7bb56387968a9caa6e9e35fff94eaf7b") +@@ -60,4 +72,4 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + !12 = !DISubroutineType(types: !13) + !13 = !{!14} + !14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +-!15 = !DILocation(line: 2, column: 3, scope: !10) +\ No newline at end of file ++!15 = !DILocation(line: 2, column: 3, scope: !10) +diff --git a/test/DebugInfo/DebugInfoChecksumCompileUnit.ll b/test/DebugInfo/DebugInfoChecksumCompileUnit.ll +index 30284818..1e42eea9 100644 +--- a/test/DebugInfo/DebugInfoChecksumCompileUnit.ll ++++ b/test/DebugInfo/DebugInfoChecksumCompileUnit.ll +@@ -1,10 +1,16 @@ + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV-OCL + ; RUN: llvm-spirv %t.bc -o %t.spv + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM + ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV-200 ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefixes=CHECK-LLVM,CHECK-LLVM-200 ++ + ; ModuleID = 'array-transform.bc' + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" + target triple = "spir64-unknown-unknown" +@@ -14,11 +20,20 @@ target triple = "spir64-unknown-unknown" + + ; CHECK-LLVM: !DIFile(filename: "array-transform.cpp" + ; CHECK-LLVM-SAME: checksumkind: CSK_MD5, checksum: "7768106c1e51aa084de0ffae6fbe50c4" +-; CHECK-SPIRV: String [[#ChecksumInfo:]] "//__CSK_MD5:7768106c1e51aa084de0ffae6fbe50c4" +-; CHECK-SPIRV: DebugSource +-; CHECK-SPIRV-SAME: [[#ChecksumInfo]] ++; CHECK-LLVM-200-SAME: source: "int main() {}" ++ ++; CHECK-SPIRV-OCL: String [[#ChecksumInfo:]] "//__CSK_MD5:7768106c1e51aa084de0ffae6fbe50c4" ++; CHECK-SPIRV-OCL: DebugSource ++; CHECK-SPIRV-OCL-SAME: [[#ChecksumInfo]] ++ ++; CHECK-SPIRV-200: String [[#Val:]] "7768106c1e51aa084de0ffae6fbe50c4" ++; CHECK-SPIRV-200: String [[#Source:]] "int main() {}" ++; CHECK-SPIRV-200: TypeInt [[#TypeInt32:]] 32 ++; 0 means MD5 ++; CHECK-SPIRV-200: Constant [[#TypeInt32]] [[#Kind:]] 0 ++; CHECK-SPIRV-200: DebugSource [[#]] [[#Kind]] [[#Val]] [[#Source]] + + !0 = !{i32 2, !"Debug Info Version", i32 3} + !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !2, producer: "spirv", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, imports: !3) +-!2 = !DIFile(filename: "array-transform.cpp", directory: "D:\\path\\to", checksumkind: CSK_MD5, checksum: "7768106c1e51aa084de0ffae6fbe50c4") ++!2 = !DIFile(filename: "array-transform.cpp", directory: "D:\\path\\to", checksumkind: CSK_MD5, checksum: "7768106c1e51aa084de0ffae6fbe50c4", source: "int main() {}") + !3 = !{} +diff --git a/test/DebugInfo/NonSemantic/DebugSourceContinued.ll b/test/DebugInfo/NonSemantic/DebugSourceContinued.ll +index 732b6c0c..5bcef8d9 100644 +--- a/test/DebugInfo/NonSemantic/DebugSourceContinued.ll ++++ b/test/DebugInfo/NonSemantic/DebugSourceContinued.ll +@@ -1,11 +1,18 @@ + ; RUN: llvm-as %s -o %t.bc + ; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -spirv-text -o %t.spt +-; RUN: FileCheck %s --input-file %t.spt --check-prefix CHECK-SPIRV ++; RUN: FileCheck %s --input-file %t.spt --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-100 + ; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM + ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-200 ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ + ; CHECK-LLVM: !DIFile(filename: "t.c", directory: "/test", source: "A + ; CHECK-LLVM-SAME-COUNT-200000: A + ; CHECK-LLVM-SAME: MayThe4thBeWithYou +@@ -19,7 +26,9 @@ + ; CHECK-SPIRV-SAME-COUNT-262130: A + ; CHECK-SPIRV: String [[#Str3:]] "A + ; CHECK-SPIRV-SAME-COUNT-5755: A +-; CHECK-SPIRV: DebugSource [[#]] [[#Str]] ++; CHECK-SPIRV-100: DebugSource [[#]] [[#Str]] ++; CHECK-SPIRV-200: [[#NONE:]] [[#]] DebugInfoNone ++; CHECK-SPIRV-200: DebugSource [[#]] [[#NONE]] [[#NONE]] [[#Str]] + ; CHECK-SPIRV: DebugSourceContinued [[#Str2]] + ; CHECK-SPIRV: DebugSourceContinued [[#Str3]] + +-- +2.20.1 + diff --git a/patches/0053-DebugInfo-Fix-CU-translation-when-GV-goes-before-CU-.patch b/patches/0053-DebugInfo-Fix-CU-translation-when-GV-goes-before-CU-.patch new file mode 100644 index 0000000..ba9bb0d --- /dev/null +++ b/patches/0053-DebugInfo-Fix-CU-translation-when-GV-goes-before-CU-.patch @@ -0,0 +1,109 @@ +From 490b0c1f4bd3a7fc4c8c6558c1c4b6d56ea2e0bb Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 19 May 2023 15:24:12 +0200 +Subject: [PATCH 53/79] [DebugInfo] Fix CU translation when GV goes before CU + (#2010) + +Translation of DebugInfo compilation units and entry points +moved before translation of GVs. + +In other case we might end up in a situation when while +quering for CUs we find none of them. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVReader.cpp | 16 ++++++------ + test/DebugInfo/gv-before-cu.ll | 47 ++++++++++++++++++++++++++++++++++ + 2 files changed, 55 insertions(+), 8 deletions(-) + create mode 100644 test/DebugInfo/gv-before-cu.ll + +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 6dd1bfdf..a3e7c946 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3323,14 +3323,6 @@ bool SPIRVToLLVM::translate() { + if (!transAddressingModel()) + return false; + +- for (unsigned I = 0, E = BM->getNumVariables(); I != E; ++I) { +- auto BV = BM->getVariable(I); +- if (BV->getStorageClass() != StorageClassFunction) +- transValue(BV, nullptr, nullptr); +- else +- transGlobalCtorDtors(BV); +- } +- + // Entry Points should be translated before all debug intrinsics. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { + if (EI->getExtOp() == SPIRVDebug::EntryPoint) +@@ -3344,6 +3336,14 @@ bool SPIRVToLLVM::translate() { + DbgTran->transDebugInst(EI); + } + ++ for (unsigned I = 0, E = BM->getNumVariables(); I != E; ++I) { ++ auto BV = BM->getVariable(I); ++ if (BV->getStorageClass() != StorageClassFunction) ++ transValue(BV, nullptr, nullptr); ++ else ++ transGlobalCtorDtors(BV); ++ } ++ + // Then translate all debug instructions. + for (SPIRVExtInst *EI : BM->getDebugInstVec()) { + DbgTran->transDebugInst(EI); +diff --git a/test/DebugInfo/gv-before-cu.ll b/test/DebugInfo/gv-before-cu.ll +new file mode 100644 +index 00000000..81db2fe1 +--- /dev/null ++++ b/test/DebugInfo/gv-before-cu.ll +@@ -0,0 +1,47 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ++; RUN: FileCheck < %t.ll %s ++ ++; CHECK: [[#GVExpr:]] = !DIGlobalVariableExpression(var: ![[#GV:]], expr: !DIExpression()) ++; CHECK: ![[#GV]] = distinct !DIGlobalVariable(name: "bar", scope: ![[#CU:]], file: ![[#File:]], line: 1, type: ![[#]], isLocal: true, isDefinition: true) ++; CHECK: ![[#CU]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: ![[#File]], producer: "C++ compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: ![[#GVs:]]) ++; CHECK: ![[#File]] = !DIFile(filename: "test.cpp", directory: "/dev/null") ++; CHECK: ![[#GVs]] = !{![[#GVExpr]]} ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++@.str = internal unnamed_addr addrspace(2) constant [3 x i8] c"bar", align 1, !dbg !0 ++ ++define spir_func void @_Z3barBase() !dbg !12 { ++entry: ++ %0 = getelementptr inbounds [3 x i8], [3 x i8] addrspace(2)* @.str, i64 0, i64 0 ++ ret void ++} ++ ++define spir_kernel void @_Z3fooBase() !dbg !13 { ++entry: ++ call spir_func void @_Z3barBase(), !dbg !15 ++ ret void ++} ++ ++!llvm.dbg.cu = !{!2} ++!llvm.module.flags = !{!10, !11} ++ ++!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) ++!1 = distinct !DIGlobalVariable(name: "bar", scope: !2, file: !3, line: 1, type: !5, isLocal: true, isDefinition: true) ++!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "C++ compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4) ++!3 = !DIFile(filename: "test.cpp", directory: "/dev/null") ++!4 = !{!0} ++!5 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 104, elements: !8) ++!6 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !7) ++!7 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) ++!8 = !{!9} ++!9 = !DISubrange(count: 3, lowerBound: 0) ++!10 = !{i32 7, !"Dwarf Version", i32 4} ++!11 = !{i32 2, !"Debug Info Version", i32 3} ++!12 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barBase", scope: null, file: !3, line: 1, type: null, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2) ++!13 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooBase", scope: null, file: !3, line: 3, type: null, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2) ++!14 = distinct !DILexicalBlock(scope: !13, file: !3, line: 3, column: 1) ++!15 = !DILocation(line: 3, column: 1, scope: !14) +-- +2.20.1 + diff --git a/patches/0054-DebugInfo-Support-translation-of-DebugBuildIdentifie.patch b/patches/0054-DebugInfo-Support-translation-of-DebugBuildIdentifie.patch new file mode 100644 index 0000000..1db5329 --- /dev/null +++ b/patches/0054-DebugInfo-Support-translation-of-DebugBuildIdentifie.patch @@ -0,0 +1,307 @@ +From a7e19c4322b03d5f4c3e7c8789f91140de1bac78 Mon Sep 17 00:00:00 2001 +From: LU-JOHN <111294400+LU-JOHN@users.noreply.github.com> +Date: Fri, 19 May 2023 15:05:37 -0500 +Subject: [PATCH 54/79] [DebugInfo] Support translation of + DebugBuildIdentifier/DebugStoragePath instruction (#1977) + +LLVM compileUnit dwoId is translated to/from DebugBuildIdentifier. +LLVM compileUnit splitDebugFilename is translated to/from DebugStoragePath. + +Specification: +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugBuildIdentifier +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugStoragePath +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 50 ++++++++++++++++++++++++++++++ + lib/SPIRV/LLVMToSPIRVDbgTran.h | 7 +++++ + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 51 +++++++++++++++++++++++++++++++ + lib/SPIRV/SPIRVToLLVMDbgTran.h | 7 +++++ + lib/SPIRV/libSPIRV/SPIRV.debug.h | 17 +++++++++++ + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 2 ++ + test/DebugInfo/storagePath_dwo.ll | 33 ++++++++++++++++++++ + 7 files changed, 167 insertions(+) + create mode 100644 test/DebugInfo/storagePath_dwo.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 753b1a22..527d692f 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -544,6 +544,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion; + Ops[DWARFVersionIdx] = M->getDwarfVersion(); + Ops[SourceIdx] = getSource(CU)->getId(); ++ ++ generateBuildIdentifierAndStoragePath(CU); ++ + auto DwarfLang = + static_cast(CU->getSourceLanguage()); + Ops[LanguageIdx] = +@@ -1403,6 +1406,53 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + return Source; + } + ++void LLVMToSPIRVDbgTran::generateBuildIdentifierAndStoragePath( ++ const DICompileUnit *DIEntry) { ++ // get information from LLVM IR ++ auto BuildIdentifier = DIEntry->getDWOId(); ++ const std::string BuildIdentifierString = std::to_string(BuildIdentifier); ++ const std::string StoragePath = DIEntry->getSplitDebugFilename().str(); ++ ++ using namespace SPIRVDebug::Operand; ++ ++ if (BuildIdentifierInsn || StoragePathInsn) { ++#ifndef NDEBUG ++ assert(BuildIdentifierInsn && StoragePathInsn && ++ "BuildIdentifier and StoragePath instructions must both be created"); ++ ++ auto PreviousBuildIdentifierString = ++ BM->get( ++ BuildIdentifierInsn ++ ->getArguments()[BuildIdentifier::IdentifierIdx]) ++ ->getStr(); ++ assert(PreviousBuildIdentifierString == BuildIdentifierString && ++ "New BuildIdentifier should match previous BuildIdentifier"); ++ auto PreviousStoragePath = ++ BM->get( ++ StoragePathInsn->getArguments()[StoragePath::PathIdx]) ++ ->getStr(); ++ assert(PreviousStoragePath == StoragePath && ++ "New StoragePath should match previous StoragePath"); ++#endif ++ return; ++ } ++ ++ // generate BuildIdentifier inst ++ SPIRVWordVec BuildIdentifierOps(BuildIdentifier::OperandCount); ++ BuildIdentifierOps[BuildIdentifier::IdentifierIdx] = ++ BM->getString(BuildIdentifierString)->getId(); ++ BuildIdentifierOps[BuildIdentifier::FlagsIdx] = ++ BM->getLiteralAsConstant(1)->getId(); // Placeholder value for now ++ BuildIdentifierInsn = static_cast(BM->addDebugInfo( ++ SPIRVDebug::BuildIdentifier, getVoidTy(), BuildIdentifierOps)); ++ ++ // generate StoragePath inst ++ SPIRVWordVec StoragePathOps(StoragePath::OperandCount); ++ StoragePathOps[StoragePath::PathIdx] = BM->getString(StoragePath)->getId(); ++ StoragePathInsn = static_cast( ++ BM->addDebugInfo(SPIRVDebug::StoragePath, getVoidTy(), StoragePathOps)); ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFileType(const DIFile *F) { + return BM->getString(getFullPath(F)); + } +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index da6685c6..0ca070d6 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -146,6 +146,10 @@ private: + template SPIRVExtInst *getSource(const T *DIEntry); + SPIRVEntry *transDbgFileType(const DIFile *F); + ++ // Generate instructions recording identifier and file where debug information ++ // was split to ++ void generateBuildIdentifierAndStoragePath(const DICompileUnit *DIEntry); ++ + // Local Variables + SPIRVEntry *transDbgLocalVariable(const DILocalVariable *Var); + +@@ -170,6 +174,9 @@ private: + std::unordered_map SPIRVCUMap; + std::vector DbgDeclareIntrinsics; + std::vector DbgValueIntrinsics; ++ ++ SPIRVExtInst *BuildIdentifierInsn{nullptr}; ++ SPIRVExtInst *StoragePathInsn{nullptr}; + }; // class LLVMToSPIRVDbgTran + + } // namespace SPIRV +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 40ad90d0..65bb0172 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -223,6 +223,18 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug + // info by default + auto Producer = findModuleProducer(); ++ assert(BuilderMap.size() != 0 && "No debug compile units"); ++ if (BuilderMap.size()==1) ++ // Only initialize once ++ setBuildIdentifierAndStoragePath(); ++ ++ if (!StoragePath.empty()) { ++ return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0, ++ StoragePath, DICompileUnit::DebugEmissionKind::FullDebug, ++ BuildIdentifier); ++ } ++ + return BuilderMap[DebugInst->getId()]->createCompileUnit( + SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); + } +@@ -1350,6 +1362,8 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) { + case SPIRVDebug::Operation: // To be translated with transExpression + case SPIRVDebug::Source: // To be used by other instructions + case SPIRVDebug::SourceContinued: ++ case SPIRVDebug::BuildIdentifier: // To be used by transCompilationUnit ++ case SPIRVDebug::StoragePath: // To be used by transCompilationUnit + return nullptr; + + case SPIRVDebug::Expression: +@@ -1514,6 +1528,43 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + getStringSourceContinued(StrIdx, Source)); + } + ++void SPIRVToLLVMDbgTran::setBuildIdentifierAndStoragePath() { ++#ifndef NDEBUG ++ bool FoundBuildIdentifier{false}; ++ bool FoundStoragePath{false}; ++#endif ++ ++ for (SPIRVExtInst *EI : BM->getDebugInstVec()) { ++ if (EI->getExtOp() == SPIRVDebug::BuildIdentifier) { ++ using namespace SPIRVDebug::Operand::BuildIdentifier; ++ SPIRVWordVec BuildIdentifierArgs = EI->getArguments(); ++ assert(BuildIdentifierArgs.size() == OperandCount && ++ "Invalid number of operands"); ++ assert(!FoundBuildIdentifier && ++ "More than one BuildIdentifier instruction not allowed"); ++ BuildIdentifier = strtoull( ++ getString(BuildIdentifierArgs[IdentifierIdx]).c_str(), NULL, 10); ++#ifndef NDEBUG ++ FoundBuildIdentifier = true; ++#endif ++ } else if (EI->getExtOp() == SPIRVDebug::StoragePath) { ++ using namespace SPIRVDebug::Operand::StoragePath; ++ SPIRVWordVec StoragePathArgs = EI->getArguments(); ++ assert(StoragePathArgs.size() == OperandCount && ++ "Invalid number of operands"); ++ assert(!FoundStoragePath && ++ "More than one StoragePath instruction not allowed"); ++ StoragePath = getString(StoragePathArgs[PathIdx]); ++#ifndef NDEBUG ++ FoundStoragePath = true; ++#endif ++ } ++ } ++ assert(((FoundBuildIdentifier && FoundStoragePath) || ++ (!FoundBuildIdentifier && !FoundStoragePath)) && ++ "BuildIdentifier and StoragePath must both be set or both unset"); ++} ++ + DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) { + assert(BuilderMap.size() != 0 && "No debug compile units"); + if (BuilderMap.size() == 1) +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 9e9dbc4c..50d0d1e5 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -89,6 +89,7 @@ public: + + private: + DIFile *getFile(const SPIRVId SourceId); ++ + DIFile * + getDIFile(const std::string &FileName, + Optional> CS = None, +@@ -204,6 +205,12 @@ private: + const SPIRVExtInstSetKind); + std::string findModuleProducer(); + Optional> ParseChecksum(StringRef Text); ++ ++ // BuildIdentifier and StoragePath must both be set or both unset. ++ // If StoragePath is empty both variables are unset and not valid. ++ uint64_t BuildIdentifier{0}; ++ std::string StoragePath{}; ++ void setBuildIdentifierAndStoragePath(); + }; + } // namespace SPIRV + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 2d52fc9a..660d9510 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -57,6 +57,8 @@ enum Instruction { + InstCount = 37, + FunctionDefinition = 101, + SourceContinued = 102, ++ BuildIdentifier = 105, ++ StoragePath = 106, + EntryPoint = 107, + Module = 200, + TypeSubrange = 201, +@@ -321,6 +323,21 @@ enum { + }; + } + ++namespace BuildIdentifier { ++enum { ++ IdentifierIdx = 0, ++ FlagsIdx = 1, ++ OperandCount = 2 ++}; ++} ++ ++namespace StoragePath { ++enum { ++ PathIdx = 0, ++ OperandCount = 1 ++}; ++} ++ + namespace TypeBasic { + enum { + NameIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index fc16a994..315f73f0 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -263,6 +263,8 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition"); + add(SPIRVDebug::SourceContinued, "DebugSourceContinued"); + add(SPIRVDebug::EntryPoint, "DebugEntryPoint"); ++ add(SPIRVDebug::BuildIdentifier, "DebugBuildIdentifier"); ++ add(SPIRVDebug::StoragePath, "DebugStoragePath"); + } + SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) + +diff --git a/test/DebugInfo/storagePath_dwo.ll b/test/DebugInfo/storagePath_dwo.ll +new file mode 100644 +index 00000000..1cbb0ab8 +--- /dev/null ++++ b/test/DebugInfo/storagePath_dwo.ll +@@ -0,0 +1,33 @@ ++; Test checks that dwoId and splitDebugFilename is preserved from LLVM IR to spirv ++; and spirv to LLVM IR translation. ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; CHECK-SPIRV: String [[#stringA_id:]] "11111" ++; CHECK-SPIRV: String [[#stringA_sf:]] "debugA_info.dwo" ++; CHECK-SPIRV: [[#buildID_A:]] [[#]] DebugBuildIdentifier [[#stringA_id]] ++; CHECK-SPIRV: [[#storageID_A:]] [[#]] DebugStoragePath [[#stringA_sf]] ++ ++; CHECK-LLVM: !DICompileUnit ++; CHECK-LLVM-SAME: splitDebugFilename: "debugA_info.dwo" ++; CHECK-LLVM-SAME: dwoId: 11111 ++; CHECK-LLVM: !DICompileUnit ++; CHECK-LLVM-SAME: splitDebugFilename: "debugA_info.dwo" ++; CHECK-LLVM-SAME: dwoId: 11111 ++ ++!llvm.dbg.cu = !{!7, !0} ++!llvm.module.flags = !{!3, !4} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Clang", isOptimized: false, runtimeVersion: 2, splitDebugFilename: "debugA_info.dwo", emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2, dwoId: 11111) ++!1 = !DIFile(filename: "", directory: "/") ++!2 = !{} ++!3 = !{i32 2, !"Dwarf Version", i32 4} ++!4 = !{i32 2, !"Debug Info Version", i32 3} ++!5 = !{!6} ++!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Clang", isOptimized: false, runtimeVersion: 2, splitDebugFilename: "debugA_info.dwo", dwoId: 11111, emissionKind: FullDebug, retainedTypes: !5) +-- +2.20.1 + diff --git a/patches/0055-DebugInfo-Fix-DebugTypeVector-Component-Count-2006.patch b/patches/0055-DebugInfo-Fix-DebugTypeVector-Component-Count-2006.patch new file mode 100644 index 0000000..b569727 --- /dev/null +++ b/patches/0055-DebugInfo-Fix-DebugTypeVector-Component-Count-2006.patch @@ -0,0 +1,92 @@ +From 1d4c7c685095ee3066c36aa12bbcf255d899faf1 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 19 May 2023 22:06:06 +0200 +Subject: [PATCH 55/79] [DebugInfo] Fix DebugTypeVector Component Count (#2006) + +It should be OpConstant + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 2 ++ + test/DebugInfo/X86/rematerialize.ll | 10 ++++++++++ + test/DebugInfo/X86/sycl-vec-3.ll | 8 ++++++++ + test/DebugInfo/X86/vector.ll | 10 ++++++++++ + 4 files changed, 30 insertions(+) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 527d692f..08e57497 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -696,6 +696,8 @@ LLVMToSPIRVDbgTran::transDbgArrayTypeNonSemantic(const DICompositeType *AT) { + if (AT->isVector()) { + assert(N == 1 && "Multidimensional vector is not expected!"); + Ops[ComponentCountIdx] = static_cast(Count->getZExtValue()); ++ if (isNonSemanticDebugInfo()) ++ transformToConstant(Ops, {ComponentCountIdx}); + return BM->addDebugInfo(SPIRVDebug::TypeVector, getVoidTy(), Ops); + } + Ops[SubrangesIdx + I] = transDbgEntry(SR)->getId(); +diff --git a/test/DebugInfo/X86/rematerialize.ll b/test/DebugInfo/X86/rematerialize.ll +index 762d8e92..76e1ca8c 100644 +--- a/test/DebugInfo/X86/rematerialize.ll ++++ b/test/DebugInfo/X86/rematerialize.ll +@@ -3,6 +3,16 @@ + ; RUN: llvm-spirv %t.bc -o %t.spv + ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll + ++; RUN: llc -O2 -filetype=obj -mtriple=x86_64-unknown-linux-gnu < %t.ll \ ++; RUN: | llvm-dwarfdump -debug-line - | FileCheck %s ++ ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-100 ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ++; RUN: llc -O2 -filetype=obj -mtriple=x86_64-unknown-linux-gnu < %t.ll \ ++; RUN: | llvm-dwarfdump -debug-line - | FileCheck %s ++ ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll + ; RUN: llc -O2 -filetype=obj -mtriple=x86_64-unknown-linux-gnu < %t.ll \ + ; RUN: | llvm-dwarfdump -debug-line - | FileCheck %s + ; +diff --git a/test/DebugInfo/X86/sycl-vec-3.ll b/test/DebugInfo/X86/sycl-vec-3.ll +index dcfacc46..d0fa9c2c 100644 +--- a/test/DebugInfo/X86/sycl-vec-3.ll ++++ b/test/DebugInfo/X86/sycl-vec-3.ll +@@ -3,6 +3,14 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s + ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-100 ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s ++ ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s ++ + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" + target triple = "spir64-unknown-unknown" + +diff --git a/test/DebugInfo/X86/vector.ll b/test/DebugInfo/X86/vector.ll +index 13894948..3cf2c3a8 100644 +--- a/test/DebugInfo/X86/vector.ll ++++ b/test/DebugInfo/X86/vector.ll +@@ -5,6 +5,16 @@ + ; RUN: llc -mtriple=x86_64-linux-gnu -O0 -filetype=obj -o %t %t.ll + ; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s + ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-100 ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ++; RUN: llc -mtriple=x86_64-linux-gnu -O0 -filetype=obj -o %t %t.ll ++; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ++ ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll ++; RUN: llc -mtriple=x86_64-linux-gnu -O0 -filetype=obj -o %t %t.ll ++; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s ++ + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" + target triple = "spir64-unknown-unknown" + +-- +2.20.1 + diff --git a/patches/0056-DebugInfo-Relax-consumer-checks-for-checksum-info-20.patch b/patches/0056-DebugInfo-Relax-consumer-checks-for-checksum-info-20.patch new file mode 100644 index 0000000..e98dcc2 --- /dev/null +++ b/patches/0056-DebugInfo-Relax-consumer-checks-for-checksum-info-20.patch @@ -0,0 +1,58 @@ +From 461476e5729136c5810d2186e6bf6cc103acfe92 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Sun, 28 May 2023 18:41:04 +0200 +Subject: [PATCH 56/79] [DebugInfo] Relax consumer checks for checksum info + (#2011) + +It's a follow up for +https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/1996 +since I couldn't update the PR + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 65bb0172..9dd9c933 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1507,18 +1507,25 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + Optional> CS; + SPIRVWord StrIdx = SourceArgs[TextIdx]; + if (Source->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { +- if (!getDbgInst(SourceArgs[ChecksumKind]) && +- !getDbgInst(SourceArgs[ChecksumValue])) { +- llvm::DIFile::ChecksumKind Kind = SPIRV::DbgChecksumKindMap::rmap( +- static_cast( +- BM->get(SourceArgs[ChecksumKind]) +- ->getZExtIntValue())); +- StringRef Checksum = getString(SourceArgs[ChecksumValue]); +- size_t ChecksumEndPos = Checksum.find_if_not(llvm::isHexDigit); +- CS.emplace(Kind, Checksum.substr(0, ChecksumEndPos)); ++ if (SourceArgs.size() >= MaxOperandCount - 1) { ++ // 2 optional parameters are ChecksumKind and ChecksumValue - they should ++ // go together ++ if (!getDbgInst(SourceArgs[ChecksumKind]) && ++ !getDbgInst(SourceArgs[ChecksumValue])) { ++ llvm::DIFile::ChecksumKind Kind = SPIRV::DbgChecksumKindMap::rmap( ++ static_cast( ++ BM->get(SourceArgs[ChecksumKind]) ++ ->getZExtIntValue())); ++ StringRef Checksum = getString(SourceArgs[ChecksumValue]); ++ size_t ChecksumEndPos = Checksum.find_if_not(llvm::isHexDigit); ++ CS.emplace(Kind, Checksum.substr(0, ChecksumEndPos)); ++ } + } + +- if (SourceArgs.size() == MaxOperandCount) ++ // Among optional parameters - text is always the last one (either 1st or ++ // 3rd) ++ if (SourceArgs.size() == MaxOperandCount || ++ SourceArgs.size() == MaxOperandCount - 2) + StrIdx = SourceArgs[TextNonSemIdx]; + else + StrIdx = SPIRVID_INVALID; +-- +2.20.1 + diff --git a/patches/0057-DebugInfo-Add-Flags-operand-for-DebugTypeBasic-for-N.patch b/patches/0057-DebugInfo-Add-Flags-operand-for-DebugTypeBasic-for-N.patch new file mode 100644 index 0000000..0eca15b --- /dev/null +++ b/patches/0057-DebugInfo-Add-Flags-operand-for-DebugTypeBasic-for-N.patch @@ -0,0 +1,103 @@ +From 1dcc2d58a1ae116205821d240d0ce2add35b9659 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 2 Jun 2023 11:50:45 +0200 +Subject: [PATCH 57/79] [DebugInfo] Add Flags operand for DebugTypeBasic for + NonSemantic spec (#2034) + +Flags operand is not optional, fill it with DebugInfoNone value (see #1965 +for clarifications why it could not be generated by clang or by LLVM +environment). +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 5 ++- + test/DebugInfo/DebugInfoTypeBasic.ll | 61 ++++++++++++++++++++++++++++ + 2 files changed, 65 insertions(+), 1 deletion(-) + create mode 100644 test/DebugInfo/DebugInfoTypeBasic.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 08e57497..539ae7da 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -590,8 +590,11 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgBaseType(const DIBasicType *BT) { + BM->getDebugInfoEIS() != SPIRVEIS_NonSemantic_Shader_DebugInfo_200) + EncTag = SPIRVDebug::Unspecified; + Ops[EncodingIdx] = EncTag; +- if (isNonSemanticDebugInfo()) ++ if (isNonSemanticDebugInfo()) { + transformToConstant(Ops, {EncodingIdx}); ++ // Flags value could not be generated by clang or by LLVM environment. ++ Ops.push_back(getDebugInfoNoneId()); ++ } + return BM->addDebugInfo(SPIRVDebug::TypeBasic, getVoidTy(), Ops); + } + +diff --git a/test/DebugInfo/DebugInfoTypeBasic.ll b/test/DebugInfo/DebugInfoTypeBasic.ll +new file mode 100644 +index 00000000..4ad5fa59 +--- /dev/null ++++ b/test/DebugInfo/DebugInfoTypeBasic.ll +@@ -0,0 +1,61 @@ ++; Test checks debug info of basic type is preserved during LLVM IR to spirv ++; and spirv to LLVM IR translation. ++ ++; Original .cpp source: ++; int main() { ++; return 0; ++; } ++ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-OCL ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-100 -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NONSEM ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; CHECK-LLVM: !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++ ++; CHECK-SPIRV: String [[#Name:]] "int" ++; CHECK-SPIRV-NONSEM: Constant [[#]] [[#Encoding:]] 4 ++; CHECK-SPIRV: Constant [[#]] [[#Size:]] 32 ++; CHECK-SPIRV-OCL: DebugTypeBasic [[#Name]] [[#Size]] 4 {{$}} ++; CHECK-SPIRV-NONSEM: [[#Flags:]] [[#]] DebugInfoNone ++; CHECK-SPIRV-NONSEM: DebugTypeBasic [[#Name]] [[#Size]] [[#Encoding]] [[#Flags]] {{$}} ++ ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define dso_local noundef i32 @_Z3foov() #0 !dbg !10 { ++ ret i32 0, !dbg !16 ++} ++ ++attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} ++!llvm.ident = !{!9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git b936816fb305cc16d2d1cd6d424c08c39a681a32)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "/app/example.cpp", directory: "/app") ++!2 = !{i32 7, !"Dwarf Version", i32 4} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 8, !"PIC Level", i32 2} ++!6 = !{i32 7, !"PIE Level", i32 2} ++!7 = !{i32 7, !"uwtable", i32 2} ++!8 = !{i32 7, !"frame-pointer", i32 2} ++!9 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git b936816fb305cc16d2d1cd6d424c08c39a681a32)"} ++!10 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !11, file: !11, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!11 = !DIFile(filename: "example.cpp", directory: "/app") ++!12 = !DISubroutineType(types: !13) ++!13 = !{!14} ++!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!15 = !{} ++!16 = !DILocation(line: 1, column: 13, scope: !10) +\ No newline at end of file +-- +2.20.1 + diff --git a/patches/0058-DebugInfo-Adjust-TypeMember-for-NonSemantic-spec-203.patch b/patches/0058-DebugInfo-Adjust-TypeMember-for-NonSemantic-spec-203.patch new file mode 100644 index 0000000..3607fed --- /dev/null +++ b/patches/0058-DebugInfo-Adjust-TypeMember-for-NonSemantic-spec-203.patch @@ -0,0 +1,387 @@ +From 9df0be68fe0469573e2cd3f19baf2181032c65b7 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Fri, 2 Jun 2023 15:23:28 +0200 +Subject: [PATCH 58/79] [DebugInfo] Adjust TypeMember for NonSemantic spec + (#2033) + +It no longer has a Scope (parent) parameter. It results in several changes including how to determine DIBuilder to use for debug info generation. + +The patch also fixes a bug of incorrect debug info assignment in case of recursion DebugInfo inst generation. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 48 ++++++++++- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 2 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 73 ++++++++++++++++- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 8 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 19 ++++- + .../Shader200/DebugInfoSubrange.ll | 2 +- + .../NonSemantic/static_member_array.ll | 80 +++++++++++++++++++ + test/DebugInfo/OpenCL100/DebugInfoSubrange.ll | 2 +- + 8 files changed, 226 insertions(+), 8 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/static_member_array.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 539ae7da..821eafdb 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -252,6 +252,17 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgEntry(const MDNode *DIEntry) { + } + SPIRVEntry *Res = transDbgEntryImpl(DIEntry); + assert(Res && "Translation failure"); ++ // We might end up having a recursive debug info generation like the ++ // following: ++ // translation of DIDerivedType (member) calls DICompositeType translation ++ // as its parent scope; ++ // translation of DICompositeType calls translation of its members ++ // (DIDerivedType with member tag). ++ // Here we make only the latest of these instructions be cached and hence ++ // reused ++ // FIXME: find a way to not create dead instruction ++ if (MDMap[DIEntry]) ++ return MDMap[DIEntry]; + MDMap[DIEntry] = Res; + return Res; + } +@@ -959,7 +970,14 @@ LLVMToSPIRVDbgTran::transDbgCompositeType(const DICompositeType *CT) { + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) { +- using namespace SPIRVDebug::Operand::TypeMember; ++ if (isNonSemanticDebugInfo()) ++ return transDbgMemberTypeNonSemantic(MT); ++ return transDbgMemberTypeOpenCL(MT); ++} ++ ++SPIRVEntry * ++LLVMToSPIRVDbgTran::transDbgMemberTypeOpenCL(const DIDerivedType *MT) { ++ using namespace SPIRVDebug::Operand::TypeMember::OpenCL; + SPIRVWordVec Ops(MinOperandCount); + + Ops[NameIdx] = BM->getString(MT->getName().str())->getId(); +@@ -986,6 +1004,34 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgMemberType(const DIDerivedType *MT) { + return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops); + } + ++SPIRVEntry * ++LLVMToSPIRVDbgTran::transDbgMemberTypeNonSemantic(const DIDerivedType *MT) { ++ using namespace SPIRVDebug::Operand::TypeMember::NonSemantic; ++ SPIRVWordVec Ops(MinOperandCount); ++ ++ Ops[NameIdx] = BM->getString(MT->getName().str())->getId(); ++ Ops[TypeIdx] = transDbgEntry(MT->getBaseType())->getId(); ++ Ops[SourceIdx] = getSource(MT)->getId(); ++ Ops[LineIdx] = MT->getLine(); ++ Ops[ColumnIdx] = 0; // This version of DIDerivedType has no column number ++ ConstantInt *Offset = getUInt(M, MT->getOffsetInBits()); ++ Ops[OffsetIdx] = SPIRVWriter->transValue(Offset, nullptr)->getId(); ++ ConstantInt *Size = getUInt(M, MT->getSizeInBits()); ++ Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); ++ Ops[FlagsIdx] = adjustAccessFlags(MT->getScope(), transDebugFlags(MT)); ++ transDbgEntry(MT->getScope())->getId(); ++ if (MT->isStaticMember()) { ++ if (llvm::Constant *C = MT->getConstant()) { ++ SPIRVValue *Val = SPIRVWriter->transValue(C, nullptr); ++ assert(isConstantOpCode(Val->getOpCode()) && ++ "LLVM constant must be translated to SPIRV constant"); ++ Ops.push_back(Val->getId()); ++ } ++ } ++ transformToConstant(Ops, {LineIdx, ColumnIdx, FlagsIdx}); ++ return BM->addDebugInfo(SPIRVDebug::TypeMember, getVoidTy(), Ops); ++} ++ + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { + using namespace SPIRVDebug::Operand::TypeInheritance; + SPIRVWordVec Ops(OperandCount); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 0ca070d6..21bd6f2f 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -119,6 +119,8 @@ private: + SPIRVEntry *transDbgEnumType(const DICompositeType *ET); + SPIRVEntry *transDbgCompositeType(const DICompositeType *CT); + SPIRVEntry *transDbgMemberType(const DIDerivedType *MT); ++ SPIRVEntry *transDbgMemberTypeOpenCL(const DIDerivedType *MT); ++ SPIRVEntry *transDbgMemberTypeNonSemantic(const DIDerivedType *MT); + SPIRVEntry *transDbgInheritance(const DIDerivedType *DT); + SPIRVEntry *transDbgPtrToMember(const DIDerivedType *DT); + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 9dd9c933..42026b62 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -535,7 +535,16 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + DebugInstCache[DebugInst] = CT; + SmallVector EltTys; + for (size_t I = FirstMemberIdx; I < Ops.size(); ++I) { +- EltTys.push_back(transDebugInst(BM->get(Ops[I]))); ++ auto *MemberInst = BM->get(Ops[I]); ++ if (MemberInst->getExtOp() == SPIRVDebug::TypeMember) { ++ auto *SPVMemberInst = BM->get(Ops[I]); ++ DINode *MemberMD = ++ transTypeMember(SPVMemberInst, DebugInst, cast(CT)); ++ EltTys.push_back(MemberMD); ++ DebugInstCache[SPVMemberInst] = MemberMD; ++ } else { ++ EltTys.emplace_back(transDebugInst(BM->get(Ops[I]))); ++ } + } + DINodeArray Elements = getDIBuilder(DebugInst).getOrCreateArray(EltTys); + getDIBuilder(DebugInst).replaceArrays(CT, Elements); +@@ -617,8 +626,18 @@ SPIRVToLLVMDbgTran::transTypeString(const SPIRVExtInst *DebugInst) { + 0 /*AlignInBits*/, Encoding); + } + +-DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::TypeMember; ++DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst, ++ const SPIRVExtInst *ParentInst, ++ DIScope *Scope) { ++ if (isNonSemanticDebugInfo(DebugInst->getExtSetKind())) ++ // In NonSemantic spec TypeMember doesn't have Scope parameter ++ return transTypeMemberNonSemantic(DebugInst, ParentInst, Scope); ++ return transTypeMemberOpenCL(DebugInst); ++} ++ ++DINode * ++SPIRVToLLVMDbgTran::transTypeMemberOpenCL(const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::TypeMember::OpenCL; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + +@@ -660,6 +679,54 @@ DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) { + Flags, BaseType); + } + ++DINode * ++SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst, ++ const SPIRVExtInst *ParentInst, ++ DIScope *Scope) { ++ if (!Scope) ++ // Will be translated later when processing TypeMember's parent ++ return nullptr; ++ using namespace SPIRVDebug::Operand::TypeMember::NonSemantic; ++ const SPIRVWordVec &Ops = DebugInst->getArguments(); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ ++ DIFile *File = getFile(Ops[SourceIdx]); ++ SPIRVWord LineNo = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); ++ StringRef Name = getString(Ops[NameIdx]); ++ DIType *BaseType = ++ transDebugInst(BM->get(Ops[TypeIdx])); ++ uint64_t OffsetInBits = ++ BM->get(Ops[OffsetIdx])->getZExtIntValue(); ++ SPIRVWord SPIRVFlags = ++ getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ DINode::DIFlags Flags = DINode::FlagZero; ++ if ((SPIRVDebug::FlagAccess & SPIRVFlags) == SPIRVDebug::FlagIsPublic) { ++ Flags |= DINode::FlagPublic; ++ } else if (SPIRVFlags & SPIRVDebug::FlagIsProtected) { ++ Flags |= DINode::FlagProtected; ++ } else if (SPIRVFlags & SPIRVDebug::FlagIsPrivate) { ++ Flags |= DINode::FlagPrivate; ++ } ++ if (SPIRVFlags & SPIRVDebug::FlagIsStaticMember) ++ Flags |= DINode::FlagStaticMember; ++ ++ if (Flags & DINode::FlagStaticMember && Ops.size() > MinOperandCount) { ++ SPIRVValue *ConstVal = BM->get(Ops[ValueIdx]); ++ assert(isConstantOpCode(ConstVal->getOpCode()) && ++ "Static member must be a constant"); ++ llvm::Value *Val = SPIRVReader->transValue(ConstVal, nullptr, nullptr); ++ return getDIBuilder(DebugInst).createStaticMemberType( ++ Scope, Name, File, LineNo, BaseType, Flags, cast(Val)); ++ } ++ uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); ++ uint64_t Alignment = 0; ++ ++ return getDIBuilder(ParentInst) ++ .createMemberType(Scope, Name, File, LineNo, Size, Alignment, ++ OffsetInBits, Flags, BaseType); ++} ++ + DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) { + using namespace SPIRVDebug::Operand::TypeEnum; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 50d0d1e5..48d7ea6b 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -128,7 +128,13 @@ private: + + DIStringType *transTypeString(const SPIRVExtInst *DebugInst); + +- DINode *transTypeMember(const SPIRVExtInst *DebugInst); ++ DINode *transTypeMember(const SPIRVExtInst *DebugInst, ++ const SPIRVExtInst *ParentInst = nullptr, ++ DIScope *Scope = nullptr); ++ DINode *transTypeMemberOpenCL(const SPIRVExtInst *DebugInst); ++ DINode *transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst, ++ const SPIRVExtInst *ParentInst, ++ DIScope *Scope); + + DINode *transTypeEnum(const SPIRVExtInst *DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 660d9510..723a0b14 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -465,6 +465,7 @@ enum { + } + + namespace TypeMember { ++namespace OpenCL { + enum { + NameIdx = 0, + TypeIdx = 1, +@@ -480,6 +481,22 @@ enum { + }; + } + ++namespace NonSemantic { ++enum { ++ NameIdx = 0, ++ TypeIdx = 1, ++ SourceIdx = 2, ++ LineIdx = 3, ++ ColumnIdx = 4, ++ OffsetIdx = 5, ++ SizeIdx = 6, ++ FlagsIdx = 7, ++ ValueIdx = 8, ++ MinOperandCount = 8 ++}; ++} ++} // namespace TypeMember ++ + namespace TypeInheritance { + enum { + ChildIdx = 0, +@@ -934,7 +951,7 @@ inline bool hasDbgInstParentScopeIdx(const uint32_t Kind, + ParentScopeIdx = TypeEnum::ParentIdx; + return true; + case SPIRVDebug::TypeComposite: +- ParentScopeIdx = TypeMember::ParentIdx; ++ ParentScopeIdx = TypeMember::OpenCL::ParentIdx; + return true; + case SPIRVDebug::TypeInheritance: + ParentScopeIdx = TypeInheritance::ParentIdx; +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +index d83e170a..3bb29f08 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +@@ -16,8 +16,8 @@ + ; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone + + ; CHECK-SPIRV: [[#DebugFuncId:]] [[#EISId]] DebugFunction ++; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugFuncId]] + ; CHECK-SPIRV: [[#DebugTypeTemplate:]] [[#EISId]] DebugTypeTemplate [[#DebugFuncId]] +-; CHECK-SPIRV: [[#LocalVarId:]] [[#EISId]] DebugLocalVariable [[#LocalVarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DebugTypeTemplate]] + ; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#DINoneId]] [[#Constant1Id]] [[#LocalVarId]] [[#DINoneId]] + + ; CHECK-SPIRV: [[#DIExprId:]] [[#EISId]] DebugExpression +diff --git a/test/DebugInfo/NonSemantic/static_member_array.ll b/test/DebugInfo/NonSemantic/static_member_array.ll +new file mode 100644 +index 00000000..05e0a706 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/static_member_array.ll +@@ -0,0 +1,80 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-100 ++; RUN: llvm-spirv %t.spv --to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-debug-info-version=nonsemantic-shader-200 ++; RUN: llvm-spirv %t.spv --to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; Generated from: ++; ++; struct A { ++; static int fully_specified; ++; static int smem[]; ++; }; ++; ++; int A::fully_specified; ++; int A::smem[] = { 0, 1, 2, 3 }; ++ ++; CHECK-SPIRV: ExtInst [[#]] [[#Member1:]] [[#]] DebugTypeMember [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#]] [[#Member2:]] [[#]] DebugTypeMember [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugTypeComposite [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member1]] [[#Member2]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member1]] ++; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugGlobalVariable [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#Member2]] ++ ++; CHECK-LLVM: ![[#GVExpr1:]] = !DIGlobalVariableExpression(var: ![[#GV1:]], expr: !DIExpression()) ++; CHECK-LLVM: ![[#GV1]] = distinct !DIGlobalVariable(name: "fully_specified", linkageName: "_ZN1A15fully_specifiedE", scope: ![[#CU:]], file: ![[#File:]], line: 7, type: ![[#GVTy1:]], isLocal: false, isDefinition: true, declaration: ![[#Decl1:]]) ++; CHECK-LLVM: ![[#CU]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus{{.*}}, file: ![[#File:]], {{.*}}, globals: ![[#GVs:]] ++; CHECK-LLVM: ![[#File]] = !DIFile(filename: "static_member_array.cpp", directory: "/Volumes/Data/radar/28706946") ++; CHECK-LLVM: ![[#GVs]] = !{![[#GVExpr1]], ![[#GVExpr2:]]} ++; CHECK-LLVM: ![[#GVExpr2]] = !DIGlobalVariableExpression(var: ![[#GV2:]], expr: !DIExpression()) ++; CHECK-LLVM: ![[#GV2]] = distinct !DIGlobalVariable(name: "smem", linkageName: "_ZN1A4smemE", scope: ![[#CU]], file: ![[#File]], line: 8, type: ![[#GVTy2:]], isLocal: false, isDefinition: true, declaration: ![[#Decl2:]]) ++; CHECK-LLVM: ![[#GVTy2]] = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 128, elements: ![[#Elements1:]]) ++; CHECK-LLVM: ![[#GVTy1]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++; CHECK-LLVM: ![[#Elements1]] = !{![[#Subrange:]]} ++; CHECK-LLVM: ![[#Subrange]] = !DISubrange(count: 4 ++; CHECK-LLVM: ![[#MemTy1:]] = !DIDerivedType(tag: DW_TAG_member, name: "smem", scope: ![[#StructTy:]], file: ![[#File]], line: 4, baseType: ![[#ArrTy:]], flags: DIFlagPublic | DIFlagStaticMember) ++; CHECK-LLVM: ![[#StructTy]] = !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: ![[#File]], line: 1, size: 8, elements: ![[#Elements2:]], identifier: "_ZTS1A") ++; CHECK-LLVM: ![[#Elements2]] = !{![[#MemTy2:]], ![[#MemTy1]]} ++; CHECK-LLVM: ![[#MemTy2:]] = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: ![[#StructTy]], file: ![[#File]], line: 3, baseType: ![[#GVTy1]], flags: DIFlagPublic | DIFlagStaticMember) ++; CHECK-LLVM: ![[#ArrTy]] = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, elements: ![[#]]) ++ ++ ++source_filename = "static_member_array.cpp" ++target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++@_ZN1A15fully_specifiedE = global i32 0, align 4, !dbg !0 ++@_ZN1A4smemE = global [4 x i32] [i32 0, i32 1, i32 2, i32 3], align 16, !dbg !6 ++ ++!llvm.dbg.cu = !{!2} ++!llvm.module.flags = !{!19, !20, !21} ++!llvm.ident = !{!22} ++ ++!0 = distinct !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) ++!1 = !DIGlobalVariable(name: "fully_specified", linkageName: "_ZN1A15fully_specifiedE", scope: !2, file: !3, line: 7, type: !9, isLocal: false, isDefinition: true, declaration: !15) ++!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 4.0.0 (trunk 286129) (llvm/trunk 286128)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) ++!3 = !DIFile(filename: "static_member_array.cpp", directory: "/Volumes/Data/radar/28706946") ++!4 = !{} ++!5 = !{!0, !6} ++!6 = distinct !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) ++!7 = !DIGlobalVariable(name: "smem", linkageName: "_ZN1A4smemE", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true, declaration: !12) ++!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, elements: !10) ++!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!10 = !{!11} ++!11 = !DISubrange(count: 4) ++!12 = !DIDerivedType(tag: DW_TAG_member, name: "smem", scope: !13, file: !3, line: 4, baseType: !16, flags: DIFlagStaticMember) ++!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 1, size: 8, elements: !14, identifier: "_ZTS1A") ++!14 = !{!15, !12} ++!15 = !DIDerivedType(tag: DW_TAG_member, name: "fully_specified", scope: !13, file: !3, line: 3, baseType: !9, flags: DIFlagStaticMember) ++!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, elements: !17) ++!17 = !{!18} ++!18 = !DISubrange(count: -1) ++!19 = !{i32 2, !"Dwarf Version", i32 4} ++!20 = !{i32 2, !"Debug Info Version", i32 3} ++!21 = !{i32 1, !"PIC Level", i32 2} ++!22 = !{!"clang version 4.0.0 (trunk 286129) (llvm/trunk 286128)"} ++ +diff --git a/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll b/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +index fcc11485..da43ec5c 100644 +--- a/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll ++++ b/test/DebugInfo/OpenCL100/DebugInfoSubrange.ll +@@ -14,8 +14,8 @@ + ; CHECK-SPIRV: Constant [[#TypeInt64Id]] [[#NegativeCount:]] 4294967295 4294967295 + + ; CHECK-SPIRV: [[#DbgFuncId:]] [[#]] DebugFunction [[#FuncNameId]] ++; CHECK-SPIRV: [[#]] [[#DbgLocVarId:]] [[#]] DebugLocalVariable [[#VarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DbgFuncId]] + ; CHECK-SPIRV: [[#DbgTemplateId:]] [[#]] DebugTypeTemplate [[#DbgFuncId]] +-; CHECK-SPIRV: [[#]] [[#DbgLocVarId:]] [[#]] DebugLocalVariable [[#VarNameId]] [[#]] [[#]] [[#]] [[#]] [[#DbgTemplateId]] + ; CHECK-SPIRV: DebugTypeArray [[#]] [[#DbgLocVarId]] [[#LowerBoundId]] + + ; CHECK-SPIRV: [[#DbgExprId:]] [[#]] DebugExpression +-- +2.20.1 + diff --git a/patches/0059-Only-generate-BuildIdentifier-if-non-semantic-debug-.patch b/patches/0059-Only-generate-BuildIdentifier-if-non-semantic-debug-.patch new file mode 100644 index 0000000..4511428 --- /dev/null +++ b/patches/0059-Only-generate-BuildIdentifier-if-non-semantic-debug-.patch @@ -0,0 +1,137 @@ +From f6991d88f643d4ccac57b379734d29d295851ba2 Mon Sep 17 00:00:00 2001 +From: LU-JOHN <111294400+LU-JOHN@users.noreply.github.com> +Date: Fri, 9 Jun 2023 04:23:38 -0500 +Subject: [PATCH 59/79] Only generate BuildIdentifier if non-semantic debug is + enabled (#2040) + +Only generate BuildIdentifier and StoragePath if non-semantic debug is enabled +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 3 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 37 ++++++++++--------- + test/DebugInfo/DebugInfoProducer.ll | 2 + + .../NonSemantic/DebugInfoProducer.ll | 4 ++ + .../Shader200}/storagePath_dwo.ll | 4 +- + 5 files changed, 29 insertions(+), 21 deletions(-) + rename test/DebugInfo/{ => NonSemantic/Shader200}/storagePath_dwo.ll (87%) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 821eafdb..757fd8ed 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -556,7 +556,8 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) { + Ops[DWARFVersionIdx] = M->getDwarfVersion(); + Ops[SourceIdx] = getSource(CU)->getId(); + +- generateBuildIdentifierAndStoragePath(CU); ++ if (isNonSemanticDebugInfo()) ++ generateBuildIdentifierAndStoragePath(CU); + + auto DwarfLang = + static_cast(CU->getSourceLanguage()); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 42026b62..42d6924f 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -211,30 +211,31 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + + BuilderMap[DebugInst->getId()] = std::make_unique(*M); + +- if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100) { +- return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), CompilerVersion, false, Flags, 0); +- } +- if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { +- StringRef Producer = getString(Ops[ProducerIdx]); +- return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); +- } +- // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug +- // info by default +- auto Producer = findModuleProducer(); + assert(BuilderMap.size() != 0 && "No debug compile units"); +- if (BuilderMap.size()==1) ++ if (isNonSemanticDebugInfo(DebugInst->getExtSetKind())) { + // Only initialize once +- setBuildIdentifierAndStoragePath(); ++ if (BuilderMap.size() == 1) ++ setBuildIdentifierAndStoragePath(); ++ ++ // This assertion is a guard/reminder to update the Producer argument to ++ // createCompileUnit() if a new DebugInfo type is ever created ++ assert(DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || ++ DebugInst->getExtSetKind() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200); + +- if (!StoragePath.empty()) { + return BuilderMap[DebugInst->getId()]->createCompileUnit( +- SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0, +- StoragePath, DICompileUnit::DebugEmissionKind::FullDebug, +- BuildIdentifier); ++ SourceLang, getFile(Ops[SourceIdx]), ++ DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 ++ ? CompilerVersion ++ : getString(Ops[ProducerIdx]), ++ false, Flags, 0, StoragePath, ++ DICompileUnit::DebugEmissionKind::FullDebug, BuildIdentifier); + } + ++ // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug ++ // info by default ++ auto Producer = findModuleProducer(); + return BuilderMap[DebugInst->getId()]->createCompileUnit( + SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); + } +diff --git a/test/DebugInfo/DebugInfoProducer.ll b/test/DebugInfo/DebugInfoProducer.ll +index fa5536fa..6fc05370 100644 +--- a/test/DebugInfo/DebugInfoProducer.ll ++++ b/test/DebugInfo/DebugInfoProducer.ll +@@ -43,6 +43,8 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + ; CHECK-LLVM-SAME: producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" + ; CHECK-LLVM-NOT: producer: "spirv" + ; CHECK-SPIRV: ModuleProcessed "Debug info producer: clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-NOT: DebugBuildIdentifier ++; CHECK-SPIRV-NOT: DebugStoragePath + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) + !1 = !DIFile(filename: "", directory: "oneAPI") +diff --git a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +index dfe1c8ce..a48e651e 100644 +--- a/test/DebugInfo/NonSemantic/DebugInfoProducer.ll ++++ b/test/DebugInfo/NonSemantic/DebugInfoProducer.ll +@@ -56,10 +56,14 @@ attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide- + ; CHECK-LLVM-100-SAME: flags: "-O2" + + ; CHECK-SPIRV-200: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-200: DebugBuildIdentifier [[#]] [[#]] ++; CHECK-SPIRV-200: DebugStoragePath [[#]] + ; CHECK-SPIRV-200: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#ProducerId]] + ; CHECK-SPIRV-200: DebugEntryPoint [[#]] [[#]] [[#ProducerId]] [[#]] {{$}} + + ; CHECK-SPIRV-100: String [[#ProducerId:]] "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16a50c9e642fd085e5ceb68c403b71b5b2e0607c)" ++; CHECK-SPIRV-100: DebugBuildIdentifier [[#]] [[#]] ++; CHECK-SPIRV-100: DebugStoragePath [[#]] + ; CHECK-SPIRV-100-NOT: DebugCompilationUnit [[#]] [[#]] [[#]] [[#]] [[#ProducerId]] {{$}} + ; CHECK-SPIRV-100: DebugEntryPoint [[#]] [[#]] [[#ProducerId]] [[#]] {{$}} + +diff --git a/test/DebugInfo/storagePath_dwo.ll b/test/DebugInfo/NonSemantic/Shader200/storagePath_dwo.ll +similarity index 87% +rename from test/DebugInfo/storagePath_dwo.ll +rename to test/DebugInfo/NonSemantic/Shader200/storagePath_dwo.ll +index 1cbb0ab8..273cee6e 100644 +--- a/test/DebugInfo/storagePath_dwo.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/storagePath_dwo.ll +@@ -2,8 +2,8 @@ + ; and spirv to LLVM IR translation. + + ; RUN: llvm-as %s -o %t.bc +-; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV +-; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -spirv-text -o - | FileCheck %s --check-prefix CHECK-SPIRV ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o %t.rev.ll + ; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM +-- +2.20.1 + diff --git a/patches/0060-Implement-DebugLine-and-DebugNoLine-2012.patch b/patches/0060-Implement-DebugLine-and-DebugNoLine-2012.patch new file mode 100644 index 0000000..309c5ce --- /dev/null +++ b/patches/0060-Implement-DebugLine-and-DebugNoLine-2012.patch @@ -0,0 +1,689 @@ +From 9c00a349fcf918674d62e6ac7a87abf390dc5a57 Mon Sep 17 00:00:00 2001 +From: LU-JOHN <111294400+LU-JOHN@users.noreply.github.com> +Date: Fri, 9 Jun 2023 07:05:17 -0500 +Subject: [PATCH 60/79] Implement DebugLine and DebugNoLine (#2012) + +Implement DebugLine/DebugNoLine for NonSemantic.Shader.DebugInfo.100 and NonSemantic.Shader.DebugInfo.200. +Updated test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll to test these changes. +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 12 ++- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 11 ++- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 19 ++++ + lib/SPIRV/libSPIRV/SPIRVEntry.cpp | 44 ++++++++- + lib/SPIRV/libSPIRV/SPIRVEntry.h | 4 + + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 2 + + lib/SPIRV/libSPIRV/SPIRVFunction.cpp | 14 ++- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 76 +++++++++++++++- + lib/SPIRV/libSPIRV/SPIRVModule.h | 10 +++ + lib/SPIRV/libSPIRV/SPIRVStream.cpp | 12 +++ + .../Shader200/DebugInfoStringType.ll | 43 +++++++-- + .../Shader200/DebugInfoSubrange.ll | 24 ++++- + .../Shader200/DebugInfoTargetFunction.ll | 21 ++++- + .../Shader200/DebugLinePriority.spt | 89 +++++++++++++++++++ + 14 files changed, 363 insertions(+), 18 deletions(-) + create mode 100644 test/DebugInfo/NonSemantic/Shader200/DebugLinePriority.spt + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 757fd8ed..d3daa263 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -233,8 +233,16 @@ void LLVMToSPIRVDbgTran::transLocationInfo() { + V = VPrev; + } + } +- BM->addLine(V, File ? File->getId() : getDebugInfoNone()->getId(), +- LineNo, Col); ++ if (BM->getDebugInfoEIS() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || ++ BM->getDebugInfoEIS() == ++ SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ BM->addDebugLine(V, getVoidTy(), ++ File ? File->getId() : getDebugInfoNoneId(), ++ LineNo, LineNo, Col, Col + 1); ++ else ++ BM->addLine(V, File ? File->getId() : getDebugInfoNoneId(), LineNo, ++ Col); + } + } // Instructions + } // Basic Blocks +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 42d6924f..6fffc4b1 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1513,7 +1513,16 @@ DebugLoc SPIRVToLLVMDbgTran::transDebugScope(const SPIRVInstruction *Inst) { + unsigned Col = 0; + MDNode *Scope = nullptr; + MDNode *InlinedAt = nullptr; +- if (auto L = Inst->getLine()) { ++ ++ // If DebugLine and OpLine are both active give DebugLine priority ++ if (auto DL = Inst->getDebugLine()) { ++ using namespace SPIRVDebug::Operand::DebugLine; ++ SPIRVWordVec DebugLineArgs = DL->getArguments(); ++ Line = ++ getConstantValueOrLiteral(DebugLineArgs, StartIdx, DL->getExtSetKind()); ++ Col = getConstantValueOrLiteral(DebugLineArgs, ColumnStartIdx, ++ DL->getExtSetKind()); ++ } else if (auto L = Inst->getLine()) { + Line = L->getLine(); + Col = L->getColumn(); + } +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 723a0b14..4f3ce378 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -57,6 +57,8 @@ enum Instruction { + InstCount = 37, + FunctionDefinition = 101, + SourceContinued = 102, ++ DebugLine = 103, ++ DebugNoLine = 104, + BuildIdentifier = 105, + StoragePath = 106, + EntryPoint = 107, +@@ -627,6 +629,23 @@ enum { + }; + } + ++namespace DebugLine { ++enum { ++ SourceIdx = 0, ++ StartIdx = 1, ++ EndIdx = 2, ++ ColumnStartIdx = 3, ++ ColumnEndIdx = 4, ++ OperandCount = 5 ++}; ++} ++ ++namespace DebugNoLine { ++enum { ++ OperandCount = 0 ++}; ++} ++ + namespace EntryPoint { + enum { + EntryPointIdx = 0, +diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.cpp b/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +index 919567a7..5ee1081b 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEntry.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +@@ -175,7 +175,7 @@ void SPIRVEntry::encodeLine(spv_ostream &O) const { + if (!Module) + return; + const std::shared_ptr &CurrLine = Module->getCurrentLine(); +- if (Line && ((CurrLine && *Line != *CurrLine) || !CurrLine)) { ++ if (Line && (!CurrLine || *Line != *CurrLine)) { + O << *Line; + Module->setCurrentLine(Line); + } +@@ -183,8 +183,43 @@ void SPIRVEntry::encodeLine(spv_ostream &O) const { + Module->setCurrentLine(nullptr); + } + ++namespace { ++bool isDebugLineEqual(const SPIRVExtInst &DL1, const SPIRVExtInst &DL2) { ++ std::vector DL1Args = DL1.getArguments(); ++ std::vector DL2Args = DL2.getArguments(); ++ ++ using namespace SPIRVDebug::Operand::DebugLine; ++ assert(DL1Args.size() == OperandCount && DL2Args.size() == OperandCount && ++ "Invalid number of operands"); ++ return DL1Args[SourceIdx] == DL2Args[SourceIdx] && ++ DL1Args[StartIdx] == DL2Args[StartIdx] && ++ DL1Args[EndIdx] == DL2Args[EndIdx] && ++ DL1Args[ColumnStartIdx] == DL2Args[ColumnStartIdx] && ++ DL1Args[ColumnEndIdx] == DL2Args[ColumnEndIdx]; ++} ++} // namespace ++ ++void SPIRVEntry::encodeDebugLine(spv_ostream &O) const { ++ if (!Module) ++ return; ++ const std::shared_ptr &CurrDebugLine = ++ Module->getCurrentDebugLine(); ++ if (DebugLine && ++ (!CurrDebugLine || !isDebugLineEqual(*DebugLine, *CurrDebugLine))) { ++ O << *DebugLine; ++ Module->setCurrentDebugLine(DebugLine); ++ } ++ if (isEndOfBlock() || ++ isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::DebugNoLine) || ++ isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVDebug::DebugNoLine)) ++ Module->setCurrentDebugLine(nullptr); ++} ++ + void SPIRVEntry::encodeAll(spv_ostream &O) const { + encodeLine(O); ++ encodeDebugLine(O); + encodeWordCountOpCode(O); + encode(O); + encodeChildren(O); +@@ -301,6 +336,11 @@ void SPIRVEntry::setLine(const std::shared_ptr &L) { + SPIRVDBG(if (L) spvdbgs() << "[setLine] " << *L << '\n';) + } + ++void SPIRVEntry::setDebugLine(const std::shared_ptr &DL) { ++ DebugLine = DL; ++ SPIRVDBG(if (DL) spvdbgs() << "[setDebugLine] " << *DL << '\n';) ++} ++ + void SPIRVEntry::addMemberDecorate(SPIRVMemberDecorate *Dec) { + assert(canHaveMemberDecorates() && + MemberDecorates.find(Dec->getPair()) == MemberDecorates.end()); +@@ -631,8 +671,6 @@ void SPIRVLine::encode(spv_ostream &O) const { + + void SPIRVLine::decode(std::istream &I) { + getDecoder(I) >> FileName >> Line >> Column; +- std::shared_ptr L(this); +- Module->setCurrentLine(L); + } + + void SPIRVLine::validate() const { +diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.h b/lib/SPIRV/libSPIRV/SPIRVEntry.h +index b43cd892..f497c95d 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEntry.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEntry.h +@@ -289,6 +289,7 @@ public: + return Id; + } + std::shared_ptr getLine() const { return Line; } ++ std::shared_ptr getDebugLine() const { return DebugLine; } + SPIRVLinkageTypeKind getLinkageType() const; + Op getOpCode() const { return OpCode; } + SPIRVModule *getModule() const { return Module; } +@@ -358,6 +359,7 @@ public: + void setHasNoId() { Attrib |= SPIRVEA_NOID; } + void setId(SPIRVId TheId) { Id = TheId; } + void setLine(const std::shared_ptr &L); ++ void setDebugLine(const std::shared_ptr &DL); + void setLinkageType(SPIRVLinkageTypeKind); + void setModule(SPIRVModule *TheModule); + void setName(const std::string &TheName); +@@ -384,6 +386,7 @@ public: + friend spv_ostream &operator<<(spv_ostream &O, const SPIRVEntry &E); + friend std::istream &operator>>(std::istream &I, SPIRVEntry &E); + virtual void encodeLine(spv_ostream &O) const; ++ virtual void encodeDebugLine(spv_ostream &O) const; + virtual void encodeAll(spv_ostream &O) const; + virtual void encodeName(spv_ostream &O) const; + virtual void encodeChildren(spv_ostream &O) const; +@@ -448,6 +451,7 @@ protected: + DecorateIdMapType DecorateIds; + MemberDecorateMapType MemberDecorates; + std::shared_ptr Line; ++ std::shared_ptr DebugLine; + }; + + class SPIRVEntryNoIdGeneric : public SPIRVEntry { +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index 315f73f0..e278726f 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -262,6 +262,8 @@ template <> inline void SPIRVMap::init() { + add(SPIRVDebug::Operation, "DebugOperation"); + add(SPIRVDebug::FunctionDefinition, "DebugFunctionDefinition"); + add(SPIRVDebug::SourceContinued, "DebugSourceContinued"); ++ add(SPIRVDebug::DebugLine, "DebugLine"); ++ add(SPIRVDebug::DebugNoLine, "DebugNoLine"); + add(SPIRVDebug::EntryPoint, "DebugEntryPoint"); + add(SPIRVDebug::BuildIdentifier, "DebugBuildIdentifier"); + add(SPIRVDebug::StoragePath, "DebugStoragePath"); +diff --git a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +index 8a339297..37698fa8 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVFunction.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVFunction.cpp +@@ -143,7 +143,8 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + SPIRVEntry *Entry = Decoder.getEntry(); + + if (Decoder.OpCode == OpLine) { +- Module->add(Entry); ++ std::shared_ptr L(static_cast(Entry)); ++ Module->setCurrentLine(L); + continue; + } + +@@ -159,6 +160,17 @@ bool SPIRVFunction::decodeBB(SPIRVDecoder &Decoder) { + assert(Inst); + if (Inst->getOpCode() == OpUndef) { + Module->add(Inst); ++ } else if (Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::DebugNoLine) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVDebug::DebugNoLine)) { ++ continue; ++ } else if (Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::DebugLine) || ++ Inst->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVDebug::DebugLine)) { ++ std::shared_ptr DL(static_cast(Inst)); ++ Module->setCurrentDebugLine(DL); + } else { + if (Inst->isExtInst(SPIRVEIS_Debug, SPIRVDebug::Scope) || + Inst->isExtInst(SPIRVEIS_OpenCL_DebugInfo_100, SPIRVDebug::Scope) || +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index dbfcd9f2..df64f167 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -186,6 +186,13 @@ public: + SPIRVWord Column) override; + const std::shared_ptr &getCurrentLine() const override; + void setCurrentLine(const std::shared_ptr &Line) override; ++ void addDebugLine(SPIRVEntry *E, SPIRVType *TheType, SPIRVId FileNameId, ++ SPIRVWord LineStart, SPIRVWord LineEnd, ++ SPIRVWord ColumnStart, SPIRVWord ColumnEnd) override; ++ const std::shared_ptr & ++ getCurrentDebugLine() const override; ++ void setCurrentDebugLine( ++ const std::shared_ptr &DebugLine) override; + void addCapability(SPIRVCapabilityKind) override; + void addCapabilityInternal(SPIRVCapabilityKind) override; + void addExtension(ExtensionID) override; +@@ -293,6 +300,8 @@ public: + const std::vector &, + SPIRVBasicBlock *, + SPIRVInstruction * = nullptr) override; ++ SPIRVEntry *createDebugInfo(SPIRVWord, SPIRVType *TheType, ++ const std::vector &) override; + SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType, + const std::vector &) override; + SPIRVEntry *addModuleProcessed(const std::string &) override; +@@ -506,6 +515,7 @@ private: + SPIRVStringVec StringVec; + SPIRVMemberNameVec MemberNameVec; + std::shared_ptr CurrentLine; ++ std::shared_ptr CurrentDebugLine; + SPIRVDecorateVec DecorateVec; + SPIRVDecGroupVec DecGroupVec; + SPIRVGroupDecVec GroupDecVec; +@@ -558,6 +568,60 @@ void SPIRVModuleImpl::addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line, + E->setLine(CurrentLine); + } + ++const std::shared_ptr & ++SPIRVModuleImpl::getCurrentDebugLine() const { ++ return CurrentDebugLine; ++} ++ ++void SPIRVModuleImpl::setCurrentDebugLine( ++ const std::shared_ptr &DebugLine) { ++ CurrentDebugLine = DebugLine; ++} ++ ++namespace { ++bool isDebugLineEqual(const SPIRVExtInst &CurrentDebugLine, SPIRVId FileNameId, ++ SPIRVId LineStartId, SPIRVId LineEndId, ++ SPIRVId ColumnStartId, SPIRVId ColumnEndId) { ++ assert(CurrentDebugLine.getExtOp() == SPIRVDebug::DebugLine); ++ const std::vector CurrentDebugLineArgs = ++ CurrentDebugLine.getArguments(); ++ ++ using namespace SPIRVDebug::Operand::DebugLine; ++ return CurrentDebugLineArgs[SourceIdx] == FileNameId && ++ CurrentDebugLineArgs[StartIdx] == LineStartId && ++ CurrentDebugLineArgs[EndIdx] == LineEndId && ++ CurrentDebugLineArgs[ColumnStartIdx] == ColumnStartId && ++ CurrentDebugLineArgs[ColumnEndIdx] == ColumnEndId; ++} ++} // namespace ++ ++void SPIRVModuleImpl::addDebugLine(SPIRVEntry *E, SPIRVType *TheType, ++ SPIRVId FileNameId, SPIRVWord LineStart, ++ SPIRVWord LineEnd, SPIRVWord ColumnStart, ++ SPIRVWord ColumnEnd) { ++ if (!(CurrentDebugLine && ++ isDebugLineEqual(*CurrentDebugLine, FileNameId, ++ getLiteralAsConstant(LineStart)->getId(), ++ getLiteralAsConstant(LineEnd)->getId(), ++ getLiteralAsConstant(ColumnStart)->getId(), ++ getLiteralAsConstant(ColumnEnd)->getId()))) { ++ using namespace SPIRVDebug::Operand::DebugLine; ++ ++ std::vector DebugLineOps(OperandCount); ++ DebugLineOps[SourceIdx] = FileNameId; ++ DebugLineOps[StartIdx] = getLiteralAsConstant(LineStart)->getId(); ++ DebugLineOps[EndIdx] = getLiteralAsConstant(LineEnd)->getId(); ++ DebugLineOps[ColumnStartIdx] = getLiteralAsConstant(ColumnStart)->getId(); ++ DebugLineOps[ColumnEndIdx] = getLiteralAsConstant(ColumnEnd)->getId(); ++ ++ CurrentDebugLine.reset(static_cast( ++ createDebugInfo(SPIRVDebug::DebugLine, TheType, DebugLineOps))); ++ } ++ ++ assert(E && "invalid entry"); ++ E->setDebugLine(CurrentDebugLine); ++} ++ + SPIRVValue *SPIRVModuleImpl::addSamplerConstant(SPIRVType *TheType, + SPIRVWord AddrMode, + SPIRVWord ParametricMode, +@@ -1298,11 +1362,16 @@ SPIRVInstruction *SPIRVModuleImpl::addExtInst( + InsertBefore); + } + ++SPIRVEntry * ++SPIRVModuleImpl::createDebugInfo(SPIRVWord InstId, SPIRVType *TheType, ++ const std::vector &Args) { ++ return new SPIRVExtInst(this, getId(), TheType, SPIRVEIS_OpenCL_DebugInfo_100, ++ ExtInstSetIds[getDebugInfoEIS()], InstId, Args); ++} ++ + SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType, + const std::vector &Args) { +- return addEntry( +- new SPIRVExtInst(this, getId(), TheType, SPIRVEIS_OpenCL_DebugInfo_100, +- ExtInstSetIds[getDebugInfoEIS()], InstId, Args)); ++ return addEntry(createDebugInfo(InstId, TheType, Args)); + } + + SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) { +@@ -1825,6 +1894,7 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { + SPIRVModuleImpl &MI = *static_cast(&M); + // Start tracking of the current line with no line + MI.CurrentLine.reset(); ++ MI.CurrentDebugLine.reset(); + + SPIRVEncoder Encoder(O); + Encoder << MagicNumber << MI.SPIRVVersion +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h +index 0241f914..b7a09cfd 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.h ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.h +@@ -198,6 +198,14 @@ public: + SPIRVWord Column) = 0; + virtual const std::shared_ptr &getCurrentLine() const = 0; + virtual void setCurrentLine(const std::shared_ptr &) = 0; ++ virtual void addDebugLine(SPIRVEntry *E, SPIRVType *TheType, ++ SPIRVId FileNameId, SPIRVWord LineStart, ++ SPIRVWord LineEnd, SPIRVWord ColumnStart, ++ SPIRVWord ColumnEnd) = 0; ++ virtual const std::shared_ptr & ++ getCurrentDebugLine() const = 0; ++ virtual void ++ setCurrentDebugLine(const std::shared_ptr &) = 0; + virtual const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *) = 0; + virtual SPIRVDecorationGroup *addDecorationGroup() = 0; + virtual SPIRVDecorationGroup * +@@ -307,6 +315,8 @@ public: + const std::vector &, + SPIRVBasicBlock *, + SPIRVInstruction * = nullptr) = 0; ++ virtual SPIRVEntry *createDebugInfo(SPIRVWord, SPIRVType *, ++ const std::vector &) = 0; + virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *, + const std::vector &) = 0; + virtual SPIRVEntry *addModuleProcessed(const std::string &) = 0; +diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.cpp b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +index 18fef3da..b30dbe2f 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVStream.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +@@ -245,9 +245,21 @@ SPIRVEntry *SPIRVDecoder::getEntry() { + Entry->setWordCount(WordCount); + if (OpCode != OpLine) + Entry->setLine(M.getCurrentLine()); ++ if (!Entry->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::DebugLine) && ++ !Entry->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVDebug::DebugLine)) ++ Entry->setDebugLine(M.getCurrentDebugLine()); ++ + IS >> *Entry; + if (Entry->isEndOfBlock() || OpCode == OpNoLine) + M.setCurrentLine(nullptr); ++ if (Entry->isEndOfBlock() || ++ Entry->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_100, ++ SPIRVDebug::DebugNoLine) || ++ Entry->isExtInst(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVDebug::DebugNoLine)) ++ M.setCurrentDebugLine(nullptr); + + if (OpExtension == OpCode) { + auto *OpExt = static_cast(Entry); +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll +index 7b82c1df..5506128a 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoStringType.ll +@@ -13,8 +13,20 @@ + ; CHECK-SPIRV: String [[#StrChar2:]] "CHARACTER_2" + ; CHECK-SPIRV: String [[#StrChar3:]] "CHARACTER_3" + ; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 0 +-; CHECK-SPIRV: Constant [[#TypeInt]] [[#ConstZero:]] 0 +-; CHECK-SPIRV: Constant [[#TypeInt]] [[#Const80:]] 80 ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#ConstZero:]] 0{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const1:]] 1{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const2:]] 2{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const6:]] 6{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const7:]] 7{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const9:]] 9{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const12:]] 12{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const23:]] 23{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const24:]] 24{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const27:]] 27{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const28:]] 28{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const36:]] 36{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const37:]] 37{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TypeInt]] [[#Const80:]] 80{{[[:space:]]}} + ; CHECK-SPIRV: TypeVoid [[#TypeVoid:]] + + ; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone +@@ -32,14 +44,33 @@ + ; CHECK-SPIRV-COUNT-4: [[#LengthAddrVar2:]] [[#EISId]] DebugLocalVariable + ; CHECK-SPIRV-NEXT: [[#EISId]] DebugTypeString [[#StrChar2]] [[#DINoneId]] [[#DINoneId]] [[#ConstZero]] [[#LengthAddrVar2]] + +-; CHECK-LLVM: !DICompileUnit(language: DW_LANG_Fortran95 ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const6]] [[#Const6]] [[#Const23]] [[#Const24]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#ConstZero]] [[#ConstZero]] [[#ConstZero]] [[#Const1]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const9]] [[#Const9]] [[#Const27]] [[#Const28]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const9]] [[#Const9]] [[#Const36]] [[#Const37]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const7]] [[#Const7]] [[#Const1]] [[#Const2]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#ConstZero]] [[#ConstZero]] [[#ConstZero]] [[#Const1]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const9]] [[#Const9]] [[#Const27]] [[#Const28]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const9]] [[#Const9]] [[#Const36]] [[#Const37]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Const12]] [[#Const12]] [[#Const1]] [[#Const2]] ++ ++; CHECK-LLVM-DAG: !DICompileUnit(language: DW_LANG_Fortran95 ++; CHECK-LLVM-DAG: ![[#Scope_hello_world:]] = distinct !DISubprogram(name: "hello_world", linkageName: "MAIN__" ++; CHECK-LLVM-DAG: !DILocation(line: 6, column: 23, scope: ![[#Scope_hello_world]] + ; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_1", size: 80) + ; CHECK-LLVM-DAG: !DIStringType(name: ".str.GREETING", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref)) +-; CHECK-LLVM-DAG: ![[#Scope:]] = distinct !DISubprogram(name: "print_greeting", linkageName: "print_greeting_" +-; CHECK-LLVM-DAG: ![[#StrLenMD:]] = !DILocalVariable(name: "STRING1.len", scope: ![[#Scope]] ++; CHECK-LLVM-DAG: ![[#Scope_print_greeting:]] = distinct !DISubprogram(name: "print_greeting", linkageName: "print_greeting_" ++; CHECK-LLVM-DAG: ![[#StrLenMD:]] = !DILocalVariable(name: "STRING1.len", scope: ![[#Scope_print_greeting]] + ; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_2", stringLength: ![[#StrLenMD]]) +-; CHECK-LLVM-DAG: ![[#StrLenMD1:]] = !DILocalVariable(name: "STRING2.len", scope: ![[#Scope]] ++; CHECK-LLVM-DAG: ![[#StrLenMD1:]] = !DILocalVariable(name: "STRING2.len", scope: ![[#Scope_print_greeting]] + ; CHECK-LLVM-DAG: !DIStringType(name: "CHARACTER_3", stringLength: ![[#StrLenMD1]]) ++; CHECK-LLVM: !DILocation(line: 9, column: 27, scope: ![[#Scope_print_greeting]] ++; CHECK-LLVM-NEXT: !DILocation(line: 9, column: 36, scope: ![[#Scope_print_greeting]] ++; CHECK-LLVM-NEXT: !DILocation(line: 7, column: 1, scope: ![[#Scope_hello_world]] ++; CHECK-LLVM-NEXT: !DILocation(line: 0, scope: ![[#Scope_print_greeting]] ++; CHECK-LLVM-NEXT: !DILocation(line: 9, column: 27, scope: ![[#Scope_print_greeting]] ++; CHECK-LLVM-NEXT: !DILocation(line: 9, column: 36, scope: ![[#Scope_print_greeting]] ++; CHECK-LLVM-NEXT: !DILocation(line: 12, column: 1, scope: ![[#Scope_print_greeting]] + + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "spir64-unknown-unknown" +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +index 3bb29f08..f3317e08 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoSubrange.ll +@@ -10,7 +10,17 @@ + ; CHECK-SPIRV: ExtInstImport [[#EISId:]] "NonSemantic.Shader.DebugInfo.200" + + ; CHECK-SPIRV: String [[#LocalVarNameId:]] "A$1$upperbound" +-; CHECK-SPIRV: TypeInt [[#TyInt64Id:]] 64 0 ++; CHECK-SPIRV-DAG: TypeInt [[#TyInt32Id:]] 32 0 ++; CHECK-SPIRV-DAG: TypeInt [[#TyInt64Id:]] 64 0 ++; CHECK-NOT: THIS LINE IS USED TO SEPARATE DAGs ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant15Id:]] 15{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant24Id:]] 24{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant25Id:]] 25{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant27Id:]] 27{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant33Id:]] 33{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant34Id:]] 34{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant67Id:]] 67{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant68Id:]] 68{{[[:space:]]}} + ; CHECK-SPIRV-DAG: Constant [[#TyInt64Id]] [[#Constant1Id:]] 1 0 + ; CHECK-SPIRV-DAG: Constant [[#TyInt64Id]] [[#Constant1000Id:]] 1000 0 + ; CHECK-SPIRV: [[#DINoneId:]] [[#EISId]] DebugInfoNone +@@ -25,10 +35,22 @@ + + ; CHECK-SPIRV: [[#EISId]] DebugTypeSubrange [[#Constant1000Id]] [[#Constant1Id]] [[#DINoneId]] [[#DINoneId]] + ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant15Id]] [[#Constant15Id]] [[#Constant67Id]] [[#Constant68Id]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant27Id]] [[#Constant27Id]] [[#Constant24Id]] [[#Constant25Id]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant34Id]] [[#Constant34Id]] [[#Constant33Id]] [[#Constant34Id]] ++ ++; CHECK-LLVM: ![[#Scope_A:]] = distinct !DISubprogram(name: "random_fill_sp.DIR.OMP.TARGET.8.split.split.split.split" + ; CHECK-LLVM: [[#Subrange1:]] = !DISubrange(lowerBound: 1, upperBound: ![[#UpperBound:]]) + ; CHECK-LLVM: [[#UpperBound]] = !DILocalVariable(name: "A$1$upperbound" ++; CHECK-LLVM: !DILocation(line: 15, column: 67, scope: ![[#Scope_A]] ++; CHECK-LLVM: ![[#Scope_B:]] = distinct !DISubprogram(name: "random_fill_sp.DIR.OMP.TARGET.8.split.split.split.split" + ; CHECK-LLVM: !DISubrange(lowerBound: !DIExpression(), upperBound: !DIExpression()) ++; CHECK-LLVM: !DILocation(line: 15, column: 67, scope: ![[#Scope_B]] ++; CHECK-LLVM: ![[#Scope_C:]] = distinct !DISubprogram(name: "test_target_map_array_default_IP_test_array_map_no_map_type_.DIR.OMP.TARGET.340.split" + ; CHECK-LLVM: !DISubrange(count: 1000, lowerBound: 1) ++; CHECK-LLVM: !DILocation(line: 27, column: 24, scope: ![[#Scope_C]] ++; CHECK-LLVM: ![[#Scope_D:]] = distinct !DISubprogram(name: "test" ++; CHECK-LLVM: !DILocation(line: 34, column: 33, scope: ![[#Scope_D]] + + ; ModuleID = 'DebugInfoSubrangeUpperBound.bc' + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +index 074305af..d2980cdf 100644 +--- a/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugInfoTargetFunction.ll +@@ -11,11 +11,30 @@ + ; CHECK-SPIRV-DAG: String [[#Func:]] "foo_wrapper" + ; CHECK-SPIRV-DAG: String [[#TargetFunc:]] "_Z3foov" + ++; CHECK-SPIRV-DAG: TypeInt [[#TyInt32Id:]] 32 0 ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant1Id:]] 1{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant2Id:]] 2{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant4Id:]] 4{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant5Id:]] 5{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant6Id:]] 6{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant8Id:]] 8{{[[:space:]]}} ++; CHECK-SPIRV-DAG: Constant [[#TyInt32Id]] [[#Constant9Id:]] 9{{[[:space:]]}} ++ + ; CHECK-SPIRV-DAG: ExtInst [[#]] [[#DebugNone:]] [[#]] DebugInfoNone + ; CHECK-SPIRV-DAG: ExtInst [[#]] [[#]] [[#]] DebugFunction [[#Func]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#DebugNone]] [[#TargetFunc]] + ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant4Id]] [[#Constant4Id]] [[#Constant5Id]] [[#Constant6Id]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant5Id]] [[#Constant5Id]] [[#Constant1Id]] [[#Constant2Id]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant8Id]] [[#Constant8Id]] [[#Constant5Id]] [[#Constant6Id]] ++; CHECK-SPIRV: [[#EISId]] DebugLine [[#]] [[#Constant9Id]] [[#Constant9Id]] [[#Constant1Id]] [[#Constant2Id]] ++ + ; CHECK-LLVM: define spir_func void @_Z11foo_wrapperv() {{.*}} !dbg ![[#DbgSubProg:]] { +-; CHECK-LLVM: ![[#DbgSubProg]] = distinct !DISubprogram(name: "foo_wrapper", linkageName: "_Z11foo_wrapperv", scope: null, file: ![[#]], line: 3, type: ![[#]], scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], templateParams: ![[#]], retainedNodes: ![[#]], targetFuncName: "_Z3foov") ++; CHECK-LLVM: ![[#Scope_foo_wrapper:]] = distinct !DISubprogram(name: "foo_wrapper", linkageName: "_Z11foo_wrapperv", scope: null, file: ![[#]], line: 3, type: ![[#]], scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], templateParams: ![[#]], retainedNodes: ![[#]], targetFuncName: "_Z3foov") ++; CHECK-LLVM: !DILocation(line: 4, column: 5, scope: ![[#Scope_foo_wrapper]] ++; CHECK-LLVM: !DILocation(line: 5, column: 1, scope: ![[#Scope_foo_wrapper]] ++; CHECK-LLVM: ![[#Scope_boo:]] = distinct !DISubprogram(name: "boo", linkageName: "_Z3boov" ++; CHECK-LLVM: !DILocation(line: 8, column: 5, scope: ![[#Scope_boo]] ++; CHECK-LLVM: !DILocation(line: 9, column: 1, scope: ![[#Scope_boo]] + + ; ModuleID = 'example.bc' + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024" +diff --git a/test/DebugInfo/NonSemantic/Shader200/DebugLinePriority.spt b/test/DebugInfo/NonSemantic/Shader200/DebugLinePriority.spt +new file mode 100644 +index 00000000..55ed4a94 +--- /dev/null ++++ b/test/DebugInfo/NonSemantic/Shader200/DebugLinePriority.spt +@@ -0,0 +1,89 @@ ++; RUN: llvm-spirv -to-binary %s -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s -check-prefix=CHECK-LLVM ++ ++; CHECK-LLVM: %[[#Var:]] = load i32, i32* @_ZN5Outer5Inner6globalE, align 4, !dbg ![[#LineLoc:]] ++; CHECK-LLVM: %inc = add nsw i32 %[[#Var]], 1, !dbg ![[#DebugLineLoc:]] ++; CHECK-LLVM: ![[#LineLoc]] = !DILocation(line: 357, column: 113, scope: ![[#Scope:]]) ++; CHECK-LLVM: ![[#DebugLineLoc]] = !DILocation(line: 8, column: 16, scope: ![[#Scope]]) ++ ++119734787 66560 393230 54 0 ++2 Capability Addresses ++2 Capability Linkage ++2 Capability Kernel ++8 Extension "SPV_KHR_non_semantic_info" ++5 ExtInstImport 1 "OpenCL.std" ++11 ExtInstImport 2 "NonSemantic.Shader.DebugInfo.200" ++3 MemoryModel 2 2 ++10 String 14 "/path/to/inlined-namespace.cxx" ++3 String 16 "0" ++3 String 18 "" ++4 String 23 "clang" ++3 String 25 "int" ++3 String 30 "foo" ++4 String 31 "_Z3foov" ++4 String 37 "Outer" ++4 String 41 "Inner" ++4 String 44 "global" ++8 String 45 "_ZN5Outer5Inner6globalE" ++3 Source 0 0 ++8 Name 6 "_ZN5Outer5Inner6globalE" ++4 Name 9 "_Z3foov" ++4 Name 10 "entry" ++3 Name 13 "inc" ++10 Decorate 6 LinkageAttributes "_ZN5Outer5Inner6globalE" Export ++4 Decorate 6 Alignment 4 ++6 Decorate 9 LinkageAttributes "_Z3foov" Export ++3 Decorate 13 NoSignedWrap ++4 TypeInt 3 32 0 ++4 Constant 3 5 0 ++4 Constant 3 12 1 ++4 Constant 3 20 65536 ++4 Constant 3 21 4 ++4 Constant 3 22 217 ++4 Constant 3 26 32 ++4 Constant 3 32 7 ++4 Constant 3 33 136 ++4 Constant 3 46 3 ++4 Constant 3 47 8 ++4 Constant 3 50 16 ++4 Constant 3 52 9 ++4 TypePointer 4 7 3 ++2 TypeVoid 7 ++3 TypeFunction 8 7 ++2 TypeBool 38 ++5 Variable 4 6 7 5 ++3 ConstantTrue 38 39 ++3 ConstantFalse 38 42 ++ ++6 ExtInst 7 15 2 DebugSource 14 ++7 ExtInst 7 17 2 DebugBuildIdentifier 16 12 ++6 ExtInst 7 19 2 DebugStoragePath 18 ++10 ExtInst 7 24 2 DebugCompilationUnit 20 21 15 22 23 ++8 ExtInst 7 27 2 DebugTypeBasic 25 26 21 ++5 ExtInst 7 28 2 DebugInfoNone ++7 ExtInst 7 29 2 DebugTypeFunction 5 28 ++15 ExtInst 7 34 2 DebugFunction 30 29 15 32 5 24 31 33 32 28 ++6 ExtInst 7 36 2 DebugSource 18 ++11 ExtInst 7 40 2 DebugLexicalBlock 36 5 5 24 37 39 ++11 ExtInst 7 43 2 DebugLexicalBlock 36 5 5 40 41 42 ++14 ExtInst 7 48 2 DebugGlobalVariable 44 27 15 46 5 43 45 6 47 ++ ++5 Function 7 9 2 8 ++ ++2 Label 10 ++7 ExtInst 7 35 2 DebugFunctionDefinition 34 9 ++6 ExtInst 7 49 2 DebugScope 34 ++4 Line 14 357 113 ++6 Load 3 11 6 2 4 ++10 ExtInst 7 51 2 DebugLine 14 47 47 50 33 ++5 IAdd 3 13 11 12 ++5 ExtInst 7 511 2 DebugNoLine ++5 ISub 3 137 11 12 ++1 NoLine ++5 Store 6 13 2 4 ++1 Return ++ ++1 FunctionEnd ++ +-- +2.20.1 + diff --git a/patches/0061-DebugInfo-Adjust-TypeInheritance-for-NonSemantic-spe.patch b/patches/0061-DebugInfo-Adjust-TypeInheritance-for-NonSemantic-spe.patch new file mode 100644 index 0000000..62512cf --- /dev/null +++ b/patches/0061-DebugInfo-Adjust-TypeInheritance-for-NonSemantic-spe.patch @@ -0,0 +1,242 @@ +From 2a2e7c138a8ff0f161e879e3fcab804b2f8f6d34 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Fri, 9 Jun 2023 14:05:37 +0200 +Subject: [PATCH 61/79] [DebugInfo] Adjust TypeInheritance for NonSemantic spec + (#2039) + +It does not have Child parameter comparing to OpenCL specification. +https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc#DebugTypeInheritance +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 20 +++--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 33 ++++++--- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 3 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 14 ++-- + test/DebugInfo/DebugInfoTypeInheritance.ll | 83 ++++++++++++++++++++++ + 5 files changed, 129 insertions(+), 24 deletions(-) + create mode 100644 test/DebugInfo/DebugInfoTypeInheritance.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index d3daa263..0562e809 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1043,16 +1043,20 @@ LLVMToSPIRVDbgTran::transDbgMemberTypeNonSemantic(const DIDerivedType *MT) { + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) { + using namespace SPIRVDebug::Operand::TypeInheritance; +- SPIRVWordVec Ops(OperandCount); +- Ops[ChildIdx] = transDbgEntry(DT->getScope())->getId(); +- Ops[ParentIdx] = transDbgEntry(DT->getBaseType())->getId(); +- ConstantInt *Offset = getUInt(M, DT->getOffsetInBits()); +- Ops[OffsetIdx] = SPIRVWriter->transValue(Offset, nullptr)->getId(); ++ const SPIRVWord Offset = isNonSemanticDebugInfo() ? 1 : 0; ++ SPIRVWordVec Ops(OperandCount - Offset); ++ // There is no Child operand in NonSemantic debug spec ++ if (!isNonSemanticDebugInfo()) ++ Ops[ChildIdx] = transDbgEntry(DT->getScope())->getId(); ++ Ops[ParentIdx - Offset] = transDbgEntry(DT->getBaseType())->getId(); ++ ConstantInt *OffsetInBits = getUInt(M, DT->getOffsetInBits()); ++ Ops[OffsetIdx - Offset] = ++ SPIRVWriter->transValue(OffsetInBits, nullptr)->getId(); + ConstantInt *Size = getUInt(M, DT->getSizeInBits()); +- Ops[SizeIdx] = SPIRVWriter->transValue(Size, nullptr)->getId(); +- Ops[FlagsIdx] = transDebugFlags(DT); ++ Ops[SizeIdx - Offset] = SPIRVWriter->transValue(Size, nullptr)->getId(); ++ Ops[FlagsIdx - Offset] = transDebugFlags(DT); + if (isNonSemanticDebugInfo()) +- transformToConstant(Ops, {FlagsIdx}); ++ transformToConstant(Ops, {FlagsIdx - Offset}); + return BM->addDebugInfo(SPIRVDebug::TypeInheritance, getVoidTy(), Ops); + } + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 6fffc4b1..978068e6 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -543,6 +543,11 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) { + transTypeMember(SPVMemberInst, DebugInst, cast(CT)); + EltTys.push_back(MemberMD); + DebugInstCache[SPVMemberInst] = MemberMD; ++ } else if (MemberInst->getExtOp() == SPIRVDebug::TypeInheritance) { ++ auto *SPVMemberInst = BM->get(Ops[I]); ++ DINode *MemberMD = transTypeInheritance(SPVMemberInst, cast(CT)); ++ EltTys.push_back(MemberMD); ++ DebugInstCache[SPVMemberInst] = MemberMD; + } else { + EltTys.emplace_back(transDebugInst(BM->get(Ops[I]))); + } +@@ -1148,25 +1153,35 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) { + return getDIBuilder(DebugInst).createTypedef(Ty, Alias, File, LineNo, Scope); + } + +-DINode * +-SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst) { ++DINode *SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst, ++ DIType *ChildClass) { ++ if (isNonSemanticDebugInfo(DebugInst->getExtSetKind()) && !ChildClass) { ++ // Will be translated later when processing TypeMember's parent ++ return nullptr; ++ } + using namespace SPIRVDebug::Operand::TypeInheritance; + const SPIRVWordVec &Ops = DebugInst->getArguments(); +- assert(Ops.size() >= OperandCount && "Invalid number of operands"); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ // No Child operand for NonSemantic debug spec ++ SPIRVWord Offset = isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ? 1 : 0; + DIType *Parent = +- transDebugInst(BM->get(Ops[ParentIdx])); +- DIType *Child = transDebugInst(BM->get(Ops[ChildIdx])); ++ transDebugInst(BM->get(Ops[ParentIdx - Offset])); ++ DIType *Child = ++ isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ++ ? ChildClass ++ : transDebugInst(BM->get(Ops[ChildIdx])); + DINode::DIFlags Flags = DINode::FlagZero; +- SPIRVWord SPIRVFlags = +- getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); ++ SPIRVWord SPIRVFlags = getConstantValueOrLiteral(Ops, FlagsIdx - Offset, ++ DebugInst->getExtSetKind()); + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) + Flags |= llvm::DINode::FlagPublic; + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected) + Flags |= llvm::DINode::FlagProtected; + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) + Flags |= llvm::DINode::FlagPrivate; +- uint64_t Offset = BM->get(Ops[OffsetIdx])->getZExtIntValue(); +- return getDIBuilder(DebugInst).createInheritance(Child, Parent, Offset, 0, ++ uint64_t OffsetVal = ++ BM->get(Ops[OffsetIdx - Offset])->getZExtIntValue(); ++ return getDIBuilder(DebugInst).createInheritance(Child, Parent, OffsetVal, 0, + Flags); + } + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 48d7ea6b..05e1506a 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -166,7 +166,8 @@ private: + + DINode *transTypedef(const SPIRVExtInst *DebugInst); + +- DINode *transTypeInheritance(const SPIRVExtInst *DebugInst); ++ DINode *transTypeInheritance(const SPIRVExtInst *DebugInst, ++ DIType *ChildClass = nullptr); + + DINode *transImportedEntry(const SPIRVExtInst *DebugInst); + +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index 4f3ce378..d4823257 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -501,12 +501,14 @@ enum { + + namespace TypeInheritance { + enum { +- ChildIdx = 0, +- ParentIdx = 1, +- OffsetIdx = 2, +- SizeIdx = 3, +- FlagsIdx = 4, +- OperandCount = 5 ++ ChildIdx = 0, ++ ParentIdx = 1, ++ OffsetIdx = 2, ++ SizeIdx = 3, ++ FlagsIdx = 4, ++ // NonSemantic ++ MinOperandCount = 4, ++ OperandCount = 5 + }; + } + +diff --git a/test/DebugInfo/DebugInfoTypeInheritance.ll b/test/DebugInfo/DebugInfoTypeInheritance.ll +new file mode 100644 +index 00000000..8096b0c9 +--- /dev/null ++++ b/test/DebugInfo/DebugInfoTypeInheritance.ll +@@ -0,0 +1,83 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-OCL ++; RUN: llvm-spirv %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spt ++; RUN: FileCheck %s --input-file %t.spt --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NONSEM ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-100 -o %t.spv ++; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll --check-prefix CHECK-LLVM ++ ++; CHECK-SPIRV: String [[#Str_C:]] "C" ++; CHECK-SPIRV: String [[#Str_B:]] "B" ++; CHECK-SPIRV: String [[#Str_A:]] "A" ++ ++; CHECK-SPIRV: [[#Class_A:]] [[#]] DebugTypeComposite [[#Str_A]] ++ ++; CHECK-SPIRV-OCL: [[#B_inherits_A:]] [[#]] DebugTypeInheritance [[#Class_B:]] [[#Class_A]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV-NONSEM: [[#B_inherits_A:]] [[#]] DebugTypeInheritance [[#Class_A]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: [[#Class_B:]] [[#]] DebugTypeComposite [[#Str_B]] {{.*}} [[#B_inherits_A]] ++ ++; CHECK-SPIRV-OCL: [[#C_inherits_B:]] [[#]] DebugTypeInheritance [[#Class_C:]] [[#Class_B]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV-NONSEM: [[#C_inherits_B:]] [[#]] DebugTypeInheritance [[#Class_B]] [[#]] [[#]] [[#]] {{$}} ++; CHECK-SPIRV: [[#Class_C:]] [[#]] DebugTypeComposite [[#Str_C]] {{.*}} [[#C_inherits_B]] ++ ++; CHECK-LLVM: ![[#Class_C:]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}identifier: "_ZTS1C") ++; CHECK-LLVM: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[#Class_C]], baseType: ![[#Class_B:]] ++; CHECK-LLVM: ![[#Class_B]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B"{{.*}}identifier: "_ZTS1B") ++; CHECK-LLVM: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[#Class_B]], baseType: ![[#Class_A:]] ++; CHECK-LLVM: ![[#Class_A]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A"{{.*}}identifier: "_ZTS1A") ++ ++target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ++target triple = "spir64-unknown-unknown" ++ ++%class.C = type { i8 } ++ ++; Function Attrs: mustprogress noinline nounwind optnone uwtable ++define dso_local noundef i32 @_Z3foov() #0 !dbg !10 { ++ %1 = alloca %class.C, align 1 ++ call void @llvm.dbg.declare(metadata %class.C* %1, metadata !16, metadata !DIExpression()), !dbg !24 ++ ret i32 0, !dbg !25 ++} ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ++declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ++ ++attributes #0 = { mustprogress noinline } ++attributes #1 = { willreturn } ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} ++!llvm.ident = !{!9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 1f8a33c19c79fd4649a07eb70ea394c60a8ce316)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "/app/example.cpp", directory: "/app") ++!2 = !{i32 7, !"Dwarf Version", i32 4} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = !{i32 1, !"wchar_size", i32 4} ++!5 = !{i32 8, !"PIC Level", i32 2} ++!6 = !{i32 7, !"PIE Level", i32 2} ++!7 = !{i32 7, !"uwtable", i32 2} ++!8 = !{i32 7, !"frame-pointer", i32 2} ++!9 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git 1f8a33c19c79fd4649a07eb70ea394c60a8ce316)"} ++!10 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !11, file: !11, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) ++!11 = !DIFile(filename: "example.cpp", directory: "/app") ++!12 = !DISubroutineType(types: !13) ++!13 = !{!14} ++!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!15 = !{} ++!16 = !DILocalVariable(name: "c", scope: !10, file: !11, line: 7, type: !17) ++!17 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C", file: !11, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !18, identifier: "_ZTS1C") ++!18 = !{!19} ++!19 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !17, baseType: !20, flags: DIFlagPublic, extraData: i32 0) ++!20 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", file: !11, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS1B") ++!21 = !{!22} ++!22 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !20, baseType: !23, flags: DIFlagPublic, extraData: i32 0) ++!23 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !11, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !15, identifier: "_ZTS1A") ++!24 = !DILocation(line: 7, column: 11, scope: !10) ++!25 = !DILocation(line: 8, column: 3, scope: !10) +-- +2.20.1 + diff --git a/patches/0062-DebugInfo-Add-Column-parameter-to-DebugInlinedAt-ins.patch b/patches/0062-DebugInfo-Add-Column-parameter-to-DebugInlinedAt-ins.patch new file mode 100644 index 0000000..dff5160 --- /dev/null +++ b/patches/0062-DebugInfo-Add-Column-parameter-to-DebugInlinedAt-ins.patch @@ -0,0 +1,238 @@ +From 0f2c3239c3565c30fd1a5932a6a1dd329e570f78 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Sun, 11 Jun 2023 13:39:02 +0200 +Subject: [PATCH 62/79] [DebugInfo] Add Column parameter to DebugInlinedAt + instruction (#2042) + +The change is done as a part of NonSemantic.Shader.200 spec, and the new +arguments for the instructions will look like: + +| \ Line| \ Column| \ Scope| Optional\ Inlined| +|--------|--------|--------|--------| +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 18 ++++++++++++- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 1 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 29 +++++++++++++++++++-- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 1 + + lib/SPIRV/libSPIRV/SPIRV.debug.h | 23 +++++++++++++--- + test/DebugInfo/Generic/inlined-locations.ll | 15 ++++++++--- + 6 files changed, 77 insertions(+), 10 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 0562e809..8945daed 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1389,7 +1389,10 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDebugLoc(const DebugLoc &Loc, + } + + SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInlinedAt(const DILocation *Loc) { +- using namespace SPIRVDebug::Operand::InlinedAt; ++ // There is a Column operand in NonSemantic.Shader.200 spec ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ return transDbgInlinedAtNonSemanticShader200(Loc); ++ using namespace SPIRVDebug::Operand::InlinedAt::OpenCL; + SPIRVWordVec Ops(MinOperandCount); + Ops[LineIdx] = Loc->getLine(); + Ops[ScopeIdx] = getScope(Loc->getScope())->getId(); +@@ -1400,6 +1403,19 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInlinedAt(const DILocation *Loc) { + return BM->addDebugInfo(SPIRVDebug::InlinedAt, getVoidTy(), Ops); + } + ++SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInlinedAtNonSemanticShader200( ++ const DILocation *Loc) { ++ using namespace SPIRVDebug::Operand::InlinedAt::NonSemantic; ++ SPIRVWordVec Ops(MinOperandCount); ++ Ops[LineIdx] = Loc->getLine(); ++ Ops[ColumnIdx] = Loc->getColumn(); ++ transformToConstant(Ops, {LineIdx, ColumnIdx}); ++ Ops[ScopeIdx] = getScope(Loc->getScope())->getId(); ++ if (DILocation *IA = Loc->getInlinedAt()) ++ Ops.push_back(transDbgEntry(IA)->getId()); ++ return BM->addDebugInfo(SPIRVDebug::InlinedAt, getVoidTy(), Ops); ++} ++ + template + SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + const std::string FileName = getFullPath(DIEntry); +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index 21bd6f2f..fa1e8cf7 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -144,6 +144,7 @@ private: + SPIRVEntry *transDebugLoc(const DebugLoc &Loc, SPIRVBasicBlock *BB, + SPIRVInstruction *InsertBefore = nullptr); + SPIRVEntry *transDbgInlinedAt(const DILocation *D); ++ SPIRVEntry *transDbgInlinedAtNonSemanticShader200(const DILocation *D); + + template SPIRVExtInst *getSource(const T *DIEntry); + SPIRVEntry *transDbgFileType(const DIFile *F); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 978068e6..ed61b4f6 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1554,7 +1554,12 @@ DebugLoc SPIRVToLLVMDbgTran::transDebugScope(const SPIRVInstruction *Inst) { + } + + MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *DebugInst) { +- using namespace SPIRVDebug::Operand::InlinedAt; ++ // There is a Column operand in NonSemantic.Shader.200 spec ++ if (DebugInst->getExtSetKind() == ++ SPIRV::SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ return transDebugInlinedNonSemanticShader200(DebugInst); ++ ++ using namespace SPIRVDebug::Operand::InlinedAt::OpenCL; + SPIRVWordVec Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + SPIRVWord Line = +@@ -1570,6 +1575,25 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *DebugInst) { + return DILocation::getDistinct(M->getContext(), Line, Col, Scope, InlinedAt); + } + ++MDNode *SPIRVToLLVMDbgTran::transDebugInlinedNonSemanticShader200( ++ const SPIRVExtInst *DebugInst) { ++ using namespace SPIRVDebug::Operand::InlinedAt::NonSemantic; ++ SPIRVWordVec Ops = DebugInst->getArguments(); ++ assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); ++ SPIRVWord Line = ++ getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); ++ unsigned Col = ++ getConstantValueOrLiteral(Ops, ColumnIdx, DebugInst->getExtSetKind()); ++ DILocalScope *Scope = ++ cast(getScope(BM->getEntry(Ops[ScopeIdx]))); ++ DILocation *InlinedAt = nullptr; ++ if (Ops.size() > InlinedIdx) { ++ InlinedAt = ++ transDebugInst(BM->get(Ops[InlinedIdx])); ++ } ++ return DILocation::getDistinct(M->getContext(), Line, Col, Scope, InlinedAt); ++} ++ + void SPIRVToLLVMDbgTran::finalize() { + if (!Enable) + return; +@@ -1673,7 +1697,8 @@ DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) { + return *BuilderMap.begin()->second; + const SPIRVWordVec &Ops = DebugInst->getArguments(); + SPIRVWord ParentScopeIdx = 0; +- if (!hasDbgInstParentScopeIdx(DebugInst->getExtOp(), ParentScopeIdx)) ++ if (!hasDbgInstParentScopeIdx(DebugInst->getExtOp(), ParentScopeIdx, ++ DebugInst->getExtSetKind())) + return *BuilderMap.begin()->second; + if (SPIRVEntry *Scope = BM->getEntry(Ops[ParentScopeIdx])) { + DebugInst = static_cast(Scope); +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 05e1506a..b166abc9 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -104,6 +104,7 @@ private: + llvm::DebugLoc transDebugScope(const SPIRVInstruction *Inst); + + MDNode *transDebugInlined(const SPIRVExtInst *Inst); ++ MDNode *transDebugInlinedNonSemanticShader200(const SPIRVExtInst *Inst); + + DICompileUnit *transCompilationUnit(const SPIRVExtInst *DebugInst, + const std::string CompilerVersion = "", +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index d4823257..ff0bb548 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -1,5 +1,6 @@ + #ifndef SPIRV_DEBUG_H + #define SPIRV_DEBUG_H ++#include "SPIRVEnum.h" + #include "SPIRVUtil.h" + #include "spirv/unified1/spirv.hpp" + #include "spirv_internal.hpp" +@@ -692,13 +693,25 @@ namespace NoScope { + } + + namespace InlinedAt { ++namespace OpenCL { + enum { + LineIdx = 0, + ScopeIdx = 1, + InlinedIdx = 2, + MinOperandCount = 2 + }; +-} ++} // namespace OpenCL ++ ++namespace NonSemantic { ++enum { ++ LineIdx = 0, ++ ColumnIdx = 1, ++ ScopeIdx = 2, ++ InlinedIdx = 3, ++ MinOperandCount = 3 ++}; ++} // namespace NonSemantic ++} // namespace ImportedEntity + + namespace LocalVariable { + enum { +@@ -963,7 +976,8 @@ enum { + // helper function to get parent scope of debug instruction, to be used + // to determine with which compile unit the particular instruction relates + inline bool hasDbgInstParentScopeIdx(const uint32_t Kind, +- uint32_t &ParentScopeIdx) { ++ uint32_t &ParentScopeIdx, ++ const SPIRV::SPIRVExtInstSetKind ExtKind = SPIRV::SPIRVEIS_OpenCL) { + switch (Kind) { + case SPIRVDebug::Typedef: + ParentScopeIdx = Typedef::ParentIdx; +@@ -996,7 +1010,10 @@ inline bool hasDbgInstParentScopeIdx(const uint32_t Kind, + ParentScopeIdx = Scope::ScopeIdx; + return true; + case SPIRVDebug::InlinedAt: +- ParentScopeIdx = InlinedAt::ScopeIdx; ++ if (ExtKind == SPIRV::SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ ParentScopeIdx = InlinedAt::NonSemantic::ScopeIdx; ++ else ++ ParentScopeIdx = InlinedAt::OpenCL::ScopeIdx; + return true; + case SPIRVDebug::LocalVariable: + ParentScopeIdx = LocalVariable::ParentIdx; +diff --git a/test/DebugInfo/Generic/inlined-locations.ll b/test/DebugInfo/Generic/inlined-locations.ll +index f2861394..2294dbaa 100644 +--- a/test/DebugInfo/Generic/inlined-locations.ll ++++ b/test/DebugInfo/Generic/inlined-locations.ll +@@ -1,11 +1,16 @@ + ; RUN: llvm-as < %s -o %t.bc + ; RUN: llvm-spirv %t.bc -o %t.spv +-; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT ++ ++; RUN: llvm-spirv %t.bc --spirv-debug-info-version=nonsemantic-shader-200 -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o - | FileCheck %s --check-prefixes=CHECK,CHECK-200 + + ; Check that the "inlinedAt" attribute of a DILocation references another + ; DILocation that is marked as distinct. Note that the checks for distinct + ; DILocations do not include the column number as SPIR-V does not allow for +-; representing this info. ++; representing this info (except for NonSemantic.Shader.DebugInfo.200). For ++; this specification we check that the column number is preserved during ++; translation. + + ; Built with clang -O -g from the source: + ; bool f(); +@@ -69,13 +74,15 @@ attributes #2 = { nounwind readnone speculatable } + !16 = !DILocalVariable(name: "b", scope: !12, file: !1, line: 3, type: !17) + !17 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) + !18 = distinct !DILocation(line: 9, column: 15, scope: !19, inlinedAt: !23) +-; CHECK: ![[loc1]] = distinct !DILocation(line: 9, scope: !{{.*}}, inlinedAt: ![[loc2:[0-9]+]]) ++; CHECK-DEFAULT: ![[loc1]] = distinct !DILocation(line: 9, scope: !{{.*}}, inlinedAt: ![[loc2:[0-9]+]]) ++; CHECK-200: ![[loc1]] = distinct !DILocation(line: 9, column: 15, scope: !{{.*}}, inlinedAt: ![[loc2:[0-9]+]]) + !19 = distinct !DILexicalBlock(scope: !20, file: !1, line: 9, column: 11) + !20 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 8, type: !14, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !21) + !21 = !{!22} + !22 = !DILocalVariable(name: "i", scope: !19, file: !1, line: 9, type: !10) + !23 = distinct !DILocation(line: 15, column: 3, scope: !7) +-; CHECK: ![[loc2]] = distinct !DILocation(line: 15, scope: !{{.*}}) ++; CHECK-DEFAULT: ![[loc2]] = distinct !DILocation(line: 15, scope: !{{.*}}) ++; CHECK-200: ![[loc2]] = distinct !DILocation(line: 15, column: 3, scope: !{{.*}}) + !24 = !DILocation(line: 3, column: 12, scope: !12, inlinedAt: !18) + ; CHECK: !{{.*}} = !DILocation(line: 3, column: 12, scope: !{{.*}}, inlinedAt: ![[loc1]]) + !25 = !DILocation(line: 16, column: 1, scope: !7) +-- +2.20.1 + diff --git a/patches/0063-DebugInfo-Add-debug-info-for-bitfield-members-1907.patch b/patches/0063-DebugInfo-Add-debug-info-for-bitfield-members-1907.patch new file mode 100644 index 0000000..e1b9ef8 --- /dev/null +++ b/patches/0063-DebugInfo-Add-debug-info-for-bitfield-members-1907.patch @@ -0,0 +1,282 @@ +From e0ca21f86c84a45d7a0a99bab240cbe32805b2a3 Mon Sep 17 00:00:00 2001 +From: asudarsa +Date: Tue, 13 Jun 2023 15:23:31 -0400 +Subject: [PATCH 63/79] [DebugInfo] Add debug info for bitfield members (#1907) + +Signed-off-by: Arvind Sudarsanam +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 7 +- + lib/SPIRV/LLVMToSPIRVDbgTran.h | 4 + + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 3 +- + lib/SPIRV/libSPIRV/SPIRV.debug.h | 41 +++++---- + test/DebugInfo/bitfields_packed.ll | 142 +++++++++++++++++++++++++++++ + 5 files changed, 174 insertions(+), 23 deletions(-) + create mode 100644 test/DebugInfo/bitfields_packed.ll + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 8945daed..3937e18d 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -454,7 +454,7 @@ void LLVMToSPIRVDbgTran::transformToConstant(std::vector &Ops, + } + } + +-SPIRVWord mapDebugFlags(DINode::DIFlags DFlags) { ++SPIRVWord LLVMToSPIRVDbgTran::mapDebugFlags(DINode::DIFlags DFlags) { + SPIRVWord Flags = 0; + if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic) + Flags |= SPIRVDebug::FlagIsPublic; +@@ -484,10 +484,13 @@ SPIRVWord mapDebugFlags(DINode::DIFlags DFlags) { + Flags |= SPIRVDebug::FlagTypePassByValue; + if (DFlags & DINode::FlagTypePassByReference) + Flags |= SPIRVDebug::FlagTypePassByReference; ++ if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) ++ if (DFlags & DINode::FlagBitField) ++ Flags |= SPIRVDebug::FlagBitField; + return Flags; + } + +-SPIRVWord transDebugFlags(const DINode *DN) { ++SPIRVWord LLVMToSPIRVDbgTran::transDebugFlags(const DINode *DN) { + SPIRVWord Flags = 0; + if (const DIGlobalVariable *GV = dyn_cast(DN)) { + if (GV->isLocalToUnit()) +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h +index fa1e8cf7..7738e1ec 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.h ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h +@@ -165,6 +165,10 @@ private: + // A module in programming language. Example - Fortran module, clang module. + SPIRVEntry *transDbgModule(const DIModule *IE); + ++ // Flags ++ SPIRVWord mapDebugFlags(DINode::DIFlags DFlags); ++ SPIRVWord transDebugFlags(const DINode *DN); ++ + SPIRVModule *BM; + Module *M; + LLVMToSPIRVBase *SPIRVWriter; +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index ed61b4f6..a50b4226 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -668,7 +668,6 @@ SPIRVToLLVMDbgTran::transTypeMemberOpenCL(const SPIRVExtInst *DebugInst) { + } + if (SPIRVFlags & SPIRVDebug::FlagIsStaticMember) + Flags |= DINode::FlagStaticMember; +- + if (Flags & DINode::FlagStaticMember && Ops.size() > MinOperandCount) { + SPIRVValue *ConstVal = BM->get(Ops[ValueIdx]); + assert(isConstantOpCode(ConstVal->getOpCode()) && +@@ -716,6 +715,8 @@ SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst, + } + if (SPIRVFlags & SPIRVDebug::FlagIsStaticMember) + Flags |= DINode::FlagStaticMember; ++ if (SPIRVFlags & SPIRVDebug::FlagBitField) ++ Flags |= DINode::FlagBitField; + + if (Flags & DINode::FlagStaticMember && Ops.size() > MinOperandCount) { + SPIRVValue *ConstVal = BM->get(Ops[ValueIdx]); +diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h +index ff0bb548..f951209d 100644 +--- a/lib/SPIRV/libSPIRV/SPIRV.debug.h ++++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h +@@ -70,26 +70,27 @@ enum Instruction { + }; + + enum Flag { +- FlagIsProtected = 1 << 0, +- FlagIsPrivate = 1 << 1, +- FlagIsPublic = FlagIsPrivate | FlagIsProtected, +- FlagAccess = FlagIsPublic, +- FlagIsLocal = 1 << 2, +- FlagIsDefinition = 1 << 3, +- FlagIsFwdDecl = 1 << 4, +- FlagIsArtificial = 1 << 5, +- FlagIsExplicit = 1 << 6, +- FlagIsPrototyped = 1 << 7, +- FlagIsObjectPointer = 1 << 8, +- FlagIsStaticMember = 1 << 9, +- FlagIsIndirectVariable = 1 << 10, +- FlagIsLValueReference = 1 << 11, +- FlagIsRValueReference = 1 << 12, +- FlagIsOptimized = 1 << 13, +- FlagIsEnumClass = 1 << 14, +- FlagTypePassByValue = 1 << 15, +- FlagTypePassByReference = 1 << 16, +- FlagUnknownPhysicalLayout = 1 << 17, ++ FlagIsProtected = 1 << 0, ++ FlagIsPrivate = 1 << 1, ++ FlagIsPublic = FlagIsPrivate | FlagIsProtected, ++ FlagAccess = FlagIsPublic, ++ FlagIsLocal = 1 << 2, ++ FlagIsDefinition = 1 << 3, ++ FlagIsFwdDecl = 1 << 4, ++ FlagIsArtificial = 1 << 5, ++ FlagIsExplicit = 1 << 6, ++ FlagIsPrototyped = 1 << 7, ++ FlagIsObjectPointer = 1 << 8, ++ FlagIsStaticMember = 1 << 9, ++ FlagIsIndirectVariable = 1 << 10, ++ FlagIsLValueReference = 1 << 11, ++ FlagIsRValueReference = 1 << 12, ++ FlagIsOptimized = 1 << 13, ++ FlagIsEnumClass = 1 << 14, ++ FlagTypePassByValue = 1 << 15, ++ FlagTypePassByReference = 1 << 16, ++ FlagUnknownPhysicalLayout = 1 << 17, ++ FlagBitField = 1 << 18 + }; + + enum EncodingTag { +diff --git a/test/DebugInfo/bitfields_packed.ll b/test/DebugInfo/bitfields_packed.ll +new file mode 100644 +index 00000000..5446e10d +--- /dev/null ++++ b/test/DebugInfo/bitfields_packed.ll +@@ -0,0 +1,142 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv --spirv-debug-info-version=ocl-100 %t.bc ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck %s --input-file %t.spt -check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NO-BITFIELD ++; RUN: llvm-spirv -r %t.spv -o %t_1.bc ++; RUN: llvm-dis %t_1.bc -o %t_1.ll ++; RUN: FileCheck %s --input-file %t_1.ll -check-prefixes=CHECK-LLVM,CHECK-LLVM-NO-BITFIELD ++ ++; RUN: llvm-spirv --spirv-ext=+SPV_KHR_non_semantic_info --spirv-debug-info-version=nonsemantic-shader-100 %t.bc ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck %s --input-file %t.spt -check-prefixes=CHECK-SPIRV,CHECK-SPIRV-BITFIELD ++; RUN: llvm-spirv -r %t.spv -o %t_1.bc ++; RUN: llvm-dis %t_1.bc -o %t_1.ll ++; RUN: FileCheck %s --input-file %t_1.ll -check-prefixes=CHECK-LLVM,CHECK-LLVM-NO-BITFIELD ++ ++; RUN: llvm-spirv --spirv-debug-info-version=nonsemantic-shader-200 %t.bc -o %t.spv ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck %s --input-file %t.spt -check-prefixes=CHECK-SPIRV,CHECK-SPIRV-BITFIELD ++; RUN: llvm-spirv -r %t.spv -o %t_1.bc ++; RUN: llvm-dis %t_1.bc -o %t_1.ll ++; RUN: FileCheck %s --input-file %t_1.ll -check-prefixes=CHECK-LLVM,CHECK-LLVM-BITFIELD ++ ++; CHECK-SPIRV: String [[#A:]] "a" ++; CHECK-SPIRV: String [[#B:]] "b" ++; CHECK-SPIRV: String [[#C:]] "c" ++; CHECK-SPIRV: String [[#D:]] "d" ++; CHECK-SPIRV: String [[#E:]] "e" ++; CHECK-SPIRV: String [[#F:]] "f" ++ ++; CHECK-SPIRV-DAG: Constant [[#]] [[#THREE:]] 3 {{$}} ++; CHECK-SPIRV-DAG: Constant [[#]] [[#ONE:]] 1 {{$}} ++ ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#A]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#B]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#C]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#D]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#E]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-NO-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#F]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#]] ++ ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#A]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#THREE]] [[#]] ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#B]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#THREE]] [[#]] ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#C]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#THREE]] [[#]] ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#D]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#THREE]] [[#]] ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#E]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#THREE]] [[#]] ++; CHECK-SPIRV-BITFIELD: ExtInst [[#]] [[#]] [[#]] DebugTypeMember [[#F]] [[#]] [[#]] [[#]] [[#]] [[#]] [[#ONE]] [[#]] ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++%struct.struct_bit_fields1 = type { i16 } ++ ++@__const._Z3fooii.arr_bf1 = private unnamed_addr addrspace(1) constant [1 x { i8, i8 }] [{ i8, i8 } { i8 -47, i8 8 }], align 2 ++ ++; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone ++define dso_local spir_func noundef i32 @_Z3fooii(i32 noundef %0, i32 noundef %1) #0 !dbg !10 { ++ %3 = alloca i32, align 4 ++ %4 = alloca i32, align 4 ++ %5 = alloca i32, align 4 ++ %6 = alloca [1 x %struct.struct_bit_fields1], align 2 ++ %7 = alloca i32, align 4 ++ %8 = addrspacecast i32* %3 to i32 addrspace(4)* ++ %9 = addrspacecast i32* %4 to i32 addrspace(4)* ++ %10 = addrspacecast i32* %5 to i32 addrspace(4)* ++ %11 = addrspacecast [1 x %struct.struct_bit_fields1]* %6 to [1 x %struct.struct_bit_fields1] addrspace(4)* ++ %12 = addrspacecast i32* %7 to i32 addrspace(4)* ++ store i32 %0, i32 addrspace(4)* %9, align 4 ++ call void @llvm.dbg.declare(metadata i32* %4, metadata !15, metadata !DIExpression()), !dbg !16 ++ store i32 %1, i32 addrspace(4)* %10, align 4 ++ call void @llvm.dbg.declare(metadata i32* %5, metadata !17, metadata !DIExpression()), !dbg !18 ++ call void @llvm.dbg.declare(metadata [1 x %struct.struct_bit_fields1]* %6, metadata !19, metadata !DIExpression()), !dbg !32 ++ %13 = bitcast [1 x %struct.struct_bit_fields1] addrspace(4)* %11 to i8 addrspace(4)*, !dbg !32 ++ call void @llvm.memcpy.p4i8.p1i8.i64(i8 addrspace(4)* align 2 %13, i8 addrspace(1)* align 2 getelementptr inbounds ([1 x { i8, i8 }], [1 x { i8, i8 }] addrspace(1)* @__const._Z3fooii.arr_bf1, i32 0, i32 0, i32 0), i64 2, i1 false), !dbg !32 ++ call void @llvm.dbg.declare(metadata i32* %7, metadata !33, metadata !DIExpression()), !dbg !34 ++ store i32 0, i32 addrspace(4)* %12, align 4, !dbg !34 ++ %14 = load i32, i32 addrspace(4)* %12, align 4, !dbg !35 ++ ret i32 %14, !dbg !36 ++} ++ ++; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) ++declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 ++ ++; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) ++declare void @llvm.memcpy.p4i8.p1i8.i64(i8 addrspace(4)* noalias nocapture writeonly, i8 addrspace(1)* noalias nocapture readonly, i64, i1 immarg) #2 ++ ++attributes #0 = { convergent mustprogress noinline norecurse nounwind optnone "approx-func-fp-math"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="bitfields-packed.cpp" "unsafe-fp-math"="true" } ++attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn } ++attributes #2 = { nocallback nofree nounwind willreturn } ++ ++!llvm.dbg.cu = !{!0} ++!opencl.spir.version = !{!2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2} ++!spirv.Source = !{!3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3, !3} ++!opencl.compiler.options = !{!4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4, !4} ++!llvm.ident = !{!5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5, !5} ++!llvm.module.flags = !{!6, !7, !8, !9} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, flags: "", runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) ++!1 = !DIFile(filename: "bitfields-packed.cpp", directory: "/tmp") ++!2 = !{i32 1, i32 2} ++!3 = !{i32 4, i32 100000} ++!4 = !{} ++!5 = !{!"Compiler"} ++!6 = !{i32 7, !"Dwarf Version", i32 4} ++!7 = !{i32 2, !"Debug Info Version", i32 3} ++!8 = !{i32 1, !"wchar_size", i32 4} ++!9 = !{i32 7, !"frame-pointer", i32 2} ++!10 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooii", scope: !11, file: !11, line: 29, type: !12, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !4) ++!11 = !DIFile(filename: "bitfields-packed.cpp", directory: "/tmp") ++!12 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !13) ++!13 = !{!14, !14, !14} ++!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!15 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !11, line: 29, type: !14) ++!16 = !DILocation(line: 29, column: 43, scope: !10) ++!17 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !11, line: 29, type: !14) ++!18 = !DILocation(line: 29, column: 50, scope: !10) ++; CHECK-LLVM: !DILocalVariable(name: "arr_bf1", {{.*}}, type: ![[#ARRAY_TYPE:]]) ++!19 = !DILocalVariable(name: "arr_bf1", scope: !10, file: !11, line: 33, type: !20) ++; CHECK-LLVM: ![[#ARRAY_TYPE]] = {{.*}}!DICompositeType(tag: DW_TAG_array_type, baseType: ![[#BITFIELD_STRUCT:]], {{.*}}) ++!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !21, size: 16, elements: !30) ++; CHECK-LLVM: ![[#BITFIELD_STRUCT]] = {{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "struct_bit_fields1", {{.*}}, identifier: "_ZTS18struct_bit_fields1") ++!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct_bit_fields1", file: !11, line: 19, size: 16, flags: DIFlagTypePassByValue, elements: !22, identifier: "_ZTS18struct_bit_fields1") ++!22 = !{!23, !25, !26, !27, !28, !29} ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 3, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 3, offset: 3, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 3, offset: 6, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "d", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 3, offset: 9, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "e", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 3, offset: 12, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-BITFIELD: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#BITFIELD_STRUCT]], {{.*}}, size: 1, offset: 15, flags: {{.*}}DIFlagBitField{{.*}}) ++; CHECK-LLVM-NO-BITFIELD-NOT: DIFlagBitField ++!23 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !21, file: !11, line: 21, baseType: !24, size: 3, flags: DIFlagBitField, extraData: i64 0) ++!24 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) ++!25 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !21, file: !11, line: 22, baseType: !24, size: 3, offset: 3, flags: DIFlagBitField, extraData: i64 0) ++!26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !21, file: !11, line: 23, baseType: !24, size: 3, offset: 6, flags: DIFlagBitField, extraData: i64 0) ++!27 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !21, file: !11, line: 24, baseType: !24, size: 3, offset: 9, flags: DIFlagBitField, extraData: i64 0) ++!28 = !DIDerivedType(tag: DW_TAG_member, name: "e", scope: !21, file: !11, line: 25, baseType: !24, size: 3, offset: 12, flags: DIFlagBitField, extraData: i64 0) ++!29 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !21, file: !11, line: 26, baseType: !24, size: 1, offset: 15, flags: DIFlagBitField, extraData: i64 0) ++!30 = !{!31} ++!31 = !DISubrange(count: 1) ++!32 = !DILocation(line: 33, column: 22, scope: !10) ++!33 = !DILocalVariable(name: "ans", scope: !10, file: !11, line: 35, type: !14) ++!34 = !DILocation(line: 35, column: 7, scope: !10) ++!35 = !DILocation(line: 36, column: 10, scope: !10) ++!36 = !DILocation(line: 36, column: 3, scope: !10) +-- +2.20.1 + diff --git a/patches/0064-Fix-SourceContinued-translation-and-clang-format-tid.patch b/patches/0064-Fix-SourceContinued-translation-and-clang-format-tid.patch new file mode 100644 index 0000000..9449d19 --- /dev/null +++ b/patches/0064-Fix-SourceContinued-translation-and-clang-format-tid.patch @@ -0,0 +1,75 @@ +From 08482a6f8f51cddcf60e7145c61293a4b03405ab Mon Sep 17 00:00:00 2001 +From: "Maksimova, Viktoria" +Date: Mon, 19 Jun 2023 09:35:45 -0700 +Subject: [PATCH 64/79] Fix SourceContinued translation and clang-format/tidy + warnings + +--- + lib/SPIRV/SPIRVReader.cpp | 2 +- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 4 ++-- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 11 +++++------ + 3 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index a3e7c946..d28f1090 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3337,7 +3337,7 @@ bool SPIRVToLLVM::translate() { + } + + for (unsigned I = 0, E = BM->getNumVariables(); I != E; ++I) { +- auto BV = BM->getVariable(I); ++ auto *BV = BM->getVariable(I); + if (BV->getStorageClass() != StorageClassFunction) + transValue(BV, nullptr, nullptr); + else +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index a50b4226..6cba6b39 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -141,11 +141,11 @@ const std::string &SPIRVToLLVMDbgTran::getString(const SPIRVId Id) { + return String->getStr(); + } + +-const std::string ++Optional + SPIRVToLLVMDbgTran::getStringSourceContinued(const SPIRVId Id, + SPIRVExtInst *DebugInst) { + if (!isValidId(Id) || getDbgInst(Id)) +- return ""; ++ return {}; + std::string Str = BM->get(Id)->getStr(); + using namespace SPIRVDebug::Operand::SourceContinued; + for (auto *I : DebugInst->getContinuedInstructions()) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index b166abc9..86cf6da7 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -90,10 +90,9 @@ public: + private: + DIFile *getFile(const SPIRVId SourceId); + +- DIFile * +- getDIFile(const std::string &FileName, +- Optional> CS = None, +- Optional Source = None); ++ DIFile *getDIFile(const std::string &FileName, ++ Optional> CS = None, ++ Optional Source = None); + DIFile *getDIFile(const SPIRVEntry *E); + unsigned getLineNo(const SPIRVEntry *E); + +@@ -206,8 +205,8 @@ private: + return nullptr; + } + const std::string &getString(const SPIRVId Id); +- const std::string getStringSourceContinued(const SPIRVId Id, +- SPIRVExtInst *DebugInst); ++ Optional getStringSourceContinued(const SPIRVId Id, ++ SPIRVExtInst *DebugInst); + SPIRVWord getConstantValueOrLiteral(const std::vector &, + const SPIRVWord, + const SPIRVExtInstSetKind); +-- +2.20.1 + diff --git a/patches/0065-Fix-clang-tidy-warnings.patch b/patches/0065-Fix-clang-tidy-warnings.patch new file mode 100644 index 0000000..90e6053 --- /dev/null +++ b/patches/0065-Fix-clang-tidy-warnings.patch @@ -0,0 +1,166 @@ +From d04ccf4d8064960d5105fc782799a251eb7d1d5a Mon Sep 17 00:00:00 2001 +From: "Maksimova, Viktoria" +Date: Wed, 28 Jun 2023 03:40:37 -0700 +Subject: [PATCH 65/79] Fix clang-tidy warnings + +--- + lib/SPIRV/LLVMToSPIRVDbgTran.cpp | 6 ++--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 39 ++++++++++++++++---------------- + 2 files changed, 23 insertions(+), 22 deletions(-) + +diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +index 3937e18d..d44b6b03 100644 +--- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp ++++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +@@ -1440,7 +1440,7 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + ->getId()); + else if (BM->getDebugInfoEIS() == + SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { +- SPIRVDebug::FileChecksumKind ChecksumKind = ++ const SPIRVDebug::FileChecksumKind ChecksumKind = + SPIRV::DbgChecksumKindMap::map(CheckSum.Kind); + + Ops.push_back( +@@ -1473,10 +1473,10 @@ SPIRVExtInst *LLVMToSPIRVDbgTran::getSource(const T *DIEntry) { + if (NumWords < MaxNumWords) + return Source; + +- uint64_t NumOfContinuedInstructions = ++ const uint64_t NumOfContinuedInstructions = + NumWords / MaxNumWords - 1 + (NumWords % MaxNumWords ? 1 : 0); + for (uint64_t J = 0; J < NumOfContinuedInstructions; J++) { +- SPIRVWord Op = BM->getString(Str.substr(0, MaxStrSize))->getId(); ++ const SPIRVWord Op = BM->getString(Str.substr(0, MaxStrSize))->getId(); + BM->addDebugInfo(SPIRVDebug::SourceContinued, getVoidTy(), {Op}); + Str.erase(0, MaxStrSize); + } +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 6cba6b39..a1102cf0 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -85,7 +85,7 @@ SPIRVToLLVMDbgTran::getDIFile(const std::string &FileName, + // relations with other debug metadata is not going through DICompileUnit + if (!Split.BaseName.empty()) { + if (Source.hasValue()) { +- StringRef SourceRef = StringRef(Source.getValue()); ++ const StringRef SourceRef = StringRef(Source.getValue()); + return BuilderMap.begin()->second->createFile( + Split.BaseName, Split.Path, CS, SourceRef); + } +@@ -149,7 +149,7 @@ SPIRVToLLVMDbgTran::getStringSourceContinued(const SPIRVId Id, + std::string Str = BM->get(Id)->getStr(); + using namespace SPIRVDebug::Operand::SourceContinued; + for (auto *I : DebugInst->getContinuedInstructions()) { +- std::string TmpStr = ++ const std::string TmpStr = + BM->get(I->getArguments()[TextIdx])->getStr(); + Str.append(TmpStr); + } +@@ -696,14 +696,14 @@ SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst, + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + + DIFile *File = getFile(Ops[SourceIdx]); +- SPIRVWord LineNo = ++ const SPIRVWord LineNo = + getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); +- StringRef Name = getString(Ops[NameIdx]); ++ const StringRef Name = getString(Ops[NameIdx]); + DIType *BaseType = + transDebugInst(BM->get(Ops[TypeIdx])); +- uint64_t OffsetInBits = ++ const uint64_t OffsetInBits = + BM->get(Ops[OffsetIdx])->getZExtIntValue(); +- SPIRVWord SPIRVFlags = ++ const SPIRVWord SPIRVFlags = + getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + DINode::DIFlags Flags = DINode::FlagZero; + if ((SPIRVDebug::FlagAccess & SPIRVFlags) == SPIRVDebug::FlagIsPublic) { +@@ -726,8 +726,8 @@ SPIRVToLLVMDbgTran::transTypeMemberNonSemantic(const SPIRVExtInst *DebugInst, + return getDIBuilder(DebugInst).createStaticMemberType( + Scope, Name, File, LineNo, BaseType, Flags, cast(Val)); + } +- uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); +- uint64_t Alignment = 0; ++ const uint64_t Size = BM->get(Ops[SizeIdx])->getZExtIntValue(); ++ const uint64_t Alignment = 0; + + return getDIBuilder(ParentInst) + .createMemberType(Scope, Name, File, LineNo, Size, Alignment, +@@ -1164,7 +1164,8 @@ DINode *SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst, + const SPIRVWordVec &Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); + // No Child operand for NonSemantic debug spec +- SPIRVWord Offset = isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ? 1 : 0; ++ const SPIRVWord Offset = ++ isNonSemanticDebugInfo(DebugInst->getExtSetKind()) ? 1 : 0; + DIType *Parent = + transDebugInst(BM->get(Ops[ParentIdx - Offset])); + DIType *Child = +@@ -1172,15 +1173,15 @@ DINode *SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst, + ? ChildClass + : transDebugInst(BM->get(Ops[ChildIdx])); + DINode::DIFlags Flags = DINode::FlagZero; +- SPIRVWord SPIRVFlags = getConstantValueOrLiteral(Ops, FlagsIdx - Offset, +- DebugInst->getExtSetKind()); ++ const SPIRVWord SPIRVFlags = getConstantValueOrLiteral( ++ Ops, FlagsIdx - Offset, DebugInst->getExtSetKind()); + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPublic) + Flags |= llvm::DINode::FlagPublic; + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsProtected) + Flags |= llvm::DINode::FlagProtected; + if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate) + Flags |= llvm::DINode::FlagPrivate; +- uint64_t OffsetVal = ++ const uint64_t OffsetVal = + BM->get(Ops[OffsetIdx - Offset])->getZExtIntValue(); + return getDIBuilder(DebugInst).createInheritance(Child, Parent, OffsetVal, 0, + Flags); +@@ -1533,7 +1534,7 @@ DebugLoc SPIRVToLLVMDbgTran::transDebugScope(const SPIRVInstruction *Inst) { + // If DebugLine and OpLine are both active give DebugLine priority + if (auto DL = Inst->getDebugLine()) { + using namespace SPIRVDebug::Operand::DebugLine; +- SPIRVWordVec DebugLineArgs = DL->getArguments(); ++ const SPIRVWordVec DebugLineArgs = DL->getArguments(); + Line = + getConstantValueOrLiteral(DebugLineArgs, StartIdx, DL->getExtSetKind()); + Col = getConstantValueOrLiteral(DebugLineArgs, ColumnStartIdx, +@@ -1581,9 +1582,9 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInlinedNonSemanticShader200( + using namespace SPIRVDebug::Operand::InlinedAt::NonSemantic; + SPIRVWordVec Ops = DebugInst->getArguments(); + assert(Ops.size() >= MinOperandCount && "Invalid number of operands"); +- SPIRVWord Line = ++ const SPIRVWord Line = + getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind()); +- unsigned Col = ++ const unsigned Col = + getConstantValueOrLiteral(Ops, ColumnIdx, DebugInst->getExtSetKind()); + DILocalScope *Scope = + cast(getScope(BM->getEntry(Ops[ScopeIdx]))); +@@ -1613,7 +1614,7 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + return getDIFile(getString(SourceArgs[FileIdx])); + + if (!isNonSemanticDebugInfo(Source->getExtSetKind())) { +- std::string ChecksumStr = ++ const std::string ChecksumStr = + getDbgInst(SourceArgs[TextIdx]) + ? "" + : getString(SourceArgs[TextIdx]); +@@ -1629,12 +1630,12 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) { + // go together + if (!getDbgInst(SourceArgs[ChecksumKind]) && + !getDbgInst(SourceArgs[ChecksumValue])) { +- llvm::DIFile::ChecksumKind Kind = SPIRV::DbgChecksumKindMap::rmap( ++ const llvm::DIFile::ChecksumKind Kind = SPIRV::DbgChecksumKindMap::rmap( + static_cast( + BM->get(SourceArgs[ChecksumKind]) + ->getZExtIntValue())); +- StringRef Checksum = getString(SourceArgs[ChecksumValue]); +- size_t ChecksumEndPos = Checksum.find_if_not(llvm::isHexDigit); ++ const StringRef Checksum = getString(SourceArgs[ChecksumValue]); ++ const size_t ChecksumEndPos = Checksum.find_if_not(llvm::isHexDigit); + CS.emplace(Kind, Checksum.substr(0, ChecksumEndPos)); + } + } +-- +2.20.1 + diff --git a/patches/0066-Backport-to-15-OpaquePointers-Adjust-builtin-variabl.patch b/patches/0066-Backport-to-15-OpaquePointers-Adjust-builtin-variabl.patch new file mode 100644 index 0000000..307ba42 --- /dev/null +++ b/patches/0066-Backport-to-15-OpaquePointers-Adjust-builtin-variabl.patch @@ -0,0 +1,335 @@ +From 22890372441444dbd7b1eca4f4890ebae9910a4d Mon Sep 17 00:00:00 2001 +From: Mateusz Chudyk +Date: Mon, 3 Jul 2023 18:40:05 +0200 +Subject: [PATCH 66/79] [Backport to 15] [OpaquePointers] Adjust builtin + variable tracking to support i8 geps (#2061) + +The existing logic for the replacement of builtin variables with calls to +functions relies on relatively brittle tracking that is broken when opaque +pointers is turned on, and will be even more thoroughly broken if/when typed +geps are replaced with i8 geps or ptradd. This patch replaces that logic with a +less brittle variant that is able to handle any sequence of bitcast, gep, or +addrspacecast instructions between the global variable and the ultimate load +instruction. + +It still will error out if the variable is used in too insane of a fashion (say, +trying to load an i32 out of the i64, or a misaligned vector type). + +Co-authored-by: Joshua Cranmer +--- + lib/SPIRV/SPIRVInternal.h | 2 +- + lib/SPIRV/SPIRVUtil.cpp | 182 +++++++++++---------------- + test/builtin-vars-gep.ll | 42 ++++--- + test/transcoding/builtin_vars_gep.ll | 12 -- + 4 files changed, 97 insertions(+), 141 deletions(-) + +diff --git a/lib/SPIRV/SPIRVInternal.h b/lib/SPIRV/SPIRVInternal.h +index 9eaaf6c0..30241c89 100644 +--- a/lib/SPIRV/SPIRVInternal.h ++++ b/lib/SPIRV/SPIRVInternal.h +@@ -1056,7 +1056,7 @@ std::string decodeSPIRVTypeName(StringRef Name, + SmallVectorImpl &Strs); + + // Copy attributes from function to call site. +-void setAttrByCalledFunc(CallInst *Call); ++CallInst *setAttrByCalledFunc(CallInst *Call); + bool isSPIRVBuiltinVariable(GlobalVariable *GV, SPIRVBuiltinVariableKind *Kind); + // Transform builtin variable from GlobalVariable to builtin call. + // e.g. +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 1ac4eb62..9a45e775 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1858,14 +1858,15 @@ bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) { + return true; + } + +-void setAttrByCalledFunc(CallInst *Call) { ++CallInst *setAttrByCalledFunc(CallInst *Call) { + Function *F = Call->getCalledFunction(); + assert(F); + if (F->isIntrinsic()) { +- return; ++ return Call; + } + Call->setCallingConv(F->getCallingConv()); + Call->setAttributes(F->getAttributes()); ++ return Call; + } + + bool isSPIRVBuiltinVariable(GlobalVariable *GV, +@@ -1915,6 +1916,75 @@ bool isSPIRVBuiltinVariable(GlobalVariable *GV, + // %4 = call spir_func i64 @_Z13get_global_idj(i32 2) #1 + // %5 = insertelement <3 x i64> %3, i64 %4, i32 2 + // %6 = extractelement <3 x i64> %5, i32 0 ++ ++/// Recursively look through the uses of a global variable, including casts or ++/// gep offsets, to find all loads of the variable. Gep offsets that are non-0 ++/// are accumulated in the AccumulatedOffset parameter, which will eventually be ++/// used to figure out which index of a variable is being used. ++static void replaceUsesOfBuiltinVar(Value *V, const APInt &AccumulatedOffset, ++ Function *ReplacementFunc) { ++ const DataLayout &DL = ReplacementFunc->getParent()->getDataLayout(); ++ SmallVector InstsToRemove; ++ for (User *U : V->users()) { ++ if (auto *Cast = dyn_cast(U)) { ++ replaceUsesOfBuiltinVar(Cast, AccumulatedOffset, ReplacementFunc); ++ InstsToRemove.push_back(Cast); ++ } else if (auto *GEP = dyn_cast(U)) { ++ APInt NewOffset = AccumulatedOffset.sextOrTrunc( ++ DL.getIndexSizeInBits(GEP->getPointerAddressSpace())); ++ if (!GEP->accumulateConstantOffset(DL, NewOffset)) ++ llvm_unreachable("Illegal GEP of a SPIR-V builtin variable"); ++ replaceUsesOfBuiltinVar(GEP, NewOffset, ReplacementFunc); ++ InstsToRemove.push_back(GEP); ++ } else if (auto *Load = dyn_cast(U)) { ++ // Figure out which index the accumulated offset corresponds to. If we ++ // have a weird offset (e.g., trying to load byte 7), bail out. ++ Type *ScalarTy = ReplacementFunc->getReturnType(); ++ APInt Index; ++ uint64_t Remainder; ++ APInt::udivrem(AccumulatedOffset, ScalarTy->getScalarSizeInBits() / 8, ++ Index, Remainder); ++ if (Remainder != 0) ++ llvm_unreachable("Illegal GEP of a SPIR-V builtin variable"); ++ ++ IRBuilder<> Builder(Load); ++ Value *Replacement; ++ if (ReplacementFunc->getFunctionType()->getNumParams() == 0) { ++ if (Load->getType() != ScalarTy) ++ llvm_unreachable("Illegal use of a SPIR-V builtin variable"); ++ Replacement = ++ setAttrByCalledFunc(Builder.CreateCall(ReplacementFunc, {})); ++ } else { ++ // The function has an index parameter. ++ if (auto *VecTy = dyn_cast(Load->getType())) { ++ if (!Index.isZero()) ++ llvm_unreachable("Illegal use of a SPIR-V builtin variable"); ++ Replacement = UndefValue::get(VecTy); ++ for (unsigned I = 0; I < VecTy->getNumElements(); I++) { ++ Replacement = Builder.CreateInsertElement( ++ Replacement, ++ setAttrByCalledFunc( ++ Builder.CreateCall(ReplacementFunc, {Builder.getInt32(I)})), ++ Builder.getInt32(I)); ++ } ++ } else if (Load->getType() == ScalarTy) { ++ Replacement = setAttrByCalledFunc(Builder.CreateCall( ++ ReplacementFunc, {Builder.getInt32(Index.getZExtValue())})); ++ } else { ++ llvm_unreachable("Illegal load type of a SPIR-V builtin variable"); ++ } ++ } ++ Load->replaceAllUsesWith(Replacement); ++ InstsToRemove.push_back(Load); ++ } else { ++ llvm_unreachable("Illegal use of a SPIR-V builtin variable"); ++ } ++ } ++ ++ for (Instruction *I : InstsToRemove) ++ I->eraseFromParent(); ++} ++ + bool lowerBuiltinVariableToCall(GlobalVariable *GV, + SPIRVBuiltinVariableKind Kind) { + // There might be dead constant users of GV (for example, SPIRVLowerConstExpr +@@ -1950,113 +2020,7 @@ bool lowerBuiltinVariableToCall(GlobalVariable *GV, + Func->setDoesNotAccessMemory(); + } + +- // Collect instructions in these containers to remove them later. +- std::vector Loads; +- std::vector Casts; +- std::vector GEPs; +- +- auto Replace = [&](std::vector Arg, Instruction *I) { +- auto *Call = CallInst::Create(Func, Arg, "", I); +- Call->takeName(I); +- setAttrByCalledFunc(Call); +- SPIRVDBG(dbgs() << "[lowerBuiltinVariableToCall] " << *I << " -> " << *Call +- << '\n';) +- I->replaceAllUsesWith(Call); +- }; +- +- // If HasIndexArg is true, we create 3 built-in calls and insertelement to +- // get 3-element vector filled with ids and replace uses of Load instruction +- // with this vector. +- // If HasIndexArg is false, the result of the Load instruction is the value +- // which should be replaced with the Func. +- // Returns true if Load was replaced, false otherwise. +- auto ReplaceIfLoad = [&](User *I) { +- auto *LD = dyn_cast(I); +- if (!LD) +- return false; +- std::vector Vectors; +- Loads.push_back(LD); +- if (HasIndexArg) { +- auto *VecTy = cast(GVTy); +- Value *EmptyVec = UndefValue::get(VecTy); +- Vectors.push_back(EmptyVec); +- const DebugLoc &DLoc = LD->getDebugLoc(); +- for (unsigned I = 0; I < VecTy->getNumElements(); ++I) { +- auto *Idx = ConstantInt::get(Type::getInt32Ty(C), I); +- auto *Call = CallInst::Create(Func, {Idx}, "", LD); +- if (DLoc) +- Call->setDebugLoc(DLoc); +- setAttrByCalledFunc(Call); +- auto *Insert = InsertElementInst::Create(Vectors.back(), Call, Idx); +- if (DLoc) +- Insert->setDebugLoc(DLoc); +- Insert->insertAfter(Call); +- Vectors.push_back(Insert); +- } +- +- Value *Ptr = LD->getPointerOperand(); +- +- if (isa(LD->getType())) { +- LD->replaceAllUsesWith(Vectors.back()); +- } else { +- auto *GEP = dyn_cast(Ptr); +- assert(GEP && "Unexpected pattern!"); +- assert(GEP->getNumIndices() == 2 && "Unexpected pattern!"); +- Value *Idx = GEP->getOperand(2); +- Value *Vec = Vectors.back(); +- auto *NewExtract = ExtractElementInst::Create(Vec, Idx); +- NewExtract->insertAfter(cast(Vec)); +- LD->replaceAllUsesWith(NewExtract); +- } +- +- } else { +- Replace({}, LD); +- } +- +- return true; +- }; +- +- // Go over the GV users, find Load and ExtractElement instructions and +- // replace them with the corresponding function call. +- for (auto *UI : GV->users()) { +- // There might or might not be an addrspacecast instruction. +- if (auto *ASCast = dyn_cast(UI)) { +- Casts.push_back(ASCast); +- for (auto *CastUser : ASCast->users()) { +- if (ReplaceIfLoad(CastUser)) +- continue; +- if (auto *GEP = dyn_cast(CastUser)) { +- GEPs.push_back(GEP); +- for (auto *GEPUser : GEP->users()) { +- if (!ReplaceIfLoad(GEPUser)) +- llvm_unreachable("Unexpected pattern!"); +- } +- } else { +- llvm_unreachable("Unexpected pattern!"); +- } +- } +- } else if (auto *GEP = dyn_cast(UI)) { +- GEPs.push_back(GEP); +- for (auto *GEPUser : GEP->users()) { +- if (!ReplaceIfLoad(GEPUser)) +- llvm_unreachable("Unexpected pattern!"); +- } +- } else if (!ReplaceIfLoad(UI)) { +- llvm_unreachable("Unexpected pattern!"); +- } +- } +- +- auto Erase = [](std::vector &ToErase) { +- for (Instruction *I : ToErase) { +- assert(I->hasNUses(0)); +- I->eraseFromParent(); +- } +- }; +- // Order of erasing is important. +- Erase(Loads); +- Erase(GEPs); +- Erase(Casts); +- ++ replaceUsesOfBuiltinVar(GV, APInt(64, 0), Func); + return true; + } + +diff --git a/test/builtin-vars-gep.ll b/test/builtin-vars-gep.ll +index c9ee2a10..0dc30747 100644 +--- a/test/builtin-vars-gep.ll ++++ b/test/builtin-vars-gep.ll +@@ -14,28 +14,32 @@ target triple = "spir64" + define spir_func void @foo() { + entry: + %GroupID = alloca [3 x i64], align 8 +- %0 = addrspacecast <3 x i64> addrspace(1)* @__spirv_BuiltInWorkgroupSize to <3 x i64> addrspace(4)* +- %1 = getelementptr <3 x i64>, <3 x i64> addrspace(4)* %0, i64 0, i64 0 ++ %0 = addrspacecast ptr addrspace(1) @__spirv_BuiltInWorkgroupSize to ptr addrspace(4) ++ %1 = getelementptr <3 x i64>, ptr addrspace(4) %0, i64 0, i64 0 + ; CHECK-LLVM: %[[GLocalSize0:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 0) #1 +-; CHECK-LLVM: %[[Ins0:[0-9]+]] = insertelement <3 x i64> undef, i64 %[[GLocalSize0]], i32 0 +-; CHECK-LLVM: %[[GLocalSize1:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 1) #1 +-; CHECK-LLVM: %[[Ins1:[0-9]+]] = insertelement <3 x i64> %[[Ins0]], i64 %[[GLocalSize1]], i32 1 ++ %2 = addrspacecast ptr addrspace(1) @__spirv_BuiltInWorkgroupSize to ptr addrspace(4) ++ %3 = getelementptr <3 x i64>, ptr addrspace(4) %2, i64 0, i64 2 ++ %4 = load i64, ptr addrspace(4) %1, align 32 ++ %5 = load i64, ptr addrspace(4) %3, align 8 + ; CHECK-LLVM: %[[GLocalSize2:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 2) #1 +-; CHECK-LLVM: %[[Ins2:[0-9]+]] = insertelement <3 x i64> %[[Ins1]], i64 %[[GLocalSize2]], i32 2 +-; CHECK-LLVM: %[[Extract:[0-9]+]] = extractelement <3 x i64> %[[Ins2]], i64 0 +- %2 = addrspacecast <3 x i64> addrspace(1)* @__spirv_BuiltInWorkgroupSize to <3 x i64> addrspace(4)* +- %3 = getelementptr <3 x i64>, <3 x i64> addrspace(4)* %2, i64 0, i64 2 +- %4 = load i64, i64 addrspace(4)* %1, align 32 +- %5 = load i64, i64 addrspace(4)* %3, align 8 +-; CHECK-LLVM: %[[GLocalSize01:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 0) #1 +-; CHECK-LLVM: %[[Ins01:[0-9]+]] = insertelement <3 x i64> undef, i64 %[[GLocalSize01]], i32 0 +-; CHECK-LLVM: %[[GLocalSize11:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 1) #1 +-; CHECK-LLVM: %[[Ins11:[0-9]+]] = insertelement <3 x i64> %[[Ins01]], i64 %[[GLocalSize11]], i32 1 +-; CHECK-LLVM: %[[GLocalSize21:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 2) #1 +-; CHECK-LLVM: %[[Ins21:[0-9]+]] = insertelement <3 x i64> %[[Ins11]], i64 %[[GLocalSize21]], i32 2 +-; CHECK-LLVM: %[[Extract1:[0-9]+]] = extractelement <3 x i64> %[[Ins21]], i64 2 +-; CHECK-LLVM: mul i64 %[[Extract]], %[[Extract1]] ++; CHECK-LLVM: mul i64 %[[GLocalSize0]], %[[GLocalSize2]] + %mul = mul i64 %4, %5 + ret void + } + ++; Function Attrs: alwaysinline convergent nounwind mustprogress ++define spir_func void @foo_i8gep() { ++entry: ++ %GroupID = alloca [3 x i64], align 8 ++ %0 = addrspacecast ptr addrspace(1) @__spirv_BuiltInWorkgroupSize to ptr addrspace(4) ++ %1 = getelementptr i8, ptr addrspace(4) %0, i64 0 ++; CHECK-LLVM: %[[GLocalSize0:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 0) #1 ++ %2 = addrspacecast ptr addrspace(1) @__spirv_BuiltInWorkgroupSize to ptr addrspace(4) ++ %3 = getelementptr i8, ptr addrspace(4) %2, i64 16 ++ %4 = load i64, ptr addrspace(4) %1, align 32 ++ %5 = load i64, ptr addrspace(4) %3, align 8 ++; CHECK-LLVM: %[[GLocalSize2:[0-9]+]] = call spir_func i64 @_Z14get_local_sizej(i32 2) #1 ++; CHECK-LLVM: mul i64 %[[GLocalSize0]], %[[GLocalSize2]] ++ %mul = mul i64 %4, %5 ++ ret void ++} +diff --git a/test/transcoding/builtin_vars_gep.ll b/test/transcoding/builtin_vars_gep.ll +index 133fcf56..2bf19241 100644 +--- a/test/transcoding/builtin_vars_gep.ll ++++ b/test/transcoding/builtin_vars_gep.ll +@@ -23,20 +23,8 @@ define spir_kernel void @f() { + entry: + %0 = load i64, i64 addrspace(1)* getelementptr (<3 x i64>, <3 x i64> addrspace(1)* @__spirv_BuiltInGlobalInvocationId, i64 0, i64 0), align 32 + ; CHECK-OCL-IR: %[[#ID1:]] = call spir_func i64 @_Z13get_global_idj(i32 0) +- ; CHECK-OCL-IR: %[[#VEC1:]] = insertelement <3 x i64> undef, i64 %[[#ID1]], i32 0 +- ; CHECK-OCL-IR: %[[#ID2:]] = call spir_func i64 @_Z13get_global_idj(i32 1) +- ; CHECK-OCL-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1 +- ; CHECK-OCL-IR: %[[#ID3:]] = call spir_func i64 @_Z13get_global_idj(i32 2) +- ; CHECK-OCL-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2 +- ; CHECK-OCL-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0 + + ; CHECK-SPV-IR: %[[#ID1:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 0) +- ; CHECK-SPV-IR: %[[#VEC1:]] = insertelement <3 x i64> undef, i64 %[[#ID1]], i32 0 +- ; CHECK-SPV-IR: %[[#ID2:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1) +- ; CHECK-SPV-IR: %[[#VEC2:]] = insertelement <3 x i64> %[[#VEC1]], i64 %[[#ID2]], i32 1 +- ; CHECK-SPV-IR: %[[#ID3:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 2) +- ; CHECK-SPV-IR: %[[#VEC3:]] = insertelement <3 x i64> %[[#VEC2]], i64 %[[#ID3]], i32 2 +- ; CHECK-SPV-IR: %[[#]] = extractelement <3 x i64> %[[#VEC3]], i64 0 + + ret void + } +-- +2.20.1 + diff --git a/patches/0067-Adjust-Source-Lang-Literal-logic-to-support-multiple.patch b/patches/0067-Adjust-Source-Lang-Literal-logic-to-support-multiple.patch new file mode 100644 index 0000000..dca791d --- /dev/null +++ b/patches/0067-Adjust-Source-Lang-Literal-logic-to-support-multiple.patch @@ -0,0 +1,134 @@ +From e7bd5e655630d145b310a76196cd1c55299e8116 Mon Sep 17 00:00:00 2001 +From: Mateusz Chudyk +Date: Tue, 1 Aug 2023 18:52:30 +0200 +Subject: [PATCH 67/79] Adjust "Source Lang Literal" logic to support multiple + CompileUnits (#2105) + +This commit changes "Source Lang Literal" flag from simple a scalar value +to a vector of pairs: (compile unit, source language). +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 44 +++++++++++++++++-- + lib/SPIRV/SPIRVToLLVMDbgTran.h | 3 ++ + .../InvalidSourceLanguageSPIRVtoLLVM.spvasm | 6 ++- + 3 files changed, 48 insertions(+), 5 deletions(-) + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index a1102cf0..180b91e0 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -173,6 +173,34 @@ DIScope *SPIRVToLLVMDbgTran::getScope(const SPIRVEntry *ScopeInst) { + return transDebugInst(static_cast(ScopeInst)); + } + ++void SPIRVToLLVMDbgTran::appendToSourceLangLiteral(DICompileUnit *CompileUnit, ++ SPIRVWord SourceLang) { ++ if (!M->getModuleFlag("Source Lang Literal")) { ++ M->addModuleFlag(llvm::Module::Warning, "Source Lang Literal", ++ MDTuple::get(M->getContext(), {})); ++ } ++ auto *SourceLangLiteral = ++ dyn_cast(M->getModuleFlag("Source Lang Literal")); ++ ++ // Copy old content ++ SmallVector Nodes; ++ for (auto &Node : SourceLangLiteral->operands()) { ++ Nodes.push_back(Node); ++ } ++ ++ // Add new entry ++ Nodes.push_back(MDTuple::get( ++ M->getContext(), SmallVector{ ++ CompileUnit, ++ ConstantAsMetadata::get(ConstantInt::get( ++ Type::getInt32Ty(M->getContext()), SourceLang)), ++ })); ++ ++ // Update ++ M->setModuleFlag(llvm::Module::Warning, "Source Lang Literal", ++ MDTuple::get(M->getContext(), Nodes)); ++} ++ + DICompileUnit * + SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + const std::string CompilerVersion, +@@ -197,6 +225,8 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + } + SPIRVWord SourceLang = + getConstantValueOrLiteral(Ops, LanguageIdx, DebugInst->getExtSetKind()); ++ SPIRVWord OriginalSourceLang = SourceLang; ++ bool InvalidSourceLang = false; + if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) { + SourceLang = convertSPIRVSourceLangToDWARFNonSemanticDbgInfo(SourceLang); + } else if (isSPIRVSourceLangValid(SourceLang)) { +@@ -205,8 +235,8 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + // Some SPIR-V producers generate invalid source language value. In such + // case the original value should be preserved in "Source Lang Literal" + // module flag for later use by LLVM IR consumers. +- M->addModuleFlag(llvm::Module::Warning, "Source Lang Literal", SourceLang); + SourceLang = dwarf::DW_LANG_OpenCL; ++ InvalidSourceLang = true; + } + + BuilderMap[DebugInst->getId()] = std::make_unique(*M); +@@ -224,20 +254,28 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst, + DebugInst->getExtSetKind() == + SPIRVEIS_NonSemantic_Shader_DebugInfo_200); + +- return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ auto *CompileUnit = BuilderMap[DebugInst->getId()]->createCompileUnit( + SourceLang, getFile(Ops[SourceIdx]), + DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 + ? CompilerVersion + : getString(Ops[ProducerIdx]), + false, Flags, 0, StoragePath, + DICompileUnit::DebugEmissionKind::FullDebug, BuildIdentifier); ++ if (InvalidSourceLang) { ++ appendToSourceLangLiteral(CompileUnit, OriginalSourceLang); ++ } ++ return CompileUnit; + } + + // TODO: Remove this workaround once we switch to NonSemantic.Shader.* debug + // info by default + auto Producer = findModuleProducer(); +- return BuilderMap[DebugInst->getId()]->createCompileUnit( ++ auto *CompileUnit = BuilderMap[DebugInst->getId()]->createCompileUnit( + SourceLang, getFile(Ops[SourceIdx]), Producer, false, Flags, 0); ++ if (InvalidSourceLang) { ++ appendToSourceLangLiteral(CompileUnit, OriginalSourceLang); ++ } ++ return CompileUnit; + } + + DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) { +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h +index 86cf6da7..e32b9b40 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.h ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h +@@ -105,6 +105,9 @@ private: + MDNode *transDebugInlined(const SPIRVExtInst *Inst); + MDNode *transDebugInlinedNonSemanticShader200(const SPIRVExtInst *Inst); + ++ void appendToSourceLangLiteral(DICompileUnit *CompileUnit, ++ SPIRVWord SourceLang); ++ + DICompileUnit *transCompilationUnit(const SPIRVExtInst *DebugInst, + const std::string CompilerVersion = "", + const std::string Flags = ""); +diff --git a/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm b/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm +index 82f1f4e5..7005573e 100644 +--- a/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm ++++ b/test/DebugInfo/InvalidSourceLanguageSPIRVtoLLVM.spvasm +@@ -36,5 +36,7 @@ + OpReturn + OpFunctionEnd + +-; CHECK: !{i32 2, !"Source Lang Literal", i32 42} +-; CHECK: !DICompileUnit(language: DW_LANG_OpenCL, ++; CHECK: {{![0-9]+}} = !{i32 2, !"Source Lang Literal", [[LIST:![0-9]+]]} ++; CHECK: [[LIST]] = !{[[ENTRY:![0-9]+]]} ++; CHECK: [[ENTRY]] = !{[[CU:![0-9]+]], i32 42} ++; CHECK: [[CU]] = distinct !DICompileUnit(language: DW_LANG_OpenCL +-- +2.20.1 + diff --git a/patches/0068-Support-for-SPV_INTEL_cache_controls-2147.patch b/patches/0068-Support-for-SPV_INTEL_cache_controls-2147.patch new file mode 100644 index 0000000..ffec8dd --- /dev/null +++ b/patches/0068-Support-for-SPV_INTEL_cache_controls-2147.patch @@ -0,0 +1,507 @@ +From f38c2207215bcc2f79bd40aad36720c3107376c7 Mon Sep 17 00:00:00 2001 +From: Andrzej Ratajewski +Date: Tue, 12 Sep 2023 10:26:03 +0200 +Subject: [PATCH 68/79] Support for SPV_INTEL_cache_controls (#2147) + +Specification: https://github.com/KhronosGroup/SPIRV-Registry/pull/216 + +Cherry-pick of KhronosGroup/SPIRV-LLVM-Translator#2140 +--- + docs/SPIRVRepresentationInLLVM.rst | 20 +++++-- + include/LLVMSPIRVExtensions.inc | 1 + + lib/SPIRV/SPIRVReader.cpp | 17 +++--- + lib/SPIRV/SPIRVReader.h | 2 +- + lib/SPIRV/SPIRVWriter.cpp | 47 ++++++++++++++++- + lib/SPIRV/libSPIRV/SPIRVDecorate.h | 34 ++++++++++++ + lib/SPIRV/libSPIRV/SPIRVEnum.h | 4 ++ + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 3 ++ + lib/SPIRV/libSPIRV/spirv_internal.hpp | 28 +++++++++- + .../basic_load_store.ll | 52 +++++++++++++++++++ + .../SPV_INTEL_cache_controls/global_var.ll | 38 ++++++++++++++ + .../SPV_INTEL_cache_controls/kernel_arg.ll | 35 +++++++++++++ + 12 files changed, 267 insertions(+), 14 deletions(-) + create mode 100644 test/extensions/INTEL/SPV_INTEL_cache_controls/basic_load_store.ll + create mode 100644 test/extensions/INTEL/SPV_INTEL_cache_controls/global_var.ll + create mode 100644 test/extensions/INTEL/SPV_INTEL_cache_controls/kernel_arg.ll + +diff --git a/docs/SPIRVRepresentationInLLVM.rst b/docs/SPIRVRepresentationInLLVM.rst +index 514a448c..ded07826 100644 +--- a/docs/SPIRVRepresentationInLLVM.rst ++++ b/docs/SPIRVRepresentationInLLVM.rst +@@ -411,14 +411,14 @@ For example: + are translated for image types, but they should be encoded in LLVM IR type name + rather than function metadata. + +-Function parameter and global variable decoration through metadata ++Function parameter, instruction and global variable decoration through metadata + ------------------------------------------------------------------ + +-Both function parameters and global variables can be decorated using LLVM ++Function parameters, instructions and global variables can be decorated using LLVM + metadata through the metadata names ``spirv.ParameterDecorations`` and + ``spirv.Decorations`` respectively. ``spirv.ParameterDecorations`` must be tied + to the kernel function while ``spirv.Decorations`` is tied directly to the +-global variable. ++instruction or global variable. + + A "decoration-node" is a metadata node consisting of one or more operands. The + first operand is an integer literal representing the SPIR-V decoration +@@ -434,7 +434,7 @@ decoration-nodes. + references to decoration-lists, where N is the number of arguments of the + function the metadata is tied to. + +-``spirv.Decorations`` example: ++``spirv.Decorations`` applied on a global variable example: + + .. code-block:: llvm + +@@ -447,6 +447,18 @@ function the metadata is tied to. + decorates a global variable ``v`` with ``Constant`` and ``LinkageAttributes`` + with extra operands ``"v"`` and ``Export`` in SPIR-V. + ++``spirv.Decorations`` applied on an instruction example: ++ ++.. code-block:: llvm ++ ++ %idx = getelementptr inbounds i32, ptr addrspace(1) %b, i64 1, !spirv.Decorations !1 ++ ... ++ !1 = !{!2} ++ !2 = !{i32 6442, i32 1, i32 2} ; {CacheControlLoadINTEL, CacheLevel=1, Cached} ++ ++decorates getelementptr instruction with CacheControlLoadINTEL decoration with ++extra operands ``i32 1`` and ``i32 2``. ++ + ``spirv.ParameterDecorations`` example: + + .. code-block:: llvm +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 5e966a5f..e3bc506c 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -58,3 +58,4 @@ EXT(SPV_INTEL_masked_gather_scatter) + EXT(SPV_INTEL_tensor_float32_conversion) // TODO: to remove old extension + EXT(SPV_INTEL_tensor_float32_rounding) + EXT(SPV_EXT_relaxed_printf_string_address_space) ++EXT(SPV_INTEL_cache_controls) +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index d28f1090..33a9a893 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3782,17 +3782,22 @@ transDecorationsToMetadataList(llvm::LLVMContext *Context, + return MDNode::get(*Context, MDs); + } + +-void SPIRVToLLVM::transVarDecorationsToMetadata(SPIRVValue *BV, Value *V) { +- if (!BV->isVariable()) ++void SPIRVToLLVM::transDecorationsToMetadata(SPIRVValue *BV, Value *V) { ++ if (!BV->isVariable() && !BV->isInst()) + return; + +- if (auto *GV = dyn_cast(V)) { ++ auto SetDecorationsMetadata = [&](auto V) { + std::vector Decorates = BV->getDecorations(); + if (!Decorates.empty()) { + MDNode *MDList = transDecorationsToMetadataList(Context, Decorates); +- GV->setMetadata(SPIRV_MD_DECORATIONS, MDList); ++ V->setMetadata(SPIRV_MD_DECORATIONS, MDList); + } +- } ++ }; ++ ++ if (auto *GV = dyn_cast(V)) ++ SetDecorationsMetadata(GV); ++ else if (auto *I = dyn_cast(V)) ++ SetDecorationsMetadata(I); + } + + bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) { +@@ -3804,7 +3809,7 @@ bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) { + + // Decoration metadata is only enabled in SPIR-V friendly mode + if (BM->getDesiredBIsRepresentation() == BIsRepresentation::SPIRVFriendlyIR) +- transVarDecorationsToMetadata(BV, V); ++ transDecorationsToMetadata(BV, V); + + DbgTran->transDbgInfo(BV, V); + return true; +diff --git a/lib/SPIRV/SPIRVReader.h b/lib/SPIRV/SPIRVReader.h +index 5a5a711b..5b031765 100644 +--- a/lib/SPIRV/SPIRVReader.h ++++ b/lib/SPIRV/SPIRVReader.h +@@ -245,7 +245,7 @@ private: + SmallVectorImpl &Funcs); + void transIntelFPGADecorations(SPIRVValue *BV, Value *V); + void transMemAliasingINTELDecorations(SPIRVValue *BV, Value *V); +- void transVarDecorationsToMetadata(SPIRVValue *BV, Value *V); ++ void transDecorationsToMetadata(SPIRVValue *BV, Value *V); + void transFunctionDecorationsToMetadata(SPIRVFunction *BF, Function *F); + void + transFunctionPointerCallArgumentAttributes(SPIRVValue *BV, CallInst *CI, +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index cf1482e2..34d0dd57 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -2414,6 +2414,48 @@ static void transMetadataDecorations(Metadata *MD, SPIRVEntry *Target) { + new SPIRVDecorateImplementInCSRINTEL(Target, Value->getZExtValue())); + break; + } ++ case spv::internal::DecorationCacheControlLoadINTEL: { ++ ErrLog.checkError( ++ NumOperands == 3, SPIRVEC_InvalidLlvmModule, ++ "CacheControlLoadINTEL requires exactly 2 extra operands"); ++ auto *CacheLevel = ++ mdconst::dyn_extract(DecoMD->getOperand(1)); ++ auto *CacheControl = ++ mdconst::dyn_extract(DecoMD->getOperand(2)); ++ ErrLog.checkError(CacheLevel, SPIRVEC_InvalidLlvmModule, ++ "CacheControlLoadINTEL cache level operand is required " ++ "to be an integer"); ++ ErrLog.checkError(CacheControl, SPIRVEC_InvalidLlvmModule, ++ "CacheControlLoadINTEL cache control operand is " ++ "required to be an integer"); ++ ++ Target->addDecorate(new SPIRVDecorateCacheControlLoadINTEL( ++ Target, CacheLevel->getZExtValue(), ++ static_cast( ++ CacheControl->getZExtValue()))); ++ break; ++ } ++ case spv::internal::DecorationCacheControlStoreINTEL: { ++ ErrLog.checkError( ++ NumOperands == 3, SPIRVEC_InvalidLlvmModule, ++ "CacheControlStoreINTEL requires exactly 2 extra operands"); ++ auto *CacheLevel = ++ mdconst::dyn_extract(DecoMD->getOperand(1)); ++ auto *CacheControl = ++ mdconst::dyn_extract(DecoMD->getOperand(2)); ++ ErrLog.checkError(CacheLevel, SPIRVEC_InvalidLlvmModule, ++ "CacheControlStoreINTEL cache level operand is " ++ "required to be an integer"); ++ ErrLog.checkError(CacheControl, SPIRVEC_InvalidLlvmModule, ++ "CacheControlStoreINTEL cache control operand is " ++ "required to be an integer"); ++ ++ Target->addDecorate(new SPIRVDecorateCacheControlStoreINTEL( ++ Target, CacheLevel->getZExtValue(), ++ static_cast( ++ CacheControl->getZExtValue()))); ++ break; ++ } + default: { + if (NumOperands == 1) { + Target->addDecorate(new SPIRVDecorate(DecoKind, Target)); +@@ -2501,9 +2543,12 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) { + BV->setFPFastMathMode(M); + } + } +- if (Instruction *Inst = dyn_cast(V)) ++ if (Instruction *Inst = dyn_cast(V)) { + if (shouldTryToAddMemAliasingDecoration(Inst)) + transMemAliasingINTELDecorations(Inst, BV); ++ if (auto *IDecoMD = Inst->getMetadata(SPIRV_MD_DECORATIONS)) ++ transMetadataDecorations(IDecoMD, BV); ++ } + + if (auto *CI = dyn_cast(V)) { + auto OC = BV->getOpCode(); +diff --git a/lib/SPIRV/libSPIRV/SPIRVDecorate.h b/lib/SPIRV/libSPIRV/SPIRVDecorate.h +index 60177d1f..2e4458e5 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVDecorate.h ++++ b/lib/SPIRV/libSPIRV/SPIRVDecorate.h +@@ -178,6 +178,9 @@ public: + case internal::DecorationInitModeINTEL: + case internal::DecorationImplementInCSRINTEL: + return ExtensionID::SPV_INTEL_global_variable_decorations; ++ case internal::DecorationCacheControlLoadINTEL: ++ case internal::DecorationCacheControlStoreINTEL: ++ return ExtensionID::SPV_INTEL_cache_controls; + default: + return {}; + } +@@ -763,6 +766,37 @@ public: + Value){}; + }; + ++class SPIRVDecorateCacheControlLoadINTEL : public SPIRVDecorate { ++public: ++ // Complete constructor for SPIRVDecorateCacheControlLoadINTEL ++ SPIRVDecorateCacheControlLoadINTEL( ++ SPIRVEntry *TheTarget, SPIRVWord CacheLevel, ++ spv::internal::LoadCacheControlINTEL CacheControl) ++ : SPIRVDecorate(spv::internal::DecorationCacheControlLoadINTEL, TheTarget, ++ CacheLevel, static_cast(CacheControl)){}; ++ ++ SPIRVWord getCacheLevel() const { return Literals.at(0); }; ++ spv::internal::LoadCacheControlINTEL getCacheControl() const { ++ return static_cast(Literals.at(1)); ++ }; ++}; ++ ++class SPIRVDecorateCacheControlStoreINTEL : public SPIRVDecorate { ++public: ++ // Complete constructor for SPIRVDecorateCacheControlStoreINTEL ++ SPIRVDecorateCacheControlStoreINTEL( ++ SPIRVEntry *TheTarget, SPIRVWord CacheLevel, ++ spv::internal::StoreCacheControlINTEL CacheControl) ++ : SPIRVDecorate(spv::internal::DecorationCacheControlStoreINTEL, ++ TheTarget, CacheLevel, ++ static_cast(CacheControl)){}; ++ ++ SPIRVWord getCacheLevel() const { return Literals.at(0); }; ++ spv::internal::StoreCacheControlINTEL getCacheControl() const { ++ return static_cast(Literals.at(1)); ++ }; ++}; ++ + } // namespace SPIRV + + #endif // SPIRV_LIBSPIRV_SPIRVDECORATE_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 3a62429f..269804f5 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -458,6 +458,10 @@ template <> inline void SPIRVMap::init() { + {internal::CapabilityGlobalVariableDecorationsINTEL}); + ADD_VEC_INIT(internal::DecorationArgumentAttributeINTEL, + {CapabilityFunctionPointersINTEL}); ++ ADD_VEC_INIT(internal::DecorationCacheControlLoadINTEL, ++ {internal::CapabilityCacheControlsINTEL}); ++ ADD_VEC_INIT(internal::DecorationCacheControlStoreINTEL, ++ {internal::CapabilityCacheControlsINTEL}); + } + + template <> inline void SPIRVMap::init() { +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index 4fbdc618..6861f2dd 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -191,6 +191,8 @@ template <> inline void SPIRVMap::init() { + add(internal::DecorationInitModeINTEL, "InitModeINTEL"); + add(internal::DecorationImplementInCSRINTEL, "ImplementInCSRINTEL"); + add(internal::DecorationArgumentAttributeINTEL, "ArgumentAttributeINTEL"); ++ add(internal::DecorationCacheControlLoadINTEL, "CacheControlLoadINTEL"); ++ add(internal::DecorationCacheControlStoreINTEL, "CacheControlStoreINTEL"); + + add(DecorationMax, "Max"); + } +@@ -618,6 +620,7 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityMaskedGatherScatterINTEL, "MaskedGatherScatterINTEL"); + add(internal::CapabilityTensorFloat32RoundingINTEL, + "TensorFloat32RoundingINTEL"); ++ add(internal::CapabilityCacheControlsINTEL, "CacheControlsINTEL"); + } + SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) + +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index c4524196..e0acc6bb 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -89,7 +89,9 @@ enum InternalDecoration { + IDecHostAccessINTEL = 6147, + IDecInitModeINTEL = 6148, + IDecImplementInCSRINTEL = 6149, +- IDecArgumentAttributeINTEL = 6409 ++ IDecArgumentAttributeINTEL = 6409, ++ IDecCacheControlLoadINTEL = 6442, ++ IDecCacheControlStoreINTEL = 6443 + }; + + enum InternalCapability { +@@ -106,7 +108,8 @@ enum InternalCapability { + ICapGlobalVariableDecorationsINTEL = 6146, + ICapabilityComplexFloatMulDivINTEL = 6414, + ICapabilityTensorFloat32RoundingINTEL = 6425, +- ICapabilityMaskedGatherScatterINTEL = 6427 ++ ICapabilityMaskedGatherScatterINTEL = 6427, ++ ICapabilityCacheControlsINTEL = 6441 + }; + + enum InternalFunctionControlMask { IFunctionControlOptNoneINTELMask = 0x10000 }; +@@ -135,6 +138,21 @@ enum InternalBuiltIn { + IBuiltInGlobalHWThreadIDINTEL = 6136, + }; + ++enum class LoadCacheControlINTEL { ++ Uncached = 0, ++ Cached = 1, ++ Streaming = 2, ++ InvalidateAfterRead = 3, ++ ConstCached = 4 ++}; ++ ++enum class StoreCacheControlINTEL { ++ Uncached = 0, ++ WriteThrough = 1, ++ WriteBack = 2, ++ Streaming = 3 ++}; ++ + #define _SPIRV_OP(x, y) constexpr x x##y = static_cast(I##x##y); + _SPIRV_OP(Capability, JointMatrixINTEL) + _SPIRV_OP(Op, TypeJointMatrixINTEL) +@@ -159,6 +177,8 @@ _SPIRV_OP(Op, MaskedScatterINTEL) + + _SPIRV_OP(Capability, TensorFloat32RoundingINTEL) + _SPIRV_OP(Op, RoundFToTF32INTEL) ++ ++_SPIRV_OP(Capability, CacheControlsINTEL) + #undef _SPIRV_OP + + constexpr SourceLanguage SourceLanguagePython = +@@ -226,6 +246,10 @@ constexpr Decoration DecorationImplementInCSRINTEL = + static_cast(IDecImplementInCSRINTEL); + constexpr Decoration DecorationArgumentAttributeINTEL = + static_cast(IDecArgumentAttributeINTEL); ++constexpr Decoration DecorationCacheControlLoadINTEL = ++ static_cast(IDecCacheControlLoadINTEL); ++constexpr Decoration DecorationCacheControlStoreINTEL = ++ static_cast(IDecCacheControlStoreINTEL); + + constexpr Capability CapabilityFastCompositeINTEL = + static_cast(ICapFastCompositeINTEL); +diff --git a/test/extensions/INTEL/SPV_INTEL_cache_controls/basic_load_store.ll b/test/extensions/INTEL/SPV_INTEL_cache_controls/basic_load_store.ll +new file mode 100644 +index 00000000..45965019 +--- /dev/null ++++ b/test/extensions/INTEL/SPV_INTEL_cache_controls/basic_load_store.ll +@@ -0,0 +1,52 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv --spirv-target-env=SPV-IR -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: Load {{[0-9]+}} {{[0-9]+}} [[LoadPtr:[0-9]+]] ++; CHECK-SPIRV-DAG: Store [[StorePtr:[0-9]+]] ++ ++; CHECK-SPIRV-DAG: Decorate [[LoadPtr]] CacheControlLoadINTEL 0 1 ++; CHECK-SPIRV-DAG: Decorate [[LoadPtr]] CacheControlLoadINTEL 1 1 ++; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 0 1 ++; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 1 2 ++ ++; CHECK-LLVM: %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %buffer, i64 1, !spirv.Decorations [[LoadMD:![0-9]+]] ++; CHECK-LLVM: load i32, i32 addrspace(1)* %arrayidx, align 4 ++ ++; CHECK-LLVM: %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %buffer, i64 0, !spirv.Decorations [[StoreMD:![0-9]+]] ++; CHECK-LLVM: store i32 %0, i32 addrspace(1)* %arrayidx1, align 4 ++ ++; CHECK-LLVM: [[LoadMD]] = !{[[CC0:![0-9]+]], [[CC1:![0-9]+]]} ++; CHECK-LLVM: [[CC0]] = !{i32 6442, i32 0, i32 1} ++; CHECK-LLVM: [[CC1]] = !{i32 6442, i32 1, i32 1} ++ ++; CHECK-LLVM: [[StoreMD]] = !{[[CC2:![0-9]+]], [[CC3:![0-9]+]]} ++; CHECK-LLVM: [[CC2]] = !{i32 6443, i32 0, i32 1} ++; CHECK-LLVM: [[CC3]] = !{i32 6443, i32 1, i32 2} ++ ++target triple = "spir64-unknown-unknown" ++ ++define spir_kernel void @test(i32 addrspace(1)* %buffer) { ++entry: ++ %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %buffer, i64 1, !spirv.Decorations !3 ++ %0 = load i32, i32 addrspace(1)* %arrayidx, align 4 ++ %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %buffer, i64 0, !spirv.Decorations !6 ++ store i32 %0, i32 addrspace(1)* %arrayidx1, align 4 ++ ret void ++} ++ ++!spirv.MemoryModel = !{!0} ++!spirv.Source = !{!1} ++!opencl.spir.version = !{!2} ++!opencl.ocl.version = !{!2} ++ ++!0 = !{i32 2, i32 2} ++!1 = !{i32 3, i32 102000} ++!2 = !{i32 1, i32 2} ++!3 = !{!4, !5} ++!4 = !{i32 6442, i32 0, i32 1} ; {CacheControlLoadINTEL, CacheLevel=0, Cached} ++!5 = !{i32 6442, i32 1, i32 1} ; {CacheControlLoadINTEL, CacheLevel=1, Cached} ++!6 = !{!7, !8} ++!7 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} ++!8 = !{i32 6443, i32 1, i32 2} ; {CacheControlStoreINTEL, CacheLevel=1, WriteBack} +diff --git a/test/extensions/INTEL/SPV_INTEL_cache_controls/global_var.ll b/test/extensions/INTEL/SPV_INTEL_cache_controls/global_var.ll +new file mode 100644 +index 00000000..6b4ab1cd +--- /dev/null ++++ b/test/extensions/INTEL/SPV_INTEL_cache_controls/global_var.ll +@@ -0,0 +1,38 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv --spirv-target-env=SPV-IR -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: Store [[StorePtr:[0-9]+]] ++ ++; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 0 1 ++; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 1 3 ++ ++; CHECK-LLVM: @p = common addrspace(1) global i32 0, align 4, !spirv.Decorations [[GlobalMD:![0-9]+]] ++; CHECK-LLVM: store i32 0, i32 addrspace(1)* @p, align 4 ++ ++; CHECK-LLVM-DAG: [[CC0:![0-9]+]] = !{i32 6443, i32 0, i32 1} ++; CHECK-LLVM-DAG: [[CC1:![0-9]+]] = !{i32 6443, i32 1, i32 3} ++; CHECK-LLVM-DAG: [[GlobalMD]] = {{.*}}[[CC0]]{{.*}}[[CC1]] ++ ++target triple = "spir64-unknown-unknown" ++ ++@p = common addrspace(1) global i32 0, align 4, !spirv.Decorations !3 ++ ++define spir_kernel void @test() { ++entry: ++ store i32 0, i32 addrspace(1)* @p, align 4 ++ ret void ++} ++ ++!spirv.MemoryModel = !{!0} ++!spirv.Source = !{!1} ++!opencl.spir.version = !{!2} ++!opencl.ocl.version = !{!2} ++ ++!0 = !{i32 2, i32 2} ++!1 = !{i32 3, i32 102000} ++!2 = !{i32 1, i32 2} ++!3 = !{!4, !5} ++!4 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} ++!5 = !{i32 6443, i32 1, i32 3} ; {CacheControlStoreINTEL, CacheLevel=1, Streaming} +diff --git a/test/extensions/INTEL/SPV_INTEL_cache_controls/kernel_arg.ll b/test/extensions/INTEL/SPV_INTEL_cache_controls/kernel_arg.ll +new file mode 100644 +index 00000000..1007021e +--- /dev/null ++++ b/test/extensions/INTEL/SPV_INTEL_cache_controls/kernel_arg.ll +@@ -0,0 +1,35 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls %t.bc -o %t.spv ++; RUN: llvm-spirv -r %t.spv --spirv-target-env=SPV-IR -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV: Decorate {{[0-9]+}} CacheControlLoadINTEL 0 0 ++; CHECK-SPIRV: Decorate {{[0-9]+}} CacheControlStoreINTEL 0 1 ++ ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-LLVM: spir_kernel {{.*}} !spirv.ParameterDecorations [[ParamDecID:![0-9]+]] ++define spir_kernel void @test(i32 addrspace(1)* %dummy, i32 addrspace(1)* %buffer) !spirv.ParameterDecorations !3 { ++entry: ++ %0 = load i32, i32 addrspace(1)* %buffer, align 4 ++ store i32 %0, i32 addrspace(1)* %buffer, align 4 ++ ret void ++} ++ ++!spirv.MemoryModel = !{!0} ++!spirv.Source = !{!1} ++!opencl.spir.version = !{!2} ++!opencl.ocl.version = !{!2} ++ ++!0 = !{i32 2, i32 2} ++!1 = !{i32 3, i32 102000} ++!2 = !{i32 1, i32 2} ++!3 = !{!4, !5} ++!4 = !{} ++!5 = !{!6, !7} ++; CHECK-LLVM: [[ParamDecID]] = !{!{{[0-9]+}}, [[BufferDecID:![0-9]+]]} ++; CHECK-LLVM: [[BufferDecID]] = !{[[StoreDecID:![0-9]+]], [[LoadDecID:![0-9]+]]} ++; CHECK-LLVM: [[StoreDecID]] = !{i32 6442, i32 0, i32 0} ++; CHECK-LLVM: [[LoadDecID]] = !{i32 6443, i32 0, i32 1} ++!6 = !{i32 6442, i32 0, i32 0} ; {CacheControlLoadINTEL, CacheLevel=0, Uncached} ++!7 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough} +-- +2.20.1 + diff --git a/patches/0069-Backport-to-15-Backport-spirv-preserve-auxdata-chang.patch b/patches/0069-Backport-to-15-Backport-spirv-preserve-auxdata-chang.patch new file mode 100644 index 0000000..dc8b26c --- /dev/null +++ b/patches/0069-Backport-to-15-Backport-spirv-preserve-auxdata-chang.patch @@ -0,0 +1,838 @@ +From ba7f92a04bbfd65e3e9b0b7e0c18bfbba4aa81f4 Mon Sep 17 00:00:00 2001 +From: Nick Sarnie +Date: Mon, 16 Oct 2023 11:01:08 +0000 +Subject: [PATCH 69/79] [Backport to 15] Backport spirv-preserve-auxdata + changes (#2180) + +Backport the below changes to 15: + +f729c49 +89d658c +9823690 +d498f48 +d24b9c6 + +I made the following changes that are not in the original changes: + +Use llvm::Optional instead of std::optional +Port tests to not use opaque pointers and related flags +Fix patch fail due to missing unrelated function in this branch + +Signed-off-by: Sarnie, Nick +--- + include/LLVMSPIRVOpts.h | 17 +++- + lib/SPIRV/SPIRVReader.cpp | 67 +++++++++++++++ + lib/SPIRV/SPIRVReader.h | 1 + + lib/SPIRV/SPIRVWriter.cpp | 83 +++++++++++++++++++ + lib/SPIRV/SPIRVWriter.h | 2 + + lib/SPIRV/libSPIRV/NonSemantic.AuxData.h | 33 ++++++++ + lib/SPIRV/libSPIRV/SPIRVEnum.h | 2 + + lib/SPIRV/libSPIRV/SPIRVExtInst.h | 11 +++ + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 17 +++- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 18 +++- + lib/SPIRV/libSPIRV/SPIRVModule.h | 8 ++ + lib/SPIRV/libSPIRV/SPIRVStream.cpp | 1 + + lib/SPIRV/libSPIRV/SPIRVStream.h | 1 + + ...eserve-all-function-attributes-attrkind.ll | 26 ++++++ + .../preserve-all-function-attributes-crash.ll | 23 +++++ + .../preserve-all-function-attributes.ll | 43 ++++++++++ + .../preserve-all-function-metadata-debug.ll | 28 +++++++ + .../preserve-all-function-metadata.ll | 47 +++++++++++ + tools/llvm-spirv/llvm-spirv.cpp | 17 +++- + 19 files changed, 439 insertions(+), 6 deletions(-) + create mode 100644 lib/SPIRV/libSPIRV/NonSemantic.AuxData.h + create mode 100644 test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-attrkind.ll + create mode 100644 test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-crash.ll + create mode 100644 test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes.ll + create mode 100644 test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata-debug.ll + create mode 100644 test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata.ll + +diff --git a/include/LLVMSPIRVOpts.h b/include/LLVMSPIRVOpts.h +index 7d1f11ff..fa1df5fd 100644 +--- a/include/LLVMSPIRVOpts.h ++++ b/include/LLVMSPIRVOpts.h +@@ -90,7 +90,9 @@ enum class DebugInfoEIS : uint32_t { + /// \brief Helper class to manage SPIR-V translation + class TranslatorOpts { + public: +- using ExtensionsStatusMap = std::map; ++ // Unset optional means not directly specified by user ++ using ExtensionsStatusMap = std::map>; ++ + using ArgList = llvm::SmallVector; + + TranslatorOpts() = default; +@@ -107,11 +109,14 @@ public: + if (ExtStatusMap.end() == I) + return false; + +- return I->second; ++ return I->second && *I->second; + } + + void setAllowedToUseExtension(ExtensionID Extension, bool Allow = true) { +- ExtStatusMap[Extension] = Allow; ++ // Only allow using the extension if it has not already been disabled ++ auto I = ExtStatusMap.find(Extension); ++ if (I == ExtStatusMap.end() || !I->second || (*I->second) == true) ++ ExtStatusMap[Extension] = Allow; + } + + VersionNumber getMaxVersion() const { return MaxVersion; } +@@ -122,6 +127,10 @@ public: + + void setMemToRegEnabled(bool Mem2Reg) { SPIRVMemToReg = Mem2Reg; } + ++ bool preserveAuxData() const { return PreserveAuxData; } ++ ++ void setPreserveAuxData(bool ArgValue) { PreserveAuxData = ArgValue; } ++ + void setGenKernelArgNameMDEnabled(bool ArgNameMD) { + GenKernelArgNameMD = ArgNameMD; + } +@@ -230,6 +239,8 @@ private: + // Add a workaround to preserve OpenCL kernel_arg_type and + // kernel_arg_type_qual metadata through OpString + bool PreserveOCLKernelArgTypeMetadataThroughString = false; ++ ++ bool PreserveAuxData = false; + }; + + } // namespace SPIRV +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 33a9a893..a4c271ed 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3380,10 +3380,16 @@ bool SPIRVToLLVM::translate() { + if (!postProcessBuiltinsReturningStruct(M, IsCpp)) + return false; + } ++ ++ for (SPIRVExtInst *EI : BM->getAuxDataInstVec()) { ++ transAuxDataInst(EI); ++ } ++ + eraseUselessFunctions(M); + + DbgTran->addDbgInfoVersion(); + DbgTran->finalize(); ++ + return true; + } + +@@ -4438,6 +4444,67 @@ Instruction *SPIRVToLLVM::transOCLBuiltinFromExtInst(SPIRVExtInst *BC, + return CI; + } + ++void SPIRVToLLVM::transAuxDataInst(SPIRVExtInst *BC) { ++ assert(BC->getExtSetKind() == SPIRV::SPIRVEIS_NonSemantic_AuxData); ++ if (!BC->getModule()->preserveAuxData()) ++ return; ++ auto Args = BC->getArguments(); ++ // Args 0 and 1 are common between attributes and metadata. ++ // 0 is the function, 1 is the name of the attribute/metadata as a string ++ auto *SpvFcn = BC->getModule()->getValue(Args[0]); ++ auto *F = static_cast(getTranslatedValue(SpvFcn)); ++ assert(F && "Function should already have been translated!"); ++ auto AttrOrMDName = BC->getModule()->get(Args[1])->getStr(); ++ switch (BC->getExtOp()) { ++ case NonSemanticAuxData::FunctionAttribute: { ++ assert(Args.size() < 4 && "Unexpected FunctionAttribute Args"); ++ // If this attr was specially handled and added elsewhere, skip it. ++ const Attribute::AttrKind AsKind = ++ Attribute::getAttrKindFromName(AttrOrMDName); ++ if (AsKind != Attribute::None && F->hasFnAttribute(AsKind)) ++ return; ++ if (AsKind == Attribute::None && F->hasFnAttribute(AttrOrMDName)) ++ return; ++ // For attributes, arg 2 is the attribute value as a string, which may not ++ // exist. ++ if (Args.size() == 3) { ++ auto AttrValue = BC->getModule()->get(Args[2])->getStr(); ++ F->addFnAttr(AttrOrMDName, AttrValue); ++ } else { ++ if (AsKind != Attribute::None) ++ F->addFnAttr(AsKind); ++ else ++ F->addFnAttr(AttrOrMDName); ++ } ++ break; ++ } ++ case NonSemanticAuxData::FunctionMetadata: { ++ // If this metadata was specially handled and added elsewhere, skip it. ++ if (F->hasMetadata(AttrOrMDName)) ++ return; ++ SmallVector MetadataArgs; ++ // Process the metadata values. ++ for (size_t CurArg = 2; CurArg < Args.size(); CurArg++) { ++ auto *Arg = BC->getModule()->get(Args[CurArg]); ++ // For metadata, the metadata values can be either values or strings. ++ if (Arg->getOpCode() == OpString) { ++ auto *ArgAsStr = static_cast(Arg); ++ MetadataArgs.push_back( ++ MDString::get(F->getContext(), ArgAsStr->getStr())); ++ } else { ++ auto *ArgAsVal = static_cast(Arg); ++ auto *TranslatedMD = transValue(ArgAsVal, F, nullptr); ++ MetadataArgs.push_back(ValueAsMetadata::get(TranslatedMD)); ++ } ++ } ++ F->setMetadata(AttrOrMDName, MDNode::get(*Context, MetadataArgs)); ++ break; ++ } ++ default: ++ llvm_unreachable("Invalid op"); ++ } ++} ++ + // SPIR-V only contains language version. Use OpenCL language version as + // SPIR version. + void SPIRVToLLVM::transSourceLanguage() { +diff --git a/lib/SPIRV/SPIRVReader.h b/lib/SPIRV/SPIRVReader.h +index 5b031765..f1de7c6f 100644 +--- a/lib/SPIRV/SPIRVReader.h ++++ b/lib/SPIRV/SPIRVReader.h +@@ -95,6 +95,7 @@ public: + bool transDecoration(SPIRVValue *, Value *); + bool transAlign(SPIRVValue *, Value *); + Instruction *transOCLBuiltinFromExtInst(SPIRVExtInst *BC, BasicBlock *BB); ++ void transAuxDataInst(SPIRVExtInst *BC); + std::vector transValue(const std::vector &, + Function *F, BasicBlock *); + Function *transFunction(SPIRVFunction *F); +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 34d0dd57..97af8e04 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -902,6 +902,8 @@ SPIRVFunction *LLVMToSPIRVBase::transFunctionDecl(Function *F) { + + transFPGAFunctionMetadata(BF, F); + ++ transAuxDataInst(BF, F); ++ + SPIRVDBG(dbgs() << "[transFunction] " << *F << " => "; + spvdbgs() << *BF << '\n';) + return BF; +@@ -1026,6 +1028,82 @@ void LLVMToSPIRVBase::transFPGAFunctionMetadata(SPIRVFunction *BF, + } + } + ++void LLVMToSPIRVBase::transAuxDataInst(SPIRVFunction *BF, Function *F) { ++ auto *BM = BF->getModule(); ++ if (!BM->preserveAuxData()) ++ return; ++ BM->addExtension(SPIRV::ExtensionID::SPV_KHR_non_semantic_info); ++ const auto &FnAttrs = F->getAttributes().getFnAttrs(); ++ for (const auto &Attr : FnAttrs) { ++ std::vector Ops; ++ Ops.push_back(BF->getId()); ++ if (Attr.isStringAttribute()) { ++ // Format for String attributes is: ++ // NonSemanticAuxDataFunctionAttribute Fcn AttrName AttrValue ++ // or, if no value: ++ // NonSemanticAuxDataFunctionAttribute Fcn AttrName ++ // ++ // AttrName and AttrValue are always Strings ++ const StringRef AttrKind = Attr.getKindAsString(); ++ const StringRef AttrValue = Attr.getValueAsString(); ++ auto *KindSpvString = BM->getString(AttrKind.str()); ++ Ops.push_back(KindSpvString->getId()); ++ if (!AttrValue.empty()) { ++ auto *ValueSpvString = BM->getString(AttrValue.str()); ++ Ops.push_back(ValueSpvString->getId()); ++ } ++ } else { ++ // Format for other types is: ++ // NonSemanticAuxDataFunctionAttribute Fcn AttrStr ++ // AttrStr is always a String. ++ const std::string AttrStr = Attr.getAsString(); ++ auto *AttrSpvString = BM->getString(AttrStr); ++ Ops.push_back(AttrSpvString->getId()); ++ } ++ BM->addAuxData(NonSemanticAuxData::FunctionAttribute, ++ transType(Type::getVoidTy(F->getContext())), Ops); ++ } ++ SmallVector> AllMD; ++ SmallVector MDNames; ++ F->getContext().getMDKindNames(MDNames); ++ F->getAllMetadata(AllMD); ++ for (auto MD : AllMD) { ++ const std::string MDName = MDNames[MD.first].str(); ++ ++ // spirv.Decorations, spirv.ParameterDecorations and debug information are ++ // handled elsewhere for both forward and reverse translation and are ++ // complicated to support here, so just skip them. ++ if (MDName == SPIRV_MD_DECORATIONS || ++ MDName == SPIRV_MD_PARAMETER_DECORATIONS || ++ MD.first == LLVMContext::MD_dbg) ++ continue; ++ ++ // Format for metadata is: ++ // NonSemanticAuxDataFunctionMetadata Fcn MDName MDVals... ++ // MDName is always a String, MDVals have different types as explained ++ // below. Also note this instruction has a variable number of operands ++ std::vector Ops; ++ Ops.push_back(BF->getId()); ++ Ops.push_back(BM->getString(MDName)->getId()); ++ for (unsigned int OpIdx = 0; OpIdx < MD.second->getNumOperands(); OpIdx++) { ++ const auto &CurOp = MD.second->getOperand(OpIdx); ++ if (auto *MDStr = dyn_cast(CurOp)) { ++ // For MDString, MDVal is String ++ auto *SPIRVStr = BM->getString(MDStr->getString().str()); ++ Ops.push_back(SPIRVStr->getId()); ++ } else if (auto *ValueAsMeta = dyn_cast(CurOp)) { ++ // For Value metadata, MDVal is a SPIRVValue ++ auto *SPIRVVal = transValue(ValueAsMeta->getValue(), nullptr); ++ Ops.push_back(SPIRVVal->getId()); ++ } else { ++ assert(false && "Unsupported metadata type"); ++ } ++ } ++ BM->addAuxData(NonSemanticAuxData::FunctionMetadata, ++ transType(Type::getVoidTy(F->getContext())), Ops); ++ } ++} ++ + SPIRVValue *LLVMToSPIRVBase::transConstant(Value *V) { + if (auto CPNull = dyn_cast(V)) + return BM->addNullConstant( +@@ -2613,6 +2691,11 @@ bool LLVMToSPIRVBase::transBuiltinSet() { + SPIRVBuiltinSetNameMap::map(BM->getDebugInfoEIS()), &EISId)) + return false; + } ++ if (BM->preserveAuxData()) { ++ if (!BM->importBuiltinSet( ++ SPIRVBuiltinSetNameMap::map(SPIRVEIS_NonSemantic_AuxData), &EISId)) ++ return false; ++ } + return true; + } + +diff --git a/lib/SPIRV/SPIRVWriter.h b/lib/SPIRV/SPIRVWriter.h +index e96e1ad0..b0982c04 100644 +--- a/lib/SPIRV/SPIRVWriter.h ++++ b/lib/SPIRV/SPIRVWriter.h +@@ -121,6 +121,8 @@ public: + SPIRVFunction *transFunctionDecl(Function *F); + void transVectorComputeMetadata(Function *F); + void transFPGAFunctionMetadata(SPIRVFunction *BF, Function *F); ++ void transAuxDataInst(SPIRVFunction *BF, Function *F); ++ + bool transGlobalVariables(); + + Op transBoolOpCode(SPIRVValue *Opn, Op OC); +diff --git a/lib/SPIRV/libSPIRV/NonSemantic.AuxData.h b/lib/SPIRV/libSPIRV/NonSemantic.AuxData.h +new file mode 100644 +index 00000000..240734af +--- /dev/null ++++ b/lib/SPIRV/libSPIRV/NonSemantic.AuxData.h +@@ -0,0 +1,33 @@ ++/* ++** Copyright (c) 2023 The Khronos Group Inc. ++** ++** Permission is hereby granted, free of charge, to any person obtaining a copy ++** of this software and/or associated documentation files (the "Materials"), ++** to deal in the Materials without restriction, including without limitation ++** the rights to use, copy, modify, merge, publish, distribute, sublicense, ++** and/or sell copies of the Materials, and to permit persons to whom the ++** Materials are furnished to do so, subject to the following conditions: ++** ++** The above copyright notice and this permission notice shall be included in ++** all copies or substantial portions of the Materials. ++** ++** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS ++** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND ++** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ++** ++** THE MATERIALS ARE 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 AUTHORS 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 MATERIALS OR THE USE OR OTHER DEALINGS ++** IN THE MATERIALS. ++*/ ++ ++namespace NonSemanticAuxData { ++enum Instruction { ++ FunctionMetadata = 0, ++ FunctionAttribute = 1, ++ PreserveCount = 2 ++}; ++} // namespace NonSemanticAuxData +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 269804f5..1bd5cc7e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -80,6 +80,7 @@ enum SPIRVExtInstSetKind { + SPIRVEIS_OpenCL_DebugInfo_100, + SPIRVEIS_NonSemantic_Shader_DebugInfo_100, + SPIRVEIS_NonSemantic_Shader_DebugInfo_200, ++ SPIRVEIS_NonSemantic_AuxData, + SPIRVEIS_Count, + }; + +@@ -135,6 +136,7 @@ template <> inline void SPIRVMap::init() { + "NonSemantic.Shader.DebugInfo.100"); + add(SPIRVEIS_NonSemantic_Shader_DebugInfo_200, + "NonSemantic.Shader.DebugInfo.200"); ++ add(SPIRVEIS_NonSemantic_AuxData, "NonSemantic.AuxData"); + } + typedef SPIRVMap SPIRVBuiltinSetNameMap; + +diff --git a/lib/SPIRV/libSPIRV/SPIRVExtInst.h b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +index e278726f..693d8dab 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVExtInst.h ++++ b/lib/SPIRV/libSPIRV/SPIRVExtInst.h +@@ -40,6 +40,7 @@ + #ifndef SPIRV_LIBSPIRV_SPIRVEXTINST_H + #define SPIRV_LIBSPIRV_SPIRVEXTINST_H + ++#include "NonSemantic.AuxData.h" + #include "OpenCL.std.h" + #include "SPIRV.debug.h" + #include "SPIRVEnum.h" +@@ -270,6 +271,16 @@ template <> inline void SPIRVMap::init() { + } + SPIRV_DEF_NAMEMAP(SPIRVDebugExtOpKind, SPIRVDebugExtOpMap) + ++typedef NonSemanticAuxData::Instruction NonSemanticAuxDataOpKind; ++template <> ++inline void SPIRVMap::init() { ++ add(NonSemanticAuxData::FunctionMetadata, ++ "NonSemanticAuxDataFunctionMetadata"); ++ add(NonSemanticAuxData::FunctionAttribute, ++ "NonSemanticAuxDataFunctionAttribute"); ++} ++SPIRV_DEF_NAMEMAP(NonSemanticAuxDataOpKind, NonSemanticAuxDataOpMap) ++ + } // namespace SPIRV + + #endif // SPIRV_LIBSPIRV_SPIRVEXTINST_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index f7b57d08..bd5b338c 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -42,6 +42,7 @@ + + #include "SPIRVBasicBlock.h" + #include "SPIRVEnum.h" ++#include "SPIRVFunction.h" + #include "SPIRVIsValidEnum.h" + #include "SPIRVOpCode.h" + #include "SPIRVStream.h" +@@ -1771,7 +1772,8 @@ public: + assert((ExtSetKind == SPIRVEIS_OpenCL || ExtSetKind == SPIRVEIS_Debug || + ExtSetKind == SPIRVEIS_OpenCL_DebugInfo_100 || + ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_100 || +- ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) && ++ ExtSetKind == SPIRVEIS_NonSemantic_Shader_DebugInfo_200 || ++ ExtSetKind == SPIRVEIS_NonSemantic_AuxData) && + "not supported"); + } + void encode(spv_ostream &O) const override { +@@ -1786,6 +1788,9 @@ public: + case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + getEncoder(O) << ExtOpDebug; + break; ++ case SPIRVEIS_NonSemantic_AuxData: ++ getEncoder(O) << ExtOpNonSemanticAuxData; ++ break; + default: + assert(0 && "not supported"); + getEncoder(O) << ExtOp; +@@ -1805,6 +1810,9 @@ public: + case SPIRVEIS_NonSemantic_Shader_DebugInfo_200: + getDecoder(I) >> ExtOpDebug; + break; ++ case SPIRVEIS_NonSemantic_AuxData: ++ getDecoder(I) >> ExtOpNonSemanticAuxData; ++ break; + default: + assert(0 && "not supported"); + getDecoder(I) >> ExtOp; +@@ -1860,6 +1868,12 @@ public: + return ArgTypes; + } + ++ llvm::Optional getRequiredExtension() const override { ++ if (SPIRVBuiltinSetNameMap::map(ExtSetKind).find("NonSemantic.") == 0) ++ return ExtensionID::SPV_KHR_non_semantic_info; ++ return {}; ++ } ++ + protected: + SPIRVExtInstSetKind ExtSetKind; + SPIRVId ExtSetId; +@@ -1867,6 +1881,7 @@ protected: + SPIRVWord ExtOp; + OCLExtOpKind ExtOpOCL; + SPIRVDebugExtOpKind ExtOpDebug; ++ NonSemanticAuxDataOpKind ExtOpNonSemanticAuxData; + }; + std::vector ContinuedInstructions; + }; +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index df64f167..ea05680a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -143,6 +143,9 @@ public: + const std::vector &getDebugInstVec() const override { + return DebugInstVec; + } ++ const std::vector &getAuxDataInstVec() const override { ++ return AuxDataInstVec; ++ } + const std::vector &getStringVec() const override { + return StringVec; + } +@@ -304,6 +307,8 @@ public: + const std::vector &) override; + SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType, + const std::vector &) override; ++ SPIRVEntry *addAuxData(SPIRVWord, SPIRVType *TheType, ++ const std::vector &) override; + SPIRVEntry *addModuleProcessed(const std::string &) override; + std::vector getModuleProcessedVec() override; + SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *, +@@ -529,6 +534,7 @@ private: + std::map IntTypeMap; + std::map LiteralMap; + std::vector DebugInstVec; ++ std::vector AuxDataInstVec; + std::vector ModuleProcessedVec; + SPIRVAliasInstMDVec AliasInstMDVec; + SPIRVAliasInstMDMap AliasInstMDMap; +@@ -715,6 +721,8 @@ void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) { + EI->getExtOp() != SPIRVDebug::NoScope) { + DebugInstVec.push_back(EI); + } ++ if (EI->getExtSetKind() == SPIRVEIS_NonSemantic_AuxData) ++ AuxDataInstVec.push_back(EI); + break; + } + case OpAsmTargetINTEL: { +@@ -1374,6 +1382,13 @@ SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType, + return addEntry(createDebugInfo(InstId, TheType, Args)); + } + ++SPIRVEntry *SPIRVModuleImpl::addAuxData(SPIRVWord InstId, SPIRVType *TheType, ++ const std::vector &Args) { ++ return addEntry(new SPIRVExtInst( ++ this, getId(), TheType, SPIRVEIS_NonSemantic_AuxData, ++ getExtInstSetId(SPIRVEIS_NonSemantic_AuxData), InstId, Args)); ++} ++ + SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) { + ModuleProcessedVec.push_back(new SPIRVModuleProcessed(this, Process)); + return ModuleProcessedVec.back(); +@@ -1968,7 +1983,8 @@ spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) { + }), + MI.DebugInstVec.end()); + +- O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() << MI.FuncVec; ++ O << SPIRVNL() << MI.DebugInstVec << MI.AuxDataInstVec << SPIRVNL() ++ << MI.FuncVec; + return O; + } + +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h +index b7a09cfd..0f09a41a 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.h ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.h +@@ -157,6 +157,8 @@ public: + virtual unsigned short getGeneratorVer() const = 0; + virtual SPIRVWord getSPIRVVersion() const = 0; + virtual const std::vector &getDebugInstVec() const = 0; ++ virtual const std::vector &getAuxDataInstVec() const = 0; ++ + virtual const std::vector &getStringVec() const = 0; + + // Module changing functions +@@ -319,6 +321,8 @@ public: + const std::vector &) = 0; + virtual SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *, + const std::vector &) = 0; ++ virtual SPIRVEntry *addAuxData(SPIRVWord, SPIRVType *, ++ const std::vector &) = 0; + virtual SPIRVEntry *addModuleProcessed(const std::string &) = 0; + virtual void addCapability(SPIRVCapabilityKind) = 0; + template void addCapabilities(const T &Caps) { +@@ -532,6 +536,10 @@ public: + .shouldPreserveOCLKernelArgTypeMetadataThroughString(); + } + ++ bool preserveAuxData() const noexcept { ++ return TranslationOpts.preserveAuxData(); ++ } ++ + SPIRVExtInstSetKind getDebugInfoEIS() const { + switch (TranslationOpts.getDebugInfoEIS()) { + case DebugInfoEIS::SPIRV_Debug: +diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.cpp b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +index b30dbe2f..65ca5cbb 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVStream.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +@@ -144,6 +144,7 @@ SPIRV_DEF_ENCDEC(Capability) + SPIRV_DEF_ENCDEC(Decoration) + SPIRV_DEF_ENCDEC(OCLExtOpKind) + SPIRV_DEF_ENCDEC(SPIRVDebugExtOpKind) ++SPIRV_DEF_ENCDEC(NonSemanticAuxDataOpKind) + SPIRV_DEF_ENCDEC(LinkageType) + + // Read a string with padded 0's at the end so that they form a stream of +diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.h b/lib/SPIRV/libSPIRV/SPIRVStream.h +index 9f746284..cd3e06e7 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVStream.h ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.h +@@ -228,6 +228,7 @@ SPIRV_DEC_ENCDEC(Capability) + SPIRV_DEC_ENCDEC(Decoration) + SPIRV_DEC_ENCDEC(OCLExtOpKind) + SPIRV_DEC_ENCDEC(SPIRVDebugExtOpKind) ++SPIRV_DEC_ENCDEC(NonSemanticAuxDataOpKind) + SPIRV_DEC_ENCDEC(LinkageType) + + const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::string &Str); +diff --git a/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-attrkind.ll b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-attrkind.ll +new file mode 100644 +index 00000000..143c86f1 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-attrkind.ll +@@ -0,0 +1,26 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-preserve-auxdata -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-preserve-auxdata ++; RUN: llvm-spirv -r --spirv-preserve-auxdata %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; CHECK-SPIRV: Extension "SPV_KHR_non_semantic_info" ++; CHECK-SPIRV: ExtInstImport [[#Import:]] "NonSemantic.AuxData" ++ ++; CHECK-SPIRV: String [[#Attr0:]] "nounwind" ++ ++; CHECK-SPIRV: Name [[#Fcn0:]] "foo" ++ ++; CHECK-SPIRV: TypeVoid [[#VoidT:]] ++ ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#Attr0Inst:]] [[#Import]] NonSemanticAuxDataFunctionAttribute [[#Fcn0]] [[#Attr0]] {{$}} ++ ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-LLVM: define spir_func void @foo() #[[#Fcn0IRAttr:]] ++define spir_func void @foo() #0 { ++entry: ++ret void ++} ++; CHECK-LLVM: attributes #[[#Fcn0IRAttr]] = { nounwind } ++attributes #0 = { nounwind } +diff --git a/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-crash.ll b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-crash.ll +new file mode 100644 +index 00000000..5ad5aa12 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes-crash.ll +@@ -0,0 +1,23 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc --spirv-preserve-auxdata --spirv-text -spirv-allow-unknown-intrinsics=llvm.genx. -o %t.txt ++; RUN: llvm-spirv --spirv-preserve-auxdata --spirv-target-env=SPV-IR --spirv-text -r %t.txt -o %t.bc ++; RUN: llvm-dis %t.bc -o %t.ll ++; RUN: FileCheck < %t.txt %s --check-prefix=CHECK-SPIRV ++; RUN: FileCheck < %t.ll %s --check-prefix=CHECK-LLVM ++ ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir-unknown-unknown" ++ ++; CHECK-LLVM: define spir_kernel void @test_array ++define spir_kernel void @test_array(i8 addrspace(1)* %in, i8 addrspace(1)* %out) { ++ call void @llvm.memmove.p1i8.p1i8.i32(i8 addrspace(1)* %out, i8 addrspace(1)* %in, i32 72, i1 false) ++ ret void ++} ++ ++; Function Attrs: nounwind ++declare void @llvm.memmove.p1i8.p1i8.i32(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture readonly, i32, i1) #0 ++; CHECK-SPIRV: Name [[#ID:]] "llvm.memmove.p1i8.p1i8.i32" ++; CHECK-LLVM-NOT: llvm.memmove ++ ++; CHECK-LLVM: attributes #0 = { nounwind } ++attributes #0 = { nounwind } +diff --git a/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes.ll b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes.ll +new file mode 100644 +index 00000000..193af4b4 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-attributes.ll +@@ -0,0 +1,43 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-preserve-auxdata -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: not llvm-spirv %t.bc -spirv-text --spirv-preserve-auxdata --spirv-ext=-SPV_KHR_non_semantic_info -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SPIRV-EXT-DISABLED ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-preserve-auxdata ++; RUN: llvm-spirv -r --spirv-preserve-auxdata %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM ++; RUN: llvm-spirv -r %t.spv -o %t.rev.without.bc ++; RUN: llvm-dis %t.rev.without.bc -o - | FileCheck %s --implicit-check-not="{{foo|bar|baz}}" ++ ++; CHECK-SPIRV: Extension "SPV_KHR_non_semantic_info" ++; CHECK-SPIRV: ExtInstImport [[#Import:]] "NonSemantic.AuxData" ++ ++; CHECK-SPIRV: String [[#Attr0:]] "foo" ++; CHECK-SPIRV: String [[#Attr1LHS:]] "bar" ++; CHECK-SPIRV: String [[#Attr1RHS:]] "baz" ++ ++; CHECK-SPIRV: Name [[#Fcn0:]] "mul_add" ++; CHECK-SPIRV: Name [[#Fcn1:]] "test" ++ ++; CHECK-SPIRV: TypeVoid [[#VoidT:]] ++ ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#Attr0Inst:]] [[#Import]] NonSemanticAuxDataFunctionAttribute [[#Fcn0]] [[#Attr0]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#Attr1Inst:]] [[#Import]] NonSemanticAuxDataFunctionAttribute [[#Fcn1]] [[#Attr1LHS]] [[#Attr1RHS]] {{$}} ++ ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-LLVM: declare spir_func void @mul_add() #[[#Fcn0IRAttr:]] ++declare spir_func void @mul_add() #0 ++ ++; CHECK-LLVM: define spir_func void @test() #[[#Fcn1IRAttr:]] ++define spir_func void @test() #1 { ++entry: ++ call spir_func void @mul_add() ++ret void ++} ++ ++; CHECK-LLVM: attributes #[[#Fcn0IRAttr]] = { {{.*}}"foo" } ++attributes #0 = { "foo" } ++; CHECK-LLVM: attributes #[[#Fcn1IRAttr]] = { {{.*}}"bar"="baz" } ++attributes #1 = { "bar"="baz" } ++ ++; CHECK-SPIRV-EXT-DISABLED: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-SPIRV-EXT-DISABLED-NEXT: SPV_KHR_non_semantic_info +diff --git a/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata-debug.ll b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata-debug.ll +new file mode 100644 +index 00000000..7ce005e0 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata-debug.ll +@@ -0,0 +1,28 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-preserve-auxdata -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++ ++; CHECK-SPIRV: Capability ++; CHECK-SPIRV-NOT: NonSemanticAuxData ++; CHECK-SPIRV: FunctionEnd ++target triple = "spir64-unknown-unknown" ++ ++define spir_func void @foo() #1 !dbg !4 { ++ret void ++} ++ ++!llvm.dbg.cu = !{!0} ++!llvm.module.flags = !{!3} ++ ++!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang 16.0.0", isOptimized: false, emissionKind: FullDebug, enums: !2) ++!1 = !DIFile(filename: "foo.c", directory: "./") ++!2 = !{} ++!3 = !{i32 2, !"Debug Info Version", i32 3} ++!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, retainedNodes: !5) ++!5 = !{!9} ++!6 = !DISubroutineType(types: !7) ++!7 = !{!8, !8, !8} ++!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ++!9 = !DILabel(scope: !4, name: "top", file: !1, line: 4) ++!10 = !DILocation(line: 4, column: 1, scope: !4) ++!11 = !DILabel(scope: !4, name: "done", file: !1, line: 7) ++!12 = !DILocation(line: 7, column: 1, scope: !4) +diff --git a/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata.ll b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata.ll +new file mode 100644 +index 00000000..abc0a042 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_non_semantic_info/preserve-all-function-metadata.ll +@@ -0,0 +1,47 @@ ++; RUN: llvm-as < %s -o %t.bc ++; RUN: llvm-spirv %t.bc -spirv-text --spirv-preserve-auxdata -o - | FileCheck %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-preserve-auxdata ++; RUN: llvm-spirv -r --spirv-preserve-auxdata %t.spv -o %t.rev.bc ++; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM ++; RUN: llvm-spirv -r %t.spv -o %t.rev.without.bc ++; RUN: llvm-dis %t.rev.without.bc -o - | FileCheck %s --implicit-check-not="{{foo|bar|baz}}" ++ ++; CHECK-SPIRV: Extension "SPV_KHR_non_semantic_info" ++; CHECK-SPIRV: ExtInstImport [[#Import:]] "NonSemantic.AuxData" ++ ++; CHECK-SPIRV: String [[#MD0Name:]] "foo" ++; CHECK-SPIRV: String [[#MD1Name:]] "bar" ++; CHECK-SPIRV: String [[#MD1Value:]] "baz" ++ ++; CHECK-SPIRV: Name [[#Fcn0:]] "test_val" ++; CHECK-SPIRV: Name [[#Fcn1:]] "test_string" ++ ++; CHECK-SPIRV: TypeInt [[#Int32T:]] 32 0 ++; CHECK-SPIRV: Constant [[#Int32T]] [[#MD0Value:]] 5 ++ ++; CHECK-SPIRV: TypeVoid [[#VoidT:]] ++ ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#ValInst:]] [[#Import]] NonSemanticAuxDataFunctionMetadata [[#Fcn0]] [[#MD0Name]] [[#MD0Value]] {{$}} ++; CHECK-SPIRV: ExtInst [[#VoidT]] [[#StrInst:]] [[#Import]] NonSemanticAuxDataFunctionMetadata [[#Fcn1]] [[#MD1Name]] [[#MD1Value]] {{$}} ++ ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-LLVM: define spir_func void @test_val() {{.*}} !foo ![[#LLVMVal:]] ++define spir_func void @test_val() #1 !foo !1 { ++ret void ++} ++ ++; CHECK-LLVM: define spir_func void @test_string() {{.*}} !bar ![[#LLVMStr:]] ++define spir_func void @test_string() #1 !bar !2 !spirv.Decorations !4 !spirv.ParameterDecorations !3 { ++ret void ++} ++ ++; CHECK-LLVM: ![[#LLVMVal]] = !{i32 5} ++!1 = !{i32 5} ++; CHECK-LLVM ![[#LLVMSTR]] = !{!"baz"} ++!2 = !{!"baz"} ++!3 = !{!4, !7, !4} ++!4 = !{!5, !6} ++!5 = !{i32 0, i32 2} ++!6 = !{i32 0, i32 8} ++!7 = !{!6} +diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp +index 85d4e61d..cfbd9d09 100644 +--- a/tools/llvm-spirv/llvm-spirv.cpp ++++ b/tools/llvm-spirv/llvm-spirv.cpp +@@ -190,6 +190,10 @@ static cl::opt + SPIRVMemToReg("spirv-mem2reg", cl::init(false), + cl::desc("LLVM/SPIR-V translation enable mem2reg")); + ++static cl::opt SPIRVPreserveAuxData( ++ "spirv-preserve-auxdata", cl::init(false), ++ cl::desc("Preserve all auxiliary data, such as function attributes and metadata")); ++ + static cl::opt SpecConstInfo( + "spec-const-info", + cl::desc("Display id of constants available for specializaion and their " +@@ -496,8 +500,11 @@ static int parseSPVExtOption( + // - during SPIR-V generation, assume that any known extension is disallowed. + // - during conversion to/from SPIR-V text representation, assume that any + // known extension is allowed. ++ llvm::Optional DefaultVal; ++ if (IsReverse) ++ DefaultVal = true; + for (const auto &It : ExtensionNamesMap) +- ExtensionsStatus[It.second] = IsReverse; ++ ExtensionsStatus[It.second] = DefaultVal; + + if (SPVExt.empty()) + return 0; // Nothing to do +@@ -699,6 +706,14 @@ int main(int Ac, char **Av) { + return -1; + } + ++ if (SPIRVPreserveAuxData) { ++ Opts.setPreserveAuxData( ++ SPIRVPreserveAuxData); ++ if (!IsReverse) ++ Opts.setAllowedToUseExtension( ++ SPIRV::ExtensionID::SPV_KHR_non_semantic_info); ++ } ++ + if (SPIRVAllowUnknownIntrinsics.getNumOccurrences() != 0) { + if (IsReverse) { + errs() +-- +2.20.1 + diff --git a/patches/0070-Backport-to-15-OpaquePointers-Handle-llvm.memset-int.patch b/patches/0070-Backport-to-15-OpaquePointers-Handle-llvm.memset-int.patch new file mode 100644 index 0000000..96ef428 --- /dev/null +++ b/patches/0070-Backport-to-15-OpaquePointers-Handle-llvm.memset-int.patch @@ -0,0 +1,340 @@ +From 07a6c642c0faf1bc8ee8ebce01d72243ea492895 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Wed, 25 Oct 2023 17:14:00 +0200 +Subject: [PATCH 70/79] [Backport to 15][OpaquePointers] Handle llvm.memset + intrinsic mangling mismatches. (#2183) + +Original change: +https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/bdd765263a0a7184dbd18fe5396313802f731e25 + +Non-constant @llvm.memset calls are presently lowered by generating synthetic +functions with the mangled name of memset. However, the reader tries to use this +name to generate the intrinsic call again. This causes verification issues if +the SPIRVWriter and SPIRVReader do not agree on whether or not to use opaque +pointers. This change uses the actual type of the function (which will take into +account whether or not it is in opaque pointer mode) to generate the LLVM +intrinsic name, fixing the mismatch issues. + +Co-authored-by: Joshua Cranmer +--- + lib/SPIRV/SPIRVReader.cpp | 9 + + test/llvm-intrinsics/memset-opaque.spt | 238 +++++++++++++++++++++++++ + test/llvm-intrinsics/memset.ll | 8 + + 3 files changed, 255 insertions(+) + create mode 100644 test/llvm-intrinsics/memset-opaque.spt + +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index a4c271ed..89b39b1c 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -2963,6 +2963,15 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { + // assuming llvm.memset is supported by the device compiler. If this + // assumption is not safe, we should have a command line option to control + // this behavior. ++ if (FuncNameRef.startswith("spirv.llvm_memset_p")) { ++ // We can't guarantee that the name is correctly mangled due to opaque ++ // pointers. Derive the correct name from the function type. ++ FuncName = ++ Intrinsic::getDeclaration(M, Intrinsic::memset, ++ {FT->getParamType(0), FT->getParamType(2)}) ++ ->getName() ++ .str(); ++ } + if (FuncNameRef.consume_front("spirv.")) { + FuncNameRef.consume_back(".volatile"); + FuncName = FuncNameRef.str(); +diff --git a/test/llvm-intrinsics/memset-opaque.spt b/test/llvm-intrinsics/memset-opaque.spt +new file mode 100644 +index 00000000..50655a50 +--- /dev/null ++++ b/test/llvm-intrinsics/memset-opaque.spt +@@ -0,0 +1,238 @@ ++; RUN: llvm-spirv %s -to-binary -o %t.spv ++; RUN: llvm-spirv -r %t.spv -o %t.bc ++; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM ++ ++; Verify that the reverse translation works correctly and converts opaque-type generated intrinsics ++; (like 'spirv.llvm_memset_p0_i32') to the typed-pointer signatures (like to '@llvm.memset.p0i8.i32'). ++ ++; CHECK-LLVM: call void @llvm.memcpy.p4i8.p2i8.i32(i8 addrspace(4)* align 4 %1, i8 addrspace(2)* align 4 %2, i32 12, i1 false) ++; CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %3, i8 addrspace(2)* align 4 %4, i32 4, i1 false) ++; CHECK-LLVM: call void @llvm.memset.p0a4i8.i32([4 x i8]* %x, i8 %v, i32 3, i1 false) ++; CHECK-LLVM: call void @llvm.memset.p0a4i8.i32([4 x i8]* %x, i8 %v, i32 %s1, i1 false) ++; CHECK-LLVM: call void @llvm.memset.p3s_struct.S1s.i32(%struct.S1 addrspace(3)* %a, i8 %v, i32 %s1, i1 false) ++; CHECK-LLVM: call void @llvm.memset.p1s_struct.S1s.i64(%struct.S1 addrspace(1)* %b, i8 %v, i64 %s2, i1 false) ++; CHECK-LLVM: call void @llvm.memset.p1s_struct.S1s.i64(%struct.S1 addrspace(1)* %b, i8 %v, i64 %s2, i1 true) ++ ++119734787 65536 393230 117 0 ++2 Capability Addresses ++2 Capability Linkage ++2 Capability Kernel ++2 Capability Int64 ++2 Capability GenericPointer ++2 Capability Int8 ++5 ExtInstImport 1 "OpenCL.std" ++3 MemoryModel 1 2 ++3 Source 4 202000 ++5 Name 3 "struct.S1" ++5 Name 9 "_Z5foo11v" ++5 Name 10 "agg.result" ++3 Name 11 "s1" ++3 Name 12 "s2" ++3 Name 13 "v" ++3 Name 18 "x" ++9 Name 39 "spirv.llvm_memset_p0_i32" ++4 Name 40 "dest" ++3 Name 41 "val" ++3 Name 42 "len" ++5 Name 43 "isvolatile" ++3 Name 47 "a" ++9 Name 49 "spirv.llvm_memset_p3_i32" ++4 Name 50 "dest" ++3 Name 51 "val" ++3 Name 52 "len" ++5 Name 53 "isvolatile" ++3 Name 56 "b" ++9 Name 58 "spirv.llvm_memset_p1_i64" ++4 Name 59 "dest" ++3 Name 60 "val" ++3 Name 61 "len" ++5 Name 62 "isvolatile" ++11 Name 65 "spirv.llvm_memset_p1_i64.volatile" ++4 Name 66 "dest" ++3 Name 67 "val" ++3 Name 68 "len" ++5 Name 69 "isvolatile" ++4 Name 71 "entry" ++6 Name 72 "loadstoreloop" ++4 Name 73 "split" ++4 Name 83 "entry" ++6 Name 84 "loadstoreloop" ++4 Name 85 "split" ++4 Name 94 "entry" ++6 Name 95 "loadstoreloop" ++4 Name 96 "split" ++4 Name 107 "entry" ++6 Name 108 "loadstoreloop" ++4 Name 109 "split" ++7 Decorate 9 LinkageAttributes "_Z5foo11v" Export ++4 Decorate 10 FuncParamAttr 4 ++4 Decorate 10 FuncParamAttr 5 ++4 Decorate 10 FuncParamAttr 3 ++4 Decorate 18 Alignment 1 ++3 Decorate 25 Constant ++3 Decorate 33 Constant ++11 Decorate 39 LinkageAttributes "spirv.llvm_memset_p0_i32" Export ++11 Decorate 49 LinkageAttributes "spirv.llvm_memset_p3_i32" Export ++11 Decorate 58 LinkageAttributes "spirv.llvm_memset_p1_i64" Export ++13 Decorate 65 LinkageAttributes "spirv.llvm_memset_p1_i64.volatile" Export ++4 TypeInt 4 32 0 ++4 TypeInt 6 64 0 ++4 TypeInt 7 8 0 ++4 Constant 4 15 4 ++4 Constant 4 21 12 ++4 Constant 7 30 21 ++4 Constant 4 35 3 ++4 Constant 4 74 0 ++4 Constant 4 80 1 ++5 Constant 6 97 0 0 ++5 Constant 6 104 1 0 ++2 TypeVoid 2 ++5 TypeStruct 3 4 4 4 ++ ++4 TypePointer 5 8 3 ++7 TypeFunction 8 2 5 4 6 7 ++4 TypeArray 16 7 15 ++4 TypePointer 17 7 16 ++4 TypePointer 19 8 7 ++4 TypeArray 22 7 21 ++4 TypePointer 24 0 22 ++4 TypePointer 26 0 7 ++4 TypePointer 28 7 7 ++4 TypePointer 32 0 16 ++2 TypeBool 36 ++7 TypeFunction 38 2 17 7 4 36 ++4 TypePointer 46 4 3 ++7 TypeFunction 48 2 46 7 4 36 ++4 TypePointer 55 5 3 ++7 TypeFunction 57 2 55 7 6 36 ++4 TypePointer 89 4 7 ++4 TypePointer 101 5 7 ++3 ConstantNull 22 23 ++5 Variable 24 25 0 23 ++7 ConstantComposite 16 31 30 30 30 30 ++ ++5 Variable 32 33 0 31 ++3 ConstantFalse 36 37 ++3 ConstantTrue 36 64 ++ ++ ++5 Function 2 9 0 8 ++3 FunctionParameter 5 10 ++3 FunctionParameter 4 11 ++3 FunctionParameter 6 12 ++3 FunctionParameter 7 13 ++ ++2 Label 14 ++4 Variable 17 18 7 ++4 Bitcast 19 20 10 ++4 Bitcast 26 27 25 ++6 CopyMemorySized 20 27 21 2 4 ++4 Bitcast 28 29 18 ++4 Bitcast 26 34 33 ++6 CopyMemorySized 29 34 15 2 4 ++8 FunctionCall 2 44 39 18 13 35 37 ++8 FunctionCall 2 45 39 18 13 11 37 ++4 GenericCastToPtr 46 47 10 ++8 FunctionCall 2 54 49 47 13 11 37 ++4 GenericCastToPtr 55 56 10 ++8 FunctionCall 2 63 58 56 13 12 37 ++8 FunctionCall 2 70 65 56 13 12 64 ++1 Return ++ ++1 FunctionEnd ++ ++5 Function 2 39 0 38 ++3 FunctionParameter 17 40 ++3 FunctionParameter 7 41 ++3 FunctionParameter 4 42 ++3 FunctionParameter 36 43 ++ ++2 Label 71 ++5 IEqual 36 75 74 42 ++4 BranchConditional 75 73 72 ++ ++2 Label 72 ++7 Phi 4 77 74 71 76 72 ++4 Bitcast 28 78 40 ++5 InBoundsPtrAccessChain 28 79 78 77 ++5 Store 79 41 2 1 ++5 IAdd 4 76 77 80 ++5 ULessThan 36 82 76 42 ++4 BranchConditional 82 72 73 ++ ++2 Label 73 ++1 Return ++ ++1 FunctionEnd ++ ++5 Function 2 49 0 48 ++3 FunctionParameter 46 50 ++3 FunctionParameter 7 51 ++3 FunctionParameter 4 52 ++3 FunctionParameter 36 53 ++ ++2 Label 83 ++5 IEqual 36 86 74 52 ++4 BranchConditional 86 85 84 ++ ++2 Label 84 ++7 Phi 4 88 74 83 87 84 ++4 Bitcast 89 90 50 ++5 InBoundsPtrAccessChain 89 91 90 88 ++5 Store 91 51 2 1 ++5 IAdd 4 87 88 80 ++5 ULessThan 36 93 87 52 ++4 BranchConditional 93 84 85 ++ ++2 Label 85 ++1 Return ++ ++1 FunctionEnd ++ ++5 Function 2 58 0 57 ++3 FunctionParameter 55 59 ++3 FunctionParameter 7 60 ++3 FunctionParameter 6 61 ++3 FunctionParameter 36 62 ++ ++2 Label 94 ++5 IEqual 36 98 97 61 ++4 BranchConditional 98 96 95 ++ ++2 Label 95 ++7 Phi 6 100 97 94 99 95 ++4 Bitcast 101 102 59 ++5 InBoundsPtrAccessChain 101 103 102 100 ++5 Store 103 60 2 1 ++5 IAdd 6 99 100 104 ++5 ULessThan 36 106 99 61 ++4 BranchConditional 106 95 96 ++ ++2 Label 96 ++1 Return ++ ++1 FunctionEnd ++ ++5 Function 2 65 0 57 ++3 FunctionParameter 55 66 ++3 FunctionParameter 7 67 ++3 FunctionParameter 6 68 ++3 FunctionParameter 36 69 ++ ++2 Label 107 ++5 IEqual 36 110 97 68 ++4 BranchConditional 110 109 108 ++ ++2 Label 108 ++7 Phi 6 112 97 107 111 108 ++4 Bitcast 101 113 66 ++5 InBoundsPtrAccessChain 101 114 113 112 ++5 Store 114 67 3 1 ++5 IAdd 6 111 112 104 ++5 ULessThan 36 116 111 68 ++4 BranchConditional 116 108 109 ++ ++2 Label 109 ++1 Return ++ ++1 FunctionEnd +diff --git a/test/llvm-intrinsics/memset.ll b/test/llvm-intrinsics/memset.ll +index 183f5393..9a71cc85 100644 +--- a/test/llvm-intrinsics/memset.ll ++++ b/test/llvm-intrinsics/memset.ll +@@ -5,6 +5,7 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: spirv-val %t.spv + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++; RUN: llvm-spirv -r %t.spv -o - -emit-opaque-pointers | llvm-dis -opaque-pointers=1 | FileCheck %s --check-prefix=CHECK-LLVM-OPAQUE + + ; CHECK-SPIRV: Decorate [[#NonConstMemset:]] LinkageAttributes "spirv.llvm_memset_p3i8_i32" + ; CHECK-SPIRV: TypeInt [[Int8:[0-9]+]] 8 0 +@@ -69,28 +70,35 @@ define spir_func void @_Z5foo11v(%struct.S1 addrspace(4)* noalias nocapture sret + %1 = bitcast %struct.S1 addrspace(4)* %agg.result to i8 addrspace(4)* + tail call void @llvm.memset.p4i8.i32(i8 addrspace(4)* align 4 %1, i8 0, i32 12, i1 false) + ; CHECK-LLVM: call void @llvm.memcpy.p4i8.p2i8.i32(i8 addrspace(4)* align 4 %1, i8 addrspace(2)* align 4 %2, i32 12, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memcpy.p4.p2.i32(ptr addrspace(4) align 4 %1, ptr addrspace(2) align 4 %2, i32 12, i1 false) + tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 21, i32 4, i1 false) + ; CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %x.bc, i8 addrspace(2)* align 4 %3, i32 4, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memcpy.p0.p2.i32(ptr align 4 %x.bc, ptr addrspace(2) align 4 %3, i32 4, i1 false) + + ; non-const value + tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 %v, i32 3, i1 false) + ; CHECK-LLVM: call void @llvm.memset.p0i8.i32(i8* %x.bc, i8 %v, i32 3, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memset.p0.i32(ptr %x.bc, i8 %v, i32 3, i1 false) + + ; non-const value and size + tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 %v, i32 %s1, i1 false) + ; CHECK-LLVM: call void @llvm.memset.p0i8.i32(i8* %x.bc, i8 %v, i32 %s1, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memset.p0.i32(ptr %x.bc, i8 %v, i32 %s1, i1 false) + + ; Address spaces, non-const value and size + %a = addrspacecast i8 addrspace(4)* %1 to i8 addrspace(3)* + tail call void @llvm.memset.p3i8.i32(i8 addrspace(3)* align 4 %a, i8 %v, i32 %s1, i1 false) + ; CHECK-LLVM: call void @llvm.memset.p3i8.i32(i8 addrspace(3)* %a, i8 %v, i32 %s1, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memset.p3.i32(ptr addrspace(3) %a, i8 %v, i32 %s1, i1 false) + %b = addrspacecast i8 addrspace(4)* %1 to i8 addrspace(1)* + tail call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 %v, i64 %s2, i1 false) + ; CHECK-LLVM: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %b, i8 %v, i64 %s2, i1 false) ++; CHECK-LLVM-OPAQUE: call void @llvm.memset.p1.i64(ptr addrspace(1) %b, i8 %v, i64 %s2, i1 false) + + ; Volatile + tail call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 %v, i64 %s2, i1 true) + ; CHECK-LLVM: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %b, i8 %v, i64 %s2, i1 true) ++; CHECK-LLVM-OPAQUE: call void @llvm.memset.p1.i64(ptr addrspace(1) %b, i8 %v, i64 %s2, i1 true) + ret void + } + +-- +2.20.1 + diff --git a/patches/0071-Backport-to-15-Implement-support-for-SPV_KHR_shader_.patch b/patches/0071-Backport-to-15-Implement-support-for-SPV_KHR_shader_.patch new file mode 100644 index 0000000..dc5b682 --- /dev/null +++ b/patches/0071-Backport-to-15-Implement-support-for-SPV_KHR_shader_.patch @@ -0,0 +1,144 @@ +From 22e6c8192a9894abc664395518050e7f69a4fa3e Mon Sep 17 00:00:00 2001 +From: Aleksander Mielczarek <110471911+naxiiv@users.noreply.github.com> +Date: Thu, 9 Nov 2023 01:29:03 +0200 +Subject: [PATCH 71/79] [Backport to 15] Implement support for + SPV_KHR_shader_clock (#2026) (#2207) + +Link to the spec: https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_shader_clock.asciidoc + +Co-authored-by: jgstarIntel +--- + include/LLVMSPIRVExtensions.inc | 1 + + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 38 ++++++++++++++- + lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h | 1 + + .../KHR/SPV_KHR_shader_clock/shader_clock.ll | 46 +++++++++++++++++++ + 4 files changed, 85 insertions(+), 1 deletion(-) + create mode 100644 test/extensions/KHR/SPV_KHR_shader_clock/shader_clock.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index e3bc506c..5a23275b 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -13,6 +13,7 @@ EXT(SPV_KHR_bit_instructions) + EXT(SPV_KHR_uniform_group_instructions) + EXT(SPV_KHR_subgroup_rotate) + EXT(SPV_KHR_non_semantic_info) ++EXT(SPV_KHR_shader_clock) + EXT(SPV_INTEL_subgroups) + EXT(SPV_INTEL_media_block_io) + EXT(SPV_INTEL_device_side_avc_motion_estimation) +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index bd5b338c..91b88f00 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3662,6 +3662,42 @@ protected: + typedef SPIRVTensorFloat32RoundingINTELInstBase SPIRV##x; + _SPIRV_OP(RoundFToTF32INTEL) + #undef _SPIRV_OP +-} // namespace SPIRV + ++template class SPIRVReadClockKHRInstBase : public SPIRVUnaryInst { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(CapabilityShaderClockKHR); ++ } ++ ++ llvm::Optional getRequiredExtension() const override { ++ return ExtensionID::SPV_KHR_shader_clock; ++ } ++ ++ void validate() const override { ++ SPIRVUnaryInst::validate(); ++ ++ SPIRVType *ResCompTy = this->getType(); ++ SPIRVWord ResCompCount = 1; ++ if (ResCompTy->isTypeVector()) { ++ ResCompCount = ResCompTy->getVectorComponentCount(); ++ ResCompTy = ResCompTy->getVectorComponentType(); ++ } ++ auto InstName = OpCodeNameMap::map(OC); ++ SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog(); ++ ++ // check for either 64 bit int type or two element vector of 32 bit int ++ // types. ++ SPVErrLog.checkError( ++ ResCompTy->isTypeInt(64) || ++ (ResCompCount == 2 && ResCompTy->isTypeInt(32)), ++ SPIRVEC_InvalidInstruction, ++ InstName + "\nResult value must be a scalar of integer" ++ " 64-bit type or two element vector of 32-bit type\n"); ++ } ++}; ++#define _SPIRV_OP(x, ...) typedef SPIRVReadClockKHRInstBase SPIRV##x; ++_SPIRV_OP(ReadClockKHR) ++#undef _SPIRV_OP ++ ++} // namespace SPIRV + #endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +index 94197e7b..a6961fcb 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +@@ -335,6 +335,7 @@ _SPIRV_OP(SUDotKHR, 4452) + _SPIRV_OP(SDotAccSatKHR, 4453) + _SPIRV_OP(UDotAccSatKHR, 4454) + _SPIRV_OP(SUDotAccSatKHR, 4455) ++_SPIRV_OP(ReadClockKHR, 5056) + _SPIRV_OP(SubgroupShuffleINTEL, 5571) + _SPIRV_OP(SubgroupShuffleDownINTEL, 5572) + _SPIRV_OP(SubgroupShuffleUpINTEL, 5573) +diff --git a/test/extensions/KHR/SPV_KHR_shader_clock/shader_clock.ll b/test/extensions/KHR/SPV_KHR_shader_clock/shader_clock.ll +new file mode 100644 +index 00000000..4ccfceb2 +--- /dev/null ++++ b/test/extensions/KHR/SPV_KHR_shader_clock/shader_clock.ll +@@ -0,0 +1,46 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_KHR_shader_clock ++; RUN: llvm-spirv %t.spv -o %t.spt --to-text ++; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV ++; RUN: llvm-spirv %t.spv -o %t.rev.bc -r -emit-opaque-pointers --spirv-target-env=SPV-IR ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM ++ ++; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ++; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension: ++; CHECK-ERROR-NEXT: SPV_KHR_shader_clock ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" ++target triple = "spir64-unknown-unknown" ++ ++; CHECK-SPIRV: Capability ShaderClockKHR ++; CHECK-SPIRV: Extension "SPV_KHR_shader_clock" ++; CHECK-SPIRV: TypeInt [[#I32Ty:]] 32 ++; CHECK-SPIRV: TypeInt [[#I64Ty:]] 64 ++; CHECK-SPIRV: TypeVector [[#I32v2Ty:]] [[#I32Ty]] 2 ++ ++; CHECK-SPIRV: FunctionParameter [[#I32Ty]] [[I32ValId:.*]] ++ ++; CHECK-SPIRV: ReadClockKHR [[#I32v2Ty]] [[#]] [[I32ValId]] ++; CHECK-SPIRV: ReadClockKHR [[#I64Ty]] [[#]] [[I32ValId]] ++ ++; CHECK-LLVM: call spir_func <2 x i32> @_Z20__spirv_ReadClockKHR ++; CHECK-LLVM: call spir_func i64 @_Z20__spirv_ReadClockKHR ++ ++define spir_func void @_Z7read_types(i32 %a) { ++ %1 = tail call spir_func <2 x i32> @_Z20__spirv_ReadClockKHRIDv2_jET_j(i32 %a) ++ %2 = tail call spir_func i64 @_Z20__spirv_ReadClockKHRImET_j(i32 %a) ++ ret void ++} ++ ++declare spir_func <2 x i32> @_Z20__spirv_ReadClockKHRIDv2_jET_j(i32) ++ ++declare spir_func i64 @_Z20__spirv_ReadClockKHRImET_j(i32) ++ ++!opencl.spir.version = !{!0} ++!spirv.Source = !{!1} ++!llvm.ident = !{!2} ++ ++!0 = !{i32 1, i32 2} ++!1 = !{i32 4, i32 100000} ++!2 = !{!"clang version 16.0.0"} +-- +2.20.1 + diff --git a/patches/0072-Backport-to-15-Add-JointMatrixGetElementCoordINTEL-i.patch b/patches/0072-Backport-to-15-Add-JointMatrixGetElementCoordINTEL-i.patch new file mode 100644 index 0000000..9724e60 --- /dev/null +++ b/patches/0072-Backport-to-15-Add-JointMatrixGetElementCoordINTEL-i.patch @@ -0,0 +1,188 @@ +From dc292a2b712c04ff933ecede6fa803c65105b535 Mon Sep 17 00:00:00 2001 +From: Dmitry Sidorov +Date: Mon, 20 Nov 2023 21:44:49 +0100 +Subject: [PATCH 72/79] [Backport to 15] Add JointMatrixGetElementCoordINTEL + instruction (#2226) + +The instruction returns (Row, Column) coordinate of dynamically selected +element of a matrix + +Updated version of the spec is here +intel/llvm#8175 + +Instruction correctness checks will be added later among non-backward +compatible changes. + +Signed-off-by: Sidorov, Dmitry +--- + lib/SPIRV/libSPIRV/SPIRVEnum.h | 2 ++ + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 15 +++++++++++++ + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 2 ++ + lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h | 2 ++ + lib/SPIRV/libSPIRV/spirv_internal.hpp | 5 +++++ + .../joint_matrix_element.ll | 21 +++++++++++++------ + 6 files changed, 41 insertions(+), 6 deletions(-) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h +index 1bd5cc7e..43dcdc6e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h +@@ -205,6 +205,8 @@ template <> inline void SPIRVMap::init() { + {CapabilitySubgroupAvcMotionEstimationINTEL}); + ADD_VEC_INIT(CapabilitySubgroupAvcMotionEstimationChromaINTEL, + {CapabilitySubgroupAvcMotionEstimationIntraINTEL}); ++ ADD_VEC_INIT(internal::CapabilityJointMatrixWIInstructionsINTEL, ++ {internal::CapabilityJointMatrixINTEL}); + } + + template <> inline void SPIRVMap::init() { +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 91b88f00..84122a6e 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -3367,9 +3367,24 @@ _SPIRV_OP(JointMatrixMad, true, 7) + _SPIRV_OP(JointMatrixSUMad, true, 7) + _SPIRV_OP(JointMatrixUSMad, true, 7) + _SPIRV_OP(JointMatrixUUMad, true, 7) ++// TODO: move to SPIRVJointMatrixINTELWorkItemInst + _SPIRV_OP(JointMatrixWorkItemLength, true, 4) + #undef _SPIRV_OP + ++class SPIRVJointMatrixINTELWorkItemInst : public SPIRVJointMatrixINTELInstBase { ++protected: ++ SPIRVCapVec getRequiredCapability() const override { ++ return getVec(internal::CapabilityJointMatrixWIInstructionsINTEL); ++ } ++}; ++ ++#define _SPIRV_OP(x, ...) \ ++ typedef SPIRVInstTemplate \ ++ SPIRV##x##INTEL; ++_SPIRV_OP(JointMatrixGetElementCoord, true, 5) ++#undef _SPIRV_OP ++ + class SPIRVSplitBarrierINTELBase : public SPIRVInstTemplateBase { + protected: + SPIRVCapVec getRequiredCapability() const override { +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index 6861f2dd..ae692edc 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -621,6 +621,8 @@ template <> inline void SPIRVMap::init() { + add(internal::CapabilityTensorFloat32RoundingINTEL, + "TensorFloat32RoundingINTEL"); + add(internal::CapabilityCacheControlsINTEL, "CacheControlsINTEL"); ++ add(internal::CapabilityJointMatrixWIInstructionsINTEL, ++ "JointMatrixWIInstructionsINTEL"); + } + SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) + +diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +index 2682f869..b4d4b58d 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h ++++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h +@@ -14,6 +14,8 @@ _SPIRV_OP_INTERNAL(JointMatrixUSMadINTEL, internal::OpJointMatrixUSMadINTEL) + _SPIRV_OP_INTERNAL(JointMatrixUUMadINTEL, internal::OpJointMatrixUUMadINTEL) + _SPIRV_OP_INTERNAL(JointMatrixWorkItemLengthINTEL, + internal::OpJointMatrixWorkItemLengthINTEL) ++_SPIRV_OP_INTERNAL(JointMatrixGetElementCoordINTEL, ++ internal::OpJointMatrixGetElementCoordINTEL) + _SPIRV_OP_INTERNAL(ComplexFMulINTEL, internal::ComplexFMulINTEL) + _SPIRV_OP_INTERNAL(ComplexFDivINTEL, internal::ComplexFDivINTEL) + _SPIRV_OP_INTERNAL(MaskedGatherINTEL, internal::OpMaskedGatherINTEL) +diff --git a/lib/SPIRV/libSPIRV/spirv_internal.hpp b/lib/SPIRV/libSPIRV/spirv_internal.hpp +index e0acc6bb..0a90b592 100644 +--- a/lib/SPIRV/libSPIRV/spirv_internal.hpp ++++ b/lib/SPIRV/libSPIRV/spirv_internal.hpp +@@ -75,6 +75,7 @@ enum InternalOp { + IOpRoundFToTF32INTEL = 6426, + IOpMaskedGatherINTEL = 6428, + IOpMaskedScatterINTEL = 6429, ++ IOpJointMatrixGetElementCoordINTEL = 6440, + IOpPrev = OpMax - 2, + IOpForward + }; +@@ -109,6 +110,7 @@ enum InternalCapability { + ICapabilityComplexFloatMulDivINTEL = 6414, + ICapabilityTensorFloat32RoundingINTEL = 6425, + ICapabilityMaskedGatherScatterINTEL = 6427, ++ ICapabilityJointMatrixWIInstructionsINTEL = 6435, + ICapabilityCacheControlsINTEL = 6441 + }; + +@@ -155,6 +157,7 @@ enum class StoreCacheControlINTEL { + + #define _SPIRV_OP(x, y) constexpr x x##y = static_cast(I##x##y); + _SPIRV_OP(Capability, JointMatrixINTEL) ++_SPIRV_OP(Capability, JointMatrixWIInstructionsINTEL) + _SPIRV_OP(Op, TypeJointMatrixINTEL) + _SPIRV_OP(Op, JointMatrixLoadINTEL) + _SPIRV_OP(Op, JointMatrixStoreINTEL) +@@ -163,6 +166,8 @@ _SPIRV_OP(Op, JointMatrixSUMadINTEL) + _SPIRV_OP(Op, JointMatrixUSMadINTEL) + _SPIRV_OP(Op, JointMatrixUUMadINTEL) + _SPIRV_OP(Op, JointMatrixWorkItemLengthINTEL) ++_SPIRV_OP(Op, JointMatrixGetElementCoordINTEL) ++ + _SPIRV_OP(Capability, HWThreadQueryINTEL) + _SPIRV_OP(BuiltIn, SubDeviceIDINTEL) + _SPIRV_OP(BuiltIn, GlobalHWThreadIDINTEL) +diff --git a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll +index f6519cfd..f0262979 100644 +--- a/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll ++++ b/test/transcoding/SPV_INTEL_joint_matrix/joint_matrix_element.ll +@@ -5,21 +5,26 @@ + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM + +-; CHECK-SPIRV: Capability JointMatrixINTEL +-; CHECK-SPIRV: Extension "SPV_INTEL_joint_matrix" +-; CHECK-SPIRV: TypeInt [[#TypeInt:]] 64 +-; CHECK-SPIRV: TypeFloat [[#TypeFloat:]] 32 +-; CHECK-SPIRV: TypeJointMatrixINTEL [[#TypeMatrix:]] [[#TypeFloat]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-DAG: Capability JointMatrixINTEL ++; CHECK-SPIRV-DAG: Capability JointMatrixWIInstructionsINTEL ++; CHECK-SPIRV-DAG: Extension "SPV_INTEL_joint_matrix" ++; CHECK-SPIRV-DAG: TypeInt [[#TypeInt32:]] 32 ++; CHECK-SPIRV-DAG: TypeInt [[#TypeInt64:]] 64 ++; CHECK-SPIRV-DAG: TypeFloat [[#TypeFloat:]] 32 ++; CHECK-SPIRV-DAG: TypeJointMatrixINTEL [[#TypeMatrix:]] [[#TypeFloat]] [[#]] [[#]] [[#]] [[#]] ++; CHECK-SPIRV-DAG: TypeVector [[#TypeVec:]] [[#TypeInt32]] 2 + ; CHECK-SPIRV: Phi [[#TypeMatrix]] [[#Matrix:]] +-; CHECK-SPIRV: JointMatrixWorkItemLengthINTEL [[#TypeInt]] [[#]] [[#Matrix]] ++; CHECK-SPIRV: JointMatrixWorkItemLengthINTEL [[#TypeInt64]] [[#]] [[#Matrix]] + ; CHECK-SPIRV: VectorExtractDynamic [[#TypeFloat]] [[#]] [[#Matrix]] [[#Index:]] + ; CHECK-SPIRV: FMul [[#TypeFloat]] [[#NewVal:]] [[#]] [[#]] + ; CHECK-SPIRV: VectorInsertDynamic [[#TypeMatrix]] [[#]] [[#Matrix]] [[#NewVal]] [[#Index]] ++; CHECK-SPIRV: JointMatrixGetElementCoordINTEL [[#TypeVec]] [[#]] [[#Matrix]] [[#Index]] + + ; CHECK-LLVM: [[Length:%.*]] = call spir_func i64 @_Z38__spirv_JointMatrixWorkItemLengthINTELPU3AS141__spirv_JointMatrixINTEL__float_16_16_0_3(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(1)* [[Matrix:%.*]]) + ; CHECK-LLVM: [[Elem:%.*]] = call spir_func float @_Z28__spirv_VectorExtractDynamicPU3AS141__spirv_JointMatrixINTEL__float_16_16_0_3l(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(1)* [[Matrix]], i64 [[Index:%.*]]) + ; CHECK-LLVM: [[NewVal:%.*]] = fmul float [[Elem]], 5.000000e+00 + ; CHECK-LLVM: {{%.*}} = call spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(1)* @_Z27__spirv_VectorInsertDynamicPU3AS141__spirv_JointMatrixINTEL__float_16_16_0_3fl(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(1)* [[Matrix]], float [[NewVal]], i64 [[Index]]) ++; CHECK-LLVM: {{%.*}} = call spir_func <2 x i32> @_Z39__spirv_JointMatrixGetElementCoordINTELPU3AS141__spirv_JointMatrixINTEL__float_16_16_0_3l(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(1)* [[Matrix]], i64 [[Index]]) + + source_filename = "/work/tmp/matrix-slice.cpp" + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +@@ -69,6 +74,7 @@ for.body.i: ; preds = %for.cond.i + %call.i.i = tail call spir_func float @_Z28__spirv_VectorExtractDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmET_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEET4_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, i64 %conv.i) #2 + %mul.i.i = fmul float %call.i.i, 5.000000e+00 + %call5.i.i = tail call spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* @_Z27__spirv_VectorInsertDynamicIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EmEPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT2_EXT3_EEES7_T4_S5_(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, float %mul.i.i, i64 %conv.i) #2 ++ %call6 = tail call spir_func <2 x i32> @_Z39__spirv_JointMatrixGetElementCoordINTELIaLm8ELm32ELN5__spv9MatrixUseE0ELNS0_12MatrixLayoutE0ELNS0_5Scope4FlagE3EEDv2_jPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT3_EXT4_EXT2_EEEm(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)* %A.sroa.0.0.i, i64 %conv.i) #2 + %inc.i = add nuw nsw i32 %i.0.i, 1 + br label %for.cond.i, !llvm.loop !7 + +@@ -92,6 +98,9 @@ declare dso_local spir_func %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4 + ; Function Attrs: convergent + declare dso_local spir_func void @_Z29__spirv_JointMatrixStoreINTELIfLm16ELm16ELN5__spv12MatrixLayoutE0ELNS0_5Scope4FlagE3EEvPT_PNS0_24__spirv_JointMatrixINTELIS4_XT0_EXT1_EXT2_EXT3_EEEmS1_S3_i(float addrspace(4)*, %spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*, i64, i32, i32, i32) local_unnamed_addr #1 + ++; Function Attrs: convergent ++declare dso_local spir_func <2 x i32> @_Z39__spirv_JointMatrixGetElementCoordINTELIaLm8ELm32ELN5__spv9MatrixUseE0ELNS0_12MatrixLayoutE0ELNS0_5Scope4FlagE3EEDv2_jPNS0_24__spirv_JointMatrixINTELIT_XT0_EXT1_EXT3_EXT4_EXT2_EEEm(%spirv.JointMatrixINTEL._float_16_16_0_3 addrspace(4)*, i64) #2 ++ + attributes #0 = { convergent norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="/work/tmp/matrix-slice.cpp" "uniform-work-group-size"="true" } + attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } + attributes #2 = { convergent } +-- +2.20.1 + diff --git a/patches/0073-Backport-to-15-Fix-SPIR-V-global-to-function-replace.patch b/patches/0073-Backport-to-15-Fix-SPIR-V-global-to-function-replace.patch new file mode 100644 index 0000000..5e30e55 --- /dev/null +++ b/patches/0073-Backport-to-15-Fix-SPIR-V-global-to-function-replace.patch @@ -0,0 +1,132 @@ +From 6b82481abc6df8de5b67c72ba1da57bcb58b75b0 Mon Sep 17 00:00:00 2001 +From: Maksim Shelegov +Date: Wed, 29 Nov 2023 03:58:58 -0800 +Subject: [PATCH 73/79] [Backport to 15] Fix SPIR-V global to function + replacement for differing load types (#2160) (#2243) + +In some cases, we will see IR with the following + +@__spirv_BuiltInGlobalInvocationId = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32 + +... + +%0 = load <6 x i32>, ptr addrspace(1) @__spirv_BuiltInGlobalInvocationId, align 32 +%1 = extractelement <6 x i32> %0, i64 0 +Note the global type and load type are different. Change the handling of vector loads from vector globals to reconstruct the global vector type and then bitcast to the load type. + +Thanks to @jcranmer-intel for helping me find the simplest solution. + +Co-authored-by: Nick Sarnie +--- + lib/SPIRV/SPIRVUtil.cpp | 29 +++++++++++++++---- + .../builtin_vars_different_type.ll | 27 +++++++++++++++++ + 2 files changed, 51 insertions(+), 5 deletions(-) + create mode 100644 test/transcoding/builtin_vars_different_type.ll + +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 9a45e775..4c5a11b8 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1922,19 +1922,20 @@ bool isSPIRVBuiltinVariable(GlobalVariable *GV, + /// are accumulated in the AccumulatedOffset parameter, which will eventually be + /// used to figure out which index of a variable is being used. + static void replaceUsesOfBuiltinVar(Value *V, const APInt &AccumulatedOffset, +- Function *ReplacementFunc) { ++ Function *ReplacementFunc, ++ GlobalVariable *GV) { + const DataLayout &DL = ReplacementFunc->getParent()->getDataLayout(); + SmallVector InstsToRemove; + for (User *U : V->users()) { + if (auto *Cast = dyn_cast(U)) { +- replaceUsesOfBuiltinVar(Cast, AccumulatedOffset, ReplacementFunc); ++ replaceUsesOfBuiltinVar(Cast, AccumulatedOffset, ReplacementFunc, GV); + InstsToRemove.push_back(Cast); + } else if (auto *GEP = dyn_cast(U)) { + APInt NewOffset = AccumulatedOffset.sextOrTrunc( + DL.getIndexSizeInBits(GEP->getPointerAddressSpace())); + if (!GEP->accumulateConstantOffset(DL, NewOffset)) + llvm_unreachable("Illegal GEP of a SPIR-V builtin variable"); +- replaceUsesOfBuiltinVar(GEP, NewOffset, ReplacementFunc); ++ replaceUsesOfBuiltinVar(GEP, NewOffset, ReplacementFunc, GV); + InstsToRemove.push_back(GEP); + } else if (auto *Load = dyn_cast(U)) { + // Figure out which index the accumulated offset corresponds to. If we +@@ -1957,7 +1958,12 @@ static void replaceUsesOfBuiltinVar(Value *V, const APInt &AccumulatedOffset, + } else { + // The function has an index parameter. + if (auto *VecTy = dyn_cast(Load->getType())) { +- if (!Index.isZero()) ++ // Reconstruct the original global variable vector because ++ // the load type may not match. ++ // global <3 x i64>, load <6 x i32> ++ VecTy = cast(GV->getValueType()); ++ if (!Index.isZero() || DL.getTypeSizeInBits(VecTy) != ++ DL.getTypeSizeInBits(Load->getType())) + llvm_unreachable("Illegal use of a SPIR-V builtin variable"); + Replacement = UndefValue::get(VecTy); + for (unsigned I = 0; I < VecTy->getNumElements(); I++) { +@@ -1967,6 +1973,19 @@ static void replaceUsesOfBuiltinVar(Value *V, const APInt &AccumulatedOffset, + Builder.CreateCall(ReplacementFunc, {Builder.getInt32(I)})), + Builder.getInt32(I)); + } ++ // Insert a bitcast from the reconstructed vector to the load vector ++ // type in case they are different. ++ // Input: ++ // %1 = load <6 x i32>, ptr addrspace(1) %0, align 32 ++ // %2 = extractelement <6 x i32> %1, i32 0 ++ // %3 = add i32 5, %2 ++ // Modified: ++ // < reconstruct global vector elements 0 and 1 > ++ // %2 = insertelement <3 x i64> %0, i64 %1, i32 2 ++ // %3 = bitcast <3 x i64> %2 to <6 x i32> ++ // %4 = extractelement <6 x i32> %3, i32 0 ++ // %5 = add i32 5, %4 ++ Replacement = Builder.CreateBitCast(Replacement, Load->getType()); + } else if (Load->getType() == ScalarTy) { + Replacement = setAttrByCalledFunc(Builder.CreateCall( + ReplacementFunc, {Builder.getInt32(Index.getZExtValue())})); +@@ -2020,7 +2039,7 @@ bool lowerBuiltinVariableToCall(GlobalVariable *GV, + Func->setDoesNotAccessMemory(); + } + +- replaceUsesOfBuiltinVar(GV, APInt(64, 0), Func); ++ replaceUsesOfBuiltinVar(GV, APInt(64, 0), Func, GV); + return true; + } + +diff --git a/test/transcoding/builtin_vars_different_type.ll b/test/transcoding/builtin_vars_different_type.ll +new file mode 100644 +index 00000000..4dc838ac +--- /dev/null ++++ b/test/transcoding/builtin_vars_different_type.ll +@@ -0,0 +1,27 @@ ++; RUN: llvm-as %s -o %t.bc ++; RUN: llvm-spirv %t.bc -o %t.spv -spirv-ext=+SPV_INTEL_vector_compute ++; RUN: llvm-spirv -r %t.spv --spirv-target-env=SPV-IR -o %t.out.bc ++; RUN: llvm-dis %t.out.bc -o - | FileCheck %s --check-prefix=CHECK-SPV-IR ++ ++target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir-unknown-unknown" ++ ++@__spirv_BuiltInGlobalInvocationId = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32 ++ ++; Function Attrs: nounwind readnone ++define spir_kernel void @f() { ++entry: ++ %0 = load <6 x i32>, ptr addrspace(1) @__spirv_BuiltInGlobalInvocationId, align 32 ++ %1 = extractelement <6 x i32> %0, i64 0 ++ %2 = add i32 5, %1 ++ ret void ++; CHECK-SPV-IR: %[[#ID0:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 0) #1 ++; CHECK-SPV-IR: %[[#ID1:]] = insertelement <3 x i64> undef, i64 %[[#ID0]], i32 0 ++; CHECK-SPV-IR: %[[#ID2:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 1) #1 ++; CHECK-SPV-IR: %[[#ID3:]] = insertelement <3 x i64> %[[#ID1]], i64 %[[#ID2]], i32 1 ++; CHECK-SPV-IR: %[[#ID4:]] = call spir_func i64 @_Z33__spirv_BuiltInGlobalInvocationIdi(i32 2) #1 ++; CHECK-SPV-IR: %[[#ID5:]] = insertelement <3 x i64> %[[#ID3]], i64 %[[#ID4]], i32 2 ++; CHECK-SPV-IR: %[[#ID6:]] = bitcast <3 x i64> %[[#ID5]] to <6 x i32> ++; CHECK-SPV-IR: %[[#ID7:]] = extractelement <6 x i32> %[[#ID6]], i32 0 ++; CHECK-SPV-IR: = add i32 5, %[[#ID7]] ++} +-- +2.20.1 + diff --git a/patches/0074-Backport-to-15-Update-LongConstantCompositeINTEL-to-.patch b/patches/0074-Backport-to-15-Update-LongConstantCompositeINTEL-to-.patch new file mode 100644 index 0000000..7109305 --- /dev/null +++ b/patches/0074-Backport-to-15-Update-LongConstantCompositeINTEL-to-.patch @@ -0,0 +1,112 @@ +From 4e0fa240f96ecac4c5b2a327ea21bd33cb30e000 Mon Sep 17 00:00:00 2001 +From: Viktoria Maximova +Date: Tue, 23 Jan 2024 12:41:03 +0100 +Subject: [PATCH 74/79] [Backport to 15] Update LongConstantCompositeINTEL to + LongCompositesINTEL capability after Headers change (#2310) + +The original change: +https://github.com/KhronosGroup/SPIRV-LLVM-Translator/commit/0166a0fb86dc6c0e8903436bbc3a89bc3273ebc0 + +* Bump SPIRV-Headers to 1c6bb2743599e6eb6f37b2969acc0aef812e32e3 +* replace internal SPV_INTEL_long_composites ext with the published SPV_INTEL_long_composites +* don't rename extension for now +--- + include/LLVMSPIRVExtensions.inc | 4 +++- + lib/SPIRV/libSPIRV/SPIRVEntry.h | 2 +- + lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 2 +- + spirv-headers-tag.conf | 2 +- + test/SpecConstants/long-spec-const-composite.ll | 2 +- + test/long-constant-array.ll | 2 +- + test/long-type-struct.ll | 2 +- + 7 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 5a23275b..9ad47a4a 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -40,7 +40,9 @@ EXT(SPV_INTEL_variable_length_array) + EXT(SPV_INTEL_fp_fast_math_mode) + EXT(SPV_INTEL_fpga_cluster_attributes) + EXT(SPV_INTEL_loop_fuse) +-EXT(SPV_INTEL_long_constant_composite) ++EXT(SPV_INTEL_long_composites) ++EXT(SPV_INTEL_long_constant_composite) // TODO: rename to ++ // SPV_INTEL_long_composites later + EXT(SPV_INTEL_optnone) + EXT(SPV_INTEL_fpga_dsp_control) + EXT(SPV_INTEL_memory_access_aliasing) +diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.h b/lib/SPIRV/libSPIRV/SPIRVEntry.h +index f497c95d..0e0bd3ce 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVEntry.h ++++ b/lib/SPIRV/libSPIRV/SPIRVEntry.h +@@ -905,7 +905,7 @@ public: + } + + SPIRVCapVec getRequiredCapability() const override { +- return getVec(CapabilityLongConstantCompositeINTEL); ++ return getVec(CapabilityLongCompositesINTEL); + } + + llvm::Optional getRequiredExtension() const override { +diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +index ae692edc..f64779be 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h ++++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +@@ -593,7 +593,7 @@ template <> inline void SPIRVMap::init() { + add(CapabilityGroupNonUniformRotateKHR, "GroupNonUniformRotateKHR"); + add(CapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"); + add(CapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"); +- add(CapabilityLongConstantCompositeINTEL, "LongConstantCompositeINTEL"); ++ add(CapabilityLongCompositesINTEL, "LongCompositesINTEL"); + add(CapabilityOptNoneINTEL, "OptNoneINTEL"); + add(CapabilityAtomicFloat16AddEXT, "AtomicFloat16AddEXT"); + add(CapabilityDebugInfoModuleINTEL, "DebugInfoModuleINTEL"); +diff --git a/spirv-headers-tag.conf b/spirv-headers-tag.conf +index 9677763a..7fae55f3 100644 +--- a/spirv-headers-tag.conf ++++ b/spirv-headers-tag.conf +@@ -1 +1 @@ +-5a121866927a16ab9d49bed4788b532c7fcea766 ++1c6bb2743599e6eb6f37b2969acc0aef812e32e3 +diff --git a/test/SpecConstants/long-spec-const-composite.ll b/test/SpecConstants/long-spec-const-composite.ll +index 974a0776..4510a1e6 100644 +--- a/test/SpecConstants/long-spec-const-composite.ll ++++ b/test/SpecConstants/long-spec-const-composite.ll +@@ -11,7 +11,7 @@ + target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" + target triple = "spir64-unknown-unknown" + +-; CHECK-SPIRV: Capability LongConstantCompositeINTEL ++; CHECK-SPIRV: Capability LongCompositesINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_long_constant_composite" + ; CHECK-SPIRV-DAG: Decorate [[First:[0-9]+]] SpecId 0 + ; CHECK-SPIRV-DAG: Decorate [[Last:[0-9]+]] SpecId 65548 +diff --git a/test/long-constant-array.ll b/test/long-constant-array.ll +index 03b33771..d0b4c3b3 100644 +--- a/test/long-constant-array.ll ++++ b/test/long-constant-array.ll +@@ -9,7 +9,7 @@ + ; TODO: run validator once it supports the extension + ; RUNx: spirv-val %t.spv + +-; CHECK-SPIRV: Capability LongConstantCompositeINTEL ++; CHECK-SPIRV: Capability LongCompositesINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_long_constant_composite" + ; CHECK-SPIRV: TypeInt [[TInt:[0-9]+]] 8 + ; CHECK-SPIRV: Constant {{[0-9]+}} [[ArrSize:[0-9]+]] 78000 +diff --git a/test/long-type-struct.ll b/test/long-type-struct.ll +index b9478f0f..a1cdfc6b 100644 +--- a/test/long-type-struct.ll ++++ b/test/long-type-struct.ll +@@ -10,7 +10,7 @@ + + ; RUN: not llvm-spirv %t.bc -o %t.spv 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +-; CHECK-SPIRV: Capability LongConstantCompositeINTEL ++; CHECK-SPIRV: Capability LongCompositesINTEL + ; CHECK-SPIRV: Extension "SPV_INTEL_long_constant_composite" + ; CHECK-SPIRV: TypeForwardPointer [[TFwdPtr:[0-9]+]] + ; CHECK-SPIRV: TypeInt [[TInt:[0-9]+]] +-- +2.20.1 + diff --git a/patches/0075-Preserve-DIExpression-in-DIGlobalVariableExpression-.patch b/patches/0075-Preserve-DIExpression-in-DIGlobalVariableExpression-.patch new file mode 100644 index 0000000..da8ad54 --- /dev/null +++ b/patches/0075-Preserve-DIExpression-in-DIGlobalVariableExpression-.patch @@ -0,0 +1,136 @@ +From f63f26cd64091d8ab15886c872e0cc2c5a109651 Mon Sep 17 00:00:00 2001 +From: LU-JOHN <111294400+LU-JOHN@users.noreply.github.com> +Date: Wed, 31 Jan 2024 07:08:38 -0600 +Subject: [PATCH 75/79] Preserve DIExpression in DIGlobalVariableExpression + (#2324) + +Ensure that SPIR-V that uses a DebugGlobalVariable's Variable field to hold an Expression +can be reverse translated. A Variable field can be used to hold an Expression in order to +preserve a DIExpression in a DIGlobalVariableExpression in LLVM IR. + +Signed-off-by: Lu, John +--- + lib/SPIRV/SPIRVToLLVMDbgTran.cpp | 34 +++++++++++----- + test/DebugInfo/DebugInfo-GV-with-DIE.spt | 51 ++++++++++++++++++++++++ + 2 files changed, 75 insertions(+), 10 deletions(-) + create mode 100644 test/DebugInfo/DebugInfo-GV-with-DIE.spt + +diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +index 180b91e0..e6f2e813 100644 +--- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp ++++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +@@ -1120,6 +1120,15 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + StaticMemberDecl = transDebugInst( + BM->get(Ops[StaticMemberDeclarationIdx])); + } ++ ++ DIExpression *DIExpr = nullptr; ++ // Check if Ops[VariableIdx] is not being used to hold a variable operand. ++ // Instead it is being used to hold an Expression that holds the initial ++ // value of the GlobalVariable. ++ if (getDbgInst(Ops[VariableIdx])) ++ DIExpr = ++ transDebugInst(BM->get(Ops[VariableIdx])); ++ + SPIRVWord Flags = + getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind()); + bool IsLocal = Flags & SPIRVDebug::FlagIsLocal; +@@ -1128,7 +1137,7 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + if (IsDefinition) { + VarDecl = getDIBuilder(DebugInst).createGlobalVariableExpression( + Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition, +- nullptr, StaticMemberDecl); ++ DIExpr, StaticMemberDecl); + } else { + VarDecl = getDIBuilder(DebugInst).createTempGlobalVariableFwdDecl( + Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, StaticMemberDecl); +@@ -1137,15 +1146,20 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) { + llvm::TempMDNode TMP(VarDecl); + VarDecl = getDIBuilder(DebugInst).replaceTemporary(std::move(TMP), VarDecl); + } +- // If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone. +- // Otherwise Ops[VariableIdx] may be a global variable or a constant(C++ +- // static const). +- if (VarDecl && !getDbgInst(Ops[VariableIdx])) { +- SPIRVValue *V = BM->get(Ops[VariableIdx]); +- Value *Var = SPIRVReader->transValue(V, nullptr, nullptr); +- llvm::GlobalVariable *GV = dyn_cast_or_null(Var); +- if (GV && !GV->hasMetadata("dbg")) +- GV->addMetadata("dbg", *VarDecl); ++ ++ // Ops[VariableIdx] was not used to hold an Expression with the initial value ++ // for the GlobalVariable ++ if (!DIExpr) { ++ // If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone. ++ // Otherwise Ops[VariableIdx] may be a global variable or a constant(C++ ++ // static const). ++ if (VarDecl && !getDbgInst(Ops[VariableIdx])) { ++ SPIRVValue *V = BM->get(Ops[VariableIdx]); ++ Value *Var = SPIRVReader->transValue(V, nullptr, nullptr); ++ llvm::GlobalVariable *GV = dyn_cast_or_null(Var); ++ if (GV && !GV->hasMetadata("dbg")) ++ GV->addMetadata("dbg", *VarDecl); ++ } + } + return VarDecl; + } +diff --git a/test/DebugInfo/DebugInfo-GV-with-DIE.spt b/test/DebugInfo/DebugInfo-GV-with-DIE.spt +new file mode 100644 +index 00000000..a3d615ff +--- /dev/null ++++ b/test/DebugInfo/DebugInfo-GV-with-DIE.spt +@@ -0,0 +1,51 @@ ++;; Ensure that reverse translation can handle an Expression in ++;; a DebugGlobalVariable's Variable field. ++;; This is used to preserve a DIExpressions in a DIGlobalVariableExpression. ++ ++; RUN: llvm-spirv -to-binary %s -o %t.spv ++; RUN: llvm-spirv -r -o %t.rev.bc %t.spv ++; RUN: llvm-dis %t.rev.bc -o %t.rev.ll ++; RUN: FileCheck %s --input-file %t.rev.ll ++ ++; CHECK: ![[#]] = !DIGlobalVariableExpression(var: ![[#GV:]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)) ++; CHECK: ![[#GV]] = distinct !DIGlobalVariable(name: "true", scope: ![[#]], file: ![[#]], line: 3777, type: ![[#]], isLocal: true, isDefinition: true) ++ ++119734787 65536 393230 31 0 ++2 Capability Addresses ++2 Capability Linkage ++2 Capability Kernel ++8 Extension "SPV_KHR_non_semantic_info" ++5 ExtInstImport 1 "OpenCL.std" ++11 ExtInstImport 2 "NonSemantic.Shader.DebugInfo.100" ++3 MemoryModel 2 2 ++7 String 3 "/path/to/test.cpp" ++3 String 6 "0" ++3 String 10 "" ++4 String 16 "bool" ++4 String 23 "true" ++3 Source 0 0 ++4 TypeInt 7 32 0 ++4 Constant 7 8 1 ++4 Constant 7 12 65536 ++4 Constant 7 13 4 ++4 Constant 7 14 6 ++4 Constant 7 17 8 ++4 Constant 7 18 2 ++4 Constant 7 21 0 ++4 Constant 7 25 7 ++4 Constant 7 28 3777 ++4 Constant 7 29 12 ++2 TypeVoid 4 ++ ++6 ExtInst 4 5 2 DebugSource 3 ++7 ExtInst 4 9 2 DebugBuildIdentifier 6 8 ++6 ExtInst 4 11 2 DebugStoragePath 10 ++9 ExtInst 4 15 2 DebugCompilationUnit 12 13 5 14 ++5 ExtInst 4 19 2 DebugInfoNone ++9 ExtInst 4 20 2 DebugTypeBasic 16 17 18 19 ++7 ExtInst 4 22 2 DebugTypeQualifier 20 21 ++7 ExtInst 4 24 2 DebugOperation 17 8 ++6 ExtInst 4 26 2 DebugOperation 25 ++7 ExtInst 4 27 2 DebugExpression 24 26 ++14 ExtInst 4 30 2 DebugGlobalVariable 23 22 5 28 21 15 10 27 29 ++ +-- +2.20.1 + diff --git a/patches/0076-Backport-to-15-Translate-atomicrmw-fadd-into-AtomicF.patch b/patches/0076-Backport-to-15-Translate-atomicrmw-fadd-into-AtomicF.patch new file mode 100644 index 0000000..deb9802 --- /dev/null +++ b/patches/0076-Backport-to-15-Translate-atomicrmw-fadd-into-AtomicF.patch @@ -0,0 +1,127 @@ +From 21d46130574100ac2b3a86235a2436b71fa6818f Mon Sep 17 00:00:00 2001 +From: Nick Sarnie +Date: Wed, 7 Dec 2022 17:59:17 -0500 +Subject: [PATCH 76/79] [Backport to 15] Translate atomicrmw fadd into + AtomicFAddEXT (#1757) + +Signed-off-by: Sarnie, Nick +--- + lib/SPIRV/OCLUtil.cpp | 1 + + lib/SPIRV/SPIRVWriter.cpp | 6 ++-- + .../atomicrmw_fadd_double.ll | 33 +++++++++++++++++++ + .../atomicrmw_fadd_float.ll | 33 +++++++++++++++++++ + 4 files changed, 71 insertions(+), 2 deletions(-) + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_double.ll + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_float.ll + +diff --git a/lib/SPIRV/OCLUtil.cpp b/lib/SPIRV/OCLUtil.cpp +index 53ebc362..e14ac421 100644 +--- a/lib/SPIRV/OCLUtil.cpp ++++ b/lib/SPIRV/OCLUtil.cpp +@@ -646,6 +646,7 @@ template <> void LLVMSPIRVAtomicRmwOpCodeMap::init() { + add(llvm::AtomicRMWInst::Min, OpAtomicSMin); + add(llvm::AtomicRMWInst::UMax, OpAtomicUMax); + add(llvm::AtomicRMWInst::UMin, OpAtomicUMin); ++ add(llvm::AtomicRMWInst::FAdd, OpAtomicFAddEXT); + } + + } // namespace SPIRV +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 97af8e04..c58c2d77 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -2191,9 +2191,11 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, + + if (AtomicRMWInst *ARMW = dyn_cast(V)) { + AtomicRMWInst::BinOp Op = ARMW->getOperation(); ++ bool SupportedAtomicInst = AtomicRMWInst::isFPOperation(Op) ++ ? Op == AtomicRMWInst::FAdd ++ : Op != AtomicRMWInst::Nand; + if (!BM->getErrorLog().checkError( +- !AtomicRMWInst::isFPOperation(Op) && Op != AtomicRMWInst::Nand, +- SPIRVEC_InvalidInstruction, V, ++ SupportedAtomicInst, SPIRVEC_InvalidInstruction, V, + "Atomic " + AtomicRMWInst::getOperationName(Op).str() + + " is not supported in SPIR-V!\n")) + return nullptr; +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_double.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_double.ll +new file mode 100644 +index 00000000..7d14bcf7 +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_double.ll +@@ -0,0 +1,33 @@ ++; RUN: llvm-as -opaque-pointers < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers --spirv-ext=+SPV_EXT_shader_atomic_float_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -opaque-pointers -to-text %t.spv -o - | FileCheck %s ++ ++; CHECK-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-DAG: Capability AtomicFloat64AddEXT ++; CHECK: TypeInt [[Int:[0-9]+]] 32 0 ++; CHECK-DAG: Constant [[Int]] [[Scope_Device:[0-9]+]] 1 {{$}} ++; CHECK-DAG: Constant [[Int]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK: TypeFloat [[Double:[0-9]+]] 64 ++; CHECK: Variable {{[0-9]+}} [[DoublePointer:[0-9]+]] ++; CHECK: Constant [[Double]] [[DoubleValue:[0-9]+]] 0 1078263808 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global double 0.000000e+00, align 8 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fadd double addrspace(1)* @f, double 42.000000e+00 seq_cst ++; CHECK: AtomicFAddEXT [[Double]] {{[0-9]+}} [[DoublePointer]] [[Scope_Device]] [[MemSem_SequentiallyConsistent]] [[DoubleValue]] ++ ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_float.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_float.ll +new file mode 100644 +index 00000000..6f33a315 +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_float.ll +@@ -0,0 +1,33 @@ ++; RUN: llvm-as -opaque-pointers < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers --spirv-ext=+SPV_EXT_shader_atomic_float_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -opaque-pointers -to-text %t.spv -o - | FileCheck %s ++ ++; CHECK-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-DAG: Capability AtomicFloat32AddEXT ++; CHECK: TypeInt [[Int:[0-9]+]] 32 0 ++; CHECK-DAG: Constant [[Int]] [[Scope_Device:[0-9]+]] 1 {{$}} ++; CHECK-DAG: Constant [[Int]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK: TypeFloat [[Float:[0-9]+]] 32 ++; CHECK: Variable {{[0-9]+}} [[FPPointer:[0-9]+]] ++; CHECK: Constant [[Float]] [[FPValue:[0-9]+]] 1109917696 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global float 0.000000e+00, align 4 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fadd float addrspace(1)* @f, float 42.000000e+00 seq_cst ++; CHECK: AtomicFAddEXT [[Float]] {{[0-9]+}} [[FPPointer]] [[Scope_Device]] [[MemSem_SequentiallyConsistent]] [[FPValue]] ++ ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +-- +2.20.1 + diff --git a/patches/0077-Backport-to-15-Translate-atomicrmw-fsub-into-FNegate.patch b/patches/0077-Backport-to-15-Translate-atomicrmw-fsub-into-FNegate.patch new file mode 100644 index 0000000..612079b --- /dev/null +++ b/patches/0077-Backport-to-15-Translate-atomicrmw-fsub-into-FNegate.patch @@ -0,0 +1,151 @@ +From c7eacb39b7ec76af8e144ac107a8bec3b2c0fa57 Mon Sep 17 00:00:00 2001 +From: Nick Sarnie +Date: Thu, 22 Dec 2022 04:47:24 -0500 +Subject: [PATCH 77/79] [Backport to 15] Translate atomicrmw fsub into FNegate + and AtomicFAddEXT (#1780) + +Signed-off-by: Sarnie, Nick +--- + lib/SPIRV/SPIRVWriter.cpp | 19 +++++++--- + .../atomicrmw_fsub_double.ll | 38 +++++++++++++++++++ + .../atomicrmw_fsub_float.ll | 38 +++++++++++++++++++ + 3 files changed, 90 insertions(+), 5 deletions(-) + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_double.ll + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_float.ll + +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index c58c2d77..013e5191 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -2191,16 +2191,16 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, + + if (AtomicRMWInst *ARMW = dyn_cast(V)) { + AtomicRMWInst::BinOp Op = ARMW->getOperation(); +- bool SupportedAtomicInst = AtomicRMWInst::isFPOperation(Op) +- ? Op == AtomicRMWInst::FAdd +- : Op != AtomicRMWInst::Nand; ++ bool SupportedAtomicInst = ++ AtomicRMWInst::isFPOperation(Op) ++ ? (Op == AtomicRMWInst::FAdd || Op == AtomicRMWInst::FSub) ++ : Op != AtomicRMWInst::Nand; + if (!BM->getErrorLog().checkError( + SupportedAtomicInst, SPIRVEC_InvalidInstruction, V, + "Atomic " + AtomicRMWInst::getOperationName(Op).str() + + " is not supported in SPIR-V!\n")) + return nullptr; + +- spv::Op OC = LLVMSPIRVAtomicRmwOpCodeMap::map(Op); + AtomicOrderingCABI Ordering = llvm::toCABI(ARMW->getOrdering()); + auto MemSem = OCLMemOrderMap::map(static_cast(Ordering)); + std::vector Operands(4); +@@ -2214,9 +2214,18 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, + Operands[1] = getUInt32(M, spv::ScopeDevice); + Operands[2] = getUInt32(M, MemSem); + Operands[3] = ARMW->getValOperand(); +- std::vector Ops = BM->getIds(transValue(Operands, BB)); ++ std::vector OpVals = transValue(Operands, BB); ++ std::vector Ops = BM->getIds(OpVals); + SPIRVType *Ty = transType(ARMW->getType()); + ++ spv::Op OC; ++ if (Op == AtomicRMWInst::FSub) { ++ // Implement FSub through FNegate and AtomicFAddExt ++ Ops[3] = BM->addUnaryInst(OpFNegate, Ty, OpVals[3], BB)->getId(); ++ OC = OpAtomicFAddEXT; ++ } else ++ OC = LLVMSPIRVAtomicRmwOpCodeMap::map(Op); ++ + return mapValue(V, BM->addInstTemplate(OC, Ops, BB, Ty)); + } + +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_double.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_double.ll +new file mode 100644 +index 00000000..af3da7e5 +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_double.ll +@@ -0,0 +1,38 @@ ++; RUN: llvm-as -opaque-pointers=0 < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers=0 --spirv-ext=+SPV_EXT_shader_atomic_float_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -to-text %t.spv -o - | FileCheck --check-prefix=CHECK-SPIRV %s ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis -opaque-pointers=0 %t.rev.bc -o - | FileCheck %s --check-prefixes=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-SPIRV-DAG: Capability AtomicFloat64AddEXT ++; CHECK-SPIRV: TypeInt [[Int:[0-9]+]] 32 0 ++; CHECK-SPIRV-DAG: Constant [[Int]] [[Scope_Device:[0-9]+]] 1 {{$}} ++; CHECK-SPIRV-DAG: Constant [[Int]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK-SPIRV: TypeFloat [[Double:[0-9]+]] 64 ++; CHECK-SPIRV: Variable {{[0-9]+}} [[DoublePointer:[0-9]+]] ++; CHECK-SPIRV: Constant [[Double]] [[DoubleValue:[0-9]+]] 0 1078263808 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global double 0.000000e+00, align 8 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fsub double addrspace(1)* @f, double 42.000000e+00 seq_cst ++; CHECK-SPIRV: FNegate [[Double]] [[NegateValue:[0-9]+]] [[DoubleValue]] ++; CHECK-SPIRV: AtomicFAddEXT [[Double]] {{[0-9]+}} [[DoublePointer]] [[Scope_Device]] [[MemSem_SequentiallyConsistent]] [[NegateValue]] ++; CHECK-LLVM: [[FNegateLLVM:%[0-9]+]] = fneg double 4.200000e+01 ++; CHECK-LLVM: call spir_func double {{.*}}atomic_add{{.*}}(double addrspace(1)* @f, double [[FNegateLLVM]]) ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_float.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_float.ll +new file mode 100644 +index 00000000..a9fab6ba +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_float.ll +@@ -0,0 +1,38 @@ ++; RUN: llvm-as -opaque-pointers=0 < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers=0 --spirv-ext=+SPV_EXT_shader_atomic_float_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -to-text %t.spv -o - | FileCheck --check-prefix=CHECK-SPIRV %s ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis -opaque-pointers=0 %t.rev.bc -o - | FileCheck %s --check-prefixes=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-SPIRV-DAG: Capability AtomicFloat32AddEXT ++; CHECK-SPIRV: TypeInt [[Int:[0-9]+]] 32 0 ++; CHECK-SPIRV-DAG: Constant [[Int]] [[Scope_Device:[0-9]+]] 1 {{$}} ++; CHECK-SPIRV-DAG: Constant [[Int]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK-SPIRV: TypeFloat [[Float:[0-9]+]] 32 ++; CHECK-SPIRV: Variable {{[0-9]+}} [[FPPointer:[0-9]+]] ++; CHECK-SPIRV: Constant [[Float]] [[FPValue:[0-9]+]] 1109917696 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global float 0.000000e+00, align 4 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fsub float addrspace(1)* @f, float 42.000000e+00 seq_cst ++; CHECK-SPIRV: FNegate [[Float]] [[NegateValue:[0-9]+]] [[FPValue]] ++; CHECK-SPIRV: AtomicFAddEXT [[Float]] {{[0-9]+}} [[FPPointer]] [[Scope_Device]] [[MemSem_SequentiallyConsistent]] [[NegateValue]] ++; CHECK-LLVM: [[FNegateLLVM:%[0-9]+]] = fneg float 4.200000e+01 ++; CHECK-LLVM: call spir_func float {{.*}}atomic_add{{.*}}(float addrspace(1)* @f, float [[FNegateLLVM]]) ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +-- +2.20.1 + diff --git a/patches/0078-Backport-to-15-add-initial-f16-type-support-for-atom.patch b/patches/0078-Backport-to-15-add-initial-f16-type-support-for-atom.patch new file mode 100644 index 0000000..28c44dd --- /dev/null +++ b/patches/0078-Backport-to-15-add-initial-f16-type-support-for-atom.patch @@ -0,0 +1,199 @@ +From b8c2582a862ac451dfb605ad56f6289527ea5e9d Mon Sep 17 00:00:00 2001 +From: Vyacheslav Levytskyy + <89994100+VyacheslavLevytskyy@users.noreply.github.com> +Date: Tue, 14 Nov 2023 16:55:37 +0100 +Subject: [PATCH 78/79] [Backport to 15] add initial f16 type support for + atomicrmw in llvm-spirv translator (#2210) + +This PR aims to add f16 type support for atomicrmw in llvm-spirv translator, with the reference to the extension documented in [1]. +There are two concerns related to the subject: + +SPIRVAtomicFAddEXTInst::getRequiredExtension() should return a list of required extension to support the requirement to list both SPV_EXT_shader_atomic_float16_add and SPV_EXT_shader_atomic_float_add extensions in the module (see "Extension Name" section of the ref [1]). However, the return type is std::optional and returning a vector would need a bigger rework. +Including SPV_EXT_shader_atomic_float16_add into --spirv-ext argument of llvm-spirv doesn't result in producing the correspondent capability (AtomicFloat16AddEXT) and extension in a SPIRV output. +$ llvm-spirv AtomicFAddEXT.ll.tmp.bc --spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_EXT_shader_atomic_float16_add -o AtomicFAddEXT.ll.tmp.spv +$ llvm-spirv -to-text AtomicFAddEXT.ll.tmp.spv -o /dev/stdout +... +2 Capability AtomicFloat32AddEXT +2 Capability AtomicFloat64AddEXT +9 Extension "SPV_EXT_shader_atomic_float_add" +... +This prevents extending the test case of AtomicFAddEXT.ll in EXT/SPV_EXT_shader_atomic_float. + +References: +[1] https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_shader_atomic_float16_add.asciidoc +--- + include/LLVMSPIRVExtensions.inc | 1 + + lib/SPIRV/SPIRVWriter.cpp | 2 +- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 12 ++++-- + lib/SPIRV/libSPIRV/SPIRVModule.cpp | 11 ++++++ + .../atomicrmw_fadd_half.ll | 34 ++++++++++++++++ + .../atomicrmw_fsub_half.ll | 39 +++++++++++++++++++ + 6 files changed, 95 insertions(+), 4 deletions(-) + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_half.ll + create mode 100644 test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_half.ll + +diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc +index 9ad47a4a..d3138c06 100644 +--- a/include/LLVMSPIRVExtensions.inc ++++ b/include/LLVMSPIRVExtensions.inc +@@ -2,6 +2,7 @@ + #define EXT(X) + #endif + ++EXT(SPV_EXT_shader_atomic_float16_add) + EXT(SPV_EXT_shader_atomic_float_add) + EXT(SPV_EXT_shader_atomic_float_min_max) + EXT(SPV_KHR_no_integer_wrap_decoration) +diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp +index 013e5191..cc4034de 100644 +--- a/lib/SPIRV/SPIRVWriter.cpp ++++ b/lib/SPIRV/SPIRVWriter.cpp +@@ -2191,7 +2191,7 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, + + if (AtomicRMWInst *ARMW = dyn_cast(V)) { + AtomicRMWInst::BinOp Op = ARMW->getOperation(); +- bool SupportedAtomicInst = ++ const bool SupportedAtomicInst = + AtomicRMWInst::isFPOperation(Op) + ? (Op == AtomicRMWInst::FAdd || Op == AtomicRMWInst::FSub) + : Op != AtomicRMWInst::Nand; +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 84122a6e..23d29dca 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -2735,16 +2735,22 @@ public: + class SPIRVAtomicFAddEXTInst : public SPIRVAtomicInstBase { + public: + llvm::Optional getRequiredExtension() const override { ++ assert(hasType()); ++ if (getType()->isTypeFloat(16)) ++ return ExtensionID::SPV_EXT_shader_atomic_float16_add; + return ExtensionID::SPV_EXT_shader_atomic_float_add; + } + + SPIRVCapVec getRequiredCapability() const override { + assert(hasType()); ++ if (getType()->isTypeFloat(16)) ++ return {CapabilityAtomicFloat16AddEXT}; + if (getType()->isTypeFloat(32)) + return {CapabilityAtomicFloat32AddEXT}; +- assert(getType()->isTypeFloat(64) && +- "AtomicFAddEXT can only be generated for f32 or f64 types"); +- return {CapabilityAtomicFloat64AddEXT}; ++ if (getType()->isTypeFloat(64)) ++ return {CapabilityAtomicFloat64AddEXT}; ++ llvm_unreachable( ++ "AtomicFAddEXT can only be generated for f16, f32, f64 types"); + } + }; + +diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +index ea05680a..bfe42179 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -653,6 +653,17 @@ void SPIRVModuleImpl::addExtension(ExtensionID Ext) { + return; + } + SPIRVExt.insert(ExtName); ++ ++ // SPV_EXT_shader_atomic_float16_add extends the ++ // SPV_EXT_shader_atomic_float_add extension. ++ // The specification requires both extensions to be added to use ++ // AtomicFloat16AddEXT capability whereas getRequiredExtension() ++ // is able to return a single extensionID. ++ if (Ext == ExtensionID::SPV_EXT_shader_atomic_float16_add) { ++ SPIRVMap::find( ++ ExtensionID::SPV_EXT_shader_atomic_float_add, &ExtName); ++ SPIRVExt.insert(ExtName); ++ } + } + + void SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) { +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_half.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_half.ll +new file mode 100644 +index 00000000..7bbc0272 +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fadd_half.ll +@@ -0,0 +1,34 @@ ++; RUN: llvm-as -opaque-pointers < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers --spirv-ext=+SPV_EXT_shader_atomic_float16_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -opaque-pointers -to-text %t.spv -o - | FileCheck %s ++ ++; CHECK-DAG: Extension "SPV_EXT_shader_atomic_float16_add" ++; CHECK-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-DAG: Capability AtomicFloat16AddEXT ++; CHECK: TypeInt [[TypeIntID:[0-9]+]] 32 0 ++; CHECK-DAG: Constant [[TypeIntID]] [[ScopeDevice:[0-9]+]] 1 {{$}} ++; CHECK-DAG: Constant [[TypeIntID]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK: TypeFloat [[TypeFloatHalfID:[0-9]+]] 16 ++; CHECK: Variable {{[0-9]+}} [[HalfPointer:[0-9]+]] ++; CHECK: Constant [[TypeFloatHalfID]] [[HalfValue:[0-9]+]] 20800 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global half 0.000000e+00, align 4 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fadd ptr addrspace(1) @f, half 42.000000e+00 seq_cst ++; CHECK: AtomicFAddEXT [[TypeFloatHalfID]] {{[0-9]+}} [[HalfPointer]] [[ScopeDevice]] [[MemSem_SequentiallyConsistent]] [[HalfValue]] ++ ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +diff --git a/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_half.ll b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_half.ll +new file mode 100644 +index 00000000..fc7473f3 +--- /dev/null ++++ b/test/extensions/EXT/SPV_EXT_shader_atomic_float_/atomicrmw_fsub_half.ll +@@ -0,0 +1,39 @@ ++; RUN: llvm-as -opaque-pointers=0 < %s -o %t.bc ++; RUN: llvm-spirv -opaque-pointers=0 --spirv-ext=+SPV_EXT_shader_atomic_float16_add %t.bc -o %t.spv ++; RUN: spirv-val %t.spv ++; RUN: llvm-spirv -to-text %t.spv -o - | FileCheck --check-prefix=CHECK-SPIRV %s ++ ++; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ++; RUN: llvm-dis -opaque-pointers=0 %t.rev.bc -o - | FileCheck %s --check-prefixes=CHECK-LLVM ++ ++; CHECK-SPIRV-DAG: Extension "SPV_EXT_shader_atomic_float16_add" ++; CHECK-SPIRV-DAG: Extension "SPV_EXT_shader_atomic_float_add" ++; CHECK-SPIRV-DAG: Capability AtomicFloat16AddEXT ++; CHECK-SPIRV: TypeInt [[Int:[0-9]+]] 32 0 ++; CHECK-SPIRV-DAG: Constant [[Int]] [[ScopeDevice:[0-9]+]] 1 {{$}} ++; CHECK-SPIRV-DAG: Constant [[Int]] [[MemSem_SequentiallyConsistent:[0-9]+]] 16 ++; CHECK-SPIRV: TypeFloat [[Half:[0-9]+]] 16 ++; CHECK-SPIRV: Variable {{[0-9]+}} [[HalfPointer:[0-9]+]] ++; CHECK-SPIRV: Constant [[Half]] [[HalfValue:[0-9]+]] 15360 ++ ++target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" ++target triple = "spir64" ++ ++@f = common dso_local local_unnamed_addr addrspace(1) global half 0.000000e+00, align 4 ++ ++; Function Attrs: nounwind ++define dso_local spir_func void @test_atomicrmw_fadd() local_unnamed_addr #0 { ++entry: ++ %0 = atomicrmw fsub half addrspace(1)* @f, half 1.0e+00 seq_cst ++; CHECK-SPIRV: FNegate [[Half]] [[NegateValue:[0-9]+]] [[HalfValue]] ++; CHECK-SPIRV: AtomicFAddEXT [[Half]] {{[0-9]+}} [[HalfPointer]] [[ScopeDevice]] [[MemSem_SequentiallyConsistent]] [[NegateValue]] ++; CHECK-LLVM: [[FNegateLLVM:%[0-9]+]] = fneg half 0xH3C00 ++; CHECK-LLVM: call spir_func half {{.*}}atomic_add{{.*}}(half addrspace(1)* @f, half [[FNegateLLVM]]) ++ ret void ++} ++ ++attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } ++ ++!llvm.module.flags = !{!0} ++ ++!0 = !{i32 1, !"wchar_size", i32 4} +-- +2.20.1 + diff --git a/patches/0079-Backport-to-15-SPV-SPV-IR-Fix-image-builtin-mangling.patch b/patches/0079-Backport-to-15-SPV-SPV-IR-Fix-image-builtin-mangling.patch new file mode 100644 index 0000000..599a739 --- /dev/null +++ b/patches/0079-Backport-to-15-SPV-SPV-IR-Fix-image-builtin-mangling.patch @@ -0,0 +1,256 @@ +From c1f08b41076fcf636cb890630faa7f788234e6f9 Mon Sep 17 00:00:00 2001 +From: Wenju He +Date: Sat, 3 Feb 2024 01:31:27 +0800 +Subject: [PATCH 79/79] [Backport to 15][SPV -> SPV-IR] Fix image builtin + mangling of unsigned type (#2273) (#2338) + +Return type of image read and Texel type of image write builtins may be unsigned. Before this PR, the builtin names in SPIR-V Friendly IR were always mangled with signed type. + +(cherry picked from commit e9b95fb) +--- + lib/SPIRV/SPIRVInternal.h | 7 ++++- + lib/SPIRV/SPIRVReader.cpp | 18 +++++++++--- + lib/SPIRV/SPIRVUtil.cpp | 37 +++++++++++++++++++++---- + lib/SPIRV/libSPIRV/SPIRVInstruction.cpp | 15 ++-------- + lib/SPIRV/libSPIRV/SPIRVInstruction.h | 3 -- + test/transcoding/image_signedness.ll | 9 ++++++ + 6 files changed, 62 insertions(+), 27 deletions(-) + +diff --git a/lib/SPIRV/SPIRVInternal.h b/lib/SPIRV/SPIRVInternal.h +index 30241c89..9adb620e 100644 +--- a/lib/SPIRV/SPIRVInternal.h ++++ b/lib/SPIRV/SPIRVInternal.h +@@ -925,6 +925,9 @@ std::string getImageBaseTypeName(StringRef Name); + /// Map OpenCL opaque type name to SPIR-V type name. + std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc = ""); + ++/// Return the index of image operands given an image op. ++size_t getImageOperandsIndex(Op OpCode); ++ + /// Check if access qualifier is encoded in the type name. + bool hasAccessQualifiedName(StringRef TyName); + +@@ -998,10 +1001,12 @@ std::string getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId, + /// \param OC opcode of corresponding built-in instruction. Used to gather info + /// for unsigned/constant arguments. + /// \param Types of arguments of SPIR-V built-in function ++/// \param Ops Operands of SPIRVInstruction + /// \return IA64 mangled name. + std::string getSPIRVFriendlyIRFunctionName(const std::string &UniqName, + spv::Op OC, ArrayRef ArgTys, +- ArrayRef PETs); ++ ArrayRef PETs, ++ ArrayRef Ops); + + /// Cast a function to a void(void) funtion pointer. + Constant *castToVoidFuncPtr(Function *F); +diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp +index 89b39b1c..b8424503 100644 +--- a/lib/SPIRV/SPIRVReader.cpp ++++ b/lib/SPIRV/SPIRVReader.cpp +@@ -3163,8 +3163,8 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName, + if (BM->getDesiredBIsRepresentation() != BIsRepresentation::SPIRVFriendlyIR) + mangleOpenClBuiltin(FuncName, ArgTys, PointerElementTys, MangledName); + else +- MangledName = getSPIRVFriendlyIRFunctionName(FuncName, BI->getOpCode(), +- ArgTys, PointerElementTys); ++ MangledName = getSPIRVFriendlyIRFunctionName( ++ FuncName, BI->getOpCode(), ArgTys, PointerElementTys, Ops); + + Function *Func = M->getFunction(MangledName); + FunctionType *FT = FunctionType::get(RetTy, ArgTys, false); +@@ -3301,7 +3301,7 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI, + } + } + +- bool IsRetSigned; ++ bool IsRetSigned = true; + switch (OC) { + case OpConvertFToU: + case OpSatConvertSToU: +@@ -3310,8 +3310,18 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI, + case OpUDotAccSatKHR: + IsRetSigned = false; + break; ++ case OpImageRead: ++ case OpImageSampleExplicitLod: { ++ const size_t Idx = getImageOperandsIndex(OC); ++ auto Ops = BI->getOperands(); ++ if (Ops.size() > Idx) { ++ auto ImOp = static_cast(Ops[Idx])->getZExtIntValue(); ++ IsRetSigned = !(ImOp & ImageOperandsMask::ImageOperandsZeroExtendMask); ++ } ++ break; ++ } + default: +- IsRetSigned = true; ++ break; + } + + if (AddRetTypePostfix) { +diff --git a/lib/SPIRV/SPIRVUtil.cpp b/lib/SPIRV/SPIRVUtil.cpp +index 4c5a11b8..88b3684f 100644 +--- a/lib/SPIRV/SPIRVUtil.cpp ++++ b/lib/SPIRV/SPIRVUtil.cpp +@@ -1525,6 +1525,18 @@ std::string getImageBaseTypeName(StringRef Name) { + return ImageTyName; + } + ++size_t getImageOperandsIndex(Op OpCode) { ++ switch (OpCode) { ++ case OpImageRead: ++ case OpImageSampleExplicitLod: ++ return 2; ++ case OpImageWrite: ++ return 3; ++ default: ++ return ~0U; ++ } ++} ++ + std::string mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc) { + std::string BaseTy; + std::string Postfixes; +@@ -2161,8 +2173,9 @@ bool postProcessBuiltinsWithArrayArguments(Module *M, bool IsCpp) { + namespace { + class SPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo { + public: +- SPIRVFriendlyIRMangleInfo(spv::Op OC, ArrayRef ArgTys) +- : OC(OC), ArgTys(ArgTys) {} ++ SPIRVFriendlyIRMangleInfo(spv::Op OC, ArrayRef ArgTys, ++ ArrayRef Ops) ++ : OC(OC), ArgTys(ArgTys), Ops(Ops) {} + + void init(StringRef UniqUnmangledName) override { + UnmangledName = UniqUnmangledName.str(); +@@ -2322,6 +2335,15 @@ public: + case OpSUDotAccSatKHR: + addUnsignedArg(1); + break; ++ case OpImageWrite: { ++ const size_t Idx = getImageOperandsIndex(OC); ++ if (Ops.size() > Idx) { ++ auto ImOp = static_cast(Ops[Idx])->getZExtIntValue(); ++ if (ImOp & ImageOperandsMask::ImageOperandsZeroExtendMask) ++ addUnsignedArg(2); ++ } ++ break; ++ } + default:; + // No special handling is needed + } +@@ -2330,6 +2352,7 @@ public: + private: + spv::Op OC; + ArrayRef ArgTys; ++ ArrayRef Ops; + }; + class OpenCLStdToSPIRVFriendlyIRMangleInfo : public BuiltinFuncMangleInfo { + public: +@@ -2407,10 +2430,12 @@ getSPIRVFriendlyIRFunctionName(OCLExtOpKind ExtOpId, ArrayRef ArgTys, + return mangleBuiltin(MangleInfo.getUnmangledName(), ArgTys, &MangleInfo); + } + +-std::string getSPIRVFriendlyIRFunctionName( +- const std::string &UniqName, spv::Op OC, ArrayRef ArgTys, +- ArrayRef PointerElementTys) { +- SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys); ++std::string ++getSPIRVFriendlyIRFunctionName(const std::string &UniqName, spv::Op OC, ++ ArrayRef ArgTys, ++ ArrayRef PointerElementTys, ++ ArrayRef Ops) { ++ SPIRVFriendlyIRMangleInfo MangleInfo(OC, ArgTys, Ops); + MangleInfo.fillPointerElementTypes(PointerElementTys); + return mangleBuiltin(UniqName, ArgTys, &MangleInfo); + } +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp b/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp +index 5d5defdd..a34e5ccb 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.cpp +@@ -40,6 +40,7 @@ + #include "SPIRVInstruction.h" + #include "SPIRVBasicBlock.h" + #include "SPIRVFunction.h" ++#include "SPIRVInternal.h" + + #include + +@@ -157,25 +158,13 @@ std::vector SPIRVInstruction::getOperandTypes() { + return getOperandTypes(getOperands()); + } + +-size_t SPIRVImageInstBase::getImageOperandsIndex() const { +- switch (OpCode) { +- case OpImageRead: +- case OpImageSampleExplicitLod: +- return 2; +- case OpImageWrite: +- return 3; +- default: +- return ~0U; +- } +-} +- + void SPIRVImageInstBase::setOpWords(const std::vector &OpsArg) { + std::vector Ops = OpsArg; + + // If the Image Operands field has the SignExtend or ZeroExtend bit set, + // either raise the minimum SPIR-V version to 1.4, or drop the operand + // if SPIR-V 1.4 cannot be emitted. +- size_t ImgOpsIndex = getImageOperandsIndex(); ++ const size_t ImgOpsIndex = getImageOperandsIndex(OpCode); + if (ImgOpsIndex != ~0U && ImgOpsIndex < Ops.size()) { + SPIRVWord ImgOps = Ops[ImgOpsIndex]; + unsigned SignZeroExtMasks = ImageOperandsMask::ImageOperandsSignExtendMask | +diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +index 23d29dca..5d369db3 100644 +--- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h ++++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h +@@ -2812,9 +2812,6 @@ public: + + protected: + void setOpWords(const std::vector &OpsArg) override; +- +-private: +- size_t getImageOperandsIndex() const; + }; + + #define _SPIRV_OP(x, ...) \ +diff --git a/test/transcoding/image_signedness.ll b/test/transcoding/image_signedness.ll +index d169251e..14cb6fe7 100644 +--- a/test/transcoding/image_signedness.ll ++++ b/test/transcoding/image_signedness.ll +@@ -5,6 +5,8 @@ + ; RUN: spirv-val %t.spv + ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc + ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM ++; RUN: llvm-spirv -r --spirv-target-env=SPV-IR %t.spv -o %t.rev.bc ++; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-SPV-IR + + ; ModuleID = 'image_signedness.ll' + target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +@@ -21,6 +23,11 @@ target triple = "spir-unknown-unknown" + ; CHECK-LLVM: call spir_func <4 x i32> @_Z12read_imageui20ocl_image1d_array_rwDv2_i( + ; CHECK-LLVM: call spir_func <4 x i32> @_Z12read_imageui14ocl_image1d_roi( + ; CHECK-LLVM: call spir_func <4 x i32> @_Z11read_imagei14ocl_image1d_roi( ++; CHECK-SPV-IR: call spir_func <4 x i32> @_Z37__spirv_ImageSampleExplicitLod_Ruint4PU3AS140__spirv_SampledImage__void_0_0_0_0_0_0_0iif( ++; CHECK-SPV-IR: call spir_func <4 x i32> @_Z36__spirv_ImageSampleExplicitLod_Rint4PU3AS140__spirv_SampledImage__void_0_0_0_0_0_0_0iif( ++; CHECK-SPV-IR: call spir_func <4 x i32> @_Z24__spirv_ImageRead_Ruint4PU3AS133__spirv_Image__void_0_0_1_0_0_0_2Dv2_ii( ++; CHECK-SPV-IR: call spir_func <4 x i32> @_Z24__spirv_ImageRead_Ruint4PU3AS133__spirv_Image__void_0_0_0_0_0_0_0ii( ++; CHECK-SPV-IR: call spir_func <4 x i32> @_Z23__spirv_ImageRead_Rint4PU3AS133__spirv_Image__void_0_0_0_0_0_0_0ii( + + ; Function Attrs: convergent nounwind + define dso_local spir_kernel void @imagereads(%opencl.image1d_ro_t addrspace(1)* %im, %opencl.image1d_array_rw_t addrspace(1)* %ima, <4 x i32> addrspace(1)* nocapture %res, <4 x i32> addrspace(1)* nocapture %resu) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !7 !kernel_arg_type_qual !8 { +@@ -42,6 +49,8 @@ entry: + ; CHECK-LLVM-LABEL: @imagewrites + ; CHECK-LLVM: call spir_func void @_Z12write_imagei14ocl_image2d_woDv2_iDv4_i( + ; CHECK-LLVM: call spir_func void @_Z13write_imageui14ocl_image2d_woDv2_iDv4_j( ++; CHECK-SPV-IR: call spir_func void @_Z18__spirv_ImageWritePU3AS133__spirv_Image__void_1_0_0_0_0_0_1Dv2_iDv4_ii( ++; CHECK-SPV-IR: call spir_func void @_Z18__spirv_ImageWritePU3AS133__spirv_Image__void_1_0_0_0_0_0_1Dv2_iDv4_ji( + + ; Function Attrs: alwaysinline convergent nounwind + define spir_kernel void @imagewrites(i32 %offset, <4 x i32> addrspace(1)* nocapture readonly %input, <4 x i32> addrspace(1)* nocapture readonly %inputu, %opencl.image2d_wo_t addrspace(1)* %output) local_unnamed_addr #0 !kernel_arg_addr_space !14 !kernel_arg_access_qual !15 !kernel_arg_type !16 !kernel_arg_base_type !17 !kernel_arg_type_qual !18 !kernel_arg_name !19 !kernel_attributes !20 { +-- +2.20.1 + diff --git a/patches/series b/patches/series new file mode 100644 index 0000000..4d76205 --- /dev/null +++ b/patches/series @@ -0,0 +1,80 @@ +0001-Integer-dot-product-4x8-packed-translation-1654.patch +0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch +0003-CI-Upgrade-to-Ubuntu-20.04.patch +0004-NFC-Replace-getPointerElementType-in-SPIRVRegularize.patch +0005-NFC-Initialize-a-variable.patch +0006-Backport-to-15-Add-SPV_INTEL_masked_gather_scatter-e.patch +0007-Backport-to-15-Translate-llvm.loop.unroll.full-metad.patch +0008-Backport-to-15-Implement-SPV_INTEL_tensor_float32_co.patch +0009-Backport-to-15-Fix-builtin-vars-translation.patch +0010-Backport-to-15-Relax-OpenCL-extended-instruction-res.patch +0011-Backport-to-15-Add-SPV_EXT_relaxed_printf_string_add.patch +0012-Deprecate-SPV_INTEL_non_constant_addrspace_printf-ex.patch +0013-Backport-to-15-Translate-readnone-attribute-as-funct.patch +0014-Backport-to-15-Put-memory-none-attribute-instead-of-.patch +0015-Allow-ReadNone-and-ReadOnly-as-Function-attributes.patch +0016-Fix-mangling-of-opcodes-from-SPV_KHR_bit_instruction.patch +0017-Update-spirv-as-invocations-1933.patch +0018-Backport-to-15-Initial-support-NonSemantic.Kernel.De.patch +0019-Backport-to-15-DebugInfo-Add-Target-Function-optiona.patch +0020-Backport-to-15-DebugInfo-Add-new-Source-Languages-ta.patch +0021-Backport-to-15-DebugInfo-Add-an-option-for-NonSemant.patch +0022-Backport-to-15-DebugInfo-Add-DebugTypeArrayDynamic-t.patch +0023-Backport-to-15-DebugInfo-Support-translation-of-DISt.patch +0024-Backport-to-15-DebugInfo-Support-translation-of-DIMo.patch +0025-Backport-to-15-DebugInfo-Start-adopting-debug-info-i.patch +0026-Backport-to-15-DebugInfo-Rename-NonSemantic.Kernel.D.patch +0027-Backport-to-15-DebugInfo-Add-more-source-languages-a.patch +0028-Backport-to-15-DebugInfo-Align-Instruction-names-to-.patch +0029-Rename-ConvertFToTF32INTEL-to-RoundFToTF32INTEL.patch +0030-Backport-to-15-Preserve-invalid-SPIRV-source-lang-li.patch +0031-Backport-to-15-Check-for-nullptr-from-getDbgInst-191.patch +0032-DebugInfo-Add-DW_ATE_complex_float-translation-1946.patch +0033-Backport-to-15-DebugInfo-Handle-null-value-of-DW_TAG.patch +0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch +0035-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch +0036-Backport-to-15-DebugInfo-Add-module-producer-info-fo.patch +0037-NFC-Use-typed-pointers-for-null-function-pointers-de.patch +0038-DebugInfo-Fix-Composite-type-translation-for-NonSema.patch +0039-DebugInfo-Add-Flag-parameter-to-DebugTypeBasic-1965.patch +0040-Backport-to-15-DebugInfo-Support-translation-of-Debu.patch +0041-Backport-to-15-DebugInfo-Add-NonSemantic.Shader.200-.patch +0042-DebugInfo-Translate-inline-namespace-debug-info-1978.patch +0043-DebugInfo-Fix-translation-of-Target-Function-operand.patch +0044-NFC-DebugInfo-Rewrite-NonSemantic-DebugInfoProducer-.patch +0045-DebugInfo-Fix-missing-2nd-operand-for-DebugImportedE.patch +0046-Restore-DebugInfoProducer.ll-test-to-original-state.patch +0047-Backport-to-15-Fix-SPIRV-Friendly-IR-mangling-for-op.patch +0048-Backport-to-15-NFC-Remove-JointMatrixINTEL-W-S-1658.patch +0049-Backport-to-15-Split-JointMatrixMadINTEL-instruction.patch +0050-DebugInfo-Support-translation-of-DebugSourceContinue.patch +0051-DebugInfo-Fix-translation-of-DebugSource-Text-argume.patch +0052-DebugInfo-Translate-checksum-info-inside-DebugSource.patch +0053-DebugInfo-Fix-CU-translation-when-GV-goes-before-CU-.patch +0054-DebugInfo-Support-translation-of-DebugBuildIdentifie.patch +0055-DebugInfo-Fix-DebugTypeVector-Component-Count-2006.patch +0056-DebugInfo-Relax-consumer-checks-for-checksum-info-20.patch +0057-DebugInfo-Add-Flags-operand-for-DebugTypeBasic-for-N.patch +0058-DebugInfo-Adjust-TypeMember-for-NonSemantic-spec-203.patch +0059-Only-generate-BuildIdentifier-if-non-semantic-debug-.patch +0060-Implement-DebugLine-and-DebugNoLine-2012.patch +0061-DebugInfo-Adjust-TypeInheritance-for-NonSemantic-spe.patch +0062-DebugInfo-Add-Column-parameter-to-DebugInlinedAt-ins.patch +0063-DebugInfo-Add-debug-info-for-bitfield-members-1907.patch +0064-Fix-SourceContinued-translation-and-clang-format-tid.patch +0065-Fix-clang-tidy-warnings.patch +0066-Backport-to-15-OpaquePointers-Adjust-builtin-variabl.patch +0067-Adjust-Source-Lang-Literal-logic-to-support-multiple.patch +0068-Support-for-SPV_INTEL_cache_controls-2147.patch +0069-Backport-to-15-Backport-spirv-preserve-auxdata-chang.patch +0070-Backport-to-15-OpaquePointers-Handle-llvm.memset-int.patch +0071-Backport-to-15-Implement-support-for-SPV_KHR_shader_.patch +0072-Backport-to-15-Add-JointMatrixGetElementCoordINTEL-i.patch +0073-Backport-to-15-Fix-SPIR-V-global-to-function-replace.patch +0074-Backport-to-15-Update-LongConstantCompositeINTEL-to-.patch +0075-Preserve-DIExpression-in-DIGlobalVariableExpression-.patch +0076-Backport-to-15-Translate-atomicrmw-fadd-into-AtomicF.patch +0077-Backport-to-15-Translate-atomicrmw-fsub-into-FNegate.patch +0078-Backport-to-15-add-initial-f16-type-support-for-atom.patch +0079-Backport-to-15-SPV-SPV-IR-Fix-image-builtin-mangling.patch +visibility-hidden.patch diff --git a/patches/visibility-hidden.patch b/patches/visibility-hidden.patch new file mode 100644 index 0000000..3cdf890 --- /dev/null +++ b/patches/visibility-hidden.patch @@ -0,0 +1,93 @@ +Author: Andreas Beckmann +Description: reduce the amount of symbols exposed by the library +Forwarded: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1963 + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -117,6 +117,9 @@ if(NOT SPIRV_TOOLS_FOUND) + "--spirv-tools-dis support.") + endif(NOT SPIRV_TOOLS_FOUND) + ++add_compile_options(-fvisibility=hidden) ++add_compile_options($<$:-fvisibility-inlines-hidden>) ++ + add_subdirectory(lib/SPIRV) + add_subdirectory(tools/llvm-spirv) + if(LLVM_SPIRV_INCLUDE_TESTS) +--- a/include/LLVMSPIRVLib.h ++++ b/include/LLVMSPIRVLib.h +@@ -46,6 +46,8 @@ + #include + #include + ++#pragma GCC visibility push(default) ++ + namespace llvm { + // Pass initialization functions need to be declared before inclusion of + // PassSupport.h. +@@ -68,8 +70,12 @@ class ModulePass; + class FunctionPass; + } // namespace llvm + ++#pragma GCC visibility pop ++ + #include "llvm/IR/Module.h" + ++#pragma GCC visibility push(default) ++ + namespace SPIRV { + + class SPIRVModule; +@@ -220,4 +226,6 @@ FunctionPass *createSPIRVLowerBitCastToN + + } // namespace llvm + ++#pragma GCC visibility pop ++ + #endif // SPIRV_H +--- a/include/LLVMSPIRVOpts.h ++++ b/include/LLVMSPIRVOpts.h +@@ -48,6 +48,8 @@ + #include + #include + ++#pragma GCC visibility push(default) ++ + namespace llvm { + class IntrinsicInst; + } // namespace llvm +@@ -245,4 +247,6 @@ private: + + } // namespace SPIRV + ++#pragma GCC visibility pop ++ + #endif // SPIRV_LLVMSPIRVOPTS_H +--- a/lib/SPIRV/libSPIRV/SPIRVStream.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVStream.cpp +@@ -82,6 +82,7 @@ static void readQuotedString(std::istrea + } + + #ifdef _SPIRV_SUPPORT_TEXT_FMT ++__attribute__ ((visibility ("default"))) + bool SPIRVUseTextFormat = false; + #endif + +--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp ++++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp +@@ -2260,6 +2260,7 @@ bool isSpirvBinary(const std::string &Im + + #ifdef _SPIRV_SUPPORT_TEXT_FMT + ++__attribute__ ((visibility ("default"))) + bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg, + bool FromText, bool ToText) { + auto SaveOpt = SPIRVUseTextFormat; +@@ -2296,6 +2297,7 @@ bool isSpirvText(const std::string &Img) + return Magic == MagicNumber; + } + ++__attribute__ ((visibility ("default"))) + bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg, + bool ToText) { + auto FromText = isSpirvText(Input); diff --git a/rules b/rules new file mode 100755 index 0000000..2f93c59 --- /dev/null +++ b/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f + +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +include /usr/share/dpkg/pkg-info.mk + +LLVM_VERSION = $(shell sed -n -r '/^Build/,/^$$/s/.*llvm-([0-9]+)-dev.*/\1/p' debian/control) + +%: + dh $@ --builddir build/ + +override_dh_auto_configure: + dh_auto_configure -- \ + -DCMAKE_SKIP_RPATH=ON \ + -DLLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR=/usr/include \ + -DBUILD_SHARED_LIBS=ON \ + -DLLVM_SPIRV_INCLUDE_TESTS=ON \ + -DLLVM_EXTERNAL_LIT=/usr/lib/llvm-$(LLVM_VERSION)/build/utils/lit/lit.py \ + -Wno-dev + +execute_after_dh_auto_install: + mv debian/tmp/usr/bin/llvm-spirv debian/tmp/usr/bin/llvm-spirv-$(LLVM_VERSION) + +ignore_test_failures = $(if $(filter $(DEB_HOST_ARCH),amd64),,-) +override_dh_auto_test: + $(ignore_test_failures)env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CURDIR)/build/lib/SPIRV dh_auto_test + + +update-symbols: + pkgkde-getbuildlogs + echo "pkgkde-symbolshelper batchpatch -v $(DEB_VERSION_EPOCH_UPSTREAM) $(DEB_SOURCE)_$(DEB_DISTRIBUTION)_logs/$(DEB_SOURCE)_$(DEB_VERSION)_*build" + + +ifneq (,$(wildcard .git)) +upstream: + git remote show $@ >/dev/null 2>&1 || git remote add $@ $(shell sed -rn 's/Repository: //p' debian/upstream/metadata) + git fetch $@ --prune +endif diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/source/lintian-overrides b/source/lintian-overrides new file mode 100644 index 0000000..588425c --- /dev/null +++ b/source/lintian-overrides @@ -0,0 +1,6 @@ +spelling-error-in-patch-description * * [debian/patches/*.patch] +very-long-line-length-in-source-file * > 512 [debian/patches/*.patch:*] + +# test data +very-long-line-length-in-source-file * > 512 [test/*.cl:*] +very-long-line-length-in-source-file * > 512 [test/*.ll:*] diff --git a/tests/control b/tests/control new file mode 100644 index 0000000..10142ea --- /dev/null +++ b/tests/control @@ -0,0 +1,40 @@ +Tests: upstream-testsuite +Architecture: amd64 +Depends: + @, + cmake, + g++, + make, + pkgconf, + spirv-headers, + spirv-tools, + clang-15, + llvm-15-dev, +Restrictions: + allow-stderr, + +Test-Command: debian/tests/upstream-testsuite +Features: test-name=upstream-testsuite-flaky +Architecture: !amd64 +Depends: + @, + cmake, + g++, + make, + pkgconf, + spirv-headers, + spirv-tools, + clang-15, + llvm-15-dev, +Restrictions: + allow-stderr, + flaky, + +Test-Command: true +Features: test-name=spirv-headers-compatibility +Depends: + spirv-headers, +Restrictions: + build-needed, + allow-stderr, + superficial, diff --git a/tests/upstream-testsuite b/tests/upstream-testsuite new file mode 100755 index 0000000..53f8d2f --- /dev/null +++ b/tests/upstream-testsuite @@ -0,0 +1,18 @@ +#!/bin/sh +set -e -u -x +LLVM_VERSION=$(sed -n -r '/^Build/,/^$/s/.*llvm-([0-9]+)-dev.*/\1/p' debian/control) +cp -a . "$AUTOPKGTEST_TMP" +cd "$AUTOPKGTEST_TMP" +mkdir build-tests +cd build-tests +cmake \ + -DLLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR=/usr/include \ + -DLLVM_SPIRV_INCLUDE_TESTS=ON \ + -DLLVM_EXTERNAL_LIT=/usr/lib/llvm-${LLVM_VERSION}/build/utils/lit/lit.py \ + -Wno-dev \ + .. +make --touch +rm -f tools/llvm-spirv/llvm-spirv +cp /usr/bin/llvm-spirv-${LLVM_VERSION} tools/llvm-spirv/llvm-spirv +make -C test clean +make test diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..1c0018d --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,4 @@ +Bug-Database: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues +Bug-Submit: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/new +Repository: https://github.com/KhronosGroup/SPIRV-LLVM-Translator.git +Repository-Browse: https://github.com/KhronosGroup/SPIRV-LLVM-Translator diff --git a/watch b/watch new file mode 100644 index 0000000..09845d7 --- /dev/null +++ b/watch @@ -0,0 +1,5 @@ +version=4 + +opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%spirv-llvm-translator-$1.tar.gz%" \ + https://github.com/KhronosGroup/SPIRV-LLVM-Translator/tags \ + (?:.*?/)?v?(15\.[\d.]*)\.tar\.gz