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:
Dimitry Andric
2025-12-28 00:23:22 +01:00
358 changed files with 6387 additions and 2851 deletions
+25
View File
@@ -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
+279 -25
View File
@@ -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