https://github.com/2876225417 created https://github.com/llvm/llvm-project/pull/182522
## Description GCC 15's libstdc++ implementation has stricter conformance to the C++ standard regarding type completeness: 1. **`std::unique_ptr<T>` destruction** requires complete type `T` at the point of destructor instantiation 2. **`std::vector<T>` operations** require complete type `T` for pointer arithmetic 3. **`std::make_unique<T>()`** requires complete type `T` at the call site 4. **Default parameters with `unique_ptr<T>`** require complete type `T` in header files These issues cause compilation failures when inline constructors/destructors or template instantiations encounter forward-declared types. ## Compatibility Issue Summary List | Category | Index | File | Issue Type | |------|------|------|---------| | **LLVM Core** | [1](#issue1) | `llvm/include/llvm/ADT/STLExtras.h` | reverse_iterator requires default ctor | | | [2](#issue2) | `llvm/include/llvm/IR/CFG.h` | reverse_iterator requires default ctor | | | [3](#issue3) | `llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp` | Requires complete type | | | [4](#issue4) | `llvm/lib/Target/BPF/BPFAsmPrinter.h` | unique_ptr requires complete type | | | [5](#issue5) | `llvm/lib/Target/BPF/BPFAsmPrinter.cpp` | unique_ptr requires complete type | | **Clang** | [6](#issue6) | `clang/lib/Interpreter/IncrementalParser.h` | Default params requires complete type | | | [7](#issue7) | `clang/lib/Interpreter/IncrementalParser.cpp` | Default params requires complete type | | | [8](#issue8) | `clang/tools/libclang/CIndexDiagnostic.h` | unique_ptr requires complete type | | | [9](#issue9) | `clang/tools/libclang/CIndexDiagnostic.cpp` | unique_ptr requires complete type | | **Clang Tools** | [10](#issue10) | `clang-tools-extra/clangd/GlobalCompilationDatabase.cpp` | make_unique requires complete type | | **LLDB** | [11](#issue11) | `lldb/include/lldb/Core/EmulateInstruction.h` | unique_ptr requires complete type | | | [12](#issue12) | `lldb/source/Core/EmulateInstruction.cpp` | unique_ptr requires complete type | | | [13](#issue13) | `lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h` | Cannot convert nullopt to nullptr | | | [14](#issue14) | `lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h` | unique_ptr requires complete type | | | [15](#issue15) | `lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h` | unique_ptr requires complete type | | | [16](#issue16) | `lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h` | unique_ptr requires complete type | | | [17](#issue17) | `lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp` | unique_ptr requires complete type | | | [18](#issue18) | `lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h` | unique_ptr requires complete type | | | [19](#issue19) | `lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp` | unique_ptr requires complete type | | **MLIR** | [20](#issue20) | `mlir/include/mlir/Query/Matcher/MatchersInternal.h` | vector/ArrayRef requires complete type | | | [21](#issue21) | `mlir/lib/Query/Matcher/MatchFinder.cpp` | Explicit template instantiation | ## Build Configurations ```bash -- The C compiler identification is Clang 23.0.0 -- The CXX compiler identification is Clang 23.0.0 -- The ASM compiler identification is Clang with GNU-like command-line -- Found assembler: /run/media/ppqwqqq/22254a39-a5f0-4e28-93d1-96678a650d53/recover_hq1024/llvm/llvm-project-built/bin/clang -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /run/media/ppqwqqq/22254a39-a5f0-4e28-93d1-96678a650d53/recover_hq1024/llvm/llvm-project-built/bin/clang - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /run/media/ppqwqqq/22254a39-a5f0-4e28-93d1-96678a650d53/recover_hq1024/llvm/llvm-project-built/bin/clang++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- bolt project is disabled -- clang project is enabled -- clang-tools-extra project is enabled -- cross-project-tests project is disabled -- lld project is enabled -- lldb project is enabled -- mlir project is enabled -- polly project is disabled -- flang project is disabled -- libc project is disabled -- compiler-rt project is disabled -- Doxygen disabled. -- Found Python3: /home/ppqwqqq/.pyenv/shims/python3.12 (found suitable version "3.12.9", minimum required is "3.8") found components: Interpreter -- Performing Test LLVM_LIBSTDCXX_MIN -- Performing Test LLVM_LIBSTDCXX_MIN - Success -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR - Success -- Looking for __GLIBC__ -- Looking for __GLIBC__ - found -- Looking for valgrind/valgrind.h -- Looking for valgrind/valgrind.h - found -- Looking for FE_ALL_EXCEPT -- Looking for FE_ALL_EXCEPT - found -- Looking for FE_INEXACT -- Looking for FE_INEXACT - found -- Performing Test HAVE_BUILTIN_THREAD_POINTER -- Performing Test HAVE_BUILTIN_THREAD_POINTER - Success -- Looking for CrashReporterClient.h -- Looking for CrashReporterClient.h - not found -- Looking for linux/magic.h -- Looking for linux/magic.h - found -- Looking for pthread_create in pthread -- Looking for pthread_create in pthread - found -- Looking for pthread_rwlock_init in pthread -- Looking for pthread_rwlock_init in pthread - found -- Looking for pthread_mutex_lock in pthread -- Looking for pthread_mutex_lock in pthread - found -- Looking for dlopen in dl -- Looking for dlopen in dl - found -- Looking for shm_open in rt -- Looking for shm_open in rt - found -- Looking for pfm_initialize in pfm -- Looking for pfm_initialize in pfm - not found -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE -- Found ZLIB: /usr/lib/libz.so (found version "1.3.2") -- Looking for compress2 -- Looking for compress2 - found -- Found LibXml2: /usr/lib/libxml2.so (found version "2.15.1") -- Looking for xmlReadMemory -- Looking for xmlReadMemory - found -- Looking for histedit.h -- Looking for histedit.h - found -- Found LibEdit: /usr/include (found version "2.11") -- Looking for arc4random -- Looking for arc4random - found -- Looking for backtrace -- Looking for backtrace - found -- backtrace facility detected in default set of libraries -- Found Backtrace: /usr/include -- Performing Test C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW -- Performing Test C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW - Success -- Looking for __register_frame -- Looking for __register_frame - found -- Looking for __deregister_frame -- Looking for __deregister_frame - found -- Looking for __unw_add_dynamic_fde -- Looking for __unw_add_dynamic_fde - not found -- Looking for _Unwind_Backtrace -- Looking for _Unwind_Backtrace - found -- Looking for getpagesize -- Looking for getpagesize - found -- Looking for sysconf -- Looking for sysconf - found -- Looking for getrusage -- Looking for getrusage - found -- Looking for isatty -- Looking for isatty - found -- Looking for futimens -- Looking for futimens - found -- Looking for futimes -- Looking for futimes - found -- Looking for getauxval -- Looking for getauxval - found -- Looking for sigaltstack -- Looking for sigaltstack - found -- Looking for mallctl -- Looking for mallctl - not found -- Looking for mallinfo -- Looking for mallinfo - found -- Looking for mallinfo2 -- Looking for mallinfo2 - found -- Looking for malloc_zone_statistics -- Looking for malloc_zone_statistics - not found -- Looking for posix_spawn -- Looking for posix_spawn - found -- Looking for pread -- Looking for pread - found -- Looking for sbrk -- Looking for sbrk - found -- Looking for strerror_r -- Looking for strerror_r - found -- Looking for strerror_s -- Looking for strerror_s - not found -- Looking for setenv -- Looking for setenv - found -- Performing Test HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC -- Performing Test HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC - Failed -- Performing Test HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC -- Performing Test HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC - Success -- Looking for pthread_getname_np -- Looking for pthread_getname_np - found -- Looking for pthread_setname_np -- Looking for pthread_setname_np - found -- Looking for pthread_get_name_np -- Looking for pthread_get_name_np - not found -- Looking for pthread_set_name_np -- Looking for pthread_set_name_np - not found -- Looking for dlopen -- Looking for dlopen - found -- Looking for proc_pid_rusage -- Looking for proc_pid_rusage - not found -- Performing Test HAVE_CXX_ATOMICS_WITHOUT_LIB -- Performing Test HAVE_CXX_ATOMICS_WITHOUT_LIB - Success -- Performing Test HAVE_CXX_ATOMICS64_WITHOUT_LIB -- Performing Test HAVE_CXX_ATOMICS64_WITHOUT_LIB - Success -- Performing Test LLVM_HAS_ATOMICS -- Performing Test LLVM_HAS_ATOMICS - Success -- LLVM host triple: x86_64-unknown-linux-gnu -- Native target architecture is X86 -- Threads enabled. -- Ninja version: 1.13.2 -- Could NOT find OCaml (missing: OCAMLFIND OCAML_VERSION OCAML_STDLIB_PATH) -- Could NOT find OCaml (missing: OCAMLFIND OCAML_VERSION OCAML_STDLIB_PATH) -- OCaml bindings disabled. -- Found Python module pygments -- Found Python module pygments.lexers.c_cpp -- Found Python module yaml -- LLVM default target triple: x86_64-unknown-linux-gnu -- Performing Test LLVM_USES_LIBSTDCXX -- Performing Test LLVM_USES_LIBSTDCXX - Success -- Performing Test LLVM_DEFAULT_TO_GLIBCXX_USE_CXX11_ABI -- Performing Test LLVM_DEFAULT_TO_GLIBCXX_USE_CXX11_ABI - Success -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER - Success -- Performing Test C_SUPPORTS_FPIC -- Performing Test C_SUPPORTS_FPIC - Success -- Performing Test CXX_SUPPORTS_FPIC -- Performing Test CXX_SUPPORTS_FPIC - Success -- Building with -fPIC -- Performing Test C_SUPPORTS_FNO_SEMANTIC_INTERPOSITION -- Performing Test C_SUPPORTS_FNO_SEMANTIC_INTERPOSITION - Success -- Performing Test CXX_SUPPORTS_FNO_SEMANTIC_INTERPOSITION -- Performing Test CXX_SUPPORTS_FNO_SEMANTIC_INTERPOSITION - Success -- Performing Test SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG -- Performing Test SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG - Success -- Performing Test C_SUPPORTS_CXX98_COMPAT_EXTRA_SEMI_FLAG -- Performing Test C_SUPPORTS_CXX98_COMPAT_EXTRA_SEMI_FLAG - Success -- Performing Test CXX_SUPPORTS_CXX98_COMPAT_EXTRA_SEMI_FLAG -- Performing Test CXX_SUPPORTS_CXX98_COMPAT_EXTRA_SEMI_FLAG - Success -- Performing Test CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG -- Performing Test CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG - Success -- Performing Test CXX_WSUGGEST_OVERRIDE_ALLOWS_ONLY_FINAL -- Performing Test CXX_WSUGGEST_OVERRIDE_ALLOWS_ONLY_FINAL - Success -- Performing Test C_WCOMMENT_ALLOWS_LINE_WRAP -- Performing Test C_WCOMMENT_ALLOWS_LINE_WRAP - Success -- Performing Test C_SUPPORTS_MISLEADING_INDENTATION_FLAG -- Performing Test C_SUPPORTS_MISLEADING_INDENTATION_FLAG - Success -- Performing Test CXX_SUPPORTS_MISLEADING_INDENTATION_FLAG -- Performing Test CXX_SUPPORTS_MISLEADING_INDENTATION_FLAG - Success -- Performing Test C_SUPPORTS_CTAD_MAYBE_UNSPPORTED_FLAG -- Performing Test C_SUPPORTS_CTAD_MAYBE_UNSPPORTED_FLAG - Success -- Performing Test CXX_SUPPORTS_CTAD_MAYBE_UNSPPORTED_FLAG -- Performing Test CXX_SUPPORTS_CTAD_MAYBE_UNSPPORTED_FLAG - Success -- Performing Test LINKER_SUPPORTS_COLOR_DIAGNOSTICS -- Performing Test LINKER_SUPPORTS_COLOR_DIAGNOSTICS - Success -- Looking for os_signpost_interval_begin -- Looking for os_signpost_interval_begin - not found -- Looking for flock -- Looking for flock - found -- Linker detection: LLD -- Performing Test LLVM_LINKER_SUPPORTS_B_SYMBOLIC_FUNCTIONS -- Performing Test LLVM_LINKER_SUPPORTS_B_SYMBOLIC_FUNCTIONS - Success -- Performing Test HAS_WERROR_GLOBAL_CTORS -- Performing Test HAS_WERROR_GLOBAL_CTORS - Success -- Performing Test LLVM_HAS_NOGLOBAL_CTOR_MUTEX -- Performing Test LLVM_HAS_NOGLOBAL_CTOR_MUTEX - Success -- Looking for __x86_64__ -- Looking for __x86_64__ - found -- Found Git: /usr/bin/git (found version "2.53.0") -- Looking for logf128 -- Looking for logf128 - found -- Targeting AArch64 -- Targeting AMDGPU -- Targeting ARM -- Targeting AVR -- Targeting BPF -- Targeting Hexagon -- Targeting Lanai -- Targeting LoongArch -- Targeting Mips -- Targeting MSP430 -- Targeting NVPTX -- Targeting PowerPC -- Targeting RISCV -- Targeting Sparc -- Targeting SPIRV -- Targeting SystemZ -- Targeting VE -- Targeting WebAssembly -- Targeting X86 -- Targeting XCore -- LLD version: 23.0.0 -- Performing Test C_SUPPORTS_WERROR_IMPLICIT_FUNCTION_DECLARATION -- Performing Test C_SUPPORTS_WERROR_IMPLICIT_FUNCTION_DECLARATION - Success -- Performing Test C_SUPPORTS_WUNDEF -- Performing Test C_SUPPORTS_WUNDEF - Success -- Performing Test C_SUPPORTS_WERROR_MISMATCHED_TAGS -- Performing Test C_SUPPORTS_WERROR_MISMATCHED_TAGS - Success -- Performing Test C_SUPPORTS_WERROR_GLOBAL_CONSTRUCTOR -- Performing Test C_SUPPORTS_WERROR_GLOBAL_CONSTRUCTOR - Success -- Performing Test CXX_SUPPORTS_WERROR_GLOBAL_CONSTRUCTOR -- Performing Test CXX_SUPPORTS_WERROR_GLOBAL_CONSTRUCTOR - Success -- Found CUDAToolkit: /opt/cuda/targets/x86_64-linux/include;/opt/cuda/targets/x86_64-linux/include/cccl (found version "13.1.115") -- Performing Test COMPILER_SUPPORTS_WARNING_WEAK_VTABLES -- Performing Test COMPILER_SUPPORTS_WARNING_WEAK_VTABLES - Success -- Looking for sys/resource.h -- Looking for sys/resource.h - found -- Looking for dlfcn.h -- Looking for dlfcn.h - found -- Looking for dladdr -- Looking for dladdr - found -- Clang version: 23.0.0git -- Looking for include file sys/inotify.h -- Looking for include file sys/inotify.h - found -- Performing Test HAVE_LINKER_FLAG_LONG_PLT -- Performing Test HAVE_LINKER_FLAG_LONG_PLT - Success -- Found Perl: /usr/bin/perl (found version "5.42.0") -- Found Python3: /home/ppqwqqq/.pyenv/shims/python3.12 (found version "3.12.9") found components: Interpreter -- Could NOT find SWIG (missing: SWIG_EXECUTABLE SWIG_DIR) (Required is at least version "4") -- Enable SWIG to generate LLDB bindings: FALSE -- Enable editline support in LLDB: TRUE -- Looking for acs_map -- Looking for acs_map - found -- Found CursesAndPanel: /usr/include -- Enable curses support in LLDB: TRUE -- Looking for lzma_auto_decoder in /usr/lib/liblzma.so -- Looking for lzma_auto_decoder in /usr/lib/liblzma.so - found -- Looking for lzma_easy_encoder in /usr/lib/liblzma.so -- Looking for lzma_easy_encoder in /usr/lib/liblzma.so - found -- Looking for lzma_lzma_preset in /usr/lib/liblzma.so -- Looking for lzma_lzma_preset in /usr/lib/liblzma.so - found -- Found LibLZMA: /usr/lib/liblzma.so (found version "5.8.2") -- Enable LZMA compression support in LLDB: TRUE -- SWIG 4 or later is required for Lua support in LLDB but could not be found -- Could NOT find LuaAndSwig (missing: LUA_EXECUTABLE LUA_LIBRARIES LUA_INCLUDE_DIR LUA_VERSION_MINOR LUA_VERSION_MAJOR LLDB_ENABLE_SWIG) -- Enable Lua scripting support in LLDB: FALSE -- SWIG 4 or later is required for Python support in LLDB but could not be found -- Could NOT find PythonAndSwig (missing: Python3_LIBRARIES Python3_INCLUDE_DIRS LLDB_ENABLE_SWIG) -- Enable Python scripting support in LLDB: FALSE -- Found LibXml2: /usr/lib/libxml2.so (found suitable version "2.15.1", minimum required is "2.8") -- Enable Libxml 2 support in LLDB: TRUE -- Could NOT find TreeSitter (missing: TreeSitter_BINARY) -- Enable Tree-sitter syntax highlighting: FALSE -- Looking for el_winsertstr -- Looking for el_winsertstr - found -- Looking for sys/types.h -- Looking for sys/types.h - found -- Looking for stdint.h -- Looking for stdint.h - found -- Looking for stddef.h -- Looking for stddef.h - found -- Check size of el_rfunc_t -- Check size of el_rfunc_t - done -- Performing Test CXX_SUPPORTS_STRINGOP_TRUNCATION -- Performing Test CXX_SUPPORTS_STRINGOP_TRUNCATION - Failed -- LLDB version: 23.0.0git -- Looking for ppoll -- Looking for ppoll - found -- Looking for ptsname_r -- Looking for ptsname_r - found -- Looking for accept4 -- Looking for accept4 - found -- Looking for termios.h -- Looking for termios.h - found -- Looking for include files sys/types.h, sys/event.h -- Looking for include files sys/types.h, sys/event.h - not found -- Looking for process_vm_readv -- Looking for process_vm_readv - found -- Looking for __NR_process_vm_readv -- Looking for __NR_process_vm_readv - found -- Looking for compression_encode_buffer in compression -- Looking for compression_encode_buffer in compression - not found -- Symbols (liblldb): exporting all symbols from the lldb namespace -- Found Doxygen: /usr/bin/doxygen (found version "1.16.1") found components: doxygen dot -- Found make: /usr/bin/make -- Found dirname: /usr/bin/dirname -- Performing Test CXX_SUPPORTS_DOCUMENTATION -- Performing Test CXX_SUPPORTS_DOCUMENTATION - Success -- Performing Test CXX_SUPPORTS_NO_DOCUMENTATION_DEPRECATED_SYNC -- Performing Test CXX_SUPPORTS_NO_DOCUMENTATION_DEPRECATED_SYNC - Success -- Looking for gettid -- Looking for gettid - found -- Registering ExampleIRTransforms as a pass plugin (static build: OFF) -- Registering Bye as a pass plugin (static build: OFF) -- LLVM FileCheck Found: /usr/bin/FileCheck -- Google Benchmark version: v0.0.0, normalized to 0.0.0 -- Looking for shm_open in rt -- Looking for shm_open in rt - found -- Performing Test HAVE_CXX_FLAG_WALL -- Performing Test HAVE_CXX_FLAG_WALL - Success -- Performing Test HAVE_CXX_FLAG_WEXTRA -- Performing Test HAVE_CXX_FLAG_WEXTRA - Success -- Performing Test HAVE_CXX_FLAG_WSHADOW -- Performing Test HAVE_CXX_FLAG_WSHADOW - Success -- Performing Test HAVE_CXX_FLAG_WFLOAT_EQUAL -- Performing Test HAVE_CXX_FLAG_WFLOAT_EQUAL - Success -- Performing Test HAVE_CXX_FLAG_WOLD_STYLE_CAST -- Performing Test HAVE_CXX_FLAG_WOLD_STYLE_CAST - Success -- Performing Test HAVE_CXX_FLAG_WSUGGEST_OVERRIDE -- Performing Test HAVE_CXX_FLAG_WSUGGEST_OVERRIDE - Success -- Performing Test HAVE_CXX_FLAG_PEDANTIC -- Performing Test HAVE_CXX_FLAG_PEDANTIC - Success -- Performing Test HAVE_CXX_FLAG_PEDANTIC_ERRORS -- Performing Test HAVE_CXX_FLAG_PEDANTIC_ERRORS - Success -- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32 -- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32 - Success -- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING -- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING - Success -- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS -- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS - Success -- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS -- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS - Success -- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING -- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING - Success -- Performing Test HAVE_CXX_FLAG_WD654 -- Performing Test HAVE_CXX_FLAG_WD654 - Failed -- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY -- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY - Success -- Enabling additional flags: -DINCLUDE_DIRECTORIES=/run/media/ppqwqqq/22254a39-a5f0-4e28-93d1-96678a650d53/recover_hq1024/llvm/llvm-project/third-party/benchmark/include -- Compiling and running to test HAVE_THREAD_SAFETY_ATTRIBUTES -- Performing Test HAVE_THREAD_SAFETY_ATTRIBUTES -- success -- Performing Test HAVE_CXX_FLAG_COVERAGE -- Performing Test HAVE_CXX_FLAG_COVERAGE - Failed -- Compiling and running to test HAVE_GNU_POSIX_REGEX -- Performing Test HAVE_GNU_POSIX_REGEX -- failed to compile -- Compiling and running to test HAVE_POSIX_REGEX -- Performing Test HAVE_POSIX_REGEX -- success -- Compiling and running to test HAVE_STEADY_CLOCK -- Performing Test HAVE_STEADY_CLOCK -- success -- Compiling and running to test HAVE_PTHREAD_AFFINITY -- Performing Test HAVE_PTHREAD_AFFINITY -- success -- Configuring done (31.1s) -- Generating done (9.3s) ``` ### Extra ```bash GLIBCXX_3.4.32 GLIBCXX_3.4.33 GLIBCXX_3.4.34 GLIBCXX_DEBUG_MESSAGE_LENGTH GLIBCXX_TUNABLES ``` >From da1d5ab7955980383ab6b9a3a7920efd34aa9c1d Mon Sep 17 00:00:00 2001 From: ppqwqqq <[email protected]> Date: Fri, 20 Feb 2026 23:41:34 +0800 Subject: [PATCH] Fix compatibility issues with GCC15+ with C++23 --- .../clangd/GlobalCompilationDatabase.cpp | 176 +++--- clang/lib/Interpreter/IncrementalParser.cpp | 8 +- clang/lib/Interpreter/IncrementalParser.h | 3 +- clang/tools/libclang/CIndexDiagnostic.cpp | 116 ++-- clang/tools/libclang/CIndexDiagnostic.h | 58 +- lldb/include/lldb/Core/EmulateInstruction.h | 13 +- .../Interfaces/ScriptedBreakpointInterface.h | 2 +- lldb/source/Core/EmulateInstruction.cpp | 7 + .../Clang/ASTStructExtractor.h | 10 +- .../Clang/ClangExpressionDeclMap.h | 33 +- .../Clang/ClangFunctionCaller.cpp | 7 + .../Clang/ClangFunctionCaller.h | 12 +- .../Clang/ClangUtilityFunction.cpp | 17 +- .../Clang/ClangUtilityFunction.h | 9 +- llvm/include/llvm/ADT/STLExtras.h | 89 ++- llvm/include/llvm/IR/CFG.h | 50 +- llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp | 571 ++++++++++-------- llvm/lib/Target/BPF/BPFAsmPrinter.cpp | 18 +- llvm/lib/Target/BPF/BPFAsmPrinter.h | 4 +- .../mlir/Query/Matcher/MatchersInternal.h | 16 +- mlir/lib/Query/Matcher/MatchFinder.cpp | 24 + 21 files changed, 704 insertions(+), 539 deletions(-) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index a1d9135111ca8..7dca3cd3e58f1 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -349,6 +349,94 @@ bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load( return true; } +// The broadcast thread announces files with new compile commands to the world. +// Primarily this is used to enqueue them for background indexing. +// +// It's on a separate thread because: +// - otherwise it would block the first parse of the initial file +// - we need to enumerate all files in the CDB, of which there are many +// - we (will) have to evaluate config for every file in the CDB, which is slow +class DirectoryBasedGlobalCompilationDatabase::BroadcastThread { + class Filter; + DirectoryBasedGlobalCompilationDatabase &Parent; + + std::mutex Mu; + std::condition_variable CV; + // Shutdown flag (CV is notified after writing). + // This is atomic so that broadcasts can also observe it and abort early. + std::atomic<bool> ShouldStop = {false}; + struct Task { + CDBLookupResult Lookup; + Context Ctx; + }; + std::deque<Task> Queue; + std::optional<Task> ActiveTask; + std::thread Thread; // Must be last member. + + // Thread body: this is just the basic queue procesing boilerplate. + void run() { + std::unique_lock<std::mutex> Lock(Mu); + while (true) { + bool Stopping = false; + CV.wait(Lock, [&] { + return (Stopping = ShouldStop.load(std::memory_order_acquire)) || + !Queue.empty(); + }); + if (Stopping) { + Queue.clear(); + CV.notify_all(); + return; + } + ActiveTask = std::move(Queue.front()); + Queue.pop_front(); + + Lock.unlock(); + { + WithContext WithCtx(std::move(ActiveTask->Ctx)); + process(ActiveTask->Lookup); + } + Lock.lock(); + ActiveTask.reset(); + CV.notify_all(); + } + } + + // Inspects a new CDB and broadcasts the files it owns. + void process(const CDBLookupResult &T); + +public: + BroadcastThread(DirectoryBasedGlobalCompilationDatabase &Parent) + : Parent(Parent), Thread([this] { run(); }) {} + + void enqueue(CDBLookupResult Lookup) { + { + assert(!Lookup.PI.SourceRoot.empty()); + std::lock_guard<std::mutex> Lock(Mu); + // New CDB takes precedence over any queued one for the same directory. + llvm::erase_if(Queue, [&](const Task &T) { + return T.Lookup.PI.SourceRoot == Lookup.PI.SourceRoot; + }); + Queue.push_back({std::move(Lookup), Context::current().clone()}); + } + CV.notify_all(); + } + + bool blockUntilIdle(Deadline Timeout) { + std::unique_lock<std::mutex> Lock(Mu); + return wait(Lock, CV, Timeout, + [&] { return Queue.empty() && !ActiveTask; }); + } + + ~BroadcastThread() { + { + std::lock_guard<std::mutex> Lock(Mu); + ShouldStop.store(true, std::memory_order_release); + } + CV.notify_all(); + Thread.join(); + } +}; + DirectoryBasedGlobalCompilationDatabase:: DirectoryBasedGlobalCompilationDatabase(const Options &Opts) : GlobalCompilationDatabase(Opts.FallbackWorkingDirectory), Opts(Opts), @@ -478,94 +566,6 @@ void DirectoryBasedGlobalCompilationDatabase::Options:: } } -// The broadcast thread announces files with new compile commands to the world. -// Primarily this is used to enqueue them for background indexing. -// -// It's on a separate thread because: -// - otherwise it would block the first parse of the initial file -// - we need to enumerate all files in the CDB, of which there are many -// - we (will) have to evaluate config for every file in the CDB, which is slow -class DirectoryBasedGlobalCompilationDatabase::BroadcastThread { - class Filter; - DirectoryBasedGlobalCompilationDatabase &Parent; - - std::mutex Mu; - std::condition_variable CV; - // Shutdown flag (CV is notified after writing). - // This is atomic so that broadcasts can also observe it and abort early. - std::atomic<bool> ShouldStop = {false}; - struct Task { - CDBLookupResult Lookup; - Context Ctx; - }; - std::deque<Task> Queue; - std::optional<Task> ActiveTask; - std::thread Thread; // Must be last member. - - // Thread body: this is just the basic queue procesing boilerplate. - void run() { - std::unique_lock<std::mutex> Lock(Mu); - while (true) { - bool Stopping = false; - CV.wait(Lock, [&] { - return (Stopping = ShouldStop.load(std::memory_order_acquire)) || - !Queue.empty(); - }); - if (Stopping) { - Queue.clear(); - CV.notify_all(); - return; - } - ActiveTask = std::move(Queue.front()); - Queue.pop_front(); - - Lock.unlock(); - { - WithContext WithCtx(std::move(ActiveTask->Ctx)); - process(ActiveTask->Lookup); - } - Lock.lock(); - ActiveTask.reset(); - CV.notify_all(); - } - } - - // Inspects a new CDB and broadcasts the files it owns. - void process(const CDBLookupResult &T); - -public: - BroadcastThread(DirectoryBasedGlobalCompilationDatabase &Parent) - : Parent(Parent), Thread([this] { run(); }) {} - - void enqueue(CDBLookupResult Lookup) { - { - assert(!Lookup.PI.SourceRoot.empty()); - std::lock_guard<std::mutex> Lock(Mu); - // New CDB takes precedence over any queued one for the same directory. - llvm::erase_if(Queue, [&](const Task &T) { - return T.Lookup.PI.SourceRoot == Lookup.PI.SourceRoot; - }); - Queue.push_back({std::move(Lookup), Context::current().clone()}); - } - CV.notify_all(); - } - - bool blockUntilIdle(Deadline Timeout) { - std::unique_lock<std::mutex> Lock(Mu); - return wait(Lock, CV, Timeout, - [&] { return Queue.empty() && !ActiveTask; }); - } - - ~BroadcastThread() { - { - std::lock_guard<std::mutex> Lock(Mu); - ShouldStop.store(true, std::memory_order_release); - } - CV.notify_all(); - Thread.join(); - } -}; - // The DirBasedCDB associates each file with a specific CDB. // When a CDB is discovered, it may claim to describe files that we associate // with a different CDB. We do not want to broadcast discovery of these, and diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index bf08911e23533..3a8a094f85504 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -196,7 +196,7 @@ void IncrementalParser::CleanUpPTU(TranslationUnitDecl *MostRecentTU) { PartialTranslationUnit & IncrementalParser::RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr<llvm::Module> M /*={}*/) { + std::unique_ptr<llvm::Module> M) { PTUs.emplace_back(PartialTranslationUnit()); PartialTranslationUnit &LastPTU = PTUs.back(); LastPTU.TUPart = TU; @@ -215,4 +215,10 @@ IncrementalParser::RegisterPTU(TranslationUnitDecl *TU, LLVM_DEBUG(llvm::dbgs() << "]\n"); return LastPTU; } + +PartialTranslationUnit & +IncrementalParser::RegisterPTU(TranslationUnitDecl *TU) { + return RegisterPTU(TU, nullptr); +} + } // end namespace clang diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index 9b042bc494efb..7be2a445c2cbd 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -68,7 +68,8 @@ class IncrementalParser { /// Register a PTU produced by Parse. PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, - std::unique_ptr<llvm::Module> M = {}); + std::unique_ptr<llvm::Module> M); + PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU); private: llvm::Expected<TranslationUnitDecl *> ParseOrWrapTopLevelDecl(); diff --git a/clang/tools/libclang/CIndexDiagnostic.cpp b/clang/tools/libclang/CIndexDiagnostic.cpp index d37597e747a84..7be91786c8a65 100644 --- a/clang/tools/libclang/CIndexDiagnostic.cpp +++ b/clang/tools/libclang/CIndexDiagnostic.cpp @@ -12,9 +12,9 @@ #include "CIndexDiagnostic.h" #include "CIndexer.h" -#include "CXTranslationUnit.h" #include "CXSourceLocation.h" #include "CXString.h" +#include "CXTranslationUnit.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Frontend/ASTUnit.h" @@ -27,10 +27,13 @@ using namespace clang::cxloc; using namespace clang::cxdiag; using namespace llvm; +CXDiagnosticSetImpl::CXDiagnosticSetImpl(bool isManaged) + : IsExternallyManaged(isManaged) {} + CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {} -void -CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) { +void CXDiagnosticSetImpl::appendDiagnostic( + std::unique_ptr<CXDiagnosticImpl> D) { Diagnostics.push_back(std::move(D)); } @@ -40,6 +43,7 @@ namespace { class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl { std::string Message; CXSourceLocation Loc; + public: CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L) : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)), @@ -77,8 +81,8 @@ class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl { *ReplacementRange = clang_getNullRange(); return cxstring::createEmpty(); } -}; - +}; + class CXDiagnosticRenderer : public DiagnosticNoteRenderer { public: CXDiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions &DiagOpts, @@ -95,7 +99,7 @@ class CXDiagnosticRenderer : public DiagnosticNoteRenderer { dyn_cast_if_present<const StoredDiagnostic *>(D); if (!SD) return; - + if (Level != DiagnosticsEngine::Note) CurrentSet = MainSet; @@ -113,7 +117,7 @@ class CXDiagnosticRenderer : public DiagnosticNoteRenderer { DiagOrStoredDiag D) override { if (!D.isNull()) return; - + CXSourceLocation L; if (Loc.hasManager()) L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); @@ -143,8 +147,8 @@ class CXDiagnosticRenderer : public DiagnosticNoteRenderer { CXDiagnosticSetImpl *CurrentSet; CXDiagnosticSetImpl *MainSet; -}; -} +}; +} // namespace CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, bool checkIfChanged) { @@ -168,8 +172,8 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, // We check here if a new diagnostic was appended since the last time the // diagnostic set was created, in which case we reset it. - CXDiagnosticSetImpl * - Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); + CXDiagnosticSetImpl *Set = + static_cast<CXDiagnosticSetImpl *>(TU->Diagnostics); if (AU->stored_diag_size() != Set->getNumDiagnostics()) { // Diagnostics in the ASTUnit were updated, reset the associated // diagnostics. @@ -186,11 +190,12 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, Set); for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(), - ei = AU->stored_diag_end(); it != ei; ++it) { + ei = AU->stored_diag_end(); + it != ei; ++it) { Renderer.emitStoredDiagnostic(*it); } } - return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); + return static_cast<CXDiagnosticSetImpl *>(TU->Diagnostics); } //----------------------------------------------------------------------------- @@ -216,7 +221,7 @@ CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { if (!D) return nullptr; - CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D); + CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl *>(D); if (Index >= Diags->getNumDiagnostics()) return nullptr; @@ -246,14 +251,14 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { SmallString<256> Str; llvm::raw_svector_ostream Out(Str); - + if (Options & CXDiagnostic_DisplaySourceLocation) { // Print source location (file:line), along with optional column // and source ranges. CXFile File; unsigned Line, Column; - clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), - &File, &Line, &Column, nullptr); + clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), &File, + &Line, &Column, nullptr); if (File) { CXString FName = clang_getFileName(File); Out << clang_getCString(FName) << ":" << Line << ":"; @@ -267,36 +272,44 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { for (unsigned I = 0; I != N; ++I) { CXFile StartFile, EndFile; CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); - + unsigned StartLine, StartColumn, EndLine, EndColumn; - clang_getSpellingLocation(clang_getRangeStart(Range), - &StartFile, &StartLine, &StartColumn, - nullptr); - clang_getSpellingLocation(clang_getRangeEnd(Range), - &EndFile, &EndLine, &EndColumn, nullptr); + clang_getSpellingLocation(clang_getRangeStart(Range), &StartFile, + &StartLine, &StartColumn, nullptr); + clang_getSpellingLocation(clang_getRangeEnd(Range), &EndFile, + &EndLine, &EndColumn, nullptr); if (StartFile != EndFile || StartFile != File) continue; - - Out << "{" << StartLine << ":" << StartColumn << "-" - << EndLine << ":" << EndColumn << "}"; + + Out << "{" << StartLine << ":" << StartColumn << "-" << EndLine << ":" + << EndColumn << "}"; PrintedRange = true; } if (PrintedRange) Out << ":"; } - + Out << " "; } } /* Print warning/error/etc. */ switch (Severity) { - case CXDiagnostic_Ignored: llvm_unreachable("impossible"); - case CXDiagnostic_Note: Out << "note: "; break; - case CXDiagnostic_Warning: Out << "warning: "; break; - case CXDiagnostic_Error: Out << "error: "; break; - case CXDiagnostic_Fatal: Out << "fatal error: "; break; + case CXDiagnostic_Ignored: + llvm_unreachable("impossible"); + case CXDiagnostic_Note: + Out << "note: "; + break; + case CXDiagnostic_Warning: + Out << "warning: "; + break; + case CXDiagnostic_Error: + Out << "error: "; + break; + case CXDiagnostic_Fatal: + Out << "fatal error: "; + break; } CXString Text = clang_getDiagnosticSpelling(Diagnostic); @@ -305,7 +318,7 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { else Out << "<no diagnostic text>"; clang_disposeString(Text); - + if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId | CXDiagnostic_DisplayCategoryName)) { bool NeedBracket = true; @@ -322,9 +335,9 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { } clang_disposeString(OptionName); } - - if (Options & (CXDiagnostic_DisplayCategoryId | - CXDiagnostic_DisplayCategoryName)) { + + if (Options & + (CXDiagnostic_DisplayCategoryId | CXDiagnostic_DisplayCategoryName)) { if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) { if (Options & CXDiagnostic_DisplayCategoryId) { if (NeedBracket) @@ -335,7 +348,7 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { NeedBracket = false; NeedComma = true; } - + if (Options & CXDiagnostic_DisplayCategoryName) { CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic); if (NeedBracket) @@ -350,11 +363,11 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { } } - (void) NeedComma; // Silence dead store warning. + (void)NeedComma; // Silence dead store warning. if (!NeedBracket) Out << "]"; } - + return cxstring::createDup(Out.str()); } @@ -364,13 +377,13 @@ unsigned clang_defaultDiagnosticDisplayOptions() { } enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { - if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag)) + if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) return D->getSeverity(); return CXDiagnostic_Ignored; } CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) { - if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag)) + if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) return D->getLocation(); return clang_getNullLocation(); } @@ -396,18 +409,18 @@ unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) { return D->getCategory(); return 0; } - + CXString clang_getDiagnosticCategoryName(unsigned Category) { // Kept for backward compatibility. return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category)); } - + CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) { if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) return D->getCategoryText(); return cxstring::createEmpty(); } - + unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) { if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) return D->getNumRanges(); @@ -415,7 +428,7 @@ unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) { } CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) { - CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag); + CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag); if (!D || Range >= D->getNumRanges()) return clang_getNullRange(); return D->getRange(Range); @@ -444,25 +457,24 @@ void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) { delete D; } } - -CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, - unsigned Index) { - if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags)) + +CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, unsigned Index) { + if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) if (Index < D->getNumDiagnostics()) return D->getDiagnostic(Index); return nullptr; } - + CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) { if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) { CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics(); - return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags; + return ChildDiags.empty() ? nullptr : (CXDiagnosticSet)&ChildDiags; } return nullptr; } unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) { - if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags)) + if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) return D->getNumDiagnostics(); return 0; } diff --git a/clang/tools/libclang/CIndexDiagnostic.h b/clang/tools/libclang/CIndexDiagnostic.h index 25589bb57474a..c109710475fd3 100644 --- a/clang/tools/libclang/CIndexDiagnostic.h +++ b/clang/tools/libclang/CIndexDiagnostic.h @@ -14,29 +14,27 @@ #define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXDIAGNOSTIC_H #include "clang-c/Index.h" +#include <assert.h> #include <memory> #include <vector> -#include <assert.h> namespace clang { class LangOptions; class StoredDiagnostic; class CXDiagnosticImpl; - + class CXDiagnosticSetImpl { std::vector<std::unique_ptr<CXDiagnosticImpl>> Diagnostics; const bool IsExternallyManaged; + public: - CXDiagnosticSetImpl(bool isManaged = false) - : IsExternallyManaged(isManaged) {} + CXDiagnosticSetImpl(bool isManaged = false); virtual ~CXDiagnosticSetImpl(); - size_t getNumDiagnostics() const { - return Diagnostics.size(); - } - + size_t getNumDiagnostics() const { return Diagnostics.size(); } + CXDiagnosticImpl *getDiagnostic(unsigned i) const { assert(i < getNumDiagnostics()); return Diagnostics[i].get(); @@ -44,23 +42,24 @@ class CXDiagnosticSetImpl { void appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D); - bool empty() const { - return Diagnostics.empty(); - } - + bool empty() const { return Diagnostics.empty(); } + bool isExternallyManaged() const { return IsExternallyManaged; } }; class CXDiagnosticImpl { public: - enum Kind { StoredDiagnosticKind, LoadedDiagnosticKind, - CustomNoteDiagnosticKind }; - + enum Kind { + StoredDiagnosticKind, + LoadedDiagnosticKind, + CustomNoteDiagnosticKind + }; + virtual ~CXDiagnosticImpl(); - + /// Return the severity of the diagnostic. virtual CXDiagnosticSeverity getSeverity() const = 0; - + /// Return the location of the diagnostic. virtual CXSourceLocation getLocation() const = 0; @@ -69,7 +68,7 @@ class CXDiagnosticImpl { /// Return the text for the diagnostic option. virtual CXString getDiagnosticOption(CXString *Disable) const = 0; - + /// Return the category of the diagnostic. virtual unsigned getCategory() const = 0; @@ -78,7 +77,7 @@ class CXDiagnosticImpl { /// Return the number of source ranges for the diagnostic. virtual unsigned getNumRanges() const = 0; - + /// Return the source ranges for the diagnostic. virtual CXSourceRange getRange(unsigned Range) const = 0; @@ -90,11 +89,9 @@ class CXDiagnosticImpl { CXSourceRange *ReplacementRange) const = 0; Kind getKind() const { return K; } - - CXDiagnosticSetImpl &getChildDiagnostics() { - return ChildDiags; - } - + + CXDiagnosticSetImpl &getChildDiagnostics() { return ChildDiags; } + protected: CXDiagnosticImpl(Kind k) : K(k) {} CXDiagnosticSetImpl ChildDiags; @@ -102,20 +99,19 @@ class CXDiagnosticImpl { void append(std::unique_ptr<CXDiagnosticImpl> D) { ChildDiags.appendDiagnostic(std::move(D)); } - + private: Kind K; }; - + /// The storage behind a CXDiagnostic struct CXStoredDiagnostic : public CXDiagnosticImpl { const StoredDiagnostic &Diag; const LangOptions &LangOpts; - - CXStoredDiagnostic(const StoredDiagnostic &Diag, - const LangOptions &LangOpts) - : CXDiagnosticImpl(StoredDiagnosticKind), - Diag(Diag), LangOpts(LangOpts) { } + + CXStoredDiagnostic(const StoredDiagnostic &Diag, const LangOptions &LangOpts) + : CXDiagnosticImpl(StoredDiagnosticKind), Diag(Diag), LangOpts(LangOpts) { + } ~CXStoredDiagnostic() override {} diff --git a/lldb/include/lldb/Core/EmulateInstruction.h b/lldb/include/lldb/Core/EmulateInstruction.h index ff1386cce570b..a023945048969 100644 --- a/lldb/include/lldb/Core/EmulateInstruction.h +++ b/lldb/include/lldb/Core/EmulateInstruction.h @@ -41,8 +41,7 @@ using BreakpointLocations = std::vector<lldb::addr_t>; class SingleStepBreakpointLocationsPredictor { public: SingleStepBreakpointLocationsPredictor( - std::unique_ptr<EmulateInstruction> emulator_up) - : m_emulator_up{std::move(emulator_up)} {} + std::unique_ptr<EmulateInstruction> emulator_up); virtual BreakpointLocations GetBreakpointLocations(Status &status); @@ -51,13 +50,13 @@ class SingleStepBreakpointLocationsPredictor { return 4; } - virtual ~SingleStepBreakpointLocationsPredictor() = default; + virtual ~SingleStepBreakpointLocationsPredictor(); protected: - // This function retrieves the address of the next instruction as it appears - // in the binary file. Essentially, it reads the value of the PC register, - // determines the size of the current instruction (where the PC is pointing), - // and returns the sum of these two values. + // This function retrieves the address of the next instruction as it + // appears in the binary file. Essentially, it reads the value of the PC + // register, determines the size of the current instruction (where the PC + // is pointing), and returns the sum of these two values. lldb::addr_t GetNextInstructionAddress(Status &error); lldb::addr_t GetBreakpointLocationAddress(lldb::addr_t entry_pc, diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h index d6d2ee786788e..695a1b8dd6e6a 100644 --- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h @@ -25,7 +25,7 @@ class ScriptedBreakpointInterface : public ScriptedInterface { /// any breakpoint locations it found in that module. virtual bool ResolverCallback(SymbolContext sym_ctx) { return true; } virtual lldb::SearchDepth GetDepth() { return lldb::eSearchDepthModule; } - virtual std::optional<std::string> GetShortHelp() { return nullptr; } + virtual std::optional<std::string> GetShortHelp() { return std::nullopt; } /// WasHit returns the breakpoint location SP for the location that was "hit". virtual lldb::BreakpointLocationSP WasHit(lldb::StackFrameSP frame_sp, lldb::BreakpointLocationSP bp_loc_sp) { diff --git a/lldb/source/Core/EmulateInstruction.cpp b/lldb/source/Core/EmulateInstruction.cpp index 634ce1075d54b..7e6bd25c22026 100644 --- a/lldb/source/Core/EmulateInstruction.cpp +++ b/lldb/source/Core/EmulateInstruction.cpp @@ -684,3 +684,10 @@ SingleStepBreakpointLocationsPredictor::GetBreakpointLocationAddress( error = Status("Instruction emulation failed unexpectedly."); return LLDB_INVALID_ADDRESS; } + +SingleStepBreakpointLocationsPredictor::SingleStepBreakpointLocationsPredictor( + std::unique_ptr<EmulateInstruction> emuluator_up) + : m_emulator_up{std::move(emuluator_up)} {} + +SingleStepBreakpointLocationsPredictor:: + ~SingleStepBreakpointLocationsPredictor() = default; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h index c285f64088956..8ce81c9efc19a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -114,15 +114,15 @@ class ASTStructExtractor : public clang::SemaConsumer { clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for - ///passthrough. NULL if it's a - ///SemaConsumer. + /// passthrough. NULL if it's a + /// SemaConsumer. clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, - ///for passthrough. NULL if it's an - ///ASTConsumer. + /// for passthrough. NULL if it's an + /// ASTConsumer. clang::Sema *m_sema; ///< The Sema to use. ClangFunctionCaller &m_function; ///< The function to populate with - ///information about the argument structure. + /// information about the argument structure. std::string m_struct_name; ///< The name of the structure to extract. }; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index d44c95068f45d..a8f20a112fdb4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -130,9 +130,9 @@ class ClangExpressionDeclMap : public ClangASTSource { /// /// \return /// True on success; false otherwise. - bool AddPersistentVariable(const clang::NamedDecl *decl, - ConstString name, TypeFromParser type, - bool is_result, bool is_lvalue); + bool AddPersistentVariable(const clang::NamedDecl *decl, ConstString name, + TypeFromParser type, bool is_result, + bool is_lvalue); /// [Used by IRForTarget] Add a variable to the struct that needs to /// be materialized each time the expression runs. @@ -252,8 +252,7 @@ class ClangExpressionDeclMap : public ClangASTSource { ConstString name, lldb::SymbolType symbol_type, Module *module = nullptr); - lldb::addr_t GetSymbolAddress(ConstString name, - lldb::SymbolType symbol_type); + lldb::addr_t GetSymbolAddress(ConstString name, lldb::SymbolType symbol_type); struct TargetInfo { lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; @@ -303,14 +302,14 @@ class ClangExpressionDeclMap : public ClangASTSource { ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. bool m_keep_result_in_memory; ///< True if result persistent variables - ///generated by this expression should stay in - ///memory. + /// generated by this expression should stay in + /// memory. Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to - ///ClangUserExpression. + /// ClangUserExpression. ValueObject *m_ctx_obj; ///< If not empty, then expression is - ///evaluated in context of this object. - ///For details see the comment to + /// evaluated in context of this object. + /// For details see the comment to ///`UserExpression::Evaluate`. /// If \c true, evaluates the expression without taking into account the @@ -334,18 +333,18 @@ class ClangExpressionDeclMap : public ClangASTSource { ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables - ///and types. + /// and types. ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. bool m_enable_lookups = false; ///< Set to true during parsing if we have - ///found the first "$__lldb" name. + /// found the first "$__lldb" name. TargetInfo m_target_info; ///< Basic information about the target. Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer - ///to use when reporting used - ///variables. + /// to use when reporting used + /// variables. clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator - ///that receives new top-level - ///functions. + /// that receives new top-level + /// functions. DiagnosticManager *m_diagnostics = nullptr; private: @@ -398,7 +397,7 @@ class ClangExpressionDeclMap : public ClangASTSource { /// Get this parser's ID for use in extracting parser- and JIT-specific data /// from persistent variables. - uint64_t GetParserID() { return (uint64_t) this; } + uint64_t GetParserID() { return (uint64_t)this; } /// Should be called on all copied functions. void MaybeRegisterFunctionBody(clang::FunctionDecl *copied_function_decl); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index d2db319afb7a0..f6186f7fca2f3 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -209,6 +209,13 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, char ClangFunctionCaller::ClangFunctionCallerHelper::ID; +ClangFunctionCaller::ClangFunctionCallerHelper::ClangFunctionCallerHelper( + ClangFunctionCaller &owner) + : m_owner(owner) {} + +ClangFunctionCaller::ClangFunctionCallerHelper::~ClangFunctionCallerHelper() = + default; + clang::ASTConsumer * ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer( clang::ASTConsumer *passthrough) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 9329ce76ec3bd..53bb60745e338 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -64,7 +64,9 @@ class ClangFunctionCaller : public FunctionCaller { // LLVM RTTI support static char ID; - ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {} + ClangFunctionCallerHelper( + ClangFunctionCaller + &owner); // Avoid make implementation in header : m_owner(owner) {} /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. @@ -79,12 +81,14 @@ class ClangFunctionCaller : public FunctionCaller { clang::ASTConsumer * ASTTransformer(clang::ASTConsumer *passthrough) override; + ~ClangFunctionCallerHelper() override; + private: ClangFunctionCaller &m_owner; std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that - ///generates the - ///argument struct - ///layout. + /// generates the + /// argument struct + /// layout. }; // LLVM RTTI support diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 112ce9be7bd1a..335500f8ac7ce 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -8,6 +8,7 @@ #include "ClangUtilityFunction.h" #include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" #include "ClangExpressionParser.h" #include "ClangExpressionSourceCode.h" #include "ClangPersistentVariables.h" @@ -15,7 +16,6 @@ #include <cstdio> #include <sys/types.h> - #include "lldb/Core/Module.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Host/Host.h" @@ -174,8 +174,23 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, } } +ClangUtilityFunction::ClangUtilityFunctionHelper::ClangUtilityFunctionHelper() = + default; + +ClangUtilityFunction::ClangUtilityFunctionHelper:: + ~ClangUtilityFunctionHelper() = default; + char ClangUtilityFunction::ClangUtilityFunctionHelper::ID; +ClangExpressionDeclMap * +ClangUtilityFunction::ClangUtilityFunctionHelper::DeclMap() { + return m_expr_decl_map_up.get(); +} + +void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap() { + return m_expr_decl_map_up.reset(); +} + void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap( ExecutionContext &exe_ctx, bool keep_result_in_memory) { std::shared_ptr<ClangASTImporter> ast_importer; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index 72ff84f3ceaf7..39ab4770a5270 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -76,16 +76,17 @@ class ClangUtilityFunction : public UtilityFunction { : public llvm::RTTIExtends<ClangUtilityFunctionHelper, ClangExpressionHelper> { public: + ClangUtilityFunctionHelper(); + ~ClangUtilityFunctionHelper() override; + // LLVM RTTI support static char ID; /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. - ClangExpressionDeclMap *DeclMap() override { - return m_expr_decl_map_up.get(); - } + ClangExpressionDeclMap *DeclMap() override; - void ResetDeclMap() { m_expr_decl_map_up.reset(); } + void ResetDeclMap(/* Requires full type */); void ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory); diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 80c97e77724e9..aec93ad9a13aa 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -341,7 +341,7 @@ class mapped_iterator public: mapped_iterator() = default; mapped_iterator(ItTy U, FuncTy F) - : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} + : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} ItTy getCurrent() { return this->I; } @@ -655,7 +655,7 @@ using std::declval; // We have to alias this since inlining the actual type at the usage site // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. -template<typename... Iters> struct ZipTupleType { +template <typename... Iters> struct ZipTupleType { using type = std::tuple<decltype(*declval<Iters>())...>; }; @@ -704,7 +704,7 @@ struct zip_common : zip_traits<ZipType, ReferenceTupleType, Iters...> { } public: - zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} + zip_common(Iters &&...ts) : iterators(std::forward<Iters>(ts)...) {} value_type operator*() const { return deref(IndexSequence{}); } @@ -861,8 +861,7 @@ detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, } namespace detail { -template <typename Iter> -Iter next_or_end(const Iter &I, const Iter &End) { +template <typename Iter> Iter next_or_end(const Iter &I, const Iter &End) { if (I == End) return End; return std::next(I); @@ -966,7 +965,7 @@ template <typename... Args> class zip_longest_range { } public: - zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} + zip_longest_range(Args &&...ts_) : ts(std::forward<Args>(ts_)...) {} iterator begin() const { return begin_impl(std::index_sequence_for<Args...>{}); @@ -980,7 +979,7 @@ template <typename... Args> class zip_longest_range { /// if the iterator has not reached the end. template <typename T, typename U, typename... Args> detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u, - Args &&... args) { + Args &&...args) { return detail::zip_longest_range<T, U, Args...>( std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); } @@ -1124,18 +1123,14 @@ template <typename ValueT, typename... RangeTs> class concat_range { } public: - concat_range(RangeTs &&... Ranges) + concat_range(RangeTs &&...Ranges) : Ranges(std::forward<RangeTs>(Ranges)...) {} - iterator begin() { - return begin_impl(std::index_sequence_for<RangeTs...>{}); - } + iterator begin() { return begin_impl(std::index_sequence_for<RangeTs...>{}); } iterator begin() const { return begin_impl(std::index_sequence_for<RangeTs...>{}); } - iterator end() { - return end_impl(std::index_sequence_for<RangeTs...>{}); - } + iterator end() { return end_impl(std::index_sequence_for<RangeTs...>{}); } iterator end() const { return end_impl(std::index_sequence_for<RangeTs...>{}); } @@ -1221,6 +1216,9 @@ class indexed_accessor_range_base { class iterator : public indexed_accessor_iterator<iterator, BaseT, T, PointerT, ReferenceT> { public: + iterator() + : indexed_accessor_iterator<iterator, BaseT, T, std::remove_cv_t<T>, T>( + nullptr, 0) {} // Index into this iterator, invoking a static method on the derived type. ReferenceT operator*() const { return DerivedT::dereference_iterator(this->getBase(), this->getIndex()); @@ -1453,8 +1451,7 @@ struct less_second { /// \brief Function object to apply a binary function to the first component of /// a std::pair. -template<typename FuncTy> -struct on_first { +template <typename FuncTy> struct on_first { FuncTy func; template <typename T> @@ -1542,22 +1539,22 @@ void shuffle(Iterator first, Iterator last, RNG &&g) { } /// Adapt std::less<T> for array_pod_sort. -template<typename T> +template <typename T> inline int array_pod_sort_comparator(const void *P1, const void *P2) { - if (std::less<T>()(*reinterpret_cast<const T*>(P1), - *reinterpret_cast<const T*>(P2))) + if (std::less<T>()(*reinterpret_cast<const T *>(P1), + *reinterpret_cast<const T *>(P2))) return -1; - if (std::less<T>()(*reinterpret_cast<const T*>(P2), - *reinterpret_cast<const T*>(P1))) + if (std::less<T>()(*reinterpret_cast<const T *>(P2), + *reinterpret_cast<const T *>(P1))) return 1; return 0; } /// get_array_pod_sort_comparator - This is an internal helper function used to /// get type deduction of T right. -template<typename T> -inline int (*get_array_pod_sort_comparator(const T &)) - (const void*, const void*) { +template <typename T> +inline int (*get_array_pod_sort_comparator(const T &))(const void *, + const void *) { return array_pod_sort_comparator<T>; } @@ -1592,12 +1589,13 @@ inline void presortShuffle(IteratorTy Start, IteratorTy End) { /// /// NOTE: If qsort_r were portable, we could allow a custom comparator and /// default to std::less. -template<class IteratorTy> +template <class IteratorTy> inline void array_pod_sort(IteratorTy Start, IteratorTy End) { // Don't inefficiently call qsort with one element or trigger undefined // behavior with an empty sequence. auto NElts = End - Start; - if (NElts <= 1) return; + if (NElts <= 1) + return; #ifdef EXPENSIVE_CHECKS detail::presortShuffle<IteratorTy>(Start, End); #endif @@ -1613,7 +1611,8 @@ inline void array_pod_sort( // Don't inefficiently call qsort with one element or trigger undefined // behavior with an empty sequence. auto NElts = End - Start; - if (NElts <= 1) return; + if (NElts <= 1) + return; #ifdef EXPENSIVE_CHECKS detail::presortShuffle<IteratorTy>(Start, End); #endif @@ -1666,12 +1665,13 @@ inline void sort(Container &&C, Compare Comp) { /// Get the size of a range. This is a wrapper function around std::distance /// which is only enabled when the operation is O(1). template <typename R> -auto size(R &&Range, - std::enable_if_t< - std::is_base_of<std::random_access_iterator_tag, - typename std::iterator_traits<decltype( - Range.begin())>::iterator_category>::value, - void> * = nullptr) { +auto size( + R &&Range, + std::enable_if_t< + std::is_base_of<std::random_access_iterator_tag, + typename std::iterator_traits< + decltype(Range.begin())>::iterator_category>::value, + void> * = nullptr) { return std::distance(Range.begin(), Range.end()); } @@ -2112,13 +2112,11 @@ auto uninitialized_copy(R &&Src, IterTy Dst) { return std::uninitialized_copy(adl_begin(Src), adl_end(Src), Dst); } -template <typename R> -void stable_sort(R &&Range) { +template <typename R> void stable_sort(R &&Range) { std::stable_sort(adl_begin(Range), adl_end(Range)); } -template <typename R, typename Compare> -void stable_sort(R &&Range, Compare C) { +template <typename R, typename Compare> void stable_sort(R &&Range, Compare C) { std::stable_sort(adl_begin(Range), adl_end(Range), C); } @@ -2130,7 +2128,7 @@ auto partition_point(R &&Range, Predicate P) { return std::partition_point(adl_begin(Range), adl_end(Range), P); } -template<typename Range, typename Predicate> +template <typename Range, typename Predicate> auto unique(Range &&R, Predicate P) { return std::unique(adl_begin(R), adl_end(R), P); } @@ -2304,8 +2302,7 @@ template <typename Container, typename StreamT, typename T = detail::ValueOfRange<Container>> inline void interleave(const Container &c, StreamT &os, const StringRef &separator) { - interleave( - c, os, [&](const T &a) { os << a; }, separator); + interleave(c, os, [&](const T &a) { os << a; }, separator); } template <typename Container, typename UnaryFunctor, typename StreamT, @@ -2325,13 +2322,10 @@ inline void interleaveComma(const Container &c, StreamT &os) { //===----------------------------------------------------------------------===// struct FreeDeleter { - void operator()(void* v) { - ::free(v); - } + void operator()(void *v) { ::free(v); } }; -template<typename First, typename Second> -struct pair_hash { +template <typename First, typename Second> struct pair_hash { size_t operator()(const std::pair<First, Second> &P) const { return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); } @@ -2589,8 +2583,9 @@ bool all_of_zip_predicate_last( std::index_sequence<InputIndexes...>) { auto constexpr OutputIndex = std::tuple_size<decltype(argsThenPredicate)>::value - 1; - return all_of_zip_predicate_first(std::get<OutputIndex>(argsThenPredicate), - std::get<InputIndexes>(argsThenPredicate)...); + return all_of_zip_predicate_first( + std::get<OutputIndex>(argsThenPredicate), + std::get<InputIndexes>(argsThenPredicate)...); } } // end namespace detail diff --git a/llvm/include/llvm/IR/CFG.h b/llvm/include/llvm/IR/CFG.h index 96d3b2fbb5b0b..e6503a2f18ebf 100644 --- a/llvm/include/llvm/IR/CFG.h +++ b/llvm/include/llvm/IR/CFG.h @@ -70,8 +70,8 @@ class PredIterator { } inline PredIterator(Ptr *bb, bool) : It(bb->user_end()) {} - inline bool operator==(const Self& x) const { return It == x.It; } - inline bool operator!=(const Self& x) const { return !operator==(x); } + inline bool operator==(const Self &x) const { return It == x.It; } + inline bool operator!=(const Self &x) const { return !operator==(x); } inline reference operator*() const { assert(!It.atEnd() && "pred_iterator out of range!"); @@ -79,27 +79,26 @@ class PredIterator { } inline pointer *operator->() const { return &operator*(); } - inline Self& operator++() { // Preincrement + inline Self &operator++() { // Preincrement assert(!It.atEnd() && "pred_iterator out of range!"); - ++It; advancePastNonTerminators(); + ++It; + advancePastNonTerminators(); return *this; } inline Self operator++(int) { // Postincrement - Self tmp = *this; ++*this; return tmp; + Self tmp = *this; + ++*this; + return tmp; } /// getOperandNo - Return the operand number in the predecessor's /// terminator of the successor. - unsigned getOperandNo() const { - return It.getOperandNo(); - } + unsigned getOperandNo() const { return It.getOperandNo(); } /// getUse - Return the operand Use in the predecessor's terminator /// of the successor. - Use &getUse() const { - return It.getUse(); - } + Use &getUse() const { return It.getUse(); } }; using pred_iterator = PredIterator<BasicBlock, Value::user_iterator>; @@ -112,7 +111,9 @@ inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { return const_pred_iterator(BB); } -inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} +inline pred_iterator pred_end(BasicBlock *BB) { + return pred_iterator(BB, true); +} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } @@ -180,6 +181,7 @@ class SuccIterator }; public: + SuccIterator() : Inst(nullptr), Idx(0) {} // begin iterator explicit inline SuccIterator(InstructionT *Inst) : Inst(Inst), Idx(0) {} // end iterator @@ -299,7 +301,7 @@ inline const_succ_range successors(const BasicBlock *BB) { // Provide specializations of GraphTraits to be able to treat a function as a // graph of basic blocks... -template <> struct GraphTraits<BasicBlock*> { +template <> struct GraphTraits<BasicBlock *> { using NodeRef = BasicBlock *; using ChildIteratorType = succ_iterator; @@ -313,7 +315,7 @@ template <> struct GraphTraits<BasicBlock*> { static_assert(GraphHasNodeNumbers<BasicBlock *>, "GraphTraits getNumber() not detected"); -template <> struct GraphTraits<const BasicBlock*> { +template <> struct GraphTraits<const BasicBlock *> { using NodeRef = const BasicBlock *; using ChildIteratorType = const_succ_iterator; @@ -333,7 +335,7 @@ static_assert(GraphHasNodeNumbers<const BasicBlock *>, // a function is considered to be when traversing the predecessor edges of a BB // instead of the successor edges. // -template <> struct GraphTraits<Inverse<BasicBlock*>> { +template <> struct GraphTraits<Inverse<BasicBlock *>> { using NodeRef = BasicBlock *; using ChildIteratorType = pred_iterator; @@ -347,7 +349,7 @@ template <> struct GraphTraits<Inverse<BasicBlock*>> { static_assert(GraphHasNodeNumbers<Inverse<BasicBlock *>>, "GraphTraits getNumber() not detected"); -template <> struct GraphTraits<Inverse<const BasicBlock*>> { +template <> struct GraphTraits<Inverse<const BasicBlock *>> { using NodeRef = const BasicBlock *; using ChildIteratorType = const_pred_iterator; @@ -369,7 +371,7 @@ static_assert(GraphHasNodeNumbers<Inverse<const BasicBlock *>>, // graph of basic blocks... these are the same as the basic block iterators, // except that the root node is implicitly the first node of the function. // -template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> { +template <> struct GraphTraits<Function *> : public GraphTraits<BasicBlock *> { static NodeRef getEntryNode(Function *F) { return &F->getEntryBlock(); } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph @@ -392,8 +394,8 @@ template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> { return F->getBlockNumberEpoch(); } }; -template <> struct GraphTraits<const Function*> : - public GraphTraits<const BasicBlock*> { +template <> +struct GraphTraits<const Function *> : public GraphTraits<const BasicBlock *> { static NodeRef getEntryNode(const Function *F) { return &F->getEntryBlock(); } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph @@ -422,8 +424,9 @@ template <> struct GraphTraits<const Function*> : // a function is considered to be when traversing the predecessor edges of a BB // instead of the successor edges. // -template <> struct GraphTraits<Inverse<Function*>> : - public GraphTraits<Inverse<BasicBlock*>> { +template <> +struct GraphTraits<Inverse<Function *>> + : public GraphTraits<Inverse<BasicBlock *>> { static NodeRef getEntryNode(Inverse<Function *> G) { return &G.Graph->getEntryBlock(); } @@ -435,8 +438,9 @@ template <> struct GraphTraits<Inverse<Function*>> : return F->getBlockNumberEpoch(); } }; -template <> struct GraphTraits<Inverse<const Function*>> : - public GraphTraits<Inverse<const BasicBlock*>> { +template <> +struct GraphTraits<Inverse<const Function *>> + : public GraphTraits<Inverse<const BasicBlock *>> { static NodeRef getEntryNode(Inverse<const Function *> G) { return &G.Graph->getEntryBlock(); } diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp index e2175cabcf7a1..ebe7505b2dce7 100644 --- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -254,6 +254,8 @@ void addWait(AMDGPU::Waitcnt &Wait, InstCounterType T, unsigned Count) { Wait.set(T, std::min(Wait.get(T), Count)); } +class WaitcntBrackets; + void setNoWait(AMDGPU::Waitcnt &Wait, InstCounterType T) { Wait.set(T, ~0u); } /// A small set of events. @@ -326,8 +328,6 @@ void WaitEventSet::dump() const { dbgs() << "\n"; } -class WaitcntBrackets; - // This abstracts the logic for generating and updating S_WAIT* instructions // away from the analysis that determines where they are needed. This was // done because the set of counters and instructions for waiting on them @@ -487,192 +487,7 @@ class WaitcntGeneratorGFX12Plus final : public WaitcntGenerator { AMDGPU::Waitcnt getAllZeroWaitcnt(bool IncludeVSCnt) const override; }; -// Flags indicating which counters should be flushed in a loop preheader. -struct PreheaderFlushFlags { - bool FlushVmCnt = false; - bool FlushDsCnt = false; -}; - -class SIInsertWaitcnts { -public: - const GCNSubtarget *ST; - const SIInstrInfo *TII = nullptr; - const SIRegisterInfo *TRI = nullptr; - const MachineRegisterInfo *MRI = nullptr; - InstCounterType SmemAccessCounter; - InstCounterType MaxCounter; - bool IsExpertMode = false; - -private: - DenseMap<const Value *, MachineBasicBlock *> SLoadAddresses; - DenseMap<MachineBasicBlock *, PreheaderFlushFlags> PreheadersToFlush; - MachineLoopInfo *MLI; - MachinePostDominatorTree *PDT; - AliasAnalysis *AA = nullptr; - - struct BlockInfo { - std::unique_ptr<WaitcntBrackets> Incoming; - bool Dirty = true; - }; - - MapVector<MachineBasicBlock *, BlockInfo> BlockInfos; - - bool ForceEmitWaitcnt[NUM_INST_CNTS]; - - std::unique_ptr<WaitcntGenerator> WCG; - - // Remember call and return instructions in the function. - DenseSet<MachineInstr *> CallInsts; - DenseSet<MachineInstr *> ReturnInsts; - - // Remember all S_ENDPGM instructions. The boolean flag is true if there might - // be outstanding stores but definitely no outstanding scratch stores, to help - // with insertion of DEALLOC_VGPRS messages. - DenseMap<MachineInstr *, bool> EndPgmInsts; - - AMDGPU::HardwareLimits Limits; - -public: - SIInsertWaitcnts(MachineLoopInfo *MLI, MachinePostDominatorTree *PDT, - AliasAnalysis *AA) - : MLI(MLI), PDT(PDT), AA(AA) { - (void)ForceExpCounter; - (void)ForceLgkmCounter; - (void)ForceVMCounter; - } - - const AMDGPU::HardwareLimits &getLimits() const { return Limits; } - - PreheaderFlushFlags getPreheaderFlushFlags(MachineLoop *ML, - const WaitcntBrackets &Brackets); - PreheaderFlushFlags isPreheaderToFlush(MachineBasicBlock &MBB, - const WaitcntBrackets &ScoreBrackets); - bool isVMEMOrFlatVMEM(const MachineInstr &MI) const; - bool isDSRead(const MachineInstr &MI) const; - bool mayStoreIncrementingDSCNT(const MachineInstr &MI) const; - bool run(MachineFunction &MF); - - void setForceEmitWaitcnt() { -// For non-debug builds, ForceEmitWaitcnt has been initialized to false; -// For debug builds, get the debug counter info and adjust if need be -#ifndef NDEBUG - if (DebugCounter::isCounterSet(ForceExpCounter) && - DebugCounter::shouldExecute(ForceExpCounter)) { - ForceEmitWaitcnt[EXP_CNT] = true; - } else { - ForceEmitWaitcnt[EXP_CNT] = false; - } - - if (DebugCounter::isCounterSet(ForceLgkmCounter) && - DebugCounter::shouldExecute(ForceLgkmCounter)) { - ForceEmitWaitcnt[DS_CNT] = true; - ForceEmitWaitcnt[KM_CNT] = true; - } else { - ForceEmitWaitcnt[DS_CNT] = false; - ForceEmitWaitcnt[KM_CNT] = false; - } - - if (DebugCounter::isCounterSet(ForceVMCounter) && - DebugCounter::shouldExecute(ForceVMCounter)) { - ForceEmitWaitcnt[LOAD_CNT] = true; - ForceEmitWaitcnt[SAMPLE_CNT] = true; - ForceEmitWaitcnt[BVH_CNT] = true; - } else { - ForceEmitWaitcnt[LOAD_CNT] = false; - ForceEmitWaitcnt[SAMPLE_CNT] = false; - ForceEmitWaitcnt[BVH_CNT] = false; - } - - ForceEmitWaitcnt[VA_VDST] = false; - ForceEmitWaitcnt[VM_VSRC] = false; -#endif // NDEBUG - } - - // Return the appropriate VMEM_*_ACCESS type for Inst, which must be a VMEM - // instruction. - WaitEventType getVmemWaitEventType(const MachineInstr &Inst) const { - switch (Inst.getOpcode()) { - // FIXME: GLOBAL_INV needs to be tracked with xcnt too. - case AMDGPU::GLOBAL_INV: - return GLOBAL_INV_ACCESS; // tracked using loadcnt, but doesn't write - // VGPRs - case AMDGPU::GLOBAL_WB: - case AMDGPU::GLOBAL_WBINV: - return VMEM_WRITE_ACCESS; // tracked using storecnt - default: - break; - } - - // Maps VMEM access types to their corresponding WaitEventType. - static const WaitEventType VmemReadMapping[NUM_VMEM_TYPES] = { - VMEM_ACCESS, VMEM_SAMPLER_READ_ACCESS, VMEM_BVH_READ_ACCESS}; - - assert(SIInstrInfo::isVMEM(Inst)); - // LDS DMA loads are also stores, but on the LDS side. On the VMEM side - // these should use VM_CNT. - if (!ST->hasVscnt() || SIInstrInfo::mayWriteLDSThroughDMA(Inst)) - return VMEM_ACCESS; - if (Inst.mayStore() && - (!Inst.mayLoad() || SIInstrInfo::isAtomicNoRet(Inst))) { - if (TII->mayAccessScratch(Inst)) - return SCRATCH_WRITE_ACCESS; - return VMEM_WRITE_ACCESS; - } - if (!ST->hasExtendedWaitCounts() || SIInstrInfo::isFLAT(Inst)) - return VMEM_ACCESS; - return VmemReadMapping[getVmemType(Inst)]; - } - - std::optional<WaitEventType> - getExpertSchedulingEventType(const MachineInstr &Inst) const; - - bool isAsync(const MachineInstr &MI) const { - if (!SIInstrInfo::isLDSDMA(MI)) - return false; - if (SIInstrInfo::usesASYNC_CNT(MI)) - return true; - const MachineOperand *Async = - TII->getNamedOperand(MI, AMDGPU::OpName::IsAsync); - return Async && (Async->getImm()); - } - - bool isNonAsyncLdsDmaWrite(const MachineInstr &MI) const { - return SIInstrInfo::mayWriteLDSThroughDMA(MI) && !isAsync(MI); - } - - bool isAsyncLdsDmaWrite(const MachineInstr &MI) const { - return SIInstrInfo::mayWriteLDSThroughDMA(MI) && isAsync(MI); - } - - bool isVmemAccess(const MachineInstr &MI) const; - bool generateWaitcntInstBefore(MachineInstr &MI, - WaitcntBrackets &ScoreBrackets, - MachineInstr *OldWaitcntInstr, - PreheaderFlushFlags FlushFlags); - bool generateWaitcnt(AMDGPU::Waitcnt Wait, - MachineBasicBlock::instr_iterator It, - MachineBasicBlock &Block, WaitcntBrackets &ScoreBrackets, - MachineInstr *OldWaitcntInstr); - void updateEventWaitcntAfter(MachineInstr &Inst, - WaitcntBrackets *ScoreBrackets); - bool isNextENDPGM(MachineBasicBlock::instr_iterator It, - MachineBasicBlock *Block) const; - bool insertForcedWaitAfter(MachineInstr &Inst, MachineBasicBlock &Block, - WaitcntBrackets &ScoreBrackets); - bool insertWaitcntInBlock(MachineFunction &MF, MachineBasicBlock &Block, - WaitcntBrackets &ScoreBrackets); - /// Removes redundant Soft Xcnt Waitcnts in \p Block emitted by the Memory - /// Legalizer. Returns true if block was modified. - bool removeRedundantSoftXcnts(MachineBasicBlock &Block); - void setSchedulingMode(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - bool ExpertMode) const; - const WaitEventSet &getWaitEvents(InstCounterType T) const { - return WCG->getWaitEvents(T); - } - InstCounterType getCounterFromEvent(WaitEventType E) const { - return WCG->getCounterFromEvent(E); - } -}; +class SIInsertWaitcnts; // This objects maintains the current score brackets of each wait counter, and // a per-register scoreboard for each wait counter. @@ -684,9 +499,9 @@ class SIInsertWaitcnts { // "s_waitcnt 0" before use. class WaitcntBrackets { public: - WaitcntBrackets(const SIInsertWaitcnts *Context) : Context(Context) { - assert(Context->TRI->getNumRegUnits() < REGUNITS_END); - } + WaitcntBrackets(const SIInsertWaitcnts *Context); //: Context(Context) { + // assert(Context->TRI->getNumRegUnits() < REGUNITS_END); + // } #ifndef NDEBUG ~WaitcntBrackets() { @@ -709,9 +524,9 @@ class WaitcntBrackets { } #endif - bool isSmemCounter(InstCounterType T) const { + bool isSmemCounter(InstCounterType T) const; /* { return T == Context->SmemAccessCounter || T == X_CNT; - } + } */ unsigned getSgprScoresIdx(InstCounterType T) const { assert(isSmemCounter(T) && "Invalid SMEM counter"); @@ -785,18 +600,19 @@ class WaitcntBrackets { bool hasPendingEvent(WaitEventType E) const { return PendingEvents.contains(E); } - bool hasPendingEvent(InstCounterType T) const { - bool HasPending = PendingEvents & Context->getWaitEvents(T); - assert(HasPending == !empty(T) && - "Expected pending events iff scoreboard is not empty"); - return HasPending; - } + bool hasPendingEvent(InstCounterType T) const; /* { + bool HasPending = PendingEvents & Context->getWaitEvents(T); + assert(HasPending == !empty(T) && + "Expected pending events iff scoreboard is not empty"); + return HasPending; + } + */ - bool hasMixedPendingEvents(InstCounterType T) const { + bool hasMixedPendingEvents(InstCounterType T) const; /* { WaitEventSet Events = PendingEvents & Context->getWaitEvents(T); // Return true if more than one bit is set in Events. return Events.twoOrMore(); - } + }*/ bool hasPendingFlat() const { return ((LastFlat[DS_CNT] > ScoreLBs[DS_CNT] && @@ -814,23 +630,23 @@ class WaitcntBrackets { return LastGDS > ScoreLBs[DS_CNT] && LastGDS <= ScoreUBs[DS_CNT]; } - unsigned getPendingGDSWait() const { + unsigned getPendingGDSWait() const; /* { return std::min(getScoreUB(DS_CNT) - LastGDS, getWaitCountMax(Context->getLimits(), DS_CNT) - 1); - } + } */ void setPendingGDS() { LastGDS = ScoreUBs[DS_CNT]; } // Return true if there might be pending writes to the vgpr-interval by VMEM // instructions with types different from V. - bool hasOtherPendingVmemTypes(MCPhysReg Reg, VmemType V) const { - for (MCRegUnit RU : regunits(Reg)) { - auto It = VMem.find(toVMEMID(RU)); - if (It != VMem.end() && (It->second.VMEMTypes & ~(1 << V))) - return true; - } - return false; - } + bool hasOtherPendingVmemTypes(MCPhysReg Reg, VmemType V) const; /* { + for (MCRegUnit RU : regunits(Reg)) { + auto It = VMem.find(toVMEMID(RU)); + if (It != VMem.end() && (It->second.VMEMTypes & ~(1 << V))) + return true; + } + return false; + } */ void clearVgprVmemTypes(MCPhysReg Reg) { for (MCRegUnit RU : regunits(Reg)) { @@ -842,11 +658,11 @@ class WaitcntBrackets { } } - void setStateOnFunctionEntryOrReturn() { + void setStateOnFunctionEntryOrReturn(); /* { setScoreUB(STORE_CNT, getScoreUB(STORE_CNT) + getWaitCountMax(Context->getLimits(), STORE_CNT)); PendingEvents |= Context->getWaitEvents(STORE_CNT); - } + }*/ ArrayRef<const MachineInstr *> getLDSDMAStores() const { return LDSDMAStores; @@ -881,23 +697,24 @@ class WaitcntBrackets { bool mergeAsyncMarks(ArrayRef<MergeInfo> MergeInfos, ArrayRef<CounterValueArray> OtherMarks); - iterator_range<MCRegUnitIterator> regunits(MCPhysReg Reg) const { - assert(Reg != AMDGPU::SCC && "Shouldn't be used on SCC"); - if (!Context->TRI->isInAllocatableClass(Reg)) - return {{}, {}}; - const TargetRegisterClass *RC = Context->TRI->getPhysRegBaseClass(Reg); - unsigned Size = Context->TRI->getRegSizeInBits(*RC); - if (Size == 16 && Context->ST->hasD16Writes32BitVgpr()) - Reg = Context->TRI->get32BitRegister(Reg); - return Context->TRI->regunits(Reg); - } + iterator_range<MCRegUnitIterator> regunits(MCPhysReg Reg) const; /* { + assert(Reg != AMDGPU::SCC && "Shouldn't be used on SCC"); + if (!Context->TRI->isInAllocatableClass(Reg)) + return {{}, {}}; + const TargetRegisterClass *RC = Context->TRI->getPhysRegBaseClass(Reg); + unsigned Size = Context->TRI->getRegSizeInBits(*RC); + if (Size == 16 && Context->ST->hasD16Writes32BitVgpr()) + Reg = Context->TRI->get32BitRegister(Reg); + return Context->TRI->regunits(Reg); + } + */ void setScoreLB(InstCounterType T, unsigned Val) { assert(T < NUM_INST_CNTS); ScoreLBs[T] = Val; } - void setScoreUB(InstCounterType T, unsigned Val) { + void setScoreUB(InstCounterType T, unsigned Val); /* { assert(T < NUM_INST_CNTS); ScoreUBs[T] = Val; @@ -907,23 +724,23 @@ class WaitcntBrackets { if (getScoreRange(EXP_CNT) > getWaitCountMax(Context->getLimits(), EXP_CNT)) ScoreLBs[EXP_CNT] = ScoreUBs[EXP_CNT] - getWaitCountMax(Context->getLimits(), EXP_CNT); - } - - void setRegScore(MCPhysReg Reg, InstCounterType T, unsigned Val) { - const SIRegisterInfo *TRI = Context->TRI; - if (Reg == AMDGPU::SCC) { - SCCScore = Val; - } else if (TRI->isVectorRegister(*Context->MRI, Reg)) { - for (MCRegUnit RU : regunits(Reg)) - VMem[toVMEMID(RU)].Scores[T] = Val; - } else if (TRI->isSGPRReg(*Context->MRI, Reg)) { - auto STy = getSgprScoresIdx(T); - for (MCRegUnit RU : regunits(Reg)) - SGPRs[RU].Scores[STy] = Val; - } else { - llvm_unreachable("Register cannot be tracked/unknown register!"); - } - } + } */ + + void setRegScore(MCPhysReg Reg, InstCounterType T, unsigned Val); /* { +const SIRegisterInfo *TRI = Context->TRI; +if (Reg == AMDGPU::SCC) { + SCCScore = Val; +} else if (TRI->isVectorRegister(*Context->MRI, Reg)) { + for (MCRegUnit RU : regunits(Reg)) + VMem[toVMEMID(RU)].Scores[T] = Val; +} else if (TRI->isSGPRReg(*Context->MRI, Reg)) { + auto STy = getSgprScoresIdx(T); + for (MCRegUnit RU : regunits(Reg)) + SGPRs[RU].Scores[STy] = Val; +} else { + llvm_unreachable("Register cannot be tracked/unknown register!"); +} +} */ void setVMemScore(VMEMID TID, InstCounterType T, unsigned Val) { VMem[TID].Scores[T] = Val; @@ -1021,6 +838,278 @@ class SIInsertWaitcntsLegacy : public MachineFunctionPass { } }; +// Flags indicating which counters should be flushed in a loop preheader. +struct PreheaderFlushFlags { + bool FlushVmCnt = false; + bool FlushDsCnt = false; +}; + +class SIInsertWaitcnts { +public: + const GCNSubtarget *ST; + const SIInstrInfo *TII = nullptr; + const SIRegisterInfo *TRI = nullptr; + const MachineRegisterInfo *MRI = nullptr; + InstCounterType SmemAccessCounter; + InstCounterType MaxCounter; + bool IsExpertMode = false; + +private: + DenseMap<const Value *, MachineBasicBlock *> SLoadAddresses; + DenseMap<MachineBasicBlock *, PreheaderFlushFlags> PreheadersToFlush; + MachineLoopInfo *MLI; + MachinePostDominatorTree *PDT; + AliasAnalysis *AA = nullptr; + + struct BlockInfo { + std::unique_ptr<WaitcntBrackets> Incoming; + bool Dirty = true; + }; + + MapVector<MachineBasicBlock *, BlockInfo> BlockInfos; + + bool ForceEmitWaitcnt[NUM_INST_CNTS]; + + std::unique_ptr<WaitcntGenerator> WCG; + + // Remember call and return instructions in the function. + DenseSet<MachineInstr *> CallInsts; + DenseSet<MachineInstr *> ReturnInsts; + + // Remember all S_ENDPGM instructions. The boolean flag is true if there might + // be outstanding stores but definitely no outstanding scratch stores, to help + // with insertion of DEALLOC_VGPRS messages. + DenseMap<MachineInstr *, bool> EndPgmInsts; + + AMDGPU::HardwareLimits Limits; + +public: + SIInsertWaitcnts(MachineLoopInfo *MLI, MachinePostDominatorTree *PDT, + AliasAnalysis *AA) + : MLI(MLI), PDT(PDT), AA(AA) { + (void)ForceExpCounter; + (void)ForceLgkmCounter; + (void)ForceVMCounter; + } + + const AMDGPU::HardwareLimits &getLimits() const { return Limits; } + + PreheaderFlushFlags getPreheaderFlushFlags(MachineLoop *ML, + const WaitcntBrackets &Brackets); + PreheaderFlushFlags isPreheaderToFlush(MachineBasicBlock &MBB, + const WaitcntBrackets &ScoreBrackets); + bool isVMEMOrFlatVMEM(const MachineInstr &MI) const; + bool isDSRead(const MachineInstr &MI) const; + bool mayStoreIncrementingDSCNT(const MachineInstr &MI) const; + bool run(MachineFunction &MF); + + void setForceEmitWaitcnt() { +// For non-debug builds, ForceEmitWaitcnt has been initialized to false; +// For debug builds, get the debug counter info and adjust if need be +#ifndef NDEBUG + if (DebugCounter::isCounterSet(ForceExpCounter) && + DebugCounter::shouldExecute(ForceExpCounter)) { + ForceEmitWaitcnt[EXP_CNT] = true; + } else { + ForceEmitWaitcnt[EXP_CNT] = false; + } + + if (DebugCounter::isCounterSet(ForceLgkmCounter) && + DebugCounter::shouldExecute(ForceLgkmCounter)) { + ForceEmitWaitcnt[DS_CNT] = true; + ForceEmitWaitcnt[KM_CNT] = true; + } else { + ForceEmitWaitcnt[DS_CNT] = false; + ForceEmitWaitcnt[KM_CNT] = false; + } + + if (DebugCounter::isCounterSet(ForceVMCounter) && + DebugCounter::shouldExecute(ForceVMCounter)) { + ForceEmitWaitcnt[LOAD_CNT] = true; + ForceEmitWaitcnt[SAMPLE_CNT] = true; + ForceEmitWaitcnt[BVH_CNT] = true; + } else { + ForceEmitWaitcnt[LOAD_CNT] = false; + ForceEmitWaitcnt[SAMPLE_CNT] = false; + ForceEmitWaitcnt[BVH_CNT] = false; + } + + ForceEmitWaitcnt[VA_VDST] = false; + ForceEmitWaitcnt[VM_VSRC] = false; +#endif // NDEBUG + } + + // Return the appropriate VMEM_*_ACCESS type for Inst, which must be a VMEM + // instruction. + WaitEventType getVmemWaitEventType(const MachineInstr &Inst) const { + switch (Inst.getOpcode()) { + // FIXME: GLOBAL_INV needs to be tracked with xcnt too. + case AMDGPU::GLOBAL_INV: + return GLOBAL_INV_ACCESS; // tracked using loadcnt, but doesn't write + // VGPRs + case AMDGPU::GLOBAL_WB: + case AMDGPU::GLOBAL_WBINV: + return VMEM_WRITE_ACCESS; // tracked using storecnt + default: + break; + } + + // Maps VMEM access types to their corresponding WaitEventType. + static const WaitEventType VmemReadMapping[NUM_VMEM_TYPES] = { + VMEM_ACCESS, VMEM_SAMPLER_READ_ACCESS, VMEM_BVH_READ_ACCESS}; + + assert(SIInstrInfo::isVMEM(Inst)); + // LDS DMA loads are also stores, but on the LDS side. On the VMEM side + // these should use VM_CNT. + if (!ST->hasVscnt() || SIInstrInfo::mayWriteLDSThroughDMA(Inst)) + return VMEM_ACCESS; + if (Inst.mayStore() && + (!Inst.mayLoad() || SIInstrInfo::isAtomicNoRet(Inst))) { + if (TII->mayAccessScratch(Inst)) + return SCRATCH_WRITE_ACCESS; + return VMEM_WRITE_ACCESS; + } + if (!ST->hasExtendedWaitCounts() || SIInstrInfo::isFLAT(Inst)) + return VMEM_ACCESS; + return VmemReadMapping[getVmemType(Inst)]; + } + + std::optional<WaitEventType> + getExpertSchedulingEventType(const MachineInstr &Inst) const; + + bool isAsync(const MachineInstr &MI) const { + if (!SIInstrInfo::isLDSDMA(MI)) + return false; + if (SIInstrInfo::usesASYNC_CNT(MI)) + return true; + const MachineOperand *Async = + TII->getNamedOperand(MI, AMDGPU::OpName::IsAsync); + return Async && (Async->getImm()); + } + + bool isNonAsyncLdsDmaWrite(const MachineInstr &MI) const { + return SIInstrInfo::mayWriteLDSThroughDMA(MI) && !isAsync(MI); + } + + bool isAsyncLdsDmaWrite(const MachineInstr &MI) const { + return SIInstrInfo::mayWriteLDSThroughDMA(MI) && isAsync(MI); + } + + bool isVmemAccess(const MachineInstr &MI) const; + bool generateWaitcntInstBefore(MachineInstr &MI, + WaitcntBrackets &ScoreBrackets, + MachineInstr *OldWaitcntInstr, + PreheaderFlushFlags FlushFlags); + bool generateWaitcnt(AMDGPU::Waitcnt Wait, + MachineBasicBlock::instr_iterator It, + MachineBasicBlock &Block, WaitcntBrackets &ScoreBrackets, + MachineInstr *OldWaitcntInstr); + void updateEventWaitcntAfter(MachineInstr &Inst, + WaitcntBrackets *ScoreBrackets); + bool isNextENDPGM(MachineBasicBlock::instr_iterator It, + MachineBasicBlock *Block) const; + bool insertForcedWaitAfter(MachineInstr &Inst, MachineBasicBlock &Block, + WaitcntBrackets &ScoreBrackets); + bool insertWaitcntInBlock(MachineFunction &MF, MachineBasicBlock &Block, + WaitcntBrackets &ScoreBrackets); + /// Removes redundant Soft Xcnt Waitcnts in \p Block emitted by the Memory + /// Legalizer. Returns true if block was modified. + bool removeRedundantSoftXcnts(MachineBasicBlock &Block); + void setSchedulingMode(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + bool ExpertMode) const; + const WaitEventSet &getWaitEvents(InstCounterType T) const { + return WCG->getWaitEvents(T); + } + InstCounterType getCounterFromEvent(WaitEventType E) const { + return WCG->getCounterFromEvent(E); + } +}; + +/* Delay */ +WaitcntBrackets::WaitcntBrackets(const SIInsertWaitcnts *Context) + : Context{Context} { + assert(Context->TRI->getNumRegUnits() < REGUNITS_END); +} + +bool WaitcntBrackets::isSmemCounter(InstCounterType T) const { + return T == Context->SmemAccessCounter || T == X_CNT; +} + +bool WaitcntBrackets::hasPendingEvent(InstCounterType T) const { + bool HasPending = PendingEvents & Context->getWaitEvents(T); + assert(HasPending == !empty(T) && + "Expected pending events iff scoreboard is not empty"); + return HasPending; +} + +bool WaitcntBrackets::hasMixedPendingEvents(InstCounterType T) const { + WaitEventSet Events = PendingEvents & Context->getWaitEvents(T); + // Return true if more than one bit is set in Events. + return Events.twoOrMore(); +} + +unsigned WaitcntBrackets::getPendingGDSWait() const { + return std::min(getScoreUB(DS_CNT) - LastGDS, + getWaitCountMax(Context->getLimits(), DS_CNT) - 1); +} + +bool WaitcntBrackets::hasOtherPendingVmemTypes(MCPhysReg Reg, + VmemType V) const { + for (MCRegUnit RU : regunits(Reg)) { + auto It = VMem.find(toVMEMID(RU)); + if (It != VMem.end() && (It->second.VMEMTypes & ~(1 << V))) + return true; + } + return false; +} + +void WaitcntBrackets::setStateOnFunctionEntryOrReturn() { + setScoreUB(STORE_CNT, getScoreUB(STORE_CNT) + + getWaitCountMax(Context->getLimits(), STORE_CNT)); + PendingEvents |= Context->getWaitEvents(STORE_CNT); +} + +iterator_range<MCRegUnitIterator> +WaitcntBrackets::regunits(MCPhysReg Reg) const { + assert(Reg != AMDGPU::SCC && "Shouldn't be used on SCC"); + if (!Context->TRI->isInAllocatableClass(Reg)) + return {{}, {}}; + const TargetRegisterClass *RC = Context->TRI->getPhysRegBaseClass(Reg); + unsigned Size = Context->TRI->getRegSizeInBits(*RC); + if (Size == 16 && Context->ST->hasD16Writes32BitVgpr()) + Reg = Context->TRI->get32BitRegister(Reg); + return Context->TRI->regunits(Reg); +} + +void WaitcntBrackets::setScoreUB(InstCounterType T, unsigned Val) { + assert(T < NUM_INST_CNTS); + ScoreUBs[T] = Val; + + if (T != EXP_CNT) + return; + + if (getScoreRange(EXP_CNT) > getWaitCountMax(Context->getLimits(), EXP_CNT)) + ScoreLBs[EXP_CNT] = + ScoreUBs[EXP_CNT] - getWaitCountMax(Context->getLimits(), EXP_CNT); +} + +void WaitcntBrackets::setRegScore(MCPhysReg Reg, InstCounterType T, + unsigned Val) { + const SIRegisterInfo *TRI = Context->TRI; + if (Reg == AMDGPU::SCC) { + SCCScore = Val; + } else if (TRI->isVectorRegister(*Context->MRI, Reg)) { + for (MCRegUnit RU : regunits(Reg)) + VMem[toVMEMID(RU)].Scores[T] = Val; + } else if (TRI->isSGPRReg(*Context->MRI, Reg)) { + auto STy = getSgprScoresIdx(T); + for (MCRegUnit RU : regunits(Reg)) + SGPRs[RU].Scores[STy] = Val; + } else { + llvm_unreachable("Register cannot be tracked/unknown register!"); + } +} + } // end anonymous namespace void WaitcntBrackets::setScoreByOperand(const MachineOperand &Op, diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp index abe081c0c76fd..4bdf1872ea7a3 100644 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -40,6 +40,12 @@ using namespace llvm; #define DEBUG_TYPE "asm-printer" +BPFAsmPrinter::BPFAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> Streamer) + : AsmPrinter(TM, std::move(Streamer), ID), BTF(nullptr), TM(TM) {} + +BPFAsmPrinter::~BPFAsmPrinter() = default; + bool BPFAsmPrinter::doInitialization(Module &M) { AsmPrinter::doInitialization(M); @@ -154,17 +160,21 @@ bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); const MachineOperand &BaseMO = MI->getOperand(OpNum); const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); - assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); - assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); + assert(BaseMO.isReg() && + "Unexpected base pointer for inline asm memory operand."); + assert(OffsetMO.isImm() && + "Unexpected offset for inline asm memory operand."); int Offset = OffsetMO.getImm(); if (ExtraCode) return true; // Unknown modifier. if (Offset < 0) - O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")"; + O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " + << -Offset << ")"; else - O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")"; + O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " + << Offset << ")"; return false; } diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.h b/llvm/lib/Target/BPF/BPFAsmPrinter.h index 75a1d7ed9f884..1e6cc3386afa2 100644 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.h +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.h @@ -18,8 +18,8 @@ namespace llvm { class BPFAsmPrinter : public AsmPrinter { public: explicit BPFAsmPrinter(TargetMachine &TM, - std::unique_ptr<MCStreamer> Streamer) - : AsmPrinter(TM, std::move(Streamer), ID), BTF(nullptr), TM(TM) {} + std::unique_ptr<MCStreamer> Streamer); + ~BPFAsmPrinter() override; StringRef getPassName() const override { return "BPF Assembly Printer"; } bool doInitialization(Module &M) override; diff --git a/mlir/include/mlir/Query/Matcher/MatchersInternal.h b/mlir/include/mlir/Query/Matcher/MatchersInternal.h index 88109430b6feb..6ff1639472700 100644 --- a/mlir/include/mlir/Query/Matcher/MatchersInternal.h +++ b/mlir/include/mlir/Query/Matcher/MatchersInternal.h @@ -72,8 +72,7 @@ class MatcherInterface // MatcherFnImpl takes a matcher function object and implements // MatcherInterface. -template <typename MatcherFn> -class MatcherFnImpl : public MatcherInterface { +template <typename MatcherFn> class MatcherFnImpl : public MatcherInterface { public: MatcherFnImpl(MatcherFn &matcherFn) : matcherFn(matcherFn) {} @@ -102,13 +101,11 @@ using VariadicOperatorFunction = bool (*)(Operation *op, template <VariadicOperatorFunction Func> class VariadicMatcher : public MatcherInterface { public: - VariadicMatcher(std::vector<DynMatcher> matchers) - : matchers(std::move(matchers)) {} + VariadicMatcher(std::vector<DynMatcher> matchers); + ~VariadicMatcher() override; - bool match(Operation *op) override { return Func(op, nullptr, matchers); } - bool match(Operation *op, SetVector<Operation *> &matchedOps) override { - return Func(op, &matchedOps, matchers); - } + bool match(Operation *op) override; + bool match(Operation *op, SetVector<Operation *> &matchedOps) override; private: std::vector<DynMatcher> matchers; @@ -169,8 +166,7 @@ class DynMatcher { }; // VariadicOperatorMatcher related types. -template <typename... Ps> -class VariadicOperatorMatcher { +template <typename... Ps> class VariadicOperatorMatcher { public: VariadicOperatorMatcher(DynMatcher::VariadicOperator varOp, Ps &&...params) : varOp(varOp), params(std::forward<Ps>(params)...) {} diff --git a/mlir/lib/Query/Matcher/MatchFinder.cpp b/mlir/lib/Query/Matcher/MatchFinder.cpp index 48a24b98f9a4e..f2b0706cbe60f 100644 --- a/mlir/lib/Query/Matcher/MatchFinder.cpp +++ b/mlir/lib/Query/Matcher/MatchFinder.cpp @@ -11,8 +11,32 @@ //===----------------------------------------------------------------------===// #include "mlir/Query/Matcher/MatchFinder.h" +#include "mlir/Query/Matcher/MatchersInternal.h" + namespace mlir::query::matcher { +template <VariadicOperatorFunction Func> +VariadicMatcher<Func>::VariadicMatcher(std::vector<DynMatcher> matchers) + : matchers(std::move(matchers)) {} + +template <VariadicOperatorFunction Func> +VariadicMatcher<Func>::~VariadicMatcher() = default; + +template <VariadicOperatorFunction Func> +bool VariadicMatcher<Func>::match(Operation *op) { + return Func(op, nullptr, matchers); +} + +template <VariadicOperatorFunction Func> +bool VariadicMatcher<Func>::match(Operation *op, + SetVector<Operation *> &matchedOps) { + return Func(op, &matchedOps, matchers); +} + +template class VariadicMatcher<&internal::allOfVariadicOperator>; + +template class VariadicMatcher<&internal::anyOfVariadicOperator>; + MatchFinder::MatchResult::MatchResult(Operation *rootOp, std::vector<Operation *> matchedOps) : rootOp(rootOp), matchedOps(std::move(matchedOps)) {} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
