Merge llvm-project release/21.x llvmorg-21.1.7-0-gcd708029e0b2
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvm-project release/21.x llvmorg-21.1.7-0-gcd708029e0b2, a.k.a. 21.1.7 release. PR: 292067 MFC after: 1 month
This commit is contained in:
@@ -469,6 +469,31 @@ OLD_FILES+=usr/lib/clang/19/share/msan_ignorelist.txt
|
||||
OLD_DIRS+=usr/lib/clang/19/share
|
||||
OLD_DIRS+=usr/lib/clang/19
|
||||
|
||||
# 20260425: new libc++ import which bumps version from 19 to 21
|
||||
OLD_FILES+=usr/include/c++/v1/__algorithm/fold.h
|
||||
OLD_FILES+=usr/include/c++/v1/__atomic/atomic_base.h
|
||||
OLD_FILES+=usr/include/c++/v1/__atomic/cxx_atomic_impl.h
|
||||
OLD_FILES+=usr/include/c++/v1/__locale_dir/locale_base_api/bsd_locale_defaults.h
|
||||
OLD_FILES+=usr/include/c++/v1/__locale_dir/locale_base_api/locale_guard.h
|
||||
OLD_FILES+=usr/include/c++/v1/__memory/builtin_new_allocator.h
|
||||
OLD_FILES+=usr/include/c++/v1/__memory/voidify.h
|
||||
OLD_FILES+=usr/include/c++/v1/__std_clang_module
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/add_const.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/add_cv.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/add_lvalue_reference.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/add_rvalue_reference.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/add_volatile.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_member_function_pointer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_member_object_pointer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_nothrow_convertible.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_scoped_enum.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_signed_integer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/is_unsigned_integer.h
|
||||
OLD_FILES+=usr/include/c++/v1/__type_traits/noexcept_move_assign_container.h
|
||||
OLD_FILES+=usr/include/c++/v1/experimental/__config
|
||||
OLD_FILES+=usr/include/c++/v1/locale.h
|
||||
OLD_FILES+=usr/include/c++/v1/stdint.h
|
||||
|
||||
# 20260420: remove perfmon
|
||||
OLD_FILES+=boot/kernel/perfmon.ko
|
||||
OLD_FILES+=usr/share/man/man4/perfmon.4.gz
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.ci/
|
||||
.clang-format
|
||||
.clang-format-ignore
|
||||
.clang-tidy
|
||||
.git-blame-ignore-revs
|
||||
.gitattributes
|
||||
@@ -15,11 +16,12 @@ bolt/
|
||||
clang/.clang-format
|
||||
clang/.clang-tidy
|
||||
clang/.gitignore
|
||||
clang/AreaTeamMembers.txt
|
||||
clang/CMakeLists.txt
|
||||
clang/CodeOwners.rst
|
||||
clang/INSTALL.txt
|
||||
clang/Maintainers.rst
|
||||
clang/NOTES.txt
|
||||
clang/README.txt
|
||||
clang/README.md
|
||||
clang/bindings/
|
||||
clang/cmake/
|
||||
clang/docs/
|
||||
@@ -29,9 +31,12 @@ clang/include/clang/AST/CMakeLists.txt
|
||||
clang/include/clang/Basic/CMakeLists.txt
|
||||
clang/include/clang/Basic/Target/
|
||||
clang/include/clang/Basic/Version.inc.in
|
||||
clang/include/clang/CIR/.clang-tidy
|
||||
clang/include/clang/CIR/CMakeLists.txt
|
||||
clang/include/clang/CIR/Dialect/CMakeLists.txt
|
||||
clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
|
||||
clang/include/clang/CIR/FrontendAction/.clang-tidy
|
||||
clang/include/clang/CIR/Interfaces/CMakeLists.txt
|
||||
clang/include/clang/CMakeLists.txt
|
||||
clang/include/clang/Config/
|
||||
clang/include/clang/Driver/CMakeLists.txt
|
||||
@@ -42,7 +47,6 @@ clang/include/clang/Serialization/CMakeLists.txt
|
||||
clang/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt
|
||||
clang/include/clang/Tooling/Syntax/CMakeLists.txt
|
||||
clang/lib/APINotes/CMakeLists.txt
|
||||
clang/lib/ARCMigrate/CMakeLists.txt
|
||||
clang/lib/AST/CMakeLists.txt
|
||||
clang/lib/ASTMatchers/CMakeLists.txt
|
||||
clang/lib/ASTMatchers/Dynamic/CMakeLists.txt
|
||||
@@ -54,9 +58,18 @@ clang/lib/Analysis/plugins/CheckerDependencyHandling/CMakeLists.txt
|
||||
clang/lib/Analysis/plugins/CheckerOptionHandling/CMakeLists.txt
|
||||
clang/lib/Analysis/plugins/SampleAnalyzer/CMakeLists.txt
|
||||
clang/lib/Basic/CMakeLists.txt
|
||||
clang/lib/CIR/.clang-tidy
|
||||
clang/lib/CIR/CMakeLists.txt
|
||||
clang/lib/CIR/CodeGen/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/IR/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
|
||||
clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
|
||||
clang/lib/CIR/FrontendAction/.clang-tidy
|
||||
clang/lib/CIR/FrontendAction/CMakeLists.txt
|
||||
clang/lib/CIR/Interfaces/CMakeLists.txt
|
||||
clang/lib/CIR/Lowering/CMakeLists.txt
|
||||
clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
|
||||
clang/lib/CMakeLists.txt
|
||||
clang/lib/CodeGen/CMakeLists.txt
|
||||
clang/lib/CodeGen/README.txt
|
||||
@@ -99,11 +112,11 @@ clang/lib/Tooling/Transformer/CMakeLists.txt
|
||||
clang/runtime/
|
||||
clang/test/
|
||||
clang/tools/CMakeLists.txt
|
||||
clang/tools/amdgpu-arch/
|
||||
clang/tools/apinotes-test/
|
||||
clang/tools/arcmt-test/
|
||||
clang/tools/c-arcmt-test/
|
||||
clang/tools/c-index-test/
|
||||
clang/tools/cir-lsp-server/
|
||||
clang/tools/cir-opt/
|
||||
clang/tools/cir-translate/
|
||||
clang/tools/clang-check/
|
||||
clang/tools/clang-diff/
|
||||
clang/tools/clang-extdef-mapping/
|
||||
@@ -118,7 +131,6 @@ clang/tools/clang-format/clang-format.py
|
||||
clang/tools/clang-format/fuzzer/
|
||||
clang/tools/clang-format/git-clang-format
|
||||
clang/tools/clang-format/git-clang-format.bat
|
||||
clang/tools/clang-format-vs/
|
||||
clang/tools/clang-fuzzer/
|
||||
clang/tools/clang-import-test/
|
||||
clang/tools/clang-installapi/
|
||||
@@ -127,17 +139,17 @@ clang/tools/clang-nvlink-wrapper/
|
||||
clang/tools/clang-offload-bundler/
|
||||
clang/tools/clang-offload-packager/
|
||||
clang/tools/clang-refactor/
|
||||
clang/tools/clang-rename/
|
||||
clang/tools/clang-repl/
|
||||
clang/tools/clang-scan-deps/CMakeLists.txt
|
||||
clang/tools/clang-shlib/
|
||||
clang/tools/clang-sycl-linker/
|
||||
clang/tools/diag-build/
|
||||
clang/tools/diagtool/
|
||||
clang/tools/driver/CMakeLists.txt
|
||||
clang/tools/driver/Info.plist.in
|
||||
clang/tools/include-mapping/
|
||||
clang/tools/libclang/
|
||||
clang/tools/nvptx-arch/
|
||||
clang/tools/offload-arch/
|
||||
clang/tools/scan-build/
|
||||
clang/tools/scan-build-py/
|
||||
clang/tools/scan-view/
|
||||
@@ -160,21 +172,22 @@ clang/utils/bundle_resources.py
|
||||
clang/utils/check_cfc/
|
||||
clang/utils/clangdiag.py
|
||||
clang/utils/convert_arm_neon.py
|
||||
clang/utils/creduce-clang-crash.py
|
||||
clang/utils/find-unused-diagnostics.sh
|
||||
clang/utils/hmaptool/
|
||||
clang/utils/make-ast-dump-check.sh
|
||||
clang/utils/modfuzz.py
|
||||
clang/utils/module-deps-to-rsp.py
|
||||
clang/utils/perf-training/
|
||||
clang/utils/reduce-clang-crash.py
|
||||
clang/utils/token-delta.py
|
||||
clang/utils/valgrind/
|
||||
clang/www/
|
||||
clang-tools-extra/
|
||||
cmake/
|
||||
compiler-rt/.clang-tidy
|
||||
compiler-rt/.gitignore
|
||||
compiler-rt/CMakeLists.txt
|
||||
compiler-rt/CODE_OWNERS.TXT
|
||||
compiler-rt/Maintainers.md
|
||||
compiler-rt/cmake/
|
||||
compiler-rt/docs/
|
||||
compiler-rt/include/CMakeLists.txt
|
||||
@@ -233,7 +246,6 @@ compiler-rt/lib/sanitizer_common/scripts/
|
||||
compiler-rt/lib/sanitizer_common/symbolizer/CMakeLists.txt
|
||||
compiler-rt/lib/sanitizer_common/tests/
|
||||
compiler-rt/lib/scudo/standalone/CMakeLists.txt
|
||||
compiler-rt/lib/scudo/standalone/benchmarks/
|
||||
compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt
|
||||
compiler-rt/lib/scudo/standalone/tests/
|
||||
compiler-rt/lib/scudo/standalone/tools/
|
||||
@@ -248,6 +260,9 @@ compiler-rt/lib/tsan/go/build.bat
|
||||
compiler-rt/lib/tsan/go/buildgo.sh
|
||||
compiler-rt/lib/tsan/rtl/CMakeLists.txt
|
||||
compiler-rt/lib/tsan/tests/
|
||||
compiler-rt/lib/tysan/CMakeLists.txt
|
||||
compiler-rt/lib/tysan/lit.cfg
|
||||
compiler-rt/lib/tysan/lit.site.cfg.in
|
||||
compiler-rt/lib/ubsan/CMakeLists.txt
|
||||
compiler-rt/lib/ubsan_minimal/CMakeLists.txt
|
||||
compiler-rt/lib/xray/CMakeLists.txt
|
||||
@@ -259,16 +274,229 @@ compiler-rt/utils/
|
||||
compiler-rt/www/
|
||||
cross-project-tests/
|
||||
flang/
|
||||
libc/
|
||||
flang-rt/
|
||||
libc/.clang-tidy
|
||||
libc/.gitignore
|
||||
libc/AOR_v20.02/
|
||||
libc/CMakeLists.txt
|
||||
libc/LICENSE.TXT
|
||||
libc/Maintainers.rst
|
||||
libc/README.txt
|
||||
libc/benchmarks/
|
||||
libc/cmake/
|
||||
libc/config/
|
||||
libc/docs/
|
||||
libc/examples/
|
||||
libc/fuzzing/
|
||||
libc/hdr/CMakeLists.txt
|
||||
libc/hdr/func/CMakeLists.txt
|
||||
libc/hdr/types/CMakeLists.txt
|
||||
libc/include/CMakeLists.txt
|
||||
libc/include/Uefi.yaml
|
||||
libc/include/arpa/
|
||||
libc/include/assert.h.def
|
||||
libc/include/assert.yaml
|
||||
libc/include/complex.h.def
|
||||
libc/include/complex.yaml
|
||||
libc/include/ctype.yaml
|
||||
libc/include/dirent.h.def
|
||||
libc/include/dirent.yaml
|
||||
libc/include/dlfcn.h.def
|
||||
libc/include/dlfcn.yaml
|
||||
libc/include/elf.h.def
|
||||
libc/include/elf.yaml
|
||||
libc/include/endian.h.def
|
||||
libc/include/endian.yaml
|
||||
libc/include/errno.h.def
|
||||
libc/include/errno.yaml
|
||||
libc/include/fcntl.h.def
|
||||
libc/include/fcntl.yaml
|
||||
libc/include/features.h.def
|
||||
libc/include/features.yaml
|
||||
libc/include/fenv.yaml
|
||||
libc/include/float.h.def
|
||||
libc/include/float.yaml
|
||||
libc/include/inttypes.h.def
|
||||
libc/include/inttypes.yaml
|
||||
libc/include/limits.h.def
|
||||
libc/include/limits.yaml
|
||||
libc/include/link.yaml
|
||||
libc/include/llvm-libc-macros/CMakeLists.txt
|
||||
libc/include/llvm-libc-macros/baremetal/CMakeLists.txt
|
||||
libc/include/llvm-libc-macros/gpu/CMakeLists.txt
|
||||
libc/include/llvm-libc-macros/linux/CMakeLists.txt
|
||||
libc/include/llvm-libc-macros/windows/CMakeLists.txt
|
||||
libc/include/llvm-libc-types/CMakeLists.txt
|
||||
libc/include/locale.h.def
|
||||
libc/include/locale.yaml
|
||||
libc/include/malloc.yaml
|
||||
libc/include/math.h.def
|
||||
libc/include/math.yaml
|
||||
libc/include/poll.h.def
|
||||
libc/include/poll.yaml
|
||||
libc/include/pthread.h.def
|
||||
libc/include/pthread.yaml
|
||||
libc/include/sched.h.def
|
||||
libc/include/sched.yaml
|
||||
libc/include/search.h.def
|
||||
libc/include/search.yaml
|
||||
libc/include/setjmp.h.def
|
||||
libc/include/setjmp.yaml
|
||||
libc/include/signal.h.def
|
||||
libc/include/signal.yaml
|
||||
libc/include/spawn.h.def
|
||||
libc/include/spawn.yaml
|
||||
libc/include/stdbit.h.def
|
||||
libc/include/stdbit.yaml
|
||||
libc/include/stdckdint.h.def
|
||||
libc/include/stdckdint.yaml
|
||||
libc/include/stdfix.h.def
|
||||
libc/include/stdfix.yaml
|
||||
libc/include/stdint.h.def
|
||||
libc/include/stdint.yaml
|
||||
libc/include/stdio.h.def
|
||||
libc/include/stdio.yaml
|
||||
libc/include/stdlib-malloc.yaml
|
||||
libc/include/stdlib.h.def
|
||||
libc/include/stdlib.yaml
|
||||
libc/include/string.h.def
|
||||
libc/include/string.yaml
|
||||
libc/include/strings.h.def
|
||||
libc/include/strings.yaml
|
||||
libc/include/sys/auxv.h.def
|
||||
libc/include/sys/auxv.yaml
|
||||
libc/include/sys/epoll.h.def
|
||||
libc/include/sys/epoll.yaml
|
||||
libc/include/sys/ioctl.h.def
|
||||
libc/include/sys/ioctl.yaml
|
||||
libc/include/sys/mman.h.def
|
||||
libc/include/sys/mman.yaml
|
||||
libc/include/sys/prctl.h.def
|
||||
libc/include/sys/prctl.yaml
|
||||
libc/include/sys/random.h.def
|
||||
libc/include/sys/random.yaml
|
||||
libc/include/sys/resource.h.def
|
||||
libc/include/sys/resource.yaml
|
||||
libc/include/sys/select.h.def
|
||||
libc/include/sys/select.yaml
|
||||
libc/include/sys/sendfile.h.def
|
||||
libc/include/sys/sendfile.yaml
|
||||
libc/include/sys/socket.h.def
|
||||
libc/include/sys/socket.yaml
|
||||
libc/include/sys/stat.h.def
|
||||
libc/include/sys/stat.yaml
|
||||
libc/include/sys/statvfs.h.def
|
||||
libc/include/sys/statvfs.yaml
|
||||
libc/include/sys/syscall.h.def
|
||||
libc/include/sys/syscall.yaml
|
||||
libc/include/sys/time.h.def
|
||||
libc/include/sys/time.yaml
|
||||
libc/include/sys/types.h.def
|
||||
libc/include/sys/types.yaml
|
||||
libc/include/sys/uio.h.def
|
||||
libc/include/sys/uio.yaml
|
||||
libc/include/sys/utsname.h.def
|
||||
libc/include/sys/utsname.yaml
|
||||
libc/include/sys/wait.h.def
|
||||
libc/include/sys/wait.yaml
|
||||
libc/include/sysexits.h.def
|
||||
libc/include/sysexits.yaml
|
||||
libc/include/termios.h.def
|
||||
libc/include/termios.yaml
|
||||
libc/include/threads.h.def
|
||||
libc/include/threads.yaml
|
||||
libc/include/time.h.def
|
||||
libc/include/time.yaml
|
||||
libc/include/uchar.h.def
|
||||
libc/include/uchar.yaml
|
||||
libc/include/unistd.h.def
|
||||
libc/include/unistd.yaml
|
||||
libc/include/wchar.h.def
|
||||
libc/include/wchar.yaml
|
||||
libc/lib/
|
||||
libc/src/.clang-tidy
|
||||
libc/src/CMakeLists.txt
|
||||
libc/src/__support/CMakeLists.txt
|
||||
libc/src/__support/CPP/.clang-tidy
|
||||
libc/src/__support/CPP/CMakeLists.txt
|
||||
libc/src/__support/FPUtil/CMakeLists.txt
|
||||
libc/src/__support/FPUtil/generic/CMakeLists.txt
|
||||
libc/src/__support/File/CMakeLists.txt
|
||||
libc/src/__support/File/linux/CMakeLists.txt
|
||||
libc/src/__support/GPU/CMakeLists.txt
|
||||
libc/src/__support/HashTable/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/baremetal/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/darwin/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/darwin/aarch64/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/gpu/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/aarch64/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/arm/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/i386/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/riscv/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/uefi/CMakeLists.txt
|
||||
libc/src/__support/OSUtil/windows/CMakeLists.txt
|
||||
libc/src/__support/RPC/CMakeLists.txt
|
||||
libc/src/__support/StringUtil/CMakeLists.txt
|
||||
libc/src/__support/StringUtil/tables/CMakeLists.txt
|
||||
libc/src/__support/fixed_point/CMakeLists.txt
|
||||
libc/src/__support/macros/CMakeLists.txt
|
||||
libc/src/__support/macros/properties/CMakeLists.txt
|
||||
libc/src/__support/math/CMakeLists.txt
|
||||
libc/src/__support/threads/CMakeLists.txt
|
||||
libc/src/__support/threads/gpu/CMakeLists.txt
|
||||
libc/src/__support/threads/linux/CMakeLists.txt
|
||||
libc/src/__support/time/CMakeLists.txt
|
||||
libc/src/__support/time/gpu/CMakeLists.txt
|
||||
libc/src/__support/time/linux/CMakeLists.txt
|
||||
libc/src/__support/time/windows/CMakeLists.txt
|
||||
libc/src/__support/wchar/CMakeLists.txt
|
||||
libc/src/arpa/
|
||||
libc/src/assert/
|
||||
libc/src/compiler/
|
||||
libc/src/complex/
|
||||
libc/src/ctype/
|
||||
libc/src/dirent/
|
||||
libc/src/dlfcn/
|
||||
libc/src/errno/
|
||||
libc/src/fcntl/
|
||||
libc/src/fenv/
|
||||
libc/src/inttypes/
|
||||
libc/src/link/
|
||||
libc/src/locale/
|
||||
libc/src/math/
|
||||
libc/src/poll/
|
||||
libc/src/pthread/
|
||||
libc/src/sched/
|
||||
libc/src/search/
|
||||
libc/src/setjmp/
|
||||
libc/src/signal/
|
||||
libc/src/spawn/
|
||||
libc/src/stdbit/
|
||||
libc/src/stdckdint/
|
||||
libc/src/stdfix/
|
||||
libc/src/stdio/
|
||||
libc/src/stdlib/
|
||||
libc/src/string/
|
||||
libc/src/strings/
|
||||
libc/src/sys/
|
||||
libc/src/termios/
|
||||
libc/src/threads/
|
||||
libc/src/time/
|
||||
libc/src/unistd/
|
||||
libc/src/wchar/
|
||||
libc/startup/
|
||||
libc/test/
|
||||
libc/utils/
|
||||
libclc/
|
||||
libcxx/.clang-format
|
||||
libcxx/.clang-tidy
|
||||
libcxx/.gitignore
|
||||
libcxx/CMakeLists.txt
|
||||
libcxx/Maintainers.md
|
||||
libcxx/TODO.TXT
|
||||
libcxx/appveyor-reqs-install.cmd
|
||||
libcxx/appveyor.yml
|
||||
libcxx/benchmarks/
|
||||
libcxx/cmake/
|
||||
libcxx/docs/
|
||||
libcxx/include/CMakeLists.txt
|
||||
@@ -278,6 +506,7 @@ libcxx/lib/
|
||||
libcxx/modules/CMakeLists.txt
|
||||
libcxx/modules/CMakeLists.txt.in
|
||||
libcxx/modules/README.md
|
||||
libcxx/src/.clang-tidy
|
||||
libcxx/src/CMakeLists.txt
|
||||
libcxx/src/support/win32/
|
||||
libcxx/test/
|
||||
@@ -290,11 +519,14 @@ libunwind/docs/
|
||||
libunwind/include/CMakeLists.txt
|
||||
libunwind/src/CMakeLists.txt
|
||||
libunwind/test/
|
||||
lld/.clang-tidy
|
||||
lld/.gitignore
|
||||
lld/CMakeLists.txt
|
||||
lld/COFF/CMakeLists.txt
|
||||
lld/Common/CMakeLists.txt
|
||||
lld/ELF/CMakeLists.txt
|
||||
lld/MachO/CMakeLists.txt
|
||||
lld/Maintainers.md
|
||||
lld/MinGW/
|
||||
lld/cmake/
|
||||
lld/docs/CMakeLists.txt
|
||||
@@ -307,7 +539,7 @@ lldb/.clang-format
|
||||
lldb/.clang-tidy
|
||||
lldb/.gitignore
|
||||
lldb/CMakeLists.txt
|
||||
lldb/CodeOwners.rst
|
||||
lldb/Maintainers.md
|
||||
lldb/bindings/CMakeLists.txt
|
||||
lldb/bindings/lua/CMakeLists.txt
|
||||
lldb/bindings/python/CMakeLists.txt
|
||||
@@ -315,6 +547,8 @@ lldb/bindings/python/get-python-config.py
|
||||
lldb/cmake/
|
||||
lldb/docs/.htaccess
|
||||
lldb/docs/CMakeLists.txt
|
||||
lldb/docs/_lldb/
|
||||
lldb/docs/_templates/
|
||||
lldb/docs/conf.py
|
||||
lldb/docs/doxygen-mainpage.dox
|
||||
lldb/docs/doxygen.cfg.in
|
||||
@@ -344,11 +578,13 @@ lldb/source/Host/macosx/
|
||||
lldb/source/Host/windows/
|
||||
lldb/source/Initialization/CMakeLists.txt
|
||||
lldb/source/Interpreter/CMakeLists.txt
|
||||
lldb/source/Interpreter/Interfaces/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/AArch64/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/ARC/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/ARM/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/Hexagon/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/LoongArch/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/MSP430/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/Mips/CMakeLists.txt
|
||||
lldb/source/Plugins/ABI/PowerPC/CMakeLists.txt
|
||||
@@ -418,9 +654,11 @@ lldb/source/Plugins/ObjectFile/Minidump/CMakeLists.txt
|
||||
lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
|
||||
lldb/source/Plugins/ObjectFile/PECOFF/
|
||||
lldb/source/Plugins/ObjectFile/Placeholder/CMakeLists.txt
|
||||
lldb/source/Plugins/ObjectFile/XCOFF/CMakeLists.txt
|
||||
lldb/source/Plugins/ObjectFile/wasm/CMakeLists.txt
|
||||
lldb/source/Plugins/OperatingSystem/CMakeLists.txt
|
||||
lldb/source/Plugins/OperatingSystem/Python/CMakeLists.txt
|
||||
lldb/source/Plugins/Platform/AIX/CMakeLists.txt
|
||||
lldb/source/Plugins/Platform/Android/
|
||||
lldb/source/Plugins/Platform/CMakeLists.txt
|
||||
lldb/source/Plugins/Platform/FreeBSD/CMakeLists.txt
|
||||
@@ -432,6 +670,7 @@ lldb/source/Plugins/Platform/POSIX/CMakeLists.txt
|
||||
lldb/source/Plugins/Platform/QemuUser/CMakeLists.txt
|
||||
lldb/source/Plugins/Platform/Windows/
|
||||
lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/AIX/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt
|
||||
@@ -446,6 +685,8 @@ lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/mach-core/
|
||||
lldb/source/Plugins/Process/minidump/CMakeLists.txt
|
||||
lldb/source/Plugins/Process/scripted/CMakeLists.txt
|
||||
lldb/source/Plugins/Protocol/CMakeLists.txt
|
||||
lldb/source/Plugins/Protocol/MCP/CMakeLists.txt
|
||||
lldb/source/Plugins/REPL/CMakeLists.txt
|
||||
lldb/source/Plugins/REPL/Clang/CMakeLists.txt
|
||||
lldb/source/Plugins/RegisterTypeBuilder/CMakeLists.txt
|
||||
@@ -488,6 +729,7 @@ lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt
|
||||
lldb/source/Symbol/CMakeLists.txt
|
||||
lldb/source/Target/CMakeLists.txt
|
||||
lldb/source/Utility/CMakeLists.txt
|
||||
lldb/source/ValueObject/CMakeLists.txt
|
||||
lldb/source/Version/CMakeLists.txt
|
||||
lldb/test/
|
||||
lldb/tools/CMakeLists.txt
|
||||
@@ -503,22 +745,20 @@ lldb/tools/lldb-fuzzer/
|
||||
lldb/tools/lldb-instr/CMakeLists.txt
|
||||
lldb/tools/lldb-server/CMakeLists.txt
|
||||
lldb/tools/lldb-test/
|
||||
lldb/tools/lldb-vscode
|
||||
lldb/unittests/
|
||||
lldb/use_lldb_suite_root.py
|
||||
lldb/utils/CMakeLists.txt
|
||||
lldb/utils/TableGen/CMakeLists.txt
|
||||
lldb/utils/lit-cpuid/
|
||||
lldb/utils/lldb-dotest/
|
||||
lldb/utils/lldb-repro/
|
||||
lldb/utils/lui/
|
||||
llvm/.clang-format
|
||||
llvm/.clang-tidy
|
||||
llvm/.gitattributes
|
||||
llvm/.gitignore
|
||||
llvm/CMakeLists.txt
|
||||
llvm/CODE_OWNERS.TXT
|
||||
llvm/CREDITS.TXT
|
||||
llvm/Maintainers.md
|
||||
llvm/README.txt
|
||||
llvm/RELEASE_TESTERS.TXT
|
||||
llvm/benchmarks/
|
||||
@@ -547,6 +787,7 @@ llvm/lib/Bitcode/Reader/CMakeLists.txt
|
||||
llvm/lib/Bitcode/Writer/CMakeLists.txt
|
||||
llvm/lib/Bitstream/CMakeLists.txt
|
||||
llvm/lib/Bitstream/Reader/CMakeLists.txt
|
||||
llvm/lib/CGData/CMakeLists.txt
|
||||
llvm/lib/CMakeLists.txt
|
||||
llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
|
||||
llvm/lib/CodeGen/CMakeLists.txt
|
||||
@@ -554,8 +795,8 @@ llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
|
||||
llvm/lib/CodeGen/MIRParser/CMakeLists.txt
|
||||
llvm/lib/CodeGen/README.txt
|
||||
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
|
||||
llvm/lib/CodeGenData/CMakeLists.txt
|
||||
llvm/lib/CodeGenTypes/CMakeLists.txt
|
||||
llvm/lib/DWARFCFIChecker/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/Classic/CMakeLists.txt
|
||||
llvm/lib/DWARFLinker/Parallel/CMakeLists.txt
|
||||
@@ -564,6 +805,7 @@ llvm/lib/DebugInfo/BTF/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/CodeView/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/DWARF/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/GSYM/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/LogicalView/CMakeLists.txt
|
||||
llvm/lib/DebugInfo/MSF/CMakeLists.txt
|
||||
@@ -586,7 +828,9 @@ llvm/lib/ExecutionEngine/PerfJITEvents/CMakeLists.txt
|
||||
llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
|
||||
llvm/lib/Extensions/
|
||||
llvm/lib/FileCheck/CMakeLists.txt
|
||||
llvm/lib/Frontend/Atomic/CMakeLists.txt
|
||||
llvm/lib/Frontend/CMakeLists.txt
|
||||
llvm/lib/Frontend/Directive/CMakeLists.txt
|
||||
llvm/lib/Frontend/Driver/CMakeLists.txt
|
||||
llvm/lib/Frontend/HLSL/CMakeLists.txt
|
||||
llvm/lib/Frontend/Offloading/CMakeLists.txt
|
||||
@@ -625,7 +869,6 @@ llvm/lib/Target/AArch64/Disassembler/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/TargetInfo/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/Utils/CMakeLists.txt
|
||||
llvm/lib/Target/AArch64/peephole-sxtw.mir
|
||||
llvm/lib/Target/AMDGPU/AsmParser/CMakeLists.txt
|
||||
llvm/lib/Target/AMDGPU/CMakeLists.txt
|
||||
llvm/lib/Target/AMDGPU/Disassembler/CMakeLists.txt
|
||||
@@ -762,6 +1005,7 @@ llvm/lib/Target/Xtensa/Disassembler/CMakeLists.txt
|
||||
llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt
|
||||
llvm/lib/Target/Xtensa/TargetInfo/CMakeLists.txt
|
||||
llvm/lib/TargetParser/CMakeLists.txt
|
||||
llvm/lib/Telemetry/CMakeLists.txt
|
||||
llvm/lib/Testing/Annotations/CMakeLists.txt
|
||||
llvm/lib/Testing/CMakeLists.txt
|
||||
llvm/lib/Testing/Support/CMakeLists.txt
|
||||
@@ -805,8 +1049,10 @@ llvm/tools/llvm-bcanalyzer/CMakeLists.txt
|
||||
llvm/tools/llvm-c-test/
|
||||
llvm/tools/llvm-cat/
|
||||
llvm/tools/llvm-cfi-verify/
|
||||
llvm/tools/llvm-cgdata/
|
||||
llvm/tools/llvm-config/
|
||||
llvm/tools/llvm-cov/CMakeLists.txt
|
||||
llvm/tools/llvm-ctxprof-util/
|
||||
llvm/tools/llvm-cvtres/
|
||||
llvm/tools/llvm-cxxdump/CMakeLists.txt
|
||||
llvm/tools/llvm-cxxfilt/CMakeLists.txt
|
||||
@@ -826,6 +1072,7 @@ llvm/tools/llvm-dwarfutil/CMakeLists.txt
|
||||
llvm/tools/llvm-dwp/CMakeLists.txt
|
||||
llvm/tools/llvm-exegesis/
|
||||
llvm/tools/llvm-extract/CMakeLists.txt
|
||||
llvm/tools/llvm-gpu-loader/
|
||||
llvm/tools/llvm-gsymutil/
|
||||
llvm/tools/llvm-ifs/
|
||||
llvm/tools/llvm-isel-fuzzer/
|
||||
@@ -921,11 +1168,11 @@ llvm/utils/codegen-diff
|
||||
llvm/utils/collect_and_build_with_pgo.py
|
||||
llvm/utils/convert-constraint-log-to-z3.py
|
||||
llvm/utils/count/
|
||||
llvm/utils/count_running_jobs.py
|
||||
llvm/utils/create_ladder_graph.py
|
||||
llvm/utils/crosstool/
|
||||
llvm/utils/demangle_tree.py
|
||||
llvm/utils/docker/
|
||||
llvm/utils/dtlto/
|
||||
llvm/utils/emacs/
|
||||
llvm/utils/extract-section.py
|
||||
llvm/utils/extract_symbols.py
|
||||
@@ -950,7 +1197,9 @@ llvm/utils/llvm-locstats/
|
||||
llvm/utils/llvm-mca-compare.py
|
||||
llvm/utils/llvm-native-gxx
|
||||
llvm/utils/llvm-original-di-preservation.py
|
||||
llvm/utils/llvm-test-mustache-spec/
|
||||
llvm/utils/llvm.grm
|
||||
llvm/utils/merge-json.py
|
||||
llvm/utils/merge-stats.py
|
||||
llvm/utils/mlgo-utils/
|
||||
llvm/utils/not/
|
||||
@@ -970,6 +1219,7 @@ llvm/utils/schedcover.py
|
||||
llvm/utils/shuffle_fuzz.py
|
||||
llvm/utils/shuffle_select_fuzz_tester.py
|
||||
llvm/utils/sort_includes.py
|
||||
llvm/utils/spirv-sim/
|
||||
llvm/utils/split-file/
|
||||
llvm/utils/sysroot.py
|
||||
llvm/utils/testgen/
|
||||
@@ -978,7 +1228,9 @@ llvm/utils/unicode-case-fold.py
|
||||
llvm/utils/update_analyze_test_checks.py
|
||||
llvm/utils/update_any_test_checks.py
|
||||
llvm/utils/update_cc_test_checks.py
|
||||
llvm/utils/update_givaluetracking_test_checks.py
|
||||
llvm/utils/update_llc_test_checks.py
|
||||
llvm/utils/update_mc_test_checks.py
|
||||
llvm/utils/update_mca_test_checks.py
|
||||
llvm/utils/update_mir_test_checks.py
|
||||
llvm/utils/update_test_body.py
|
||||
@@ -994,6 +1246,7 @@ mlir/
|
||||
offload/
|
||||
openmp/.gitignore
|
||||
openmp/CMakeLists.txt
|
||||
openmp/Maintainers.md
|
||||
openmp/README.rst
|
||||
openmp/cmake/
|
||||
openmp/docs/
|
||||
@@ -1010,8 +1263,9 @@ openmp/runtime/test/
|
||||
openmp/runtime/tools/
|
||||
openmp/tools/
|
||||
polly/
|
||||
pstl/
|
||||
pyproject.toml
|
||||
runtimes/
|
||||
third-party/
|
||||
third-party/benchmark/
|
||||
third-party/unittest/
|
||||
third-party/update_benchmark.sh
|
||||
utils/
|
||||
|
||||
@@ -6953,6 +6953,21 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor);
|
||||
* @}
|
||||
*/
|
||||
|
||||
CINDEX_DEPRECATED
|
||||
typedef void *CXRemapping;
|
||||
|
||||
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *);
|
||||
|
||||
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping
|
||||
clang_getRemappingsFromFileList(const char **, unsigned);
|
||||
|
||||
CINDEX_DEPRECATED CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
|
||||
|
||||
CINDEX_DEPRECATED CINDEX_LINKAGE void
|
||||
clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *);
|
||||
|
||||
CINDEX_DEPRECATED CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
|
||||
|
||||
LLVM_CLANG_C_EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
||||
@@ -143,7 +143,7 @@ class APValue {
|
||||
AddrLabelDiff
|
||||
};
|
||||
|
||||
class LValueBase {
|
||||
class alignas(uint64_t) LValueBase {
|
||||
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
|
||||
DynamicAllocLValue>
|
||||
PtrTy;
|
||||
|
||||
@@ -648,8 +648,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
bool containsNonRelocatablePointerAuth(QualType T) {
|
||||
if (!isPointerAuthenticationAvailable())
|
||||
return false;
|
||||
return findPointerAuthContent(T) ==
|
||||
PointerAuthContent::AddressDiscriminatedData;
|
||||
return findPointerAuthContent(T) != PointerAuthContent::None;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -9417,9 +9417,9 @@ def NonStringDocs : Documentation {
|
||||
let Category = DocCatDecl;
|
||||
let Content = [{
|
||||
The ``nonstring`` attribute can be applied to the declaration of a variable or
|
||||
a field whose type is a character array to specify that the character array is
|
||||
not intended to behave like a null-terminated string. This will silence
|
||||
diagnostics with code like:
|
||||
a field whose type is a character pointer or character array to specify that
|
||||
the buffer is not intended to behave like a null-terminated string. This will
|
||||
silence diagnostics with code like:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
||||
@@ -507,6 +507,14 @@ def note_odr_number_of_bases : Note<
|
||||
"class has %0 base %plural{1:class|:classes}0">;
|
||||
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
||||
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
||||
def note_odr_incompatible_fixed_underlying_type : Note<
|
||||
"enumeration %0 declared with incompatible fixed underlying types (%1 vs. "
|
||||
"%2)">;
|
||||
def note_odr_fixed_underlying_type : Note<
|
||||
"enumeration %0 has fixed underlying type here">;
|
||||
def note_odr_missing_fixed_underlying_type : Note<
|
||||
"enumeration %0 missing fixed underlying type here">;
|
||||
|
||||
def err_odr_field_type_inconsistent : Error<
|
||||
"field %0 declared with incompatible types in different "
|
||||
"translation units (%1 vs. %2)">;
|
||||
|
||||
@@ -624,6 +624,7 @@ def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
|
||||
def ModuleLock : DiagGroup<"module-lock">;
|
||||
def ModuleBuild : DiagGroup<"module-build">;
|
||||
def ModuleImport : DiagGroup<"module-import">;
|
||||
def ModuleValidation : DiagGroup<"module-validation">;
|
||||
def ModuleConflict : DiagGroup<"module-conflict">;
|
||||
def ModuleFileExtension : DiagGroup<"module-file-extension">;
|
||||
def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">;
|
||||
|
||||
@@ -82,6 +82,10 @@ def remark_module_import : Remark<
|
||||
"importing module '%0'%select{| into '%3'}2 from '%1'">,
|
||||
ShowInSystemHeader,
|
||||
InGroup<ModuleImport>;
|
||||
def remark_module_validation : Remark<
|
||||
"validating %0 input files in module '%1' from '%2'">,
|
||||
ShowInSystemHeader,
|
||||
InGroup<ModuleValidation>;
|
||||
|
||||
def err_imported_module_not_found : Error<
|
||||
"module '%0' in precompiled file '%1' %select{(imported by precompiled file '%2') |}4"
|
||||
|
||||
@@ -147,14 +147,17 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
|
||||
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
|
||||
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
|
||||
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
|
||||
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics)
|
||||
EXTENSION(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics)
|
||||
FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics &&
|
||||
PP.getTargetInfo().getTriple().isOSDarwin())
|
||||
FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics &&
|
||||
PP.getTargetInfo().getTriple().isOSDarwin())
|
||||
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
|
||||
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
|
||||
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
|
||||
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
|
||||
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
|
||||
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
|
||||
FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
|
||||
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
|
||||
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
|
||||
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
|
||||
@@ -163,7 +166,7 @@ FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
|
||||
|
||||
FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa)
|
||||
FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel)
|
||||
FEATURE(ptrauth_objc_signable_class, true)
|
||||
FEATURE(ptrauth_objc_signable_class, LangOpts.PointerAuthIntrinsics)
|
||||
FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls)
|
||||
|
||||
EXTENSION(swiftcc,
|
||||
|
||||
@@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL
|
||||
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
|
||||
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
|
||||
|
||||
LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors")
|
||||
|
||||
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
|
||||
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
|
||||
|
||||
@@ -496,6 +498,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign,
|
||||
|
||||
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
|
||||
|
||||
LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
|
||||
|
||||
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
|
||||
|
||||
#undef LANGOPT
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// Constant discriminator to be used with block descriptor pointers. The value
|
||||
/// is ptrauth_string_discriminator("block_descriptor")
|
||||
constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
|
||||
|
||||
/// Constant discriminator to be used with function pointers in .init_array and
|
||||
/// .fini_array. The value is ptrauth_string_discriminator("init_fini")
|
||||
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
|
||||
@@ -223,6 +227,18 @@ struct PointerAuthOptions {
|
||||
/// The ABI for function addresses in .init_array and .fini_array
|
||||
PointerAuthSchema InitFiniPointers;
|
||||
|
||||
/// The ABI for block invocation function pointers.
|
||||
PointerAuthSchema BlockInvocationFunctionPointers;
|
||||
|
||||
/// The ABI for block object copy/destroy function pointers.
|
||||
PointerAuthSchema BlockHelperFunctionPointers;
|
||||
|
||||
/// The ABI for __block variable copy/destroy function pointers.
|
||||
PointerAuthSchema BlockByrefHelperFunctionPointers;
|
||||
|
||||
/// The ABI for pointers to block descriptors.
|
||||
PointerAuthSchema BlockDescriptorPointers;
|
||||
|
||||
/// The ABI for Objective-C method lists.
|
||||
PointerAuthSchema ObjCMethodListFunctionPointers;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -990,6 +990,13 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
|
||||
Visibility<[ClangOption, CLOption, FlangOption]>,
|
||||
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
|
||||
Group<Link_Group>;
|
||||
def Xthinlto_distributor_EQ : CommaJoined<["-"], "Xthinlto-distributor=">,
|
||||
Flags<[LinkOption]>,
|
||||
Visibility<[ClangOption, CLOption]>,
|
||||
HelpText<"Pass <arg> to the ThinLTO distributor process. Can be specified "
|
||||
"multiple times or with comma-separated values.">,
|
||||
MetaVarName<"<arg>">,
|
||||
Group<Link_Group>;
|
||||
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
|
||||
Visibility<[ClangOption, FlangOption]>,
|
||||
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
|
||||
@@ -1910,6 +1917,14 @@ defm bounds_safety : BoolFOption<
|
||||
BothFlags<[], [CC1Option],
|
||||
" experimental bounds safety extension for C">>;
|
||||
|
||||
defm lifetime_safety : BoolFOption<
|
||||
"experimental-lifetime-safety",
|
||||
LangOpts<"EnableLifetimeSafety">, DefaultFalse,
|
||||
PosFlag<SetTrue, [], [CC1Option], "Enable">,
|
||||
NegFlag<SetFalse, [], [CC1Option], "Disable">,
|
||||
BothFlags<[], [CC1Option],
|
||||
" experimental lifetime safety for C++">>;
|
||||
|
||||
defm addrsig : BoolFOption<"addrsig",
|
||||
CodeGenOpts<"Addrsig">, DefaultFalse,
|
||||
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
|
||||
@@ -4249,7 +4264,12 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
|
||||
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
|
||||
HelpText<"Do not assume that any loop is finite.">,
|
||||
Visibility<[ClangOption, CC1Option]>;
|
||||
|
||||
def fthinlto_distributor_EQ : Joined<["-"], "fthinlto-distributor=">,
|
||||
Group<f_Group>,
|
||||
HelpText<"Path to the ThinLTO distributor process. If specified, "
|
||||
"ThinLTO backend compilations will be distributed by LLD">,
|
||||
MetaVarName<"<path>">,
|
||||
Visibility<[ClangOption, CLOption]>;
|
||||
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
|
||||
HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>;
|
||||
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
|
||||
@@ -4507,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening",
|
||||
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
|
||||
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
|
||||
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
|
||||
defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">;
|
||||
}
|
||||
|
||||
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
|
||||
|
||||
@@ -4694,6 +4694,13 @@ struct FormatStyle {
|
||||
/// <conditional-body> <conditional-body>
|
||||
/// \endcode
|
||||
bool AfterIfMacros;
|
||||
/// If ``true``, put a space between alternative operator ``not`` and the
|
||||
/// opening parenthesis.
|
||||
/// \code
|
||||
/// true: false:
|
||||
/// return not (a || b); vs. return not(a || b);
|
||||
/// \endcode
|
||||
bool AfterNot;
|
||||
/// If ``true``, put a space between operator overloading and opening
|
||||
/// parentheses.
|
||||
/// \code
|
||||
@@ -4742,9 +4749,9 @@ struct FormatStyle {
|
||||
: AfterControlStatements(false), AfterForeachMacros(false),
|
||||
AfterFunctionDeclarationName(false),
|
||||
AfterFunctionDefinitionName(false), AfterIfMacros(false),
|
||||
AfterOverloadedOperator(false), AfterPlacementOperator(true),
|
||||
AfterRequiresInClause(false), AfterRequiresInExpression(false),
|
||||
BeforeNonEmptyParentheses(false) {}
|
||||
AfterNot(false), AfterOverloadedOperator(false),
|
||||
AfterPlacementOperator(true), AfterRequiresInClause(false),
|
||||
AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {}
|
||||
|
||||
bool operator==(const SpaceBeforeParensCustom &Other) const {
|
||||
return AfterControlStatements == Other.AfterControlStatements &&
|
||||
@@ -4753,6 +4760,7 @@ struct FormatStyle {
|
||||
Other.AfterFunctionDeclarationName &&
|
||||
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
|
||||
AfterIfMacros == Other.AfterIfMacros &&
|
||||
AfterNot == Other.AfterNot &&
|
||||
AfterOverloadedOperator == Other.AfterOverloadedOperator &&
|
||||
AfterPlacementOperator == Other.AfterPlacementOperator &&
|
||||
AfterRequiresInClause == Other.AfterRequiresInClause &&
|
||||
|
||||
@@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer {
|
||||
/// True if this is the first time we're lexing the input file.
|
||||
bool IsFirstTimeLexingFile;
|
||||
|
||||
/// True if current lexing token is the first pp-token.
|
||||
bool IsFirstPPToken;
|
||||
|
||||
// NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
|
||||
// it also points to '\n.'
|
||||
const char *NewLinePtr;
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the NoTrivialPPDirectiveTracer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||
#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
||||
namespace clang {
|
||||
class Preprocessor;
|
||||
|
||||
/// Consider the following code:
|
||||
///
|
||||
/// # 1 __FILE__ 1 3
|
||||
/// export module a;
|
||||
///
|
||||
/// According to the wording in
|
||||
/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html):
|
||||
///
|
||||
/// A module directive may only appear as the first preprocessing tokens in a
|
||||
/// file (excluding the global module fragment.)
|
||||
///
|
||||
/// and the wording in
|
||||
/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file):
|
||||
/// module-file:
|
||||
/// pp-global-module-fragment[opt] pp-module group[opt]
|
||||
/// pp-private-module-fragment[opt]
|
||||
///
|
||||
/// `#` is the first pp-token in the translation unit, and it was rejected by
|
||||
/// clang, but they really should be exempted from this rule. The goal is to not
|
||||
/// allow any preprocessor conditionals or most state changes, but these don't
|
||||
/// fit that.
|
||||
///
|
||||
/// State change would mean most semantically observable preprocessor state,
|
||||
/// particularly anything that is order dependent. Global flags like being a
|
||||
/// system header/module shouldn't matter.
|
||||
///
|
||||
/// We should exempt a brunch of directives, even though it violates the current
|
||||
/// standard wording.
|
||||
///
|
||||
/// This class used to trace 'no-trivial' pp-directives in main file, which may
|
||||
/// change the preprocessing state.
|
||||
///
|
||||
/// FIXME: Once the wording of the standard is revised, we need to follow the
|
||||
/// wording of the standard. Currently this is just a workaround
|
||||
class NoTrivialPPDirectiveTracer : public PPCallbacks {
|
||||
Preprocessor &PP;
|
||||
|
||||
/// Whether preprocessing main file. We only focus on the main file.
|
||||
bool InMainFile = true;
|
||||
|
||||
/// Whether one or more conditional, include or other 'no-trivial'
|
||||
/// pp-directives has seen before.
|
||||
bool SeenNoTrivialPPDirective = false;
|
||||
|
||||
void setSeenNoTrivialPPDirective();
|
||||
|
||||
public:
|
||||
NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {}
|
||||
|
||||
bool hasSeenNoTrivialPPDirective() const;
|
||||
|
||||
/// Callback invoked whenever the \p Lexer moves to a different file for
|
||||
/// lexing. Unlike \p FileChanged line number directives and other related
|
||||
/// pragmas do not trigger callbacks to \p LexedFileChanged.
|
||||
///
|
||||
/// \param FID The \p FileID that the \p Lexer moved to.
|
||||
///
|
||||
/// \param Reason Whether the \p Lexer entered a new file or exited one.
|
||||
///
|
||||
/// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
|
||||
/// to.
|
||||
///
|
||||
/// \param PrevFID The \p FileID the \p Lexer was using before the change.
|
||||
///
|
||||
/// \param Loc The location where the \p Lexer entered a new file from or the
|
||||
/// location that the \p Lexer moved into after exiting a file.
|
||||
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
|
||||
SourceLocation Loc) override;
|
||||
|
||||
/// Callback invoked whenever an embed directive has been processed,
|
||||
/// regardless of whether the embed will actually find a file.
|
||||
///
|
||||
/// \param HashLoc The location of the '#' that starts the embed directive.
|
||||
///
|
||||
/// \param FileName The name of the file being included, as written in the
|
||||
/// source code.
|
||||
///
|
||||
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||
/// otherwise, it was enclosed in quotes.
|
||||
///
|
||||
/// \param File The actual file that may be included by this embed directive.
|
||||
///
|
||||
/// \param Params The parameters used by the directive.
|
||||
void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled,
|
||||
OptionalFileEntryRef File,
|
||||
const LexEmbedParametersResult &Params) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked whenever an inclusion directive of
|
||||
/// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
|
||||
/// of whether the inclusion will actually result in an inclusion.
|
||||
///
|
||||
/// \param HashLoc The location of the '#' that starts the inclusion
|
||||
/// directive.
|
||||
///
|
||||
/// \param IncludeTok The token that indicates the kind of inclusion
|
||||
/// directive, e.g., 'include' or 'import'.
|
||||
///
|
||||
/// \param FileName The name of the file being included, as written in the
|
||||
/// source code.
|
||||
///
|
||||
/// \param IsAngled Whether the file name was enclosed in angle brackets;
|
||||
/// otherwise, it was enclosed in quotes.
|
||||
///
|
||||
/// \param FilenameRange The character range of the quotes or angle brackets
|
||||
/// for the written file name.
|
||||
///
|
||||
/// \param File The actual file that may be included by this inclusion
|
||||
/// directive.
|
||||
///
|
||||
/// \param SearchPath Contains the search path which was used to find the file
|
||||
/// in the file system. If the file was found via an absolute include path,
|
||||
/// SearchPath will be empty. For framework includes, the SearchPath and
|
||||
/// RelativePath will be split up. For example, if an include of "Some/Some.h"
|
||||
/// is found via the framework path
|
||||
/// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
|
||||
/// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
|
||||
/// "Some.h".
|
||||
///
|
||||
/// \param RelativePath The path relative to SearchPath, at which the include
|
||||
/// file was found. This is equal to FileName except for framework includes.
|
||||
///
|
||||
/// \param SuggestedModule The module suggested for this header, if any.
|
||||
///
|
||||
/// \param ModuleImported Whether this include was translated into import of
|
||||
/// \p SuggestedModule.
|
||||
///
|
||||
/// \param FileType The characteristic kind, indicates whether a file or
|
||||
/// directory holds normal user code, system code, or system code which is
|
||||
/// implicitly 'extern "C"' in C++ mode.
|
||||
///
|
||||
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
||||
StringRef FileName, bool IsAngled,
|
||||
CharSourceRange FilenameRange,
|
||||
OptionalFileEntryRef File, StringRef SearchPath,
|
||||
StringRef RelativePath, const Module *SuggestedModule,
|
||||
bool ModuleImported,
|
||||
SrcMgr::CharacteristicKind FileType) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked whenever there was an explicit module-import
|
||||
/// syntax.
|
||||
///
|
||||
/// \param ImportLoc The location of import directive token.
|
||||
///
|
||||
/// \param Path The identifiers (and their locations) of the module
|
||||
/// "path", e.g., "std.vector" would be split into "std" and "vector".
|
||||
///
|
||||
/// \param Imported The imported module; can be null if importing failed.
|
||||
///
|
||||
void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
|
||||
const Module *Imported) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Callback invoked when the end of the main file is reached.
|
||||
///
|
||||
/// No subsequent callbacks will be made.
|
||||
void EndOfMainFile() override { setSeenNoTrivialPPDirective(); }
|
||||
|
||||
/// Callback invoked when start reading any pragma directive.
|
||||
void PragmaDirective(SourceLocation Loc,
|
||||
PragmaIntroducerKind Introducer) override {}
|
||||
|
||||
/// Called by Preprocessor::HandleMacroExpandedIdentifier when a
|
||||
/// macro invocation is found.
|
||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range, const MacroArgs *Args) override;
|
||||
|
||||
/// Hook called whenever a macro definition is seen.
|
||||
void MacroDefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever a macro \#undef is seen.
|
||||
/// \param MacroNameTok The active Token
|
||||
/// \param MD A MacroDefinition for the named macro.
|
||||
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
|
||||
///
|
||||
/// MD is released immediately following this callback.
|
||||
void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
const MacroDirective *Undef) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever the 'defined' operator is seen.
|
||||
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#if is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param ConditionValue The evaluated value of the condition.
|
||||
///
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void If(SourceLocation Loc, SourceRange ConditionRange,
|
||||
ConditionValueKind ConditionValue) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elif is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param ConditionValue The evaluated value of the condition.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elif(SourceLocation Loc, SourceRange ConditionRange,
|
||||
ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#ifdef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elifdef branch is taken.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
/// Hook called whenever an \#elifdef is skipped.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
|
||||
SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#ifndef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
|
||||
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#elifndef branch is taken.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDefinition &MD) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
/// Hook called whenever an \#elifndef is skipped.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param ConditionRange The SourceRange of the expression being tested.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
// FIXME: better to pass in a list (or tree!) of Tokens.
|
||||
void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
|
||||
SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#else is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
void Else(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
/// Hook called whenever an \#endif is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
|
||||
void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H
|
||||
@@ -82,6 +82,7 @@ class PreprocessorLexer;
|
||||
class PreprocessorOptions;
|
||||
class ScratchBuffer;
|
||||
class TargetInfo;
|
||||
class NoTrivialPPDirectiveTracer;
|
||||
|
||||
namespace Builtin {
|
||||
class Context;
|
||||
@@ -353,6 +354,11 @@ class Preprocessor {
|
||||
/// First pp-token source location in current translation unit.
|
||||
SourceLocation FirstPPTokenLoc;
|
||||
|
||||
/// A preprocessor directive tracer to trace whether the preprocessing
|
||||
/// state changed. These changes would mean most semantically observable
|
||||
/// preprocessor state, particularly anything that is order dependent.
|
||||
NoTrivialPPDirectiveTracer *DirTracer = nullptr;
|
||||
|
||||
/// A position within a C++20 import-seq.
|
||||
class StdCXXImportSeq {
|
||||
public:
|
||||
@@ -609,6 +615,8 @@ class Preprocessor {
|
||||
return State == NamedModuleImplementation && !getName().contains(':');
|
||||
}
|
||||
|
||||
bool isNotAModuleDecl() const { return State == NotAModuleDecl; }
|
||||
|
||||
StringRef getName() const {
|
||||
assert(isNamedModule() && "Can't get name from a non named module");
|
||||
return Name;
|
||||
@@ -3087,6 +3095,10 @@ class Preprocessor {
|
||||
bool setDeserializedSafeBufferOptOutMap(
|
||||
const SmallVectorImpl<SourceLocation> &SrcLocSeqs);
|
||||
|
||||
/// Whether we've seen pp-directives which may have changed the preprocessing
|
||||
/// state.
|
||||
bool hasSeenNoTrivialPPDirective() const;
|
||||
|
||||
private:
|
||||
/// Helper functions to forward lexing to the actual lexer. They all share the
|
||||
/// same signature.
|
||||
|
||||
@@ -86,12 +86,12 @@ class Token {
|
||||
// macro stringizing or charizing operator.
|
||||
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
|
||||
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
|
||||
|
||||
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
||||
// re-added, e.g. via EnterTokenStream. Annotation
|
||||
// tokens are *not* reinjected.
|
||||
FirstPPToken = 0x1000, // This token is the first pp token in the
|
||||
// translation unit.
|
||||
IsReinjected = 0x800, // A phase 4 token that was produced before and
|
||||
// re-added, e.g. via EnterTokenStream. Annotation
|
||||
// tokens are *not* reinjected.
|
||||
HasSeenNoTrivialPPDirective =
|
||||
0x1000, // Whether we've seen any 'no-trivial' pp-directives before
|
||||
// current position.
|
||||
};
|
||||
|
||||
tok::TokenKind getKind() const { return Kind; }
|
||||
@@ -321,8 +321,9 @@ class Token {
|
||||
/// lexer uses identifier tokens to represent placeholders.
|
||||
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
|
||||
|
||||
/// Returns true if this token is the first pp-token.
|
||||
bool isFirstPPToken() const { return getFlag(FirstPPToken); }
|
||||
bool hasSeenNoTrivialPPDirective() const {
|
||||
return getFlag(HasSeenNoTrivialPPDirective);
|
||||
}
|
||||
};
|
||||
|
||||
/// Information about the conditional stack (\#if directives)
|
||||
|
||||
@@ -350,11 +350,6 @@ class Sema;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned BindsToRvalue : 1;
|
||||
|
||||
/// Whether this was an identity conversion with qualification
|
||||
/// conversion for the implicit object argument.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
unsigned IsImplicitObjectArgumentQualificationConversion : 1;
|
||||
|
||||
/// Whether this binds an implicit object argument to a
|
||||
/// non-static member function without a ref-qualifier.
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
@@ -453,11 +448,11 @@ class Sema;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (!C.hasSameType(getFromType(), getToType(2)))
|
||||
return false;
|
||||
if (BindsToRvalue && IsLvalueReference)
|
||||
return false;
|
||||
if (IsImplicitObjectArgumentQualificationConversion)
|
||||
return C.hasSameUnqualifiedType(getFromType(), getToType(2));
|
||||
return C.hasSameType(getFromType(), getToType(2));
|
||||
return true;
|
||||
}
|
||||
|
||||
ImplicitConversionRank getRank() const;
|
||||
|
||||
@@ -9836,7 +9836,7 @@ class Sema final : public SemaBase {
|
||||
SourceLocation ModuleLoc, ModuleDeclKind MDK,
|
||||
ModuleIdPath Path, ModuleIdPath Partition,
|
||||
ModuleImportState &ImportState,
|
||||
bool IntroducerIsFirstPPToken);
|
||||
bool SeenNoTrivialPPDirective);
|
||||
|
||||
/// The parser has processed a global-module-fragment declaration that begins
|
||||
/// the definition of the global module fragment of the current module unit.
|
||||
|
||||
@@ -1725,6 +1725,9 @@ ASTContext::PointerAuthContent ASTContext::findPointerAuthContent(QualType T) {
|
||||
assert(isPointerAuthenticationAvailable());
|
||||
|
||||
T = T.getCanonicalType();
|
||||
if (T->isDependentType())
|
||||
return PointerAuthContent::None;
|
||||
|
||||
if (T.hasAddressDiscriminatedPointerAuth())
|
||||
return PointerAuthContent::AddressDiscriminatedData;
|
||||
const RecordDecl *RD = T->getAsRecordDecl();
|
||||
@@ -3032,7 +3035,7 @@ bool ASTContext::hasUniqueObjectRepresentations(
|
||||
return true;
|
||||
}
|
||||
|
||||
// All other pointers (except __ptrauth pointers) are unique.
|
||||
// All other pointers are unique.
|
||||
if (Ty->isPointerType())
|
||||
return !Ty.hasAddressDiscriminatedPointerAuth();
|
||||
|
||||
|
||||
@@ -456,7 +456,9 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
|
||||
const Decl *D1, const Decl *D2,
|
||||
const Decl *PrimaryDecl = nullptr) {
|
||||
// If either declaration has an attribute on it, we treat the declarations
|
||||
// as not being structurally equivalent.
|
||||
// as not being structurally equivalent unless both declarations are implicit
|
||||
// (ones generated by the compiler like __NSConstantString_tag).
|
||||
//
|
||||
// FIXME: this should be handled on a case-by-case basis via tablegen in
|
||||
// Attr.td. There are multiple cases to consider: one declaration with the
|
||||
// attribute, another without it; different attribute syntax|spellings for
|
||||
@@ -468,7 +470,7 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context,
|
||||
D1Attr = *D1->getAttrs().begin();
|
||||
if (D2->hasAttrs())
|
||||
D2Attr = *D2->getAttrs().begin();
|
||||
if (D1Attr || D2Attr) {
|
||||
if ((D1Attr || D2Attr) && !D1->isImplicit() && !D2->isImplicit()) {
|
||||
const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
|
||||
Context.Diag2(DiagnoseDecl->getLocation(),
|
||||
diag::warn_odr_tag_type_with_attributes)
|
||||
@@ -873,7 +875,29 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
else if (T1->getTypeClass() == Type::FunctionNoProto &&
|
||||
T2->getTypeClass() == Type::FunctionProto)
|
||||
TC = Type::FunctionNoProto;
|
||||
else
|
||||
else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
|
||||
(T1->getTypeClass() == Type::Enum ||
|
||||
T2->getTypeClass() == Type::Enum)) {
|
||||
// In C23, if not being strict about token equivalence, we need to handle
|
||||
// the case where one type is an enumeration and the other type is an
|
||||
// integral type.
|
||||
//
|
||||
// C23 6.7.3.3p16: The enumerated type is compatible with the underlying
|
||||
// type of the enumeration.
|
||||
//
|
||||
// Treat the enumeration as its underlying type and use the builtin type
|
||||
// class comparison.
|
||||
if (T1->getTypeClass() == Type::Enum) {
|
||||
T1 = T1->getAs<EnumType>()->getDecl()->getIntegerType();
|
||||
if (!T2->isBuiltinType() || T1.isNull()) // Sanity check
|
||||
return false;
|
||||
} else if (T2->getTypeClass() == Type::Enum) {
|
||||
T2 = T2->getAs<EnumType>()->getDecl()->getIntegerType();
|
||||
if (!T1->isBuiltinType() || T2.isNull()) // Sanity check
|
||||
return false;
|
||||
}
|
||||
TC = Type::Builtin;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2067,6 +2091,48 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
!CheckStructurallyEquivalentAttributes(Context, D1, D2))
|
||||
return false;
|
||||
|
||||
// In C23, if one enumeration has a fixed underlying type, the other shall
|
||||
// have a compatible fixed underlying type (6.2.7).
|
||||
if (Context.LangOpts.C23) {
|
||||
if (D1->isFixed() != D2->isFixed()) {
|
||||
if (Context.Complain) {
|
||||
Context.Diag2(D2->getLocation(),
|
||||
Context.getApplicableDiagnostic(
|
||||
diag::err_odr_tag_type_inconsistent))
|
||||
<< Context.ToCtx.getTypeDeclType(D2)
|
||||
<< (&Context.FromCtx != &Context.ToCtx);
|
||||
Context.Diag1(D1->getLocation(),
|
||||
D1->isFixed()
|
||||
? diag::note_odr_fixed_underlying_type
|
||||
: diag::note_odr_missing_fixed_underlying_type)
|
||||
<< D1;
|
||||
Context.Diag2(D2->getLocation(),
|
||||
D2->isFixed()
|
||||
? diag::note_odr_fixed_underlying_type
|
||||
: diag::note_odr_missing_fixed_underlying_type)
|
||||
<< D2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (D1->isFixed()) {
|
||||
assert(D2->isFixed() && "enums expected to have fixed underlying types");
|
||||
if (!IsStructurallyEquivalent(Context, D1->getIntegerType(),
|
||||
D2->getIntegerType())) {
|
||||
if (Context.Complain) {
|
||||
Context.Diag2(D2->getLocation(),
|
||||
Context.getApplicableDiagnostic(
|
||||
diag::err_odr_tag_type_inconsistent))
|
||||
<< Context.ToCtx.getTypeDeclType(D2)
|
||||
<< (&Context.FromCtx != &Context.ToCtx);
|
||||
Context.Diag2(D2->getLocation(),
|
||||
diag::note_odr_incompatible_fixed_underlying_type)
|
||||
<< D2 << D2->getIntegerType() << D1->getIntegerType();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm::SmallVector<const EnumConstantDecl *, 8> D1Enums, D2Enums;
|
||||
auto CopyEnumerators =
|
||||
[](auto &&Range, llvm::SmallVectorImpl<const EnumConstantDecl *> &Cont) {
|
||||
|
||||
@@ -1448,6 +1448,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().StructuralIfLiteral = false;
|
||||
}
|
||||
|
||||
// If this type contains any address discriminated values we should
|
||||
// have already indicated that the only special member functions that
|
||||
// can possibly be trivial are the default constructor and destructor.
|
||||
if (T.hasAddressDiscriminatedPointerAuth())
|
||||
data().HasTrivialSpecialMembers &=
|
||||
SMF_DefaultConstructor | SMF_Destructor;
|
||||
|
||||
// C++14 [meta.unary.prop]p4:
|
||||
// T is a class type [...] with [...] no non-static data members other
|
||||
// than subobjects of zero size
|
||||
|
||||
@@ -4441,7 +4441,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
|
||||
}
|
||||
} else if (!IsAccess) {
|
||||
return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
|
||||
} else if (IsConstant && Info.checkingPotentialConstantExpression() &&
|
||||
} else if ((IsConstant || BaseType->isReferenceType()) &&
|
||||
Info.checkingPotentialConstantExpression() &&
|
||||
BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) {
|
||||
// This variable might end up being constexpr. Don't diagnose it yet.
|
||||
} else if (IsConstant) {
|
||||
@@ -4478,9 +4479,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
|
||||
// a null BaseVal. Any constexpr-unknown variable seen here is an error:
|
||||
// we can't access a constexpr-unknown object.
|
||||
if (!BaseVal) {
|
||||
Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
|
||||
<< AK << VD;
|
||||
Info.Note(VD->getLocation(), diag::note_declared_at);
|
||||
if (!Info.checkingPotentialConstantExpression()) {
|
||||
Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1)
|
||||
<< AK << VD;
|
||||
Info.Note(VD->getLocation(), diag::note_declared_at);
|
||||
}
|
||||
return CompleteObject();
|
||||
}
|
||||
} else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) {
|
||||
@@ -7906,8 +7909,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc,
|
||||
// so its layout is unspecified. For now, we'll simply treat these cases
|
||||
// as unsupported (this should only be possible with OpenCL bool vectors
|
||||
// whose element count isn't a multiple of the byte size).
|
||||
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector)
|
||||
<< QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth();
|
||||
if (Info)
|
||||
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector)
|
||||
<< QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7916,8 +7920,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc,
|
||||
// The layout for x86_fp80 vectors seems to be handled very inconsistently
|
||||
// by both clang and LLVM, so for now we won't allow bit_casts involving
|
||||
// it in a constexpr context.
|
||||
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type)
|
||||
<< EltTy;
|
||||
if (Info)
|
||||
Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type)
|
||||
<< EltTy;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -10929,10 +10934,6 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
|
||||
|
||||
bool ZeroInit = E->requiresZeroInitialization();
|
||||
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
|
||||
// If we've already performed zero-initialization, we're already done.
|
||||
if (Result.hasValue())
|
||||
return true;
|
||||
|
||||
if (ZeroInit)
|
||||
return ZeroInitialization(E, T);
|
||||
|
||||
@@ -14478,12 +14479,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
||||
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
|
||||
return false;
|
||||
|
||||
// If we have Unknown pointers we should fail if they are not global values.
|
||||
if (!(IsGlobalLValue(LHSValue.getLValueBase()) &&
|
||||
IsGlobalLValue(RHSValue.getLValueBase())) &&
|
||||
(LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown))
|
||||
return false;
|
||||
|
||||
// Reject differing bases from the normal codepath; we special-case
|
||||
// comparisons to null.
|
||||
if (!HasSameBase(LHSValue, RHSValue)) {
|
||||
@@ -14545,6 +14540,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
||||
(LHSValue.Base && isZeroSized(RHSValue)))
|
||||
return DiagComparison(
|
||||
diag::note_constexpr_pointer_comparison_zero_sized);
|
||||
if (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)
|
||||
return DiagComparison(
|
||||
diag::note_constexpr_pointer_comparison_unspecified);
|
||||
// FIXME: Verify both variables are live.
|
||||
return Success(CmpResult::Unequal, E);
|
||||
}
|
||||
|
||||
@@ -14565,7 +14564,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
||||
if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
|
||||
bool WasArrayIndex;
|
||||
unsigned Mismatch = FindDesignatorMismatch(
|
||||
getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex);
|
||||
LHSValue.Base.isNull() ? QualType()
|
||||
: getType(LHSValue.Base).getNonReferenceType(),
|
||||
LHSDesignator, RHSDesignator, WasArrayIndex);
|
||||
// At the point where the designators diverge, the comparison has a
|
||||
// specified value if:
|
||||
// - we are comparing array indices
|
||||
@@ -14609,7 +14610,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
|
||||
// compare pointers within the object in question; otherwise, the result
|
||||
// depends on where the object is located in memory.
|
||||
if (!LHSValue.Base.isNull() && IsRelational) {
|
||||
QualType BaseTy = getType(LHSValue.Base);
|
||||
QualType BaseTy = getType(LHSValue.Base).getNonReferenceType();
|
||||
if (BaseTy->isIncompleteType())
|
||||
return Error(E);
|
||||
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
|
||||
|
||||
@@ -2715,6 +2715,11 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const {
|
||||
return false;
|
||||
|
||||
QualType CanonicalType = getTypePtr()->CanonicalType;
|
||||
|
||||
// Any type that is, or contains, address discriminated data is never POD.
|
||||
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
|
||||
return false;
|
||||
|
||||
switch (CanonicalType->getTypeClass()) {
|
||||
// Everything not explicitly mentioned is not POD.
|
||||
default:
|
||||
@@ -2773,6 +2778,11 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
|
||||
if (CanonicalType->isDependentType())
|
||||
return false;
|
||||
|
||||
// Any type that is, or contains, address discriminated data is never a
|
||||
// trivial type.
|
||||
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
|
||||
return false;
|
||||
|
||||
// C++0x [basic.types]p9:
|
||||
// Scalar types, trivial class types, arrays of such types, and
|
||||
// cv-qualified versions of these types are collectively called trivial
|
||||
@@ -2870,6 +2880,12 @@ bool QualType::isBitwiseCloneableType(const ASTContext &Context) const {
|
||||
|
||||
if (CanonicalType->isIncompleteType())
|
||||
return false;
|
||||
|
||||
// Any type that is, or contains, address discriminated data is never
|
||||
// bitwise clonable.
|
||||
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(CanonicalType))
|
||||
return false;
|
||||
|
||||
const auto *RD = CanonicalType->getAsRecordDecl(); // struct/union/class
|
||||
if (!RD)
|
||||
return true;
|
||||
@@ -3115,6 +3131,10 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
|
||||
if (BaseTy->isIncompleteType())
|
||||
return false;
|
||||
|
||||
// Any type that is, or contains, address discriminated data is non-POD.
|
||||
if (const_cast<ASTContext&>(Context).containsAddressDiscriminatedPointerAuth(*this))
|
||||
return false;
|
||||
|
||||
// As an extension, Clang treats vector types as Scalar types.
|
||||
if (BaseTy->isScalarType() || BaseTy->isVectorType())
|
||||
return true;
|
||||
|
||||
@@ -1331,7 +1331,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet,
|
||||
FSet.removeLock(FactMan, NegC);
|
||||
}
|
||||
else {
|
||||
if (inCurrentScope(*Entry) && !Entry->asserted())
|
||||
if (inCurrentScope(*Entry) && !Entry->asserted() && !Entry->reentrant())
|
||||
Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(),
|
||||
NegC.toString(), Entry->loc());
|
||||
}
|
||||
|
||||
@@ -769,6 +769,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
|
||||
case llvm::Triple::FreeBSD:
|
||||
return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
|
||||
Opts);
|
||||
case llvm::Triple::OpenBSD:
|
||||
return std::make_unique<OpenBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
|
||||
Opts);
|
||||
default:
|
||||
return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
|
||||
}
|
||||
|
||||
@@ -461,6 +461,8 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
|
||||
|
||||
case AttrFeatureKind::Feature:
|
||||
Ret.Features.push_back("+" + Value.str());
|
||||
if (Value == "lasx")
|
||||
Ret.Features.push_back("+lsx");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
|
||||
LongWidth = LongAlign = 32;
|
||||
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
|
||||
PointerWidth = PointerAlign = 32;
|
||||
PtrDiffType = SignedInt;
|
||||
PtrDiffType = IntPtrType = SignedInt;
|
||||
SizeType = UnsignedInt;
|
||||
SuitableAlign = 64;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
|
||||
IntMaxType = Int64Type;
|
||||
LongWidth = LongAlign = 64;
|
||||
PointerWidth = PointerAlign = 64;
|
||||
PtrDiffType = SignedLong;
|
||||
PtrDiffType = IntPtrType = SignedLong;
|
||||
SizeType = UnsignedLong;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
|
||||
IntMaxType = Int64Type;
|
||||
LongWidth = LongAlign = 32;
|
||||
PointerWidth = PointerAlign = 32;
|
||||
PtrDiffType = SignedInt;
|
||||
PtrDiffType = IntPtrType = SignedInt;
|
||||
SizeType = UnsignedInt;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,9 @@ class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
|
||||
DefineStd(Builder, "unix", Opts);
|
||||
if (this->HasFloat128)
|
||||
Builder.defineMacro("__FLOAT128__");
|
||||
|
||||
if (Opts.C11)
|
||||
Builder.defineMacro("__STDC_NO_THREADS__");
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -496,6 +499,7 @@ class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
|
||||
case llvm::Triple::sparcv9:
|
||||
this->MCountName = "_mcount";
|
||||
break;
|
||||
case llvm::Triple::loongarch64:
|
||||
case llvm::Triple::riscv64:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -649,6 +649,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo {
|
||||
: X86_32TargetInfo(Triple, Opts) {
|
||||
this->WCharType = TargetInfo::UnsignedShort;
|
||||
this->WIntType = TargetInfo::UnsignedInt;
|
||||
this->UseMicrosoftManglingForC = true;
|
||||
DoubleAlign = LongLongAlign = 64;
|
||||
resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-"
|
||||
"i128:128-f80:32-n8:16:32-a:0:32-S32",
|
||||
@@ -986,6 +987,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo {
|
||||
: X86_64TargetInfo(Triple, Opts) {
|
||||
this->WCharType = TargetInfo::UnsignedShort;
|
||||
this->WIntType = TargetInfo::UnsignedInt;
|
||||
this->UseMicrosoftManglingForC = true;
|
||||
}
|
||||
|
||||
void getTargetDefines(const LangOptions &Opts,
|
||||
|
||||
@@ -176,6 +176,11 @@ class Address {
|
||||
static Address invalid() { return Address(nullptr); }
|
||||
bool isValid() const { return Pointer.getPointer() != nullptr; }
|
||||
|
||||
llvm::Value *getPointerIfNotSigned() const {
|
||||
assert(isValid() && "pointer isn't valid");
|
||||
return !isSigned() ? Pointer.getPointer() : nullptr;
|
||||
}
|
||||
|
||||
/// This function is used in situations where the caller is doing some sort of
|
||||
/// opaque "laundering" of the pointer.
|
||||
void replaceBasePointer(llvm::Value *P) {
|
||||
|
||||
@@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
|
||||
// Optional copy/dispose helpers.
|
||||
bool hasInternalHelper = false;
|
||||
if (blockInfo.NeedsCopyDispose) {
|
||||
auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers;
|
||||
// copy_func_helper_decl
|
||||
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
|
||||
elements.add(copyHelper);
|
||||
elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());
|
||||
|
||||
// destroy_func_decl
|
||||
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
|
||||
elements.add(disposeHelper);
|
||||
elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());
|
||||
|
||||
if (cast<llvm::Function>(copyHelper->stripPointerCasts())
|
||||
->hasInternalLinkage() ||
|
||||
@@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
|
||||
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
|
||||
info.CanBeGlobal = true;
|
||||
return;
|
||||
}
|
||||
else if (C.getLangOpts().ObjC &&
|
||||
CGM.getLangOpts().getGC() == LangOptions::NonGC)
|
||||
} else if (C.getLangOpts().ObjC &&
|
||||
CGM.getLangOpts().getGC() == LangOptions::NonGC)
|
||||
info.HasCapturedVariableLayout = true;
|
||||
|
||||
if (block->doesNotEscape())
|
||||
@@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
|
||||
|
||||
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
|
||||
auto GenVoidPtrTy =
|
||||
llvm::PointerType *GenVoidPtrTy =
|
||||
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
|
||||
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
|
||||
auto GenVoidPtrSize = CharUnits::fromQuantity(
|
||||
@@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
: CGM.getNSConcreteStackBlock();
|
||||
isa = blockISA;
|
||||
|
||||
// Build the block descriptor.
|
||||
descriptor = buildBlockDescriptor(CGM, blockInfo);
|
||||
|
||||
// Compute the initial on-stack block flags.
|
||||
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
|
||||
flags = BLOCK_HAS_SIGNATURE;
|
||||
@@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
flags |= BLOCK_USE_STRET;
|
||||
if (blockInfo.NoEscape)
|
||||
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
|
||||
|
||||
// Build the block descriptor.
|
||||
descriptor = buildBlockDescriptor(CGM, blockInfo);
|
||||
}
|
||||
|
||||
auto projectField = [&](unsigned index, const Twine &name) -> Address {
|
||||
@@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
|
||||
getIntSize(), "block.align");
|
||||
}
|
||||
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
||||
if (!IsOpenCL)
|
||||
addHeaderField(descriptor, getPointerSize(), "block.descriptor");
|
||||
else if (auto *Helper =
|
||||
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
||||
|
||||
if (!IsOpenCL) {
|
||||
llvm::Value *blockFnPtr =
|
||||
llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);
|
||||
QualType type = blockInfo.getBlockExpr()
|
||||
->getType()
|
||||
->castAs<BlockPointerType>()
|
||||
->getPointeeType();
|
||||
addSignedHeaderField(
|
||||
blockFnPtr,
|
||||
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
|
||||
GlobalDecl(), type, getPointerSize(), "block.invoke");
|
||||
|
||||
addSignedHeaderField(
|
||||
descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,
|
||||
GlobalDecl(), type, getPointerSize(), "block.descriptor");
|
||||
} else if (auto *Helper =
|
||||
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
||||
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
||||
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
|
||||
addHeaderField(
|
||||
I.first,
|
||||
@@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
|
||||
CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
|
||||
I.second);
|
||||
}
|
||||
}
|
||||
} else
|
||||
addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
|
||||
}
|
||||
|
||||
// Finally, capture all the values into the block.
|
||||
@@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
||||
ASTContext &Ctx = getContext();
|
||||
CallArgList Args;
|
||||
|
||||
llvm::Value *FuncPtr = nullptr;
|
||||
|
||||
if (getLangOpts().OpenCL) {
|
||||
// For OpenCL, BlockPtr is already casted to generic block literal.
|
||||
|
||||
@@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
||||
if (!isa<ParmVarDecl>(E->getCalleeDecl()))
|
||||
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
|
||||
else {
|
||||
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
|
||||
FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
|
||||
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
|
||||
getPointerAlign());
|
||||
}
|
||||
@@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
||||
BlockPtr =
|
||||
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
|
||||
// Get pointer to the block invoke function
|
||||
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
|
||||
FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
|
||||
|
||||
// First argument is a block literal casted to a void pointer
|
||||
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
|
||||
@@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
|
||||
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
|
||||
|
||||
// Prepare the callee.
|
||||
CGCallee Callee(CGCalleeInfo(), Func);
|
||||
CGPointerAuthInfo PointerAuth;
|
||||
if (auto &AuthSchema =
|
||||
CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
|
||||
assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");
|
||||
PointerAuth =
|
||||
EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType);
|
||||
}
|
||||
|
||||
CGCallee Callee(CGCalleeInfo(), Func, PointerAuth);
|
||||
|
||||
// And call the block.
|
||||
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
|
||||
@@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
|
||||
|
||||
bool IsOpenCL = CGM.getLangOpts().OpenCL;
|
||||
bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
|
||||
auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth;
|
||||
if (!IsOpenCL) {
|
||||
// isa
|
||||
if (IsWindows)
|
||||
fields.addNullPointer(CGM.Int8PtrPtrTy);
|
||||
else
|
||||
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
|
||||
CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers,
|
||||
GlobalDecl(), QualType());
|
||||
CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),
|
||||
QualType());
|
||||
|
||||
// __flags
|
||||
BlockFlags flags = BLOCK_IS_GLOBAL;
|
||||
@@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
|
||||
}
|
||||
|
||||
// Function
|
||||
fields.add(blockFn);
|
||||
if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
|
||||
QualType FnType = blockInfo.getBlockExpr()
|
||||
->getType()
|
||||
->castAs<BlockPointerType>()
|
||||
->getPointeeType();
|
||||
fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);
|
||||
} else
|
||||
fields.add(blockFn);
|
||||
|
||||
if (!IsOpenCL) {
|
||||
// Descriptor
|
||||
fields.add(buildBlockDescriptor(CGM, blockInfo));
|
||||
llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo);
|
||||
fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
|
||||
GlobalDecl(), QualType());
|
||||
} else if (auto *Helper =
|
||||
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
|
||||
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
|
||||
@@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
|
||||
// it. It's not quite worth the annoyance to avoid creating it in the
|
||||
// first place.
|
||||
if (!needsEHCleanup(captureType.isDestructedType()))
|
||||
if (auto *I =
|
||||
cast_or_null<llvm::Instruction>(dstField.getBasePointer()))
|
||||
if (auto *I = cast_or_null<llvm::Instruction>(
|
||||
dstField.getPointerIfNotSigned()))
|
||||
I->eraseFromParent();
|
||||
}
|
||||
break;
|
||||
@@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
|
||||
unsigned nextHeaderIndex = 0;
|
||||
CharUnits nextHeaderOffset;
|
||||
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
|
||||
const Twine &name) {
|
||||
const Twine &name, bool isFunction = false) {
|
||||
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
|
||||
if (isFunction) {
|
||||
if (auto &Schema = CGM.getCodeGenOpts()
|
||||
.PointerAuth.BlockByrefHelperFunctionPointers) {
|
||||
auto PointerAuth = EmitPointerAuthInfo(
|
||||
Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType());
|
||||
value = EmitPointerAuthSign(PointerAuth, value);
|
||||
}
|
||||
}
|
||||
Builder.CreateStore(value, fieldAddr);
|
||||
|
||||
nextHeaderIndex++;
|
||||
@@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
|
||||
storeHeaderField(V, getIntSize(), "byref.size");
|
||||
|
||||
if (helpers) {
|
||||
storeHeaderField(helpers->CopyHelper, getPointerSize(),
|
||||
"byref.copyHelper");
|
||||
storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper",
|
||||
/*isFunction=*/true);
|
||||
storeHeaderField(helpers->DisposeHelper, getPointerSize(),
|
||||
"byref.disposeHelper");
|
||||
"byref.disposeHelper", /*isFunction=*/true);
|
||||
}
|
||||
|
||||
if (ByRefHasLifetime && HasByrefExtendedLayout) {
|
||||
|
||||
@@ -4787,19 +4787,6 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
|
||||
}
|
||||
};
|
||||
|
||||
struct DisableDebugLocationUpdates {
|
||||
CodeGenFunction &CGF;
|
||||
bool disabledDebugInfo;
|
||||
DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) {
|
||||
if ((disabledDebugInfo = isa<CXXDefaultArgExpr>(E) && CGF.getDebugInfo()))
|
||||
CGF.disableDebugInfo();
|
||||
}
|
||||
~DisableDebugLocationUpdates() {
|
||||
if (disabledDebugInfo)
|
||||
CGF.enableDebugInfo();
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
RValue CallArg::getRValue(CodeGenFunction &CGF) const {
|
||||
@@ -4836,7 +4823,9 @@ void CodeGenFunction::EmitWritebacks(const CallArgList &args) {
|
||||
|
||||
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
|
||||
QualType type) {
|
||||
DisableDebugLocationUpdates Dis(*this, E);
|
||||
std::optional<DisableDebugLocationUpdates> Dis;
|
||||
if (isa<CXXDefaultArgExpr>(E))
|
||||
Dis.emplace(*this);
|
||||
if (const ObjCIndirectCopyRestoreExpr *CRE =
|
||||
dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
|
||||
assert(getLangOpts().ObjCAutoRefCount);
|
||||
@@ -6229,3 +6218,12 @@ RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
|
||||
return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot);
|
||||
return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot);
|
||||
}
|
||||
|
||||
DisableDebugLocationUpdates::DisableDebugLocationUpdates(CodeGenFunction &CGF)
|
||||
: CGF(CGF) {
|
||||
CGF.disableDebugInfo();
|
||||
}
|
||||
|
||||
DisableDebugLocationUpdates::~DisableDebugLocationUpdates() {
|
||||
CGF.enableDebugInfo();
|
||||
}
|
||||
|
||||
@@ -457,6 +457,12 @@ inline FnInfoOpts &operator&=(FnInfoOpts &A, FnInfoOpts B) {
|
||||
return A;
|
||||
}
|
||||
|
||||
struct DisableDebugLocationUpdates {
|
||||
CodeGenFunction &CGF;
|
||||
DisableDebugLocationUpdates(CodeGenFunction &CGF);
|
||||
~DisableDebugLocationUpdates();
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
} // end namespace clang
|
||||
|
||||
|
||||
@@ -707,11 +707,15 @@ struct GetReturnObjectManager {
|
||||
Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
|
||||
|
||||
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
|
||||
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
|
||||
GroEmission.getOriginalAllocatedAddress().getPointer());
|
||||
assert(GroAlloca && "expected alloca to be emitted");
|
||||
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
|
||||
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
|
||||
|
||||
if (!GroVarDecl->isNRVOVariable()) {
|
||||
// NRVO variables don't have allocas and won't have the same issue.
|
||||
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
|
||||
GroEmission.getOriginalAllocatedAddress().getPointer());
|
||||
assert(GroAlloca && "expected alloca to be emitted");
|
||||
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
|
||||
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
|
||||
}
|
||||
|
||||
// Remember the top of EHStack before emitting the cleanup.
|
||||
auto old_top = CGF.EHStack.stable_begin();
|
||||
|
||||
@@ -170,6 +170,10 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction,
|
||||
if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions)
|
||||
return;
|
||||
|
||||
llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram();
|
||||
if (!SP || !SP->getKeyInstructionsEnabled())
|
||||
return;
|
||||
|
||||
addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1);
|
||||
|
||||
llvm::Instruction *BackupI =
|
||||
@@ -2641,7 +2645,8 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
|
||||
// existing information in the DWARF. The type is assumed to be 'void *'.
|
||||
void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable,
|
||||
const CXXRecordDecl *RD) {
|
||||
if (!CGM.getTarget().getCXXABI().isItaniumFamily())
|
||||
if (!CGM.getTarget().getCXXABI().isItaniumFamily() ||
|
||||
CGM.getTarget().getTriple().isOSBinFormatCOFF())
|
||||
return;
|
||||
|
||||
ASTContext &Context = CGM.getContext();
|
||||
|
||||
@@ -3314,7 +3314,14 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
||||
auto *FD = LambdaCaptureFields.lookup(BD);
|
||||
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
|
||||
}
|
||||
return EmitLValue(BD->getBinding());
|
||||
// Suppress debug location updates when visiting the binding, since the
|
||||
// binding may emit instructions that would otherwise be associated with the
|
||||
// binding itself, rather than the expression referencing the binding. (this
|
||||
// leads to jumpy debug stepping behavior where the location/debugger jump
|
||||
// back to the binding declaration, then back to the expression referencing
|
||||
// the binding)
|
||||
DisableDebugLocationUpdates D(*this);
|
||||
return EmitLValue(BD->getBinding(), NotKnownNonNull);
|
||||
}
|
||||
|
||||
// We can form DeclRefExprs naming GUID declarations when reconstituting
|
||||
|
||||
@@ -2313,7 +2313,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
|
||||
bool IsExact = !IsDynamicCastToVoid &&
|
||||
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
|
||||
DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
|
||||
CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy);
|
||||
CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy) &&
|
||||
!getLangOpts().PointerAuthCalls;
|
||||
|
||||
// C++ [expr.dynamic.cast]p4:
|
||||
// If the value of v is a null pointer value in the pointer case, the result
|
||||
|
||||
@@ -873,8 +873,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
|
||||
|
||||
for (const BaseInfo &Base : Bases) {
|
||||
bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;
|
||||
Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
|
||||
VTableClass, Offset + Base.Offset);
|
||||
if (!Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
|
||||
VTableClass, Offset + Base.Offset))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1620,7 +1621,7 @@ llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
|
||||
if (CE->isGLValue())
|
||||
RetType = CGM.getContext().getLValueReferenceType(RetType);
|
||||
|
||||
return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
|
||||
return tryEmitAbstract(CE->getAPValueResult(), RetType);
|
||||
}
|
||||
|
||||
llvm::Constant *
|
||||
|
||||
@@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
|
||||
if (HaveInsertPoint())
|
||||
EmitStopPoint(&S);
|
||||
|
||||
ApplyAtomGroup Grp(getDebugInfo());
|
||||
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
|
||||
}
|
||||
|
||||
|
||||
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
||||
ApplyAtomGroup Grp(getDebugInfo());
|
||||
if (const LabelDecl *Target = S.getConstantTarget()) {
|
||||
EmitBranchThroughCleanup(getJumpDestForLabel(Target));
|
||||
return;
|
||||
@@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
||||
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
|
||||
|
||||
EmitBranch(IndGotoBB);
|
||||
if (CurBB && CurBB->getTerminator())
|
||||
addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
|
||||
@@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
|
||||
llvm::ConstantAsMetadata::get(Loc)));
|
||||
}
|
||||
|
||||
// Make inline-asm calls Key for the debug info feature Key Instructions.
|
||||
CGF.addInstToNewSourceAtom(&Result, nullptr);
|
||||
|
||||
if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent())
|
||||
// Conservatively, mark all inline asm blocks in CUDA or OpenCL as
|
||||
// convergent (meaning, they may call an intrinsically convergent op, such
|
||||
@@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
|
||||
}
|
||||
}
|
||||
|
||||
ApplyAtomGroup Grp(CGF.getDebugInfo());
|
||||
LValue Dest = ResultRegDests[i];
|
||||
// ResultTypeRequiresCast elements correspond to the first
|
||||
// ResultTypeRequiresCast.size() elements of RegResults.
|
||||
@@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
|
||||
unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]);
|
||||
Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
|
||||
if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
|
||||
Builder.CreateStore(Tmp, A);
|
||||
llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
|
||||
CGF.addInstToCurrentSourceAtom(S, S->getValueOperand());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -727,7 +727,7 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
};
|
||||
|
||||
/// Header for data within LifetimeExtendedCleanupStack.
|
||||
struct LifetimeExtendedCleanupHeader {
|
||||
struct alignas(uint64_t) LifetimeExtendedCleanupHeader {
|
||||
/// The size of the following cleanup object.
|
||||
unsigned Size;
|
||||
/// The kind of cleanup to push.
|
||||
@@ -949,7 +949,8 @@ class CodeGenFunction : public CodeGenTypeCache {
|
||||
LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size +
|
||||
(Header.IsConditional ? sizeof(ActiveFlag) : 0));
|
||||
|
||||
static_assert(sizeof(Header) % alignof(T) == 0,
|
||||
static_assert((alignof(LifetimeExtendedCleanupHeader) == alignof(T)) &&
|
||||
(alignof(T) == alignof(RawAddress)),
|
||||
"Cleanup will be allocated on misaligned address");
|
||||
char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
|
||||
new (Buffer) LifetimeExtendedCleanupHeader(Header);
|
||||
|
||||
@@ -143,7 +143,7 @@ class EHScopeStack {
|
||||
///
|
||||
/// Cleanup implementations should generally be declared in an
|
||||
/// anonymous namespace.
|
||||
class Cleanup {
|
||||
class alignas(uint64_t) Cleanup {
|
||||
// Anchor the construction vtable.
|
||||
virtual void anchor();
|
||||
|
||||
|
||||
@@ -20,6 +20,951 @@ using namespace clang;
|
||||
using namespace CodeGen;
|
||||
using namespace llvm;
|
||||
|
||||
// The 0th bit simulates the `vta` of RVV
|
||||
// The 1st bit simulates the `vma` of RVV
|
||||
static constexpr unsigned RVV_VTA = 0x1;
|
||||
static constexpr unsigned RVV_VMA = 0x2;
|
||||
|
||||
// RISC-V Vector builtin helper functions are marked NOINLINE to prevent
|
||||
// excessive inlining in CodeGenFunction::EmitRISCVBuiltinExpr's large switch
|
||||
// statement, which would significantly increase compilation time.
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVVLEFFBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
// Move mask to right before vl.
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()};
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()};
|
||||
}
|
||||
Value *NewVL = Ops[2];
|
||||
Ops.erase(Ops.begin() + 2);
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
|
||||
llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
|
||||
// Store new_vl.
|
||||
clang::CharUnits Align;
|
||||
if (IsMasked)
|
||||
Align = CGM.getNaturalPointeeTypeAlignment(
|
||||
E->getArg(E->getNumArgs() - 2)->getType());
|
||||
else
|
||||
Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType());
|
||||
llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1});
|
||||
Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align));
|
||||
return V;
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVVSSEBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
// Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride,
|
||||
// mask, vl)
|
||||
std::swap(Ops[0], Ops[3]);
|
||||
} else {
|
||||
// Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
|
||||
}
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedStoreBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
// Builtin: (mask, ptr, index, value, vl).
|
||||
// Intrinsic: (value, ptr, index, mask, vl)
|
||||
std::swap(Ops[0], Ops[3]);
|
||||
} else {
|
||||
// Builtin: (ptr, index, value, vl).
|
||||
// Intrinsic: (value, ptr, index, vl)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
|
||||
}
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[4]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVPseudoUnaryBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
}
|
||||
auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
|
||||
Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
|
||||
if (IsMasked) {
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
// maskedoff, op1, op2, mask, vl, policy
|
||||
IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
|
||||
} else {
|
||||
// passthru, op1, op2, vl
|
||||
IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
|
||||
}
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVPseudoVNotBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
}
|
||||
auto ElemTy = cast<llvm::VectorType>(ResultType)->getElementType();
|
||||
Ops.insert(Ops.begin() + 2, llvm::Constant::getAllOnesValue(ElemTy));
|
||||
if (IsMasked) {
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
// maskedoff, op1, po2, mask, vl, policy
|
||||
IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()};
|
||||
} else {
|
||||
// passthru, op1, op2, vl
|
||||
IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()};
|
||||
}
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVPseudoMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// op1, vl
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType()};
|
||||
Ops.insert(Ops.begin() + 1, Ops[0]);
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVPseudoVFUnaryBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
Ops.insert(Ops.begin() + 2, Ops[1]);
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
// maskedoff, op1, op2, mask, vl
|
||||
IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops.back()->getType()};
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
// op1, po2, vl
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
|
||||
Ops.insert(Ops.begin() + 2, Ops[1]);
|
||||
}
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVPseudoVWCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
}
|
||||
auto ElemTy = cast<llvm::VectorType>(Ops[1]->getType())->getElementType();
|
||||
Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy));
|
||||
if (IsMasked) {
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
// maskedoff, op1, op2, mask, vl, policy
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[4]->getType()};
|
||||
} else {
|
||||
// passtru, op1, op2, vl
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[3]->getType()};
|
||||
}
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVPseudoVNCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
} else {
|
||||
if (PolicyAttrs & RVV_VTA)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
}
|
||||
Ops.insert(Ops.begin() + 2,
|
||||
llvm::Constant::getNullValue(Ops.back()->getType()));
|
||||
if (IsMasked) {
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
// maskedoff, op1, xlen, mask, vl
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[4]->getType(),
|
||||
Ops[4]->getType()};
|
||||
} else {
|
||||
// passthru, op1, xlen, vl
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType(),
|
||||
Ops[3]->getType()};
|
||||
}
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVVlenbBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
LLVMContext &Context = CGM.getLLVMContext();
|
||||
llvm::MDBuilder MDHelper(Context);
|
||||
llvm::Metadata *OpsMD[] = {llvm::MDString::get(Context, "vlenb")};
|
||||
llvm::MDNode *RegName = llvm::MDNode::get(Context, OpsMD);
|
||||
llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName);
|
||||
llvm::Function *F =
|
||||
CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF->SizeTy});
|
||||
return Builder.CreateCall(F, Metadata);
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVVsetvliBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, {ResultType});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVVSEMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
if (IsMasked) {
|
||||
// Builtin: (mask, ptr, value, vl).
|
||||
// Intrinsic: (value, ptr, mask, vl)
|
||||
std::swap(Ops[0], Ops[2]);
|
||||
} else {
|
||||
// Builtin: (ptr, value, vl).
|
||||
// Intrinsic: (value, ptr, vl)
|
||||
std::swap(Ops[0], Ops[1]);
|
||||
}
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
bool NoPassthru =
|
||||
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
|
||||
(!IsMasked && (PolicyAttrs & RVV_VTA));
|
||||
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(),
|
||||
Ops.back()->getType()};
|
||||
else
|
||||
IntrinsicTypes = {ResultType, Ops[Offset]->getType(),
|
||||
Ops.back()->getType()};
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if (NoPassthru)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
|
||||
if (ReturnValue.isNull())
|
||||
return LoadValue;
|
||||
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegStoreTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
// Masked
|
||||
// Builtin: (mask, ptr, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, mask, vl, SegInstSEW)
|
||||
// Unmasked
|
||||
// Builtin: (ptr, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, vl, SegInstSEW)
|
||||
if (IsMasked)
|
||||
std::swap(Ops[0], Ops[2]);
|
||||
else
|
||||
std::swap(Ops[0], Ops[1]);
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadFFTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
bool NoPassthru =
|
||||
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
|
||||
(!IsMasked && (PolicyAttrs & RVV_VTA));
|
||||
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(),
|
||||
Ops[0]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {ResultType, Ops.back()->getType(),
|
||||
Ops[Offset]->getType()};
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if (NoPassthru)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
Value *NewVL = Ops[2];
|
||||
Ops.erase(Ops.begin() + 2);
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
|
||||
// Get alignment from the new vl operand
|
||||
clang::CharUnits Align =
|
||||
CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType());
|
||||
llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0);
|
||||
// Store new_vl
|
||||
llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1);
|
||||
Builder.CreateStore(V, Address(NewVL, V->getType(), Align));
|
||||
if (ReturnValue.isNull())
|
||||
return ReturnTuple;
|
||||
return Builder.CreateStore(ReturnTuple, ReturnValue.getValue());
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegLoadTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
bool NoPassthru =
|
||||
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
|
||||
(!IsMasked && (PolicyAttrs & RVV_VTA));
|
||||
unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1;
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType(),
|
||||
Ops[0]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {ResultType, Ops[Offset]->getType(),
|
||||
Ops.back()->getType()};
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if (NoPassthru)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
|
||||
if (ReturnValue.isNull())
|
||||
return LoadValue;
|
||||
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegStoreTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 4> IntrinsicTypes;
|
||||
// Masked
|
||||
// Builtin: (mask, ptr, stride, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, stride, mask, vl, SegInstSEW)
|
||||
// Unmasked
|
||||
// Builtin: (ptr, stride, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, stride, vl, SegInstSEW)
|
||||
if (IsMasked)
|
||||
std::swap(Ops[0], Ops[3]);
|
||||
else
|
||||
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType(),
|
||||
Ops[3]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVAveragingBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, op1, round_mode, vl)
|
||||
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl,
|
||||
// policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F = CGM.getIntrinsic(
|
||||
ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVNarrowingClipBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, op1, round_mode, vl)
|
||||
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl,
|
||||
// policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F =
|
||||
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingPointBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, op1, round_mode, vl)
|
||||
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
bool HasRoundModeOp =
|
||||
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
|
||||
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F = CGM.getIntrinsic(
|
||||
ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVWideningFloatingPointBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, op1, round_mode, vl)
|
||||
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
bool HasRoundModeOp =
|
||||
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
|
||||
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F =
|
||||
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegLoadTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 5> IntrinsicTypes;
|
||||
|
||||
bool NoPassthru =
|
||||
(IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) |
|
||||
(!IsMasked && (PolicyAttrs & RVV_VTA));
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
|
||||
if (NoPassthru)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType(), Ops[4]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
|
||||
|
||||
if (ReturnValue.isNull())
|
||||
return LoadValue;
|
||||
return Builder.CreateStore(LoadValue, ReturnValue.getValue());
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegStoreTupleBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 5> IntrinsicTypes;
|
||||
// Masked
|
||||
// Builtin: (mask, ptr, index, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, index, mask, vl, SegInstSEW)
|
||||
// Unmasked
|
||||
// Builtin: (ptr, index, v_tuple, vl)
|
||||
// Intrinsic: (tuple, ptr, index, vl, SegInstSEW)
|
||||
|
||||
if (IsMasked)
|
||||
std::swap(Ops[0], Ops[3]);
|
||||
else
|
||||
std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
|
||||
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW));
|
||||
|
||||
if (IsMasked)
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType(), Ops[4]->getType()};
|
||||
else
|
||||
IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops[3]->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVFMABuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode,
|
||||
// vl, policy)
|
||||
// Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm,
|
||||
// vl, policy)
|
||||
|
||||
bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5;
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F = CGM.getIntrinsic(
|
||||
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVWideningFMABuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode, vl,
|
||||
// policy) Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm,
|
||||
// vl, policy)
|
||||
|
||||
bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5;
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 4);
|
||||
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F =
|
||||
CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(),
|
||||
Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingUnaryBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, round_mode, vl)
|
||||
// Masked: (passthru, op0, mask, frm, vl, policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
bool HasRoundModeOp =
|
||||
IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4)
|
||||
: (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3);
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
IntrinsicTypes = {ResultType, Ops.back()->getType()};
|
||||
llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingConvBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, frm, vl)
|
||||
// Masked: (passthru, op0, mask, frm, vl, policy)
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
bool HasRoundModeOp =
|
||||
IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4)
|
||||
: (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3);
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
if (IsMasked)
|
||||
Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
|
||||
|
||||
llvm::Function *F = CGM.getIntrinsic(
|
||||
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingReductionBuiltin(
|
||||
CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue,
|
||||
llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
llvm::SmallVector<llvm::Type *, 3> IntrinsicTypes;
|
||||
// LLVM intrinsic
|
||||
// Unmasked: (passthru, op0, op1, round_mode, vl)
|
||||
// Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy)
|
||||
|
||||
bool HasMaskedOff =
|
||||
!((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
|
||||
(!IsMasked && PolicyAttrs & RVV_VTA));
|
||||
bool HasRoundModeOp =
|
||||
IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5)
|
||||
: (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4);
|
||||
|
||||
if (!HasRoundModeOp)
|
||||
Ops.insert(Ops.end() - 1,
|
||||
ConstantInt::get(Ops.back()->getType(), 7)); // frm
|
||||
|
||||
if (IsMasked)
|
||||
std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2);
|
||||
|
||||
if (!HasMaskedOff)
|
||||
Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
|
||||
|
||||
llvm::Function *F = CGM.getIntrinsic(
|
||||
ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()});
|
||||
return Builder.CreateCall(F, Ops, "");
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVReinterpretBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto &CGM = CGF->CGM;
|
||||
|
||||
if (ResultType->isIntOrIntVectorTy(1) ||
|
||||
Ops[0]->getType()->isIntOrIntVectorTy(1)) {
|
||||
assert(isa<ScalableVectorType>(ResultType) &&
|
||||
isa<ScalableVectorType>(Ops[0]->getType()));
|
||||
|
||||
LLVMContext &Context = CGM.getLLVMContext();
|
||||
ScalableVectorType *Boolean64Ty =
|
||||
ScalableVectorType::get(llvm::Type::getInt1Ty(Context), 64);
|
||||
|
||||
if (ResultType->isIntOrIntVectorTy(1)) {
|
||||
// Casting from m1 vector integer -> vector boolean
|
||||
// Ex: <vscale x 8 x i8>
|
||||
// --(bitcast)--------> <vscale x 64 x i1>
|
||||
// --(vector_extract)-> <vscale x 8 x i1>
|
||||
llvm::Value *BitCast = Builder.CreateBitCast(Ops[0], Boolean64Ty);
|
||||
return Builder.CreateExtractVector(ResultType, BitCast,
|
||||
ConstantInt::get(CGF->Int64Ty, 0));
|
||||
} else {
|
||||
// Casting from vector boolean -> m1 vector integer
|
||||
// Ex: <vscale x 1 x i1>
|
||||
// --(vector_insert)-> <vscale x 64 x i1>
|
||||
// --(bitcast)-------> <vscale x 8 x i8>
|
||||
llvm::Value *Boolean64Val = Builder.CreateInsertVector(
|
||||
Boolean64Ty, llvm::PoisonValue::get(Boolean64Ty), Ops[0],
|
||||
ConstantInt::get(CGF->Int64Ty, 0));
|
||||
return Builder.CreateBitCast(Boolean64Val, ResultType);
|
||||
}
|
||||
}
|
||||
return Builder.CreateBitCast(Ops[0], ResultType);
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVGetBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
auto *VecTy = cast<ScalableVectorType>(ResultType);
|
||||
if (auto *OpVecTy = dyn_cast<ScalableVectorType>(Ops[0]->getType())) {
|
||||
unsigned MaxIndex =
|
||||
OpVecTy->getMinNumElements() / VecTy->getMinNumElements();
|
||||
assert(isPowerOf2_32(MaxIndex));
|
||||
// Mask to only valid indices.
|
||||
Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty());
|
||||
Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
|
||||
Ops[1] =
|
||||
Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(),
|
||||
VecTy->getMinNumElements()));
|
||||
return Builder.CreateExtractVector(ResultType, Ops[0], Ops[1]);
|
||||
}
|
||||
|
||||
return Builder.CreateIntrinsic(
|
||||
Intrinsic::riscv_tuple_extract, {ResultType, Ops[0]->getType()},
|
||||
{Ops[0], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())});
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVSetBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
if (auto *ResVecTy = dyn_cast<ScalableVectorType>(ResultType)) {
|
||||
auto *VecTy = cast<ScalableVectorType>(Ops[2]->getType());
|
||||
unsigned MaxIndex =
|
||||
ResVecTy->getMinNumElements() / VecTy->getMinNumElements();
|
||||
assert(isPowerOf2_32(MaxIndex));
|
||||
// Mask to only valid indices.
|
||||
Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty());
|
||||
Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1);
|
||||
Ops[1] =
|
||||
Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(),
|
||||
VecTy->getMinNumElements()));
|
||||
return Builder.CreateInsertVector(ResultType, Ops[0], Ops[2], Ops[1]);
|
||||
}
|
||||
|
||||
return Builder.CreateIntrinsic(
|
||||
Intrinsic::riscv_tuple_insert, {ResultType, Ops[2]->getType()},
|
||||
{Ops[0], Ops[2], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())});
|
||||
}
|
||||
|
||||
static LLVM_ATTRIBUTE_NOINLINE Value *
|
||||
emitRVVCreateBuiltin(CodeGenFunction *CGF, const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue, llvm::Type *ResultType,
|
||||
Intrinsic::ID ID, SmallVectorImpl<Value *> &Ops,
|
||||
int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) {
|
||||
auto &Builder = CGF->Builder;
|
||||
llvm::Value *ReturnVector = llvm::PoisonValue::get(ResultType);
|
||||
auto *VecTy = cast<ScalableVectorType>(Ops[0]->getType());
|
||||
for (unsigned I = 0, N = Ops.size(); I < N; ++I) {
|
||||
if (isa<ScalableVectorType>(ResultType)) {
|
||||
llvm::Value *Idx = ConstantInt::get(Builder.getInt64Ty(),
|
||||
VecTy->getMinNumElements() * I);
|
||||
ReturnVector =
|
||||
Builder.CreateInsertVector(ResultType, ReturnVector, Ops[I], Idx);
|
||||
} else {
|
||||
llvm::Value *Idx = ConstantInt::get(Builder.getInt32Ty(), I);
|
||||
ReturnVector = Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert,
|
||||
{ResultType, Ops[I]->getType()},
|
||||
{ReturnVector, Ops[I], Idx});
|
||||
}
|
||||
}
|
||||
return ReturnVector;
|
||||
}
|
||||
|
||||
Value *CodeGenFunction::EmitRISCVCpuInit() {
|
||||
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {VoidPtrTy}, false);
|
||||
llvm::FunctionCallee Func =
|
||||
@@ -180,10 +1125,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
|
||||
}
|
||||
|
||||
Intrinsic::ID ID = Intrinsic::not_intrinsic;
|
||||
// The 0th bit simulates the `vta` of RVV
|
||||
// The 1st bit simulates the `vma` of RVV
|
||||
constexpr unsigned RVV_VTA = 0x1;
|
||||
constexpr unsigned RVV_VMA = 0x2;
|
||||
int PolicyAttrs = 0;
|
||||
bool IsMasked = false;
|
||||
// This is used by segment load/store to determine it's llvm type.
|
||||
|
||||
@@ -75,6 +75,8 @@ TargetCodeGenInfo::~TargetCodeGenInfo() = default;
|
||||
// If someone can figure out a general rule for this, that would be great.
|
||||
// It's probably just doomed to be platform-dependent, though.
|
||||
unsigned TargetCodeGenInfo::getSizeOfUnwindException() const {
|
||||
if (getABIInfo().getContext().getLangOpts().hasSEHExceptions())
|
||||
return getABIInfo().getDataLayout().getPointerSizeInBits() > 32 ? 64 : 48;
|
||||
// Verified for:
|
||||
// x86-64 FreeBSD, Linux, Darwin
|
||||
// x86-32 FreeBSD, Linux, Darwin
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "ABIInfoImpl.h"
|
||||
#include "TargetInfo.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::CodeGen;
|
||||
@@ -109,7 +110,8 @@ class SparcV9ABIInfo : public ABIInfo {
|
||||
SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
|
||||
|
||||
private:
|
||||
ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
|
||||
ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit,
|
||||
unsigned &RegOffset) const;
|
||||
void computeInfo(CGFunctionInfo &FI) const override;
|
||||
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
|
||||
AggValueSlot Slot) const override;
|
||||
@@ -222,127 +224,114 @@ class SparcV9ABIInfo : public ABIInfo {
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
ABIArgInfo
|
||||
SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
|
||||
ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,
|
||||
unsigned &RegOffset) const {
|
||||
if (Ty->isVoidType())
|
||||
return ABIArgInfo::getIgnore();
|
||||
|
||||
uint64_t Size = getContext().getTypeSize(Ty);
|
||||
auto &Context = getContext();
|
||||
auto &VMContext = getVMContext();
|
||||
|
||||
uint64_t Size = Context.getTypeSize(Ty);
|
||||
unsigned Alignment = Context.getTypeAlign(Ty);
|
||||
bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0);
|
||||
|
||||
// Anything too big to fit in registers is passed with an explicit indirect
|
||||
// pointer / sret pointer.
|
||||
if (Size > SizeLimit)
|
||||
if (Size > SizeLimit) {
|
||||
RegOffset += 1;
|
||||
return getNaturalAlignIndirect(
|
||||
Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
|
||||
/*ByVal=*/false);
|
||||
}
|
||||
|
||||
// Treat an enum type as its underlying type.
|
||||
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
|
||||
Ty = EnumTy->getDecl()->getIntegerType();
|
||||
|
||||
// Integer types smaller than a register are extended.
|
||||
if (Size < 64 && Ty->isIntegerType())
|
||||
if (Size < 64 && Ty->isIntegerType()) {
|
||||
RegOffset += 1;
|
||||
return ABIArgInfo::getExtend(Ty);
|
||||
}
|
||||
|
||||
if (const auto *EIT = Ty->getAs<BitIntType>())
|
||||
if (EIT->getNumBits() < 64)
|
||||
if (EIT->getNumBits() < 64) {
|
||||
RegOffset += 1;
|
||||
return ABIArgInfo::getExtend(Ty);
|
||||
}
|
||||
|
||||
// Other non-aggregates go in registers.
|
||||
if (!isAggregateTypeForABI(Ty))
|
||||
if (!isAggregateTypeForABI(Ty)) {
|
||||
RegOffset += Size / 64;
|
||||
return ABIArgInfo::getDirect();
|
||||
}
|
||||
|
||||
// If a C++ object has either a non-trivial copy constructor or a non-trivial
|
||||
// destructor, it is passed with an explicit indirect pointer / sret pointer.
|
||||
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
|
||||
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
|
||||
RegOffset += 1;
|
||||
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
|
||||
RAA == CGCXXABI::RAA_DirectInMemory);
|
||||
}
|
||||
|
||||
// This is a small aggregate type that should be passed in registers.
|
||||
// Build a coercion type from the LLVM struct type.
|
||||
llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
|
||||
if (!StrTy)
|
||||
if (!StrTy) {
|
||||
RegOffset += Size / 64;
|
||||
return ABIArgInfo::getDirect();
|
||||
}
|
||||
|
||||
CoerceBuilder CB(getVMContext(), getDataLayout());
|
||||
CoerceBuilder CB(VMContext, getDataLayout());
|
||||
CB.addStruct(0, StrTy);
|
||||
// All structs, even empty ones, should take up a register argument slot,
|
||||
// so pin the minimum struct size to one bit.
|
||||
CB.pad(llvm::alignTo(
|
||||
std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),
|
||||
64));
|
||||
RegOffset += CB.Size / 64;
|
||||
|
||||
// If we're dealing with overaligned structs we may need to add a padding in
|
||||
// the front, to preserve the correct register-memory mapping.
|
||||
//
|
||||
// See SCD 2.4.1, pages 3P-11 and 3P-12.
|
||||
llvm::Type *Padding =
|
||||
NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr;
|
||||
RegOffset += NeedPadding ? 1 : 0;
|
||||
|
||||
// Try to use the original type for coercion.
|
||||
llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
|
||||
|
||||
if (CB.InReg)
|
||||
return ABIArgInfo::getDirectInReg(CoerceTy);
|
||||
else
|
||||
return ABIArgInfo::getDirect(CoerceTy);
|
||||
ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);
|
||||
AAI.setInReg(CB.InReg);
|
||||
return AAI;
|
||||
}
|
||||
|
||||
RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
||||
QualType Ty, AggValueSlot Slot) const {
|
||||
ABIArgInfo AI = classifyType(Ty, 16 * 8);
|
||||
llvm::Type *ArgTy = CGT.ConvertType(Ty);
|
||||
if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
|
||||
AI.setCoerceToType(ArgTy);
|
||||
|
||||
CharUnits SlotSize = CharUnits::fromQuantity(8);
|
||||
auto TInfo = getContext().getTypeInfoInChars(Ty);
|
||||
|
||||
CGBuilderTy &Builder = CGF.Builder;
|
||||
Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"),
|
||||
getVAListElementType(CGF), SlotSize);
|
||||
llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
|
||||
// Zero-sized types have a width of one byte for parameter passing purposes.
|
||||
TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));
|
||||
|
||||
auto TypeInfo = getContext().getTypeInfoInChars(Ty);
|
||||
|
||||
Address ArgAddr = Address::invalid();
|
||||
CharUnits Stride;
|
||||
switch (AI.getKind()) {
|
||||
case ABIArgInfo::Expand:
|
||||
case ABIArgInfo::CoerceAndExpand:
|
||||
case ABIArgInfo::InAlloca:
|
||||
llvm_unreachable("Unsupported ABI kind for va_arg");
|
||||
|
||||
case ABIArgInfo::Extend: {
|
||||
Stride = SlotSize;
|
||||
CharUnits Offset = SlotSize - TypeInfo.Width;
|
||||
ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Direct: {
|
||||
auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
|
||||
Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);
|
||||
ArgAddr = Addr;
|
||||
break;
|
||||
}
|
||||
|
||||
case ABIArgInfo::Indirect:
|
||||
case ABIArgInfo::IndirectAliased:
|
||||
Stride = SlotSize;
|
||||
ArgAddr = Addr.withElementType(ArgPtrTy);
|
||||
ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,
|
||||
TypeInfo.Align);
|
||||
break;
|
||||
|
||||
case ABIArgInfo::Ignore:
|
||||
return Slot.asRValue();
|
||||
}
|
||||
|
||||
// Update VAList.
|
||||
Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next");
|
||||
Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);
|
||||
|
||||
return CGF.EmitLoadOfAnyValue(
|
||||
CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot);
|
||||
// Arguments bigger than 2*SlotSize bytes are passed indirectly.
|
||||
return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
|
||||
/*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
|
||||
SlotSize,
|
||||
/*AllowHigherAlign=*/true, Slot);
|
||||
}
|
||||
|
||||
void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
|
||||
FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);
|
||||
unsigned RetOffset = 0;
|
||||
ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset);
|
||||
FI.getReturnInfo() = RetType;
|
||||
|
||||
// Indirect returns will have its pointer passed as an argument.
|
||||
unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0;
|
||||
for (auto &I : FI.arguments())
|
||||
I.info = classifyType(I.type, 16 * 8);
|
||||
I.info = classifyType(I.type, 16 * 8, ArgOffset);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -837,17 +837,30 @@ void ToolChain::addFortranRuntimeLibs(const ArgList &Args,
|
||||
|
||||
void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args,
|
||||
ArgStringList &CmdArgs) const {
|
||||
// Default to the <driver-path>/../lib directory. This works fine on the
|
||||
// platforms that we have tested so far. We will probably have to re-fine
|
||||
// this in the future. In particular, on some platforms, we may need to use
|
||||
// lib64 instead of lib.
|
||||
auto AddLibSearchPathIfExists = [&](const Twine &Path) {
|
||||
// Linker may emit warnings about non-existing directories
|
||||
if (!llvm::sys::fs::is_directory(Path))
|
||||
return;
|
||||
|
||||
if (getTriple().isKnownWindowsMSVCEnvironment())
|
||||
CmdArgs.push_back(Args.MakeArgString("-libpath:" + Path));
|
||||
else
|
||||
CmdArgs.push_back(Args.MakeArgString("-L" + Path));
|
||||
};
|
||||
|
||||
// Search for flang_rt.* at the same location as clang_rt.* with
|
||||
// LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0. On most platforms, flang_rt is
|
||||
// located at the path returned by getRuntimePath() which is already added to
|
||||
// the library search path. This exception is for Apple-Darwin.
|
||||
AddLibSearchPathIfExists(getCompilerRTPath());
|
||||
|
||||
// Fall back to the non-resource directory <driver-path>/../lib. We will
|
||||
// probably have to refine this in the future. In particular, on some
|
||||
// platforms, we may need to use lib64 instead of lib.
|
||||
SmallString<256> DefaultLibPath =
|
||||
llvm::sys::path::parent_path(getDriver().Dir);
|
||||
llvm::sys::path::append(DefaultLibPath, "lib");
|
||||
if (getTriple().isKnownWindowsMSVCEnvironment())
|
||||
CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
|
||||
else
|
||||
CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
|
||||
AddLibSearchPathIfExists(DefaultLibPath);
|
||||
}
|
||||
|
||||
void ToolChain::addFlangRTLibPath(const ArgList &Args,
|
||||
|
||||
@@ -467,3 +467,18 @@ void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the triple {aarch64.aarch64_be}-none-elf?
|
||||
bool aarch64::isAArch64BareMetal(const llvm::Triple &Triple) {
|
||||
if (Triple.getArch() != llvm::Triple::aarch64 &&
|
||||
Triple.getArch() != llvm::Triple::aarch64_be)
|
||||
return false;
|
||||
|
||||
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
|
||||
return false;
|
||||
|
||||
if (Triple.getOS() != llvm::Triple::UnknownOS)
|
||||
return false;
|
||||
|
||||
return Triple.getEnvironmentName() == "elf";
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
|
||||
|
||||
void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
|
||||
llvm::Triple &triple);
|
||||
bool isAArch64BareMetal(const llvm::Triple &Triple);
|
||||
|
||||
} // end namespace aarch64
|
||||
} // end namespace target
|
||||
|
||||
@@ -23,7 +23,9 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
||||
if (Triple.getArch() == llvm::Triple::sparcv9) {
|
||||
const char *DefV9CPU;
|
||||
|
||||
if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
|
||||
if (Triple.isOSSolaris())
|
||||
DefV9CPU = "-Av9b";
|
||||
else if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
|
||||
DefV9CPU = "-Av9a";
|
||||
else
|
||||
DefV9CPU = "-Av9";
|
||||
@@ -35,6 +37,13 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
||||
.Case("niagara4", "-Av9d")
|
||||
.Default(DefV9CPU);
|
||||
} else {
|
||||
const char *DefV8CPU;
|
||||
|
||||
if (Triple.isOSSolaris())
|
||||
DefV8CPU = "-Av8plus";
|
||||
else
|
||||
DefV8CPU = "-Av8";
|
||||
|
||||
return llvm::StringSwitch<const char *>(Name)
|
||||
.Case("v8", "-Av8")
|
||||
.Case("supersparc", "-Av8")
|
||||
@@ -70,7 +79,7 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
|
||||
.Case("gr712rc", "-Aleon")
|
||||
.Case("leon4", "-Aleon")
|
||||
.Case("gr740", "-Aleon")
|
||||
.Default("-Av8");
|
||||
.Default(DefV8CPU);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +139,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args,
|
||||
return "";
|
||||
}
|
||||
|
||||
void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
||||
void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
const ArgList &Args,
|
||||
std::vector<StringRef> &Features) {
|
||||
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
|
||||
if (FloatABI == sparc::FloatABI::Soft)
|
||||
@@ -150,11 +160,22 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
||||
Features.push_back("-popc");
|
||||
}
|
||||
|
||||
// Those OSes default to enabling VIS on 64-bit SPARC.
|
||||
// See also the corresponding code for external assemblers in
|
||||
// sparc::getSparcAsmModeForCPU().
|
||||
bool IsSparcV9ATarget =
|
||||
(Triple.getArch() == llvm::Triple::sparcv9) &&
|
||||
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
|
||||
bool IsSparcV9BTarget = Triple.isOSSolaris();
|
||||
bool IsSparcV8PlusTarget =
|
||||
Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris();
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
|
||||
if (A->getOption().matches(options::OPT_mvis))
|
||||
Features.push_back("+vis");
|
||||
else
|
||||
Features.push_back("-vis");
|
||||
} else if (IsSparcV9ATarget) {
|
||||
Features.push_back("+vis");
|
||||
}
|
||||
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
|
||||
@@ -162,6 +183,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
||||
Features.push_back("+vis2");
|
||||
else
|
||||
Features.push_back("-vis2");
|
||||
} else if (IsSparcV9BTarget) {
|
||||
Features.push_back("+vis2");
|
||||
}
|
||||
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
|
||||
@@ -182,6 +205,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
|
||||
if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) {
|
||||
if (A->getOption().matches(options::OPT_mv8plus))
|
||||
Features.push_back("+v8plus");
|
||||
} else if (IsSparcV8PlusTarget) {
|
||||
Features.push_back("+v8plus");
|
||||
}
|
||||
|
||||
if (Args.hasArg(options::OPT_ffixed_g1))
|
||||
|
||||
@@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
|
||||
std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
|
||||
const llvm::Triple &Triple);
|
||||
|
||||
void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
|
||||
void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
const llvm::opt::ArgList &Args,
|
||||
std::vector<llvm::StringRef> &Features);
|
||||
const char *getSparcAsmModeForCPU(llvm::StringRef Name,
|
||||
const llvm::Triple &Triple);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "clang/Driver/CommonArgs.h"
|
||||
#include "clang/Driver/InputInfo.h"
|
||||
|
||||
#include "Arch/AArch64.h"
|
||||
#include "Arch/ARM.h"
|
||||
#include "Arch/RISCV.h"
|
||||
#include "clang/Driver/Compilation.h"
|
||||
@@ -31,21 +32,6 @@ using namespace clang::driver;
|
||||
using namespace clang::driver::tools;
|
||||
using namespace clang::driver::toolchains;
|
||||
|
||||
/// Is the triple {aarch64.aarch64_be}-none-elf?
|
||||
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
|
||||
if (Triple.getArch() != llvm::Triple::aarch64 &&
|
||||
Triple.getArch() != llvm::Triple::aarch64_be)
|
||||
return false;
|
||||
|
||||
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
|
||||
return false;
|
||||
|
||||
if (Triple.getOS() != llvm::Triple::UnknownOS)
|
||||
return false;
|
||||
|
||||
return Triple.getEnvironmentName() == "elf";
|
||||
}
|
||||
|
||||
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
|
||||
if (!Triple.isRISCV())
|
||||
return false;
|
||||
@@ -363,8 +349,9 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
|
||||
}
|
||||
|
||||
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
|
||||
return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) ||
|
||||
isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
|
||||
return arm::isARMEABIBareMetal(Triple) ||
|
||||
aarch64::isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) ||
|
||||
isPPCBareMetal(Triple);
|
||||
}
|
||||
|
||||
Tool *BareMetal::buildLinker() const {
|
||||
@@ -694,9 +681,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
NeedCRTs)
|
||||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd)));
|
||||
|
||||
if (TC.getTriple().isRISCV())
|
||||
CmdArgs.push_back("-X");
|
||||
|
||||
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
|
||||
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
|
||||
// arm*-*-*bsd).
|
||||
|
||||
@@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
|
||||
options::OPT_fno_ptrauth_objc_interface_sel);
|
||||
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
|
||||
options::OPT_fno_ptrauth_objc_class_ro);
|
||||
|
||||
if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
|
||||
handlePAuthABI(Args, CmdArgs);
|
||||
|
||||
@@ -2731,16 +2730,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
|
||||
CmdArgs.push_back(MipsTargetFeature);
|
||||
}
|
||||
|
||||
// Those OSes default to enabling VIS on 64-bit SPARC.
|
||||
// See also the corresponding code for external assemblers in
|
||||
// sparc::getSparcAsmModeForCPU().
|
||||
bool IsSparcV9ATarget =
|
||||
(C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) &&
|
||||
(Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
|
||||
if (IsSparcV9ATarget && SparcTargetFeatures.empty()) {
|
||||
CmdArgs.push_back("-target-feature");
|
||||
CmdArgs.push_back("+vis");
|
||||
}
|
||||
for (const char *Feature : SparcTargetFeatures) {
|
||||
CmdArgs.push_back("-target-feature");
|
||||
CmdArgs.push_back(Feature);
|
||||
|
||||
@@ -547,15 +547,22 @@ const char *tools::getLDMOption(const llvm::Triple &T, const ArgList &Args) {
|
||||
case llvm::Triple::aarch64:
|
||||
if (T.isOSManagarm())
|
||||
return "aarch64managarm";
|
||||
else if (aarch64::isAArch64BareMetal(T))
|
||||
return "aarch64elf";
|
||||
return "aarch64linux";
|
||||
case llvm::Triple::aarch64_be:
|
||||
if (aarch64::isAArch64BareMetal(T))
|
||||
return "aarch64elfb";
|
||||
return "aarch64linuxb";
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
case llvm::Triple::armeb:
|
||||
case llvm::Triple::thumbeb:
|
||||
return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi"
|
||||
: "armelf_linux_eabi";
|
||||
case llvm::Triple::thumbeb: {
|
||||
bool IsBigEndian = tools::arm::isARMBigEndian(T, Args);
|
||||
if (arm::isARMEABIBareMetal(T))
|
||||
return IsBigEndian ? "armelfb" : "armelf";
|
||||
return IsBigEndian ? "armelfb_linux_eabi" : "armelf_linux_eabi";
|
||||
}
|
||||
case llvm::Triple::m68k:
|
||||
return "m68kelf";
|
||||
case llvm::Triple::ppc:
|
||||
@@ -856,7 +863,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
case llvm::Triple::sparc:
|
||||
case llvm::Triple::sparcel:
|
||||
case llvm::Triple::sparcv9:
|
||||
sparc::getSparcTargetFeatures(D, Args, Features);
|
||||
sparc::getSparcTargetFeatures(D, Triple, Args, Features);
|
||||
break;
|
||||
case llvm::Triple::r600:
|
||||
case llvm::Triple::amdgcn:
|
||||
@@ -1320,6 +1327,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
|
||||
if (Args.hasArg(options::OPT_ftime_report))
|
||||
CmdArgs.push_back(
|
||||
Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
|
||||
|
||||
if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) {
|
||||
CmdArgs.push_back(
|
||||
Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue())));
|
||||
CmdArgs.push_back(
|
||||
Args.MakeArgString("--thinlto-remote-compiler=" +
|
||||
Twine(ToolChain.getDriver().getClangProgramPath())));
|
||||
|
||||
for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ))
|
||||
CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A));
|
||||
}
|
||||
}
|
||||
|
||||
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
|
||||
@@ -3247,14 +3265,8 @@ void tools::handleVectorizeSLPArgs(const ArgList &Args,
|
||||
|
||||
void tools::handleInterchangeLoopsArgs(const ArgList &Args,
|
||||
ArgStringList &CmdArgs) {
|
||||
// FIXME: instead of relying on shouldEnableVectorizerAtOLevel, we may want to
|
||||
// implement a separate function to infer loop interchange from opt level.
|
||||
// For now, enable loop-interchange at the same opt levels as loop-vectorize.
|
||||
bool EnableInterchange = shouldEnableVectorizerAtOLevel(Args, false);
|
||||
OptSpecifier InterchangeAliasOption =
|
||||
EnableInterchange ? options::OPT_O_Group : options::OPT_floop_interchange;
|
||||
if (Args.hasFlag(options::OPT_floop_interchange, InterchangeAliasOption,
|
||||
options::OPT_fno_loop_interchange, EnableInterchange))
|
||||
if (Args.hasFlag(options::OPT_floop_interchange,
|
||||
options::OPT_fno_loop_interchange, false))
|
||||
CmdArgs.push_back("-floop-interchange");
|
||||
}
|
||||
|
||||
|
||||
@@ -3187,28 +3187,46 @@ void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
||||
|
||||
ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
|
||||
|
||||
// On arm64e, enable pointer authentication (for the return address and
|
||||
// indirect calls), as well as usage of the intrinsics.
|
||||
if (getArchName() == "arm64e") {
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
|
||||
options::OPT_fno_ptrauth_returns))
|
||||
CC1Args.push_back("-fptrauth-returns");
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
|
||||
options::OPT_fno_ptrauth_intrinsics))
|
||||
CC1Args.push_back("-fptrauth-intrinsics");
|
||||
|
||||
// On arm64e, we enable all the features required for the Darwin userspace
|
||||
// ABI
|
||||
if (getTriple().isArm64e()) {
|
||||
// Core platform ABI
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
|
||||
options::OPT_fno_ptrauth_calls))
|
||||
CC1Args.push_back("-fptrauth-calls");
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
|
||||
options::OPT_fno_ptrauth_returns))
|
||||
CC1Args.push_back("-fptrauth-returns");
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
|
||||
options::OPT_fno_ptrauth_intrinsics))
|
||||
CC1Args.push_back("-fptrauth-intrinsics");
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
|
||||
options::OPT_fno_ptrauth_indirect_gotos))
|
||||
CC1Args.push_back("-fptrauth-indirect-gotos");
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
|
||||
options::OPT_fno_ptrauth_auth_traps))
|
||||
CC1Args.push_back("-fptrauth-auth-traps");
|
||||
|
||||
// C++ v-table ABI
|
||||
if (!DriverArgs.hasArg(
|
||||
options::OPT_fptrauth_vtable_pointer_address_discrimination,
|
||||
options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))
|
||||
CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");
|
||||
if (!DriverArgs.hasArg(
|
||||
options::OPT_fptrauth_vtable_pointer_type_discrimination,
|
||||
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
|
||||
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");
|
||||
|
||||
// Objective-C ABI
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_isa,
|
||||
options::OPT_fno_ptrauth_objc_isa))
|
||||
CC1Args.push_back("-fptrauth-objc-isa");
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_class_ro,
|
||||
options::OPT_fno_ptrauth_objc_class_ro))
|
||||
CC1Args.push_back("-fptrauth-objc-class-ro");
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_interface_sel,
|
||||
options::OPT_fno_ptrauth_objc_interface_sel))
|
||||
CC1Args.push_back("-fptrauth-objc-interface-sel");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args,
|
||||
// Add the target features.
|
||||
switch (TC.getArch()) {
|
||||
default:
|
||||
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
|
||||
break;
|
||||
case llvm::Triple::aarch64:
|
||||
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
|
||||
|
||||
@@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
|
||||
|
||||
CmdArgs.push_back("-lmoldname");
|
||||
CmdArgs.push_back("-lmingwex");
|
||||
for (auto Lib : Args.getAllArgValues(options::OPT_l))
|
||||
for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
|
||||
if (StringRef(Lib).starts_with("msvcr") ||
|
||||
StringRef(Lib).starts_with("ucrt") ||
|
||||
StringRef(Lib).starts_with("crtdll"))
|
||||
StringRef(Lib).starts_with("crtdll")) {
|
||||
std::string CRTLib = (llvm::Twine("-l") + Lib).str();
|
||||
// Respect the user's chosen crt variant, but still provide it
|
||||
// again as the last linker argument, because some of the libraries
|
||||
// we added above may depend on it.
|
||||
CmdArgs.push_back(Args.MakeArgStringRef(CRTLib));
|
||||
return;
|
||||
}
|
||||
}
|
||||
CmdArgs.push_back("-lmsvcrt");
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
if (Nopie || Profiling)
|
||||
CmdArgs.push_back("-nopie");
|
||||
|
||||
if (Triple.isRISCV64()) {
|
||||
if (Triple.isLoongArch64() || Triple.isRISCV64()) {
|
||||
CmdArgs.push_back("-X");
|
||||
if (Args.hasArg(options::OPT_mno_relax))
|
||||
CmdArgs.push_back("--no-relax");
|
||||
|
||||
@@ -411,7 +411,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
}
|
||||
if (CurrentState.BreakBeforeClosingBrace &&
|
||||
(Current.closesBlockOrBlockTypeList(Style) ||
|
||||
(Current.is(tok::r_brace) &&
|
||||
(Current.is(tok::r_brace) && Current.MatchingParen &&
|
||||
Current.isBlockIndentedInitRBrace(Style)))) {
|
||||
return true;
|
||||
}
|
||||
@@ -628,9 +628,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
|
||||
// name.
|
||||
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
|
||||
CurrentState.BreakBeforeParameter) {
|
||||
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous)
|
||||
if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment))
|
||||
for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) {
|
||||
if (Tok->is(TT_LineComment))
|
||||
return false;
|
||||
if (Tok->is(TT_TemplateCloser)) {
|
||||
Tok = Tok->MatchingParen;
|
||||
assert(Tok);
|
||||
}
|
||||
if (Tok->FirstAfterPPLine)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -727,6 +727,7 @@ template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
|
||||
IO.mapOptional("AfterFunctionDeclarationName",
|
||||
Spacing.AfterFunctionDeclarationName);
|
||||
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
|
||||
IO.mapOptional("AfterNot", Spacing.AfterNot);
|
||||
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
|
||||
IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
|
||||
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
|
||||
@@ -1748,7 +1749,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
||||
GoogleStyle.AttributeMacros.push_back("absl_nullable");
|
||||
GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
|
||||
GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
|
||||
GoogleStyle.DerivePointerAlignment = true;
|
||||
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
|
||||
GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
|
||||
{"^<.*\\.h>", 1, 0, false},
|
||||
@@ -1857,6 +1857,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
|
||||
} else if (Language == FormatStyle::LK_ObjC) {
|
||||
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
|
||||
GoogleStyle.ColumnLimit = 100;
|
||||
GoogleStyle.DerivePointerAlignment = true;
|
||||
// "Regroup" doesn't work well for ObjC yet (main header heuristic,
|
||||
// relationship between ObjC standard library headers and other heades,
|
||||
// #imports, etc.)
|
||||
@@ -2131,48 +2132,70 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
|
||||
Input >> Styles;
|
||||
if (Input.error())
|
||||
return Input.error();
|
||||
if (Styles.empty())
|
||||
return make_error_code(ParseError::Success);
|
||||
|
||||
for (unsigned i = 0; i < Styles.size(); ++i) {
|
||||
// Ensures that only the first configuration can skip the Language option.
|
||||
if (Styles[i].Language == FormatStyle::LK_None && i != 0)
|
||||
const auto StyleCount = Styles.size();
|
||||
|
||||
// Start from the second style as (only) the first one may be the default.
|
||||
for (unsigned I = 1; I < StyleCount; ++I) {
|
||||
const auto Lang = Styles[I].Language;
|
||||
if (Lang == FormatStyle::LK_None)
|
||||
return make_error_code(ParseError::Error);
|
||||
// Ensure that each language is configured at most once.
|
||||
for (unsigned j = 0; j < i; ++j) {
|
||||
if (Styles[i].Language == Styles[j].Language) {
|
||||
for (unsigned J = 0; J < I; ++J) {
|
||||
if (Lang == Styles[J].Language) {
|
||||
LLVM_DEBUG(llvm::dbgs()
|
||||
<< "Duplicate languages in the config file on positions "
|
||||
<< j << " and " << i << "\n");
|
||||
<< J << " and " << I << '\n');
|
||||
return make_error_code(ParseError::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Look for a suitable configuration starting from the end, so we can
|
||||
// find the configuration for the specific language first, and the default
|
||||
// configuration (which can only be at slot 0) after it.
|
||||
FormatStyle::FormatStyleSet StyleSet;
|
||||
bool LanguageFound = false;
|
||||
for (const FormatStyle &Style : llvm::reverse(Styles)) {
|
||||
const auto Lang = Style.Language;
|
||||
if (Lang != FormatStyle::LK_None)
|
||||
StyleSet.Add(Style);
|
||||
if (Lang == Language ||
|
||||
// For backward compatibility.
|
||||
(Lang == FormatStyle::LK_Cpp && Language == FormatStyle::LK_C)) {
|
||||
LanguageFound = true;
|
||||
} else if (IsDotHFile && Language == FormatStyle::LK_Cpp &&
|
||||
(Lang == FormatStyle::LK_C || Lang == FormatStyle::LK_ObjC)) {
|
||||
Language = Lang;
|
||||
LanguageFound = true;
|
||||
|
||||
int LanguagePos = -1; // Position of the style for Language.
|
||||
int CppPos = -1; // Position of the style for C++.
|
||||
int CPos = -1; // Position of the style for C.
|
||||
|
||||
// Search Styles for Language and store the positions of C++ and C styles in
|
||||
// case Language is not found.
|
||||
for (unsigned I = 0; I < StyleCount; ++I) {
|
||||
const auto Lang = Styles[I].Language;
|
||||
if (Lang == Language) {
|
||||
LanguagePos = I;
|
||||
break;
|
||||
}
|
||||
if (Lang == FormatStyle::LK_Cpp)
|
||||
CppPos = I;
|
||||
else if (Lang == FormatStyle::LK_C)
|
||||
CPos = I;
|
||||
}
|
||||
if (!LanguageFound) {
|
||||
if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
|
||||
|
||||
// If Language is not found, use the default style if there is one. Otherwise,
|
||||
// use the C style for C++ .h files and for backward compatibility, the C++
|
||||
// style for .c files.
|
||||
if (LanguagePos < 0) {
|
||||
if (Styles[0].Language == FormatStyle::LK_None) // Default style.
|
||||
LanguagePos = 0;
|
||||
else if (IsDotHFile && Language == FormatStyle::LK_Cpp)
|
||||
LanguagePos = CPos;
|
||||
else if (!IsDotHFile && Language == FormatStyle::LK_C)
|
||||
LanguagePos = CppPos;
|
||||
if (LanguagePos < 0)
|
||||
return make_error_code(ParseError::Unsuitable);
|
||||
FormatStyle DefaultStyle = Styles[0];
|
||||
DefaultStyle.Language = Language;
|
||||
StyleSet.Add(std::move(DefaultStyle));
|
||||
}
|
||||
*Style = *StyleSet.Get(Language);
|
||||
|
||||
for (const auto &S : llvm::reverse(llvm::drop_begin(Styles)))
|
||||
Style->StyleSet.Add(S);
|
||||
|
||||
*Style = Styles[LanguagePos];
|
||||
|
||||
if (LanguagePos == 0) {
|
||||
if (Style->Language == FormatStyle::LK_None) // Default style.
|
||||
Style->Language = Language;
|
||||
Style->StyleSet.Add(*Style);
|
||||
}
|
||||
|
||||
if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
|
||||
Style->BinPackArguments) {
|
||||
// See comment on FormatStyle::TSC_Wrapped.
|
||||
@@ -2203,14 +2226,8 @@ FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
|
||||
if (!Styles)
|
||||
return std::nullopt;
|
||||
auto It = Styles->find(Language);
|
||||
if (It == Styles->end()) {
|
||||
if (Language != FormatStyle::LK_C)
|
||||
return std::nullopt;
|
||||
// For backward compatibility.
|
||||
It = Styles->find(FormatStyle::LK_Cpp);
|
||||
if (It == Styles->end())
|
||||
return std::nullopt;
|
||||
}
|
||||
if (It == Styles->end())
|
||||
return std::nullopt;
|
||||
FormatStyle Style = It->second;
|
||||
Style.StyleSet = *this;
|
||||
return Style;
|
||||
@@ -4042,6 +4059,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
|
||||
switch (Style.Language) {
|
||||
case FormatStyle::LK_C:
|
||||
LangOpts.C11 = 1;
|
||||
LangOpts.C23 = 1;
|
||||
break;
|
||||
case FormatStyle::LK_Cpp:
|
||||
case FormatStyle::LK_ObjC:
|
||||
|
||||
@@ -53,12 +53,13 @@ bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const {
|
||||
|
||||
bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const {
|
||||
assert(is(tok::r_brace));
|
||||
assert(MatchingParen);
|
||||
assert(MatchingParen->is(tok::l_brace));
|
||||
if (!Style.Cpp11BracedListStyle ||
|
||||
Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent) {
|
||||
return false;
|
||||
}
|
||||
const auto *LBrace = MatchingParen;
|
||||
assert(LBrace && LBrace->is(tok::l_brace));
|
||||
if (LBrace->is(BK_BracedInit))
|
||||
return true;
|
||||
if (LBrace->Previous && LBrace->Previous->is(tok::equal))
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace format {
|
||||
TYPE(ConflictAlternative) \
|
||||
TYPE(ConflictEnd) \
|
||||
TYPE(ConflictStart) \
|
||||
/* l_brace of if/for/while */ \
|
||||
/* l_brace of if/for/while/switch/catch */ \
|
||||
TYPE(ControlStatementLBrace) \
|
||||
TYPE(ControlStatementRBrace) \
|
||||
TYPE(CppCastLParen) \
|
||||
|
||||
@@ -93,12 +93,6 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
|
||||
auto &Tok = *Tokens.back();
|
||||
const auto NewlinesBefore = Tok.NewlinesBefore;
|
||||
switch (FormatOff) {
|
||||
case FO_CurrentLine:
|
||||
if (NewlinesBefore == 0)
|
||||
Tok.Finalized = true;
|
||||
else
|
||||
FormatOff = FO_None;
|
||||
break;
|
||||
case FO_NextLine:
|
||||
if (NewlinesBefore > 1) {
|
||||
FormatOff = FO_None;
|
||||
@@ -107,6 +101,13 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
|
||||
FormatOff = FO_CurrentLine;
|
||||
}
|
||||
break;
|
||||
case FO_CurrentLine:
|
||||
if (NewlinesBefore == 0) {
|
||||
Tok.Finalized = true;
|
||||
break;
|
||||
}
|
||||
FormatOff = FO_None;
|
||||
[[fallthrough]];
|
||||
default:
|
||||
if (!FormattingDisabled && FormatOffRegex.match(Tok.TokenText)) {
|
||||
if (Tok.is(tok::comment) &&
|
||||
|
||||
@@ -45,15 +45,18 @@ std::pair<tooling::Replacements, unsigned>
|
||||
IntegerLiteralSeparatorFixer::process(const Environment &Env,
|
||||
const FormatStyle &Style) {
|
||||
switch (Style.Language) {
|
||||
case FormatStyle::LK_Cpp:
|
||||
case FormatStyle::LK_ObjC:
|
||||
Separator = '\'';
|
||||
break;
|
||||
case FormatStyle::LK_CSharp:
|
||||
case FormatStyle::LK_Java:
|
||||
case FormatStyle::LK_JavaScript:
|
||||
Separator = '_';
|
||||
break;
|
||||
case FormatStyle::LK_Cpp:
|
||||
case FormatStyle::LK_ObjC:
|
||||
if (Style.Standard >= FormatStyle::LS_Cpp14) {
|
||||
Separator = '\'';
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -829,11 +829,6 @@ class AnnotatingParser {
|
||||
if (Parent && Parent->is(TT_PointerOrReference))
|
||||
Parent->overwriteFixedType(TT_BinaryOperator);
|
||||
}
|
||||
// An arrow after an ObjC method expression is not a lambda arrow.
|
||||
if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
|
||||
CurrentToken->Next->is(TT_LambdaArrow)) {
|
||||
CurrentToken->Next->overwriteFixedType(TT_Unknown);
|
||||
}
|
||||
Left->MatchingParen = CurrentToken;
|
||||
CurrentToken->MatchingParen = Left;
|
||||
// FirstObjCSelectorName is set when a colon is found. This does
|
||||
@@ -2590,6 +2585,9 @@ class AnnotatingParser {
|
||||
if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName))
|
||||
return false;
|
||||
|
||||
if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName))
|
||||
return false;
|
||||
|
||||
if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends))
|
||||
return false;
|
||||
|
||||
@@ -2996,14 +2994,18 @@ class AnnotatingParser {
|
||||
const FormatToken *PrevToken = Tok.getPreviousNonComment();
|
||||
if (!PrevToken)
|
||||
return TT_UnaryOperator;
|
||||
if (PrevToken->is(TT_TypeName))
|
||||
if (PrevToken->isTypeName(LangOpts))
|
||||
return TT_PointerOrReference;
|
||||
if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp))
|
||||
return TT_BinaryOperator;
|
||||
|
||||
const FormatToken *NextToken = Tok.getNextNonComment();
|
||||
auto *NextToken = Tok.getNextNonComment();
|
||||
if (!NextToken)
|
||||
return TT_PointerOrReference;
|
||||
if (NextToken->is(tok::greater)) {
|
||||
NextToken->setFinalizedType(TT_TemplateCloser);
|
||||
return TT_PointerOrReference;
|
||||
}
|
||||
|
||||
if (InTemplateArgument && NextToken->is(tok::kw_noexcept))
|
||||
return TT_BinaryOperator;
|
||||
@@ -3112,7 +3114,7 @@ class AnnotatingParser {
|
||||
|
||||
// It's more likely that & represents operator& than an uninitialized
|
||||
// reference.
|
||||
if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() &&
|
||||
if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() &&
|
||||
IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) &&
|
||||
NextToken && NextToken->Tok.isAnyIdentifier()) {
|
||||
if (auto NextNext = NextToken->getNextNonComment();
|
||||
@@ -3773,18 +3775,12 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,
|
||||
if (Current.is(TT_FunctionDeclarationName))
|
||||
return true;
|
||||
|
||||
if (!Current.Tok.getIdentifierInfo())
|
||||
if (!Current.isOneOf(tok::identifier, tok::kw_operator))
|
||||
return false;
|
||||
|
||||
const auto *Prev = Current.getPreviousNonComment();
|
||||
assert(Prev);
|
||||
|
||||
if (Prev->is(tok::coloncolon))
|
||||
Prev = Prev->Previous;
|
||||
|
||||
if (!Prev)
|
||||
return false;
|
||||
|
||||
const auto &Previous = *Prev;
|
||||
|
||||
if (const auto *PrevPrev = Previous.getPreviousNonComment();
|
||||
@@ -3833,6 +3829,8 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,
|
||||
|
||||
// Find parentheses of parameter list.
|
||||
if (Current.is(tok::kw_operator)) {
|
||||
if (Line.startsWith(tok::kw_friend))
|
||||
return true;
|
||||
if (Previous.Tok.getIdentifierInfo() &&
|
||||
!Previous.isOneOf(tok::kw_return, tok::kw_co_return)) {
|
||||
return true;
|
||||
@@ -3998,29 +3996,28 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (IsCpp &&
|
||||
(LineIsFunctionDeclaration ||
|
||||
(FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
|
||||
Line.endsWith(tok::semi, tok::r_brace)) {
|
||||
auto *Tok = Line.Last->Previous;
|
||||
while (Tok->isNot(tok::r_brace))
|
||||
Tok = Tok->Previous;
|
||||
if (auto *LBrace = Tok->MatchingParen; LBrace) {
|
||||
assert(LBrace->is(tok::l_brace));
|
||||
Tok->setBlockKind(BK_Block);
|
||||
LBrace->setBlockKind(BK_Block);
|
||||
LBrace->setFinalizedType(TT_FunctionLBrace);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsCpp && SeenName && AfterLastAttribute &&
|
||||
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
|
||||
AfterLastAttribute->MustBreakBefore = true;
|
||||
if (LineIsFunctionDeclaration)
|
||||
Line.ReturnTypeWrapped = true;
|
||||
}
|
||||
|
||||
if (IsCpp) {
|
||||
if ((LineIsFunctionDeclaration ||
|
||||
(FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
|
||||
Line.endsWith(tok::semi, tok::r_brace)) {
|
||||
auto *Tok = Line.Last->Previous;
|
||||
while (Tok->isNot(tok::r_brace))
|
||||
Tok = Tok->Previous;
|
||||
if (auto *LBrace = Tok->MatchingParen; LBrace && LBrace->is(TT_Unknown)) {
|
||||
assert(LBrace->is(tok::l_brace));
|
||||
Tok->setBlockKind(BK_Block);
|
||||
LBrace->setBlockKind(BK_Block);
|
||||
LBrace->setFinalizedType(TT_FunctionLBrace);
|
||||
}
|
||||
}
|
||||
|
||||
if (SeenName && AfterLastAttribute &&
|
||||
mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
|
||||
AfterLastAttribute->MustBreakBefore = true;
|
||||
if (LineIsFunctionDeclaration)
|
||||
Line.ReturnTypeWrapped = true;
|
||||
}
|
||||
|
||||
if (!LineIsFunctionDeclaration) {
|
||||
// Annotate */&/&& in `operator` function calls as binary operators.
|
||||
for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) {
|
||||
@@ -4066,6 +4063,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (First->is(TT_ElseLBrace)) {
|
||||
First->CanBreakBefore = true;
|
||||
First->MustBreakBefore = true;
|
||||
}
|
||||
|
||||
bool InFunctionDecl = Line.MightBeFunctionDecl;
|
||||
bool InParameterList = false;
|
||||
for (auto *Current = First->Next; Current; Current = Current->Next) {
|
||||
@@ -5474,7 +5476,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
||||
if (Left.TokenText == "!")
|
||||
return Style.SpaceAfterLogicalNot;
|
||||
assert(Left.TokenText == "not");
|
||||
return Right.isOneOf(tok::coloncolon, TT_UnaryOperator);
|
||||
return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||
|
||||
(Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot);
|
||||
}
|
||||
|
||||
// If the next token is a binary operator or a selector name, we have
|
||||
@@ -6266,7 +6269,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
||||
}
|
||||
|
||||
if (Right.is(tok::colon) &&
|
||||
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {
|
||||
!Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon,
|
||||
TT_BitFieldColon)) {
|
||||
return false;
|
||||
}
|
||||
if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
|
||||
|
||||
@@ -2266,7 +2266,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
|
||||
if (!tryToParseLambdaIntroducer())
|
||||
return false;
|
||||
|
||||
bool SeenArrow = false;
|
||||
FormatToken *Arrow = nullptr;
|
||||
bool InTemplateParameterList = false;
|
||||
|
||||
while (FormatTok->isNot(tok::l_brace)) {
|
||||
@@ -2341,17 +2341,13 @@ bool UnwrappedLineParser::tryToParseLambda() {
|
||||
case tok::ellipsis:
|
||||
case tok::kw_true:
|
||||
case tok::kw_false:
|
||||
if (SeenArrow || InTemplateParameterList) {
|
||||
if (Arrow || InTemplateParameterList) {
|
||||
nextToken();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
case tok::arrow:
|
||||
// This might or might not actually be a lambda arrow (this could be an
|
||||
// ObjC method invocation followed by a dereferencing arrow). We might
|
||||
// reset this back to TT_Unknown in TokenAnnotator.
|
||||
FormatTok->setFinalizedType(TT_LambdaArrow);
|
||||
SeenArrow = true;
|
||||
Arrow = FormatTok;
|
||||
nextToken();
|
||||
break;
|
||||
case tok::kw_requires: {
|
||||
@@ -2373,6 +2369,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
|
||||
FormatTok->setFinalizedType(TT_LambdaLBrace);
|
||||
LSquare.setFinalizedType(TT_LambdaLSquare);
|
||||
|
||||
if (Arrow)
|
||||
Arrow->setFinalizedType(TT_LambdaArrow);
|
||||
|
||||
NestedLambdas.push_back(Line->SeenDecltypeAuto);
|
||||
parseChildBlock();
|
||||
assert(!NestedLambdas.empty());
|
||||
@@ -2386,11 +2385,6 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
|
||||
const FormatToken *LeftSquare = FormatTok;
|
||||
nextToken();
|
||||
if (Previous) {
|
||||
if (Previous->Tok.getIdentifierInfo() &&
|
||||
!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
|
||||
tok::kw_co_return)) {
|
||||
return false;
|
||||
}
|
||||
if (Previous->closesScope()) {
|
||||
// Not a potential C-style cast.
|
||||
if (Previous->isNot(tok::r_paren))
|
||||
@@ -2400,6 +2394,13 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
|
||||
// and `int (*)()`.
|
||||
if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren))
|
||||
return false;
|
||||
} else if (Previous->is(tok::star)) {
|
||||
Previous = Previous->getPreviousNonComment();
|
||||
}
|
||||
if (Previous && Previous->Tok.getIdentifierInfo() &&
|
||||
!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
|
||||
tok::kw_co_return)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (LeftSquare->isCppStructuredBinding(IsCpp))
|
||||
|
||||
@@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
|
||||
Discrimination::Constant, InitFiniPointerConstantDiscriminator);
|
||||
}
|
||||
|
||||
Opts.BlockInvocationFunctionPointers =
|
||||
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||
Opts.BlockHelperFunctionPointers =
|
||||
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||
Opts.BlockByrefHelperFunctionPointers =
|
||||
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||
if (LangOpts.PointerAuthBlockDescriptorPointers)
|
||||
Opts.BlockDescriptorPointers =
|
||||
PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
|
||||
BlockDescriptorConstantDiscriminator);
|
||||
|
||||
Opts.ObjCMethodListFunctionPointers =
|
||||
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
|
||||
Opts.ObjCMethodListPointer =
|
||||
@@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
|
||||
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
|
||||
if (Opts.PointerAuthObjcClassROPointers)
|
||||
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
|
||||
if (Opts.PointerAuthBlockDescriptorPointers)
|
||||
GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
|
||||
}
|
||||
|
||||
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
|
||||
@@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
|
||||
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
|
||||
Opts.AArch64JumpTableHardening =
|
||||
Args.hasArg(OPT_faarch64_jump_table_hardening);
|
||||
|
||||
Opts.PointerAuthBlockDescriptorPointers =
|
||||
Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
|
||||
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
|
||||
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
|
||||
Opts.PointerAuthObjcInterfaceSel =
|
||||
|
||||
@@ -1535,6 +1535,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
#undef TARGET_OS
|
||||
}
|
||||
|
||||
if (LangOpts.PointerAuthIntrinsics)
|
||||
Builder.defineMacro("__PTRAUTH__");
|
||||
|
||||
// Get other target #defines.
|
||||
TI.getTargetDefines(LangOpts, Builder);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ _mm512_mask_dpwsud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsud_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwsud_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
@@ -218,7 +218,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwsuds_epi32(
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsuds_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwsuds_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
@@ -239,7 +239,7 @@ _mm512_mask_dpwusd_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusd_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwusd_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
@@ -260,7 +260,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwusds_epi32(
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusds_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwusds_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
@@ -281,7 +281,7 @@ _mm512_mask_dpwuud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuud_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwuud_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
@@ -302,7 +302,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwuuds_epi32(
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuuds_epi32(
|
||||
__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) {
|
||||
__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) {
|
||||
return (__m512i)__builtin_ia32_selectd_512(
|
||||
(__mmask16)__U, (__v16si)_mm512_dpwuuds_epi32(__A, __B, __C),
|
||||
(__v16si)_mm512_setzero_si512());
|
||||
|
||||
@@ -519,34 +519,34 @@ _mm_maskz_min_pbh(__mmask8 __U, __m128bh __A, __m128bh __B) {
|
||||
(__mmask8)__U, (__v8bf)_mm_min_pbh(__A, __B), (__v8bf)_mm_setzero_pbh());
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16eq((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16eq((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16lt((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16lt((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16le((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16le((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16gt((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16gt((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16ge((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16ge((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh A,
|
||||
__m128bh B) {
|
||||
return __builtin_ia32_vcomisbf16neq((__v8bf)A, (__v8bf)B);
|
||||
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh __A,
|
||||
__m128bh __B) {
|
||||
return __builtin_ia32_vcomisbf16neq((__v8bf)__A, (__v8bf)__B);
|
||||
}
|
||||
|
||||
#define _mm256_cmp_pbh_mask(__A, __B, __P) \
|
||||
|
||||
@@ -253,7 +253,7 @@ _mm_mask_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwsud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwsud_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -266,7 +266,7 @@ _mm256_mask_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
_mm256_maskz_dpwsud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwsud_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
@@ -279,7 +279,7 @@ _mm_mask_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwsuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwsuds_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -292,7 +292,7 @@ _mm256_mask_dpwsuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwsuds_epi32(
|
||||
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwsuds_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
@@ -305,7 +305,7 @@ _mm_mask_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwusd_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwusd_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -318,7 +318,7 @@ _mm256_mask_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
_mm256_maskz_dpwusd_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwusd_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
@@ -331,7 +331,7 @@ _mm_mask_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwusds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwusds_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -344,7 +344,7 @@ _mm256_mask_dpwusds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwusds_epi32(
|
||||
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwusds_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
@@ -357,7 +357,7 @@ _mm_mask_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwuud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwuud_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -370,7 +370,7 @@ _mm256_mask_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256
|
||||
_mm256_maskz_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
_mm256_maskz_dpwuud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwuud_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
@@ -383,7 +383,7 @@ _mm_mask_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m128i __DEFAULT_FN_ATTRS128
|
||||
_mm_maskz_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) {
|
||||
_mm_maskz_dpwuuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) {
|
||||
return (__m128i)__builtin_ia32_selectd_128(
|
||||
(__mmask8)__U, (__v4si)_mm_dpwuuds_epi32(__A, __B, __C),
|
||||
(__v4si)_mm_setzero_si128());
|
||||
@@ -396,7 +396,7 @@ _mm256_mask_dpwuuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
}
|
||||
|
||||
static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwuuds_epi32(
|
||||
__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) {
|
||||
__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) {
|
||||
return (__m256i)__builtin_ia32_selectd_256(
|
||||
(__mmask8)__U, (__v8si)_mm256_dpwuuds_epi32(__A, __B, __C),
|
||||
(__v8si)_mm256_setzero_si256());
|
||||
|
||||
@@ -697,7 +697,16 @@ template <typename _Tp> struct __remove_address_space<__constant _Tp> {
|
||||
#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
|
||||
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
|
||||
|
||||
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
|
||||
#ifdef __OPENCL_CPP_VERSION__
|
||||
#define CLINKAGE extern "C"
|
||||
#else
|
||||
#define CLINKAGE
|
||||
#endif
|
||||
|
||||
CLINKAGE int printf(__constant const char *st, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
|
||||
#undef CLINKAGE
|
||||
#endif
|
||||
|
||||
#ifdef cl_intel_device_side_avc_motion_estimation
|
||||
|
||||
@@ -95,7 +95,7 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
|
||||
__ptrauth qualifier; the compiler will perform this check
|
||||
automatically. */
|
||||
|
||||
#if __has_feature(ptrauth_intrinsics)
|
||||
#if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__)
|
||||
|
||||
/* Strip the signature from a value without authenticating it.
|
||||
|
||||
@@ -388,6 +388,6 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
|
||||
#define __ptrauth_objc_isa_uintptr
|
||||
#define __ptrauth_objc_super_pointer
|
||||
|
||||
#endif /* __has_feature(ptrauth_intrinsics) */
|
||||
#endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */
|
||||
|
||||
#endif /* __PTRAUTH_H */
|
||||
|
||||
@@ -174,8 +174,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
|
||||
ExtendedTokenMode = 0;
|
||||
|
||||
NewLinePtr = nullptr;
|
||||
|
||||
IsFirstPPToken = true;
|
||||
}
|
||||
|
||||
/// Lexer constructor - Create a new lexer object for the specified buffer
|
||||
@@ -3225,7 +3223,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
|
||||
bool atStartOfLine = IsAtStartOfLine;
|
||||
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
|
||||
bool leadingSpace = HasLeadingSpace;
|
||||
bool isFirstPPToken = IsFirstPPToken;
|
||||
|
||||
Token Tok;
|
||||
Lex(Tok);
|
||||
@@ -3236,7 +3233,6 @@ std::optional<Token> Lexer::peekNextPPToken() {
|
||||
HasLeadingSpace = leadingSpace;
|
||||
IsAtStartOfLine = atStartOfLine;
|
||||
IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
|
||||
IsFirstPPToken = isFirstPPToken;
|
||||
// Restore the lexer back to non-skipping mode.
|
||||
LexingRawMode = false;
|
||||
|
||||
@@ -3726,11 +3722,6 @@ bool Lexer::Lex(Token &Result) {
|
||||
HasLeadingEmptyMacro = false;
|
||||
}
|
||||
|
||||
if (IsFirstPPToken) {
|
||||
Result.setFlag(Token::FirstPPToken);
|
||||
IsFirstPPToken = false;
|
||||
}
|
||||
|
||||
bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
|
||||
IsAtPhysicalStartOfLine = false;
|
||||
bool isRawLex = isLexingRawMode();
|
||||
|
||||
@@ -1467,7 +1467,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
|
||||
if (s != PossibleNewDigitStart)
|
||||
DigitsBegin = PossibleNewDigitStart;
|
||||
else
|
||||
IsSingleZero = (s == ThisTokEnd); // Is the only thing we've seen a 0?
|
||||
IsSingleZero = (s == ThisTokBegin + 1);
|
||||
|
||||
if (s == ThisTokEnd)
|
||||
return; // Done, simple octal number like 01234
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "clang/Lex/MacroArgs.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/ModuleLoader.h"
|
||||
#include "clang/Lex/NoTrivialPPDirectiveTracer.h"
|
||||
#include "clang/Lex/Pragma.h"
|
||||
#include "clang/Lex/PreprocessingRecord.h"
|
||||
#include "clang/Lex/PreprocessorLexer.h"
|
||||
@@ -247,8 +248,6 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
|
||||
llvm::errs() << " [LeadingSpace]";
|
||||
if (Tok.isExpandDisabled())
|
||||
llvm::errs() << " [ExpandDisabled]";
|
||||
if (Tok.isFirstPPToken())
|
||||
llvm::errs() << " [First pp-token]";
|
||||
if (Tok.needsCleaning()) {
|
||||
const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
|
||||
llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength())
|
||||
@@ -577,8 +576,11 @@ void Preprocessor::EnterMainSourceFile() {
|
||||
// export module M; // error: module declaration must occur
|
||||
// // at the start of the translation unit.
|
||||
if (getLangOpts().CPlusPlusModules) {
|
||||
auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
|
||||
DirTracer = Tracer.get();
|
||||
addPPCallbacks(std::move(Tracer));
|
||||
std::optional<Token> FirstPPTok = CurLexer->peekNextPPToken();
|
||||
if (FirstPPTok && FirstPPTok->isFirstPPToken())
|
||||
if (FirstPPTok)
|
||||
FirstPPTokenLoc = FirstPPTok->getLocation();
|
||||
}
|
||||
}
|
||||
@@ -940,6 +942,8 @@ void Preprocessor::Lex(Token &Result) {
|
||||
StdCXXImportSeqState.handleHeaderName();
|
||||
break;
|
||||
case tok::kw_export:
|
||||
if (hasSeenNoTrivialPPDirective())
|
||||
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
|
||||
TrackGMFState.handleExport();
|
||||
StdCXXImportSeqState.handleExport();
|
||||
ModuleDeclState.handleExport();
|
||||
@@ -966,6 +970,8 @@ void Preprocessor::Lex(Token &Result) {
|
||||
}
|
||||
break;
|
||||
} else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) {
|
||||
if (hasSeenNoTrivialPPDirective())
|
||||
Result.setFlag(Token::HasSeenNoTrivialPPDirective);
|
||||
TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
|
||||
ModuleDeclState.handleModule();
|
||||
break;
|
||||
@@ -1680,3 +1686,31 @@ const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Preprocessor::hasSeenNoTrivialPPDirective() const {
|
||||
return DirTracer && DirTracer->hasSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const {
|
||||
return SeenNoTrivialPPDirective;
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() {
|
||||
if (InMainFile && !SeenNoTrivialPPDirective)
|
||||
SeenNoTrivialPPDirective = true;
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::LexedFileChanged(
|
||||
FileID FID, LexedFileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) {
|
||||
InMainFile = (FID == PP.getSourceManager().getMainFileID());
|
||||
}
|
||||
|
||||
void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok,
|
||||
const MacroDefinition &MD,
|
||||
SourceRange Range,
|
||||
const MacroArgs *Args) {
|
||||
// FIXME: Does only enable builtin macro expansion make sense?
|
||||
if (!MD.getMacroInfo()->isBuiltinMacro())
|
||||
setSeenNoTrivialPPDirective();
|
||||
}
|
||||
|
||||
@@ -3342,7 +3342,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
|
||||
Actions.ActOnBlockError(CaretLoc, getCurScope());
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
EnterExpressionEvaluationContextForFunction PotentiallyEvaluated(
|
||||
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
||||
StmtResult Stmt(ParseCompoundStatementBody());
|
||||
BlockScope.Exit();
|
||||
if (!Stmt.isInvalid())
|
||||
|
||||
@@ -2361,9 +2361,10 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
|
||||
// Parse a global-module-fragment, if present.
|
||||
if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) {
|
||||
SourceLocation SemiLoc = ConsumeToken();
|
||||
if (!Introducer.isFirstPPToken()) {
|
||||
if (ImportState != Sema::ModuleImportState::FirstDecl ||
|
||||
Introducer.hasSeenNoTrivialPPDirective()) {
|
||||
Diag(StartLoc, diag::err_global_module_introducer_not_at_start)
|
||||
<< SourceRange(StartLoc, SemiLoc);
|
||||
<< SourceRange(StartLoc, SemiLoc);
|
||||
return nullptr;
|
||||
}
|
||||
if (MDK == Sema::ModuleDeclKind::Interface) {
|
||||
@@ -2418,7 +2419,8 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
|
||||
ExpectAndConsumeSemi(diag::err_module_expected_semi);
|
||||
|
||||
return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition,
|
||||
ImportState, Introducer.isFirstPPToken());
|
||||
ImportState,
|
||||
Introducer.hasSeenNoTrivialPPDirective());
|
||||
}
|
||||
|
||||
Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
|
||||
|
||||
@@ -503,8 +503,12 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk,
|
||||
|
||||
TransferFunctions TF(VD);
|
||||
BackwardDataflowWorklist Worklist(*AC.getCFG(), AC);
|
||||
llvm::DenseSet<const CFGBlock *> Visited;
|
||||
Worklist.enqueueBlock(&VarBlk);
|
||||
while (const CFGBlock *B = Worklist.dequeue()) {
|
||||
if (Visited.contains(B))
|
||||
continue;
|
||||
Visited.insert(B);
|
||||
// First check the current block.
|
||||
for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend();
|
||||
ri != re; ++ri) {
|
||||
@@ -2887,8 +2891,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
|
||||
.setAlwaysAdd(Stmt::UnaryOperatorClass);
|
||||
}
|
||||
|
||||
bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored(
|
||||
diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc());
|
||||
bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
|
||||
// Install the logical handler.
|
||||
std::optional<LogicalErrorHandler> LEH;
|
||||
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
|
||||
|
||||
@@ -12014,13 +12014,20 @@ static void DiagnoseMixedUnicodeImplicitConversion(Sema &S, const Type *Source,
|
||||
SourceLocation CC) {
|
||||
assert(Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType() &&
|
||||
Source != Target);
|
||||
|
||||
// Lone surrogates have a distinct representation in UTF-32.
|
||||
// Converting between UTF-16 and UTF-32 codepoints seems very widespread,
|
||||
// so don't warn on such conversion.
|
||||
if (Source->isChar16Type() && Target->isChar32Type())
|
||||
return;
|
||||
|
||||
Expr::EvalResult Result;
|
||||
if (E->EvaluateAsInt(Result, S.getASTContext(), Expr::SE_AllowSideEffects,
|
||||
S.isConstantEvaluatedContext())) {
|
||||
llvm::APSInt Value(32);
|
||||
Value = Result.Val.getInt();
|
||||
bool IsASCII = Value <= 0x7F;
|
||||
bool IsBMP = Value <= 0xD7FF || (Value >= 0xE000 && Value <= 0xFFFF);
|
||||
bool IsBMP = Value <= 0xDFFF || (Value >= 0xE000 && Value <= 0xFFFF);
|
||||
bool ConversionPreservesSemantics =
|
||||
IsASCII || (!Source->isChar8Type() && !Target->isChar8Type() && IsBMP);
|
||||
|
||||
|
||||
@@ -1097,10 +1097,6 @@ static bool CheckFunctionConstraintsWithoutInstantiation(
|
||||
}
|
||||
|
||||
Sema::ContextRAII SavedContext(SemaRef, FD);
|
||||
std::optional<Sema::CXXThisScopeRAII> ThisScope;
|
||||
if (auto *Method = dyn_cast<CXXMethodDecl>(FD))
|
||||
ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
|
||||
/*ThisQuals=*/Method->getMethodQualifiers());
|
||||
return SemaRef.CheckConstraintSatisfaction(
|
||||
Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
|
||||
}
|
||||
|
||||
@@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
|
||||
if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
|
||||
continue;
|
||||
|
||||
if (isa<InferredNoReturnAttr>(I)) {
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(New)) {
|
||||
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
continue; // Don't propagate inferred noreturn attributes to explicit
|
||||
// specializations.
|
||||
}
|
||||
}
|
||||
|
||||
if (mergeDeclAttribute(*this, New, I, LocalAMK))
|
||||
foundAny = true;
|
||||
}
|
||||
@@ -19643,6 +19651,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
||||
Q && Q.isAddressDiscriminated()) {
|
||||
Record->setArgPassingRestrictions(
|
||||
RecordArgPassingKind::CanNeverPassInRegs);
|
||||
Record->setNonTrivialToPrimitiveCopy(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) {
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
// Skip explicit specializations here as they may have
|
||||
// a user-provided definition that may deliberately differ from the primary
|
||||
// template. If an explicit specialization truly never returns, the user
|
||||
// should explicitly mark it with [[noreturn]].
|
||||
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
auto *NonConstFD = const_cast<FunctionDecl *>(FD);
|
||||
DiagnosticsEngine &Diags = S.getDiagnostics();
|
||||
if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) &&
|
||||
@@ -5011,10 +5018,10 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
|
||||
|
||||
static void handleNonStringAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
// This only applies to fields and variable declarations which have an array
|
||||
// type.
|
||||
// type or pointer type, with character elements.
|
||||
QualType QT = cast<ValueDecl>(D)->getType();
|
||||
if (!QT->isArrayType() ||
|
||||
!QT->getBaseElementTypeUnsafe()->isAnyCharacterType()) {
|
||||
if ((!QT->isArrayType() && !QT->isPointerType()) ||
|
||||
!QT->getPointeeOrArrayElementType()->isAnyCharacterType()) {
|
||||
S.Diag(D->getBeginLoc(), diag::warn_attribute_non_character_array)
|
||||
<< AL << AL.isRegularKeywordAttribute() << QT << AL.getRange();
|
||||
return;
|
||||
|
||||
@@ -9309,14 +9309,14 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType,
|
||||
// If we have an atomic type, try a non-atomic assignment, then just add an
|
||||
// atomic qualification step.
|
||||
if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
|
||||
AssignConvertType result =
|
||||
AssignConvertType Result =
|
||||
CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
|
||||
if (result != AssignConvertType::Compatible)
|
||||
return result;
|
||||
if (!IsAssignConvertCompatible(Result))
|
||||
return Result;
|
||||
if (Kind != CK_NoOp && ConvertRHS)
|
||||
RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
|
||||
Kind = CK_NonAtomicToAtomic;
|
||||
return AssignConvertType::Compatible;
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If the left-hand side is a reference type, then we are in a
|
||||
|
||||
@@ -347,6 +347,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II,
|
||||
CheckTypenameType(ElaboratedTypeKeyword::None, SourceLocation(),
|
||||
SS.getWithLocInContext(Context), II, NameLoc, &TSI,
|
||||
/*DeducedTSTContext=*/true);
|
||||
if (T.isNull())
|
||||
return ParsedType();
|
||||
return CreateParsedType(T, TSI);
|
||||
}
|
||||
|
||||
|
||||
@@ -264,10 +264,11 @@ Sema::DeclGroupPtrTy
|
||||
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
|
||||
ModuleDeclKind MDK, ModuleIdPath Path,
|
||||
ModuleIdPath Partition, ModuleImportState &ImportState,
|
||||
bool IntroducerIsFirstPPToken) {
|
||||
bool SeenNoTrivialPPDirective) {
|
||||
assert(getLangOpts().CPlusPlusModules &&
|
||||
"should only have module decl in standard C++ modules");
|
||||
|
||||
bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
|
||||
bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
|
||||
// If any of the steps here fail, we count that as invalidating C++20
|
||||
// module state;
|
||||
@@ -335,7 +336,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
|
||||
|
||||
// In C++20, A module directive may only appear as the first preprocessing
|
||||
// tokens in a file (excluding the global module fragment.).
|
||||
if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) {
|
||||
if (getLangOpts().CPlusPlusModules &&
|
||||
(!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {
|
||||
Diag(ModuleLoc, diag::err_module_decl_not_at_start);
|
||||
SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
|
||||
Diag(BeginLoc, diag::note_global_module_introducer_missing)
|
||||
|
||||
@@ -245,7 +245,6 @@ void StandardConversionSequence::setAsIdentityConversion() {
|
||||
IsLvalueReference = true;
|
||||
BindsToFunctionLvalue = false;
|
||||
BindsToRvalue = false;
|
||||
IsImplicitObjectArgumentQualificationConversion = false;
|
||||
BindsImplicitObjectArgumentWithoutRefQualifier = false;
|
||||
ObjCLifetimeConversionBinding = false;
|
||||
FromBracedInitList = false;
|
||||
@@ -5318,7 +5317,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
|
||||
ICS.Standard.DirectBinding = BindsDirectly;
|
||||
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
|
||||
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
|
||||
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
|
||||
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
|
||||
ICS.Standard.ObjCLifetimeConversionBinding =
|
||||
@@ -5498,7 +5496,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
|
||||
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||
ICS.Standard.BindsToFunctionLvalue = false;
|
||||
ICS.Standard.BindsToRvalue = true;
|
||||
ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false;
|
||||
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
|
||||
ICS.Standard.ObjCLifetimeConversionBinding = false;
|
||||
} else if (ICS.isUserDefined()) {
|
||||
@@ -5521,8 +5518,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
|
||||
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
|
||||
ICS.UserDefined.After.BindsToFunctionLvalue = false;
|
||||
ICS.UserDefined.After.BindsToRvalue = !LValRefType;
|
||||
ICS.UserDefined.After.IsImplicitObjectArgumentQualificationConversion =
|
||||
false;
|
||||
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
|
||||
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
|
||||
ICS.UserDefined.After.FromBracedInitList = false;
|
||||
@@ -5807,7 +5802,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
|
||||
StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
|
||||
Result.UserDefined.After;
|
||||
SCS.ReferenceBinding = true;
|
||||
SCS.IsImplicitObjectArgumentQualificationConversion = false;
|
||||
SCS.IsLvalueReference = ToType->isLValueReferenceType();
|
||||
SCS.BindsToRvalue = true;
|
||||
SCS.BindsToFunctionLvalue = false;
|
||||
@@ -6005,12 +5999,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
|
||||
// affects the conversion rank.
|
||||
QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
|
||||
ImplicitConversionKind SecondKind;
|
||||
bool IsQualificationConversion = false;
|
||||
if (ImplicitParamType.getCanonicalType() == FromTypeCanon) {
|
||||
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
|
||||
SecondKind = ICK_Identity;
|
||||
} else if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
|
||||
SecondKind = ICK_Identity;
|
||||
IsQualificationConversion = true;
|
||||
} else if (S.IsDerivedFrom(Loc, FromType, ClassType)) {
|
||||
SecondKind = ICK_Derived_To_Base;
|
||||
} else if (!Method->isExplicitObjectMemberFunction()) {
|
||||
@@ -6051,8 +6041,6 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
|
||||
ICS.Standard.setFromType(FromType);
|
||||
ICS.Standard.setAllToTypes(ImplicitParamType);
|
||||
ICS.Standard.ReferenceBinding = true;
|
||||
ICS.Standard.IsImplicitObjectArgumentQualificationConversion =
|
||||
IsQualificationConversion;
|
||||
ICS.Standard.DirectBinding = true;
|
||||
ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
|
||||
ICS.Standard.BindsToFunctionLvalue = false;
|
||||
|
||||
@@ -2287,7 +2287,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
|
||||
// we can diagnose if we don't see any variable declarations. This
|
||||
// covers a case like declaring a typedef, function, or structure
|
||||
// type rather than a variable.
|
||||
NonVarSeen = DI;
|
||||
//
|
||||
// Note, _Static_assert is acceptable because it does not declare an
|
||||
// identifier at all, so "for object having" does not apply.
|
||||
if (!isa<StaticAssertDecl>(DI))
|
||||
NonVarSeen = DI;
|
||||
}
|
||||
}
|
||||
// Diagnose if we saw a non-variable declaration but no variable
|
||||
|
||||
@@ -4749,8 +4749,6 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
|
||||
EnterExpressionEvaluationContext EECtx{
|
||||
*this, ExpressionEvaluationContext::Unevaluated, CSD};
|
||||
|
||||
ContextRAII CurContext(*this, CSD->getDeclContext(),
|
||||
/*NewThisContext=*/false);
|
||||
if (!AreArgsDependent &&
|
||||
CheckConstraintSatisfaction(
|
||||
NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()),
|
||||
|
||||
@@ -5525,6 +5525,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
|
||||
// FIXME: A substitution can be incomplete on a non-structural part of the
|
||||
// type. Use the canonical type for now, until the TemplateInstantiator can
|
||||
// deal with that.
|
||||
|
||||
// Workaround: Implicit deduction guides use InjectedClassNameTypes, whereas
|
||||
// the explicit guides don't. The substitution doesn't transform these types,
|
||||
// so let it transform their specializations instead.
|
||||
bool IsDeductionGuide = isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
|
||||
if (IsDeductionGuide) {
|
||||
if (auto *Injected = P->getAs<InjectedClassNameType>())
|
||||
P = Injected->getInjectedSpecializationType();
|
||||
}
|
||||
QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(),
|
||||
FTD->getDeclName(), &IsIncompleteSubstitution);
|
||||
if (InstP.isNull() && !IsIncompleteSubstitution)
|
||||
@@ -5539,9 +5548,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
|
||||
if (auto *PA = dyn_cast<PackExpansionType>(A);
|
||||
PA && !isa<PackExpansionType>(InstP))
|
||||
A = PA->getPattern();
|
||||
if (!S.Context.hasSameType(
|
||||
S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()),
|
||||
S.Context.getUnqualifiedArrayType(A.getNonReferenceType())))
|
||||
auto T1 = S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType());
|
||||
auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType());
|
||||
if (IsDeductionGuide) {
|
||||
if (auto *Injected = T1->getAs<InjectedClassNameType>())
|
||||
T1 = Injected->getInjectedSpecializationType();
|
||||
if (auto *Injected = T2->getAs<InjectedClassNameType>())
|
||||
T2 = Injected->getInjectedSpecializationType();
|
||||
}
|
||||
if (!S.Context.hasSameType(T1, T2))
|
||||
return TemplateDeductionResult::NonDeducedMismatch;
|
||||
return TemplateDeductionResult::Success;
|
||||
}
|
||||
|
||||
@@ -5685,7 +5685,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
};
|
||||
Function->setDeclarationNameLoc(NameLocPointsToPattern());
|
||||
|
||||
EnterExpressionEvaluationContext EvalContext(
|
||||
EnterExpressionEvaluationContextForFunction EvalContext(
|
||||
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
||||
|
||||
Qualifiers ThisTypeQuals;
|
||||
|
||||
@@ -1768,7 +1768,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,
|
||||
// Objective-C lifetime, this is a non-trivial assignment.
|
||||
if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime())
|
||||
return false;
|
||||
|
||||
ASTContext &Context = Self.getASTContext();
|
||||
if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||
|
||||
Context.containsAddressDiscriminatedPointerAuth(RhsT))
|
||||
return false;
|
||||
return !Result.get()->hasNonTrivialCall(Self.Context);
|
||||
}
|
||||
|
||||
|
||||
@@ -3103,6 +3103,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
||||
F.Kind == MK_ImplicitModule)
|
||||
N = ForceValidateUserInputs ? NumUserInputs : 0;
|
||||
|
||||
if (N != 0)
|
||||
Diag(diag::remark_module_validation)
|
||||
<< N << F.ModuleName << F.FileName;
|
||||
|
||||
for (unsigned I = 0; I < N; ++I) {
|
||||
InputFile IF = getInputFile(F, I+1, Complain);
|
||||
if (!IF.getFile() || IF.isOutOfDate())
|
||||
|
||||
@@ -4340,8 +4340,7 @@ class ASTDeclContextNameLookupTrait
|
||||
// parent of parent. We DON'T remove the enum constant from its parent. So
|
||||
// we don't need to care about merging problems here.
|
||||
if (auto *ECD = dyn_cast<EnumConstantDecl>(D);
|
||||
ECD && DC.isFileContext() && ECD->getOwningModule() &&
|
||||
ECD->getTopLevelOwningNamedModule()->isNamedModule()) {
|
||||
ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) {
|
||||
if (llvm::all_of(
|
||||
DC.noload_lookup(
|
||||
cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),
|
||||
|
||||
@@ -34,8 +34,10 @@ class CrossProcessModuleCache : public ModuleCache {
|
||||
}
|
||||
|
||||
std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
|
||||
std::string TimestampFilename =
|
||||
serialization::ModuleFile::getTimestampFilename(ModuleFilename);
|
||||
llvm::sys::fs::file_status Status;
|
||||
if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{})
|
||||
if (llvm::sys::fs::status(TimestampFilename, Status) != std::error_code{})
|
||||
return 0;
|
||||
return llvm::sys::toTimeT(Status.getLastModificationTime());
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ void AssumeModelingChecker::checkPostStmt(const AttributedStmt *A,
|
||||
continue;
|
||||
|
||||
const auto *Assumption = AssumptionVal.getAsInteger();
|
||||
assert(Assumption && "We should know the exact outcome of an assume expr");
|
||||
if (Assumption && Assumption->isZero()) {
|
||||
C.addSink();
|
||||
}
|
||||
|
||||
@@ -916,7 +916,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
|
||||
QualType T = Ex->getTypeOfArgument();
|
||||
|
||||
for (ExplodedNode *N : CheckedSet) {
|
||||
if (Ex->getKind() == UETT_SizeOf) {
|
||||
if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf ||
|
||||
Ex->getKind() == UETT_CountOf) {
|
||||
if (!T->isIncompleteType() && !T->isConstantSizeType()) {
|
||||
assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
|
||||
|
||||
|
||||
@@ -71,21 +71,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
|
||||
Bldr.takeNodes(Pred);
|
||||
|
||||
assert(ThisRD);
|
||||
SVal V = Call.getArgSVal(0);
|
||||
const Expr *VExpr = Call.getArgExpr(0);
|
||||
|
||||
// If the value being copied is not unknown, load from its location to get
|
||||
// an aggregate rvalue.
|
||||
if (std::optional<Loc> L = V.getAs<Loc>())
|
||||
V = Pred->getState()->getSVal(*L);
|
||||
else
|
||||
assert(V.isUnknownOrUndef());
|
||||
if (!ThisRD->isEmpty()) {
|
||||
SVal V = Call.getArgSVal(0);
|
||||
const Expr *VExpr = Call.getArgExpr(0);
|
||||
|
||||
ExplodedNodeSet Tmp;
|
||||
evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
|
||||
/*isLoad=*/true);
|
||||
for (ExplodedNode *N : Tmp)
|
||||
evalBind(Dst, CallExpr, N, ThisVal, V, true);
|
||||
// If the value being copied is not unknown, load from its location to get
|
||||
// an aggregate rvalue.
|
||||
if (std::optional<Loc> L = V.getAs<Loc>())
|
||||
V = Pred->getState()->getSVal(*L);
|
||||
else
|
||||
assert(V.isUnknownOrUndef());
|
||||
|
||||
ExplodedNodeSet Tmp;
|
||||
evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
|
||||
/*isLoad=*/true);
|
||||
for (ExplodedNode *N : Tmp)
|
||||
evalBind(Dst, CallExpr, N, ThisVal, V, true);
|
||||
} else {
|
||||
// We can't copy empty classes because of empty base class optimization.
|
||||
// In that case, copying the empty base class subobject would overwrite the
|
||||
// object that it overlaps with - so let's not do that.
|
||||
// See issue-157467.cpp for an example.
|
||||
Dst.Add(Pred);
|
||||
}
|
||||
|
||||
PostStmt PS(CallExpr, LCtx);
|
||||
for (ExplodedNode *N : Dst) {
|
||||
|
||||
@@ -264,7 +264,7 @@ END_COMPILERRT_OUTLINE_FUNCTION(NAME(LDNM))
|
||||
|
||||
NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
// GNU property note for BTI and PAC
|
||||
GNU_PROPERTY_BTI_PAC
|
||||
// GNU property note for BTI, PAC, and GCS
|
||||
GNU_PROPERTY_BTI_PAC_GCS
|
||||
|
||||
#endif // defined(__aarch64__) || defined(__arm64ec__)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user