From 413f6b95a4360fc9854ca775027913a633835cfa Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Mon, 29 Apr 2024 14:47:46 -0400 Subject: [PATCH 01/22] [TableGen][GISel][NFC] clang-tidy GlobalISelEmitter.cpp (#90492) Fixes a couple of style issues, such as: - unused includes - variable naming - `else if` after `return` --- llvm/utils/TableGen/GlobalISelEmitter.cpp | 42 +++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 0eb258ff89a288..cf7e4398741ca5 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -45,12 +45,10 @@ #include "llvm/Support/CodeGenCoverage.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" -#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include #include using namespace llvm; @@ -792,8 +790,8 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( "nested predicate that uses operands"); TreePattern *TP = Predicate.getOrigPatFragRecord(); WaitingForNamedOperands = TP->getNumArgs(); - for (unsigned i = 0; i < WaitingForNamedOperands; ++i) - StoreIdxForName[getScopedName(Call.Scope, TP->getArgName(i))] = i; + for (unsigned I = 0; I < WaitingForNamedOperands; ++I) + StoreIdxForName[getScopedName(Call.Scope, TP->getArgName(I))] = I; } InsnMatcher.addPredicate(Predicate); continue; @@ -878,8 +876,8 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( if (IsIntrinsic && !II) return failedImport("Expected IntInit containing intrinsic ID)"); - for (unsigned i = 0; i != NumChildren; ++i) { - const TreePatternNode &SrcChild = Src.getChild(i); + for (unsigned I = 0; I != NumChildren; ++I) { + const TreePatternNode &SrcChild = Src.getChild(I); // We need to determine the meaning of a literal integer based on the // context. If this is a field required to be an immediate (such as an @@ -888,19 +886,19 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( // argument that is required to be an immediate, we should not emit an LLT // type check, and should not be looking for a G_CONSTANT defined // register. - bool OperandIsImmArg = SrcGIOrNull->isInOperandImmArg(i); + bool OperandIsImmArg = SrcGIOrNull->isInOperandImmArg(I); // SelectionDAG allows pointers to be represented with iN since it doesn't // distinguish between pointers and integers but they are different types // in GlobalISel. Coerce integers to pointers to address space 0 if the // context indicates a pointer. // - bool OperandIsAPointer = SrcGIOrNull->isInOperandAPointer(i); + bool OperandIsAPointer = SrcGIOrNull->isInOperandAPointer(I); if (IsIntrinsic) { // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately // following the defs is an intrinsic ID. - if (i == 0) { + if (I == 0) { OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, SrcChild.getName(), TempOpIdx); OM.addPredicate(II); @@ -911,8 +909,8 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( // // Note that we have to look at the i-1th parameter, because we don't // have the intrinsic ID in the intrinsic's parameter list. - OperandIsAPointer |= II->isParamAPointer(i - 1); - OperandIsImmArg |= II->isParamImmArg(i - 1); + OperandIsAPointer |= II->isParamAPointer(I - 1); + OperandIsImmArg |= II->isParamImmArg(I - 1); } if (auto Error = @@ -967,9 +965,9 @@ Error GlobalISelEmitter::importChildMatcher( // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is // "MY_PAT:op1:op2" and the ones with same "name" represent same operand. std::string PatternName = std::string(SrcChild.getOperator()->getName()); - for (unsigned i = 0; i < SrcChild.getNumChildren(); ++i) { + for (unsigned I = 0; I < SrcChild.getNumChildren(); ++I) { PatternName += ":"; - PatternName += SrcChild.getChild(i).getName(); + PatternName += SrcChild.getChild(I).getName(); } SrcChildName = PatternName; } @@ -1042,11 +1040,11 @@ Error GlobalISelEmitter::importChildMatcher( OM, SrcChild.getOperator(), TempOpIdx)) return Error; - for (unsigned i = 0, e = SrcChild.getNumChildren(); i != e; ++i) { - auto &SubOperand = SrcChild.getChild(i); + for (unsigned I = 0, E = SrcChild.getNumChildren(); I != E; ++I) { + auto &SubOperand = SrcChild.getChild(I); if (!SubOperand.getName().empty()) { if (auto Error = Rule.defineComplexSubOperand( - SubOperand.getName(), SrcChild.getOperator(), RendererID, i, + SubOperand.getName(), SrcChild.getOperator(), RendererID, I, SrcChildName)) return Error; } @@ -1232,10 +1230,12 @@ Expected GlobalISelEmitter::importExplicitUseRenderer( if (DstChild.getOperator()->getName() == "tframeindex") { DstMIBuilder.addRenderer(DstChild.getName()); return InsertPt; - } else if (DstChild.getOperator()->getName() == "imm") { + } + if (DstChild.getOperator()->getName() == "imm") { DstMIBuilder.addRenderer(DstChild.getName()); return InsertPt; - } else if (DstChild.getOperator()->getName() == "fpimm") { + } + if (DstChild.getOperator()->getName() == "fpimm") { DstMIBuilder.addRenderer( DstChild.getName()); return InsertPt; @@ -1748,7 +1748,7 @@ Error GlobalISelEmitter::importDefaultOperandRenderers( if (const DefInit *DefaultDefOp = dyn_cast(DefaultOp)) { std::optional OpTyOrNone = MVTToLLT(N.getSimpleType(0)); - auto Def = DefaultDefOp->getDef(); + auto *Def = DefaultDefOp->getDef(); if (Def->getName() == "undef_tied_input") { unsigned TempRegID = M.allocateTempRegID(); M.insertAction(InsertPt, *OpTyOrNone, @@ -2449,13 +2449,13 @@ void GlobalISelEmitter::run(raw_ostream &OS) { } // Comparison function to order records by name. - auto orderByName = [](const Record *A, const Record *B) { + auto OrderByName = [](const Record *A, const Record *B) { return A->getName() < B->getName(); }; std::vector ComplexPredicates = RK.getAllDerivedDefinitions("GIComplexOperandMatcher"); - llvm::sort(ComplexPredicates, orderByName); + llvm::sort(ComplexPredicates, OrderByName); std::vector CustomRendererFns; transform(RK.getAllDerivedDefinitions("GICustomOperandRenderer"), From 7eac39f650227427a32b0db1a511b2b12c48a0fc Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 29 Apr 2024 12:49:31 -0600 Subject: [PATCH 02/22] [libc++] Mark scoped_lock and unique_lock constructors as [[nodiscard]] (#89397) It's basically always a bug to discard a scoped_lock or a unique_lock. Fixes #89388 --- libcxx/include/__mutex/unique_lock.h | 20 ++++--- libcxx/include/mutex | 16 +++--- .../diagnostics/mutex.nodiscard.verify.cpp | 54 +++++++++++++++++-- .../thread.lock.guard/nodiscard.verify.cpp | 30 ----------- 4 files changed, 71 insertions(+), 49 deletions(-) delete mode 100644 libcxx/test/libcxx/thread/thread.lock/thread.lock.guard/nodiscard.verify.cpp diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h index c27ce4b24c1ae8..4a616ba51ee1cf 100644 --- a/libcxx/include/__mutex/unique_lock.h +++ b/libcxx/include/__mutex/unique_lock.h @@ -36,26 +36,28 @@ class _LIBCPP_TEMPLATE_VIS unique_lock { bool __owns_; public: - _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} - _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) + : __m_(std::addressof(__m)), __owns_(true) { __m_->lock(); } - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT : __m_(std::addressof(__m)), __owns_(false) {} - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {} - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {} + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) + : __m_(std::addressof(__m)), __owns_(true) {} template - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} template - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} _LIBCPP_HIDE_FROM_ABI ~unique_lock() { @@ -66,7 +68,9 @@ class _LIBCPP_TEMPLATE_VIS unique_lock { unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; - _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT + : __m_(__u.__m_), + __owns_(__u.__owns_) { __u.__m_ = nullptr; __u.__owns_ = false; } diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 12fae9a88b9d7e..0d2b5914bc4fd5 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -427,10 +427,10 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock; template <> class _LIBCPP_TEMPLATE_VIS scoped_lock<> { public: - explicit scoped_lock() {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {} ~scoped_lock() = default; - _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {} scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; @@ -445,13 +445,15 @@ private: mutex_type& __m_; public: - explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) + _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + : __m_(__m) { __m_.lock(); } ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } - _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} @@ -465,9 +467,11 @@ class _LIBCPP_TEMPLATE_VIS scoped_lock { typedef tuple<_MArgs&...> _MutexTuple; public: - _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { std::lock(__margs...); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { + std::lock(__margs...); + } - _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {} _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { typedef typename __make_tuple_indices::type _Indices; diff --git a/libcxx/test/libcxx/diagnostics/mutex.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/mutex.nodiscard.verify.cpp index a98eb5f142113b..b9890ced55bb11 100644 --- a/libcxx/test/libcxx/diagnostics/mutex.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/mutex.nodiscard.verify.cpp @@ -12,14 +12,58 @@ // check that functions are marked [[nodiscard]] -// clang-format off - #include +#include +#include #include "test_macros.h" void test() { - std::mutex mutex; - std::lock_guard{mutex}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} - std::lock_guard{mutex, std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + // std::scoped_lock + { +#if TEST_STD_VER >= 17 + using M = std::mutex; + M m0, m1, m2; + // clang-format off + std::scoped_lock<>{}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + + std::scoped_lock<>{std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{std::adopt_lock, m0}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{std::adopt_lock, m0, m1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::scoped_lock{std::adopt_lock, m0, m1, m2}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + // clang-format on +#endif + } + + // std::unique_lock + { + using M = std::timed_mutex; // necessary for the time_point and duration constructors + M m; + std::chrono::time_point time_point; + std::chrono::milliseconds duration; + std::unique_lock other; + + // clang-format off + std::unique_lock{}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m, std::defer_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m, std::try_to_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m, std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m, time_point}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock{m, duration}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::unique_lock(std::move(other)); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + // clang-format on + } + + // std::lock_guard + { + std::mutex m; + // clang-format off + std::lock_guard{m}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + std::lock_guard{m, std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} + // clang-format on + } } diff --git a/libcxx/test/libcxx/thread/thread.lock/thread.lock.guard/nodiscard.verify.cpp b/libcxx/test/libcxx/thread/thread.lock/thread.lock.guard/nodiscard.verify.cpp deleted file mode 100644 index 5fe68c83b3d9f6..00000000000000 --- a/libcxx/test/libcxx/thread/thread.lock/thread.lock.guard/nodiscard.verify.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: no-threads - -// [[nodiscard]] isn't supported in C++03 (not even as an extension) -// UNSUPPORTED: c++03 - -// - -// template class lock_guard; - -// [[nodiscard]] explicit lock_guard(mutex_type& m); -// [[nodiscard]] lock_guard(mutex_type& m, adopt_lock_t); - -// Test that we properly apply [[nodiscard]] to lock_guard's constructors, -// which is a libc++ extension. - -#include - -void f() { - std::mutex m; - std::lock_guard{m}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} - std::lock_guard{m, std::adopt_lock}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} -} From 3ab4ae9e58c09dfd8203547ba8916f3458a0a481 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 29 Apr 2024 12:00:12 -0700 Subject: [PATCH 03/22] [clang codegen] Fix MS ABI detection of user-provided constructors. (#90151) In the context of determining whether a class counts as an "aggregate", a constructor template counts as a user-provided constructor. Fixes #86384 --- clang/docs/ReleaseNotes.rst | 6 ++++++ clang/lib/CodeGen/MicrosoftCXXABI.cpp | 12 +++++++++--- clang/test/CodeGen/arm64-microsoft-arguments.cpp | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d0e663d93e46f..55e1670b7e2fa0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -63,6 +63,12 @@ ABI Changes in This Version MSVC uses a different mangling for these objects, compatibility is not affected. (#GH85423). +- Fixed Microsoft calling convention for returning certain classes with a + templated constructor. If a class has a templated constructor, it should + be returned indirectly even if it meets all the other requirements for + returning a class in a register. This affects some uses of std::pair. + (#GH86384). + AST Dumping Potentially Breaking Changes ---------------------------------------- diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d38a26940a3cb6..d47927745759e1 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1131,9 +1131,15 @@ static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty, return false; if (RD->hasNonTrivialCopyAssignment()) return false; - for (const CXXConstructorDecl *Ctor : RD->ctors()) - if (Ctor->isUserProvided()) - return false; + for (const Decl *D : RD->decls()) { + if (auto *Ctor = dyn_cast(D)) { + if (Ctor->isUserProvided()) + return false; + } else if (auto *Template = dyn_cast(D)) { + if (isa(Template->getTemplatedDecl())) + return false; + } + } if (RD->hasNonTrivialDestructor()) return false; return true; diff --git a/clang/test/CodeGen/arm64-microsoft-arguments.cpp b/clang/test/CodeGen/arm64-microsoft-arguments.cpp index e8309888dcfe21..85472645acb3b3 100644 --- a/clang/test/CodeGen/arm64-microsoft-arguments.cpp +++ b/clang/test/CodeGen/arm64-microsoft-arguments.cpp @@ -201,3 +201,18 @@ S11 f11() { S11 x; return func11(x); } + +// GH86384 +// Pass and return object with template constructor (pass directly, +// return indirectly). +// CHECK: define dso_local void @"?f12@@YA?AUS12@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.S12) align 4 {{.*}}) +// CHECK: call void @"?func12@@YA?AUS12@@U1@@Z"(ptr dead_on_unwind inreg writable sret(%struct.S12) align 4 {{.*}}, i64 {{.*}}) +struct S12 { + template S12(T*) {} + int x; +}; +S12 func12(S12 x); +S12 f12() { + S12 x((int*)0); + return func12(x); +} From b83e65dcf87925efe6b6623b15a160981422b1bb Mon Sep 17 00:00:00 2001 From: Pol M Date: Mon, 29 Apr 2024 21:10:20 +0200 Subject: [PATCH 04/22] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (#76615) This patch adds constexpr support for __builtin_shufflevector and __builtin_convertvector. NB: the changes went in under 2903df02fb3c057849aaa796a91289b01950a5f0 , this commit is just github PR bookkeepping. From 99ce84cef0185fe9eaec51e40ea80f69f06981f0 Mon Sep 17 00:00:00 2001 From: Troy Butler <118708570+Troy-Butler@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:24:29 -0400 Subject: [PATCH 05/22] [clang][NFC] Reformat suspicious condition (#89923) Addresses issue #89805. Assignment + comparison performed in conditional statement. Resolved by parenthesizing comparison operation. Fixes #89805. --------- Signed-off-by: Troy-Butler --- clang/lib/Lex/Pragma.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 499813f8ab7df0..ced407355e0015 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1444,7 +1444,7 @@ struct PragmaWarningHandler : public PragmaHandler { .Case("once", PPCallbacks::PWS_Once) .Case("suppress", PPCallbacks::PWS_Suppress) .Default(-1); - if ((SpecifierValid = SpecifierInt != -1)) + if (SpecifierValid = (SpecifierInt != -1)) Specifier = static_cast(SpecifierInt); From 359ab3aebba302fb4c37373b9907bc8880be7363 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Mon, 29 Apr 2024 15:46:18 -0400 Subject: [PATCH 06/22] [CIR] Add options to emit ClangIR and enable the ClangIR pipeline Introduce just the option definitions and support for their existance at a few different points in the frontend. This will be followed soon by functionality that uses it. Reviewers: bcardosolopes, jansvoboda11, AaronBallman, erichkeane, MaskRay Reviewed By: erichkeane Pull Request: https://github.com/llvm/llvm-project/pull/89030 --- clang/include/clang/Driver/Options.td | 11 +++++++++++ clang/include/clang/Frontend/FrontendOptions.h | 9 ++++++++- clang/lib/Driver/Driver.cpp | 3 +++ clang/lib/Frontend/CompilerInvocation.cpp | 4 ++++ clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 2 ++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 263d1edf141a0b..25f479dccc3c80 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2886,6 +2886,17 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group, Group, HelpText<"Force linking the clang builtins runtime library">; + +/// ClangIR-specific options - BEGIN +defm clangir : BoolFOption<"clangir", + FrontendOpts<"UseClangIRPipeline">, DefaultFalse, + PosFlag, + NegFlag LLVM pipeline to compile">, + BothFlags<[], [ClangOption, CC1Option], "">>; +def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>, + Group, HelpText<"Build ASTs and then lower to ClangIR">; +/// ClangIR-specific options - END + def flto_EQ : Joined<["-"], "flto=">, Visibility<[ClangOption, CLOption, CC1Option, FC1Option, FlangOption]>, Group, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index a738c1f3757682..bd4981ca0ac08c 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -65,6 +65,9 @@ enum ActionKind { /// Translate input source into HTML. EmitHTML, + /// Emit a .cir file + EmitCIR, + /// Emit a .ll file. EmitLLVM, @@ -408,6 +411,10 @@ class FrontendOptions { LLVM_PREFERRED_TYPE(bool) unsigned GenReducedBMI : 1; + /// Use Clang IR pipeline to emit code + LLVM_PREFERRED_TYPE(bool) + unsigned UseClangIRPipeline : 1; + CodeCompleteOptions CodeCompleteOpts; /// Specifies the output format of the AST. @@ -590,7 +597,7 @@ class FrontendOptions { EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false), EmitSymbolGraphSymbolLabelsForTesting(false), EmitPrettySymbolGraphs(false), GenReducedBMI(false), - TimeTraceGranularity(500) {} + UseClangIRPipeline(false), TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 76b7b9fdfb4f9b..114320f5d31468 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -361,6 +361,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || (PhaseArg = DAL.getLastArg(options::OPT__analyze)) || + (PhaseArg = DAL.getLastArg(options::OPT_emit_cir)) || (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { FinalPhase = phases::Compile; @@ -4799,6 +4800,8 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction(Input, types::TY_Remap); if (Args.hasArg(options::OPT_emit_ast)) return C.MakeAction(Input, types::TY_AST); + if (Args.hasArg(options::OPT_emit_cir)) + return C.MakeAction(Input, types::TY_CIR); if (Args.hasArg(options::OPT_module_file_info)) return C.MakeAction(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 8236051e30c4a5..8312abc3603953 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2549,6 +2549,7 @@ static const auto &getFrontendActionTable() { {frontend::DumpTokens, OPT_dump_tokens}, {frontend::EmitAssembly, OPT_S}, {frontend::EmitBC, OPT_emit_llvm_bc}, + {frontend::EmitCIR, OPT_emit_cir}, {frontend::EmitHTML, OPT_emit_html}, {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, @@ -2891,6 +2892,8 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule) Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module" << "-emit-module"; + if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir)) + Opts.UseClangIRPipeline = true; if (Args.hasArg(OPT_aux_target_cpu)) Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu)); @@ -4337,6 +4340,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::ASTView: case frontend::EmitAssembly: case frontend::EmitBC: + case frontend::EmitCIR: case frontend::EmitHTML: case frontend::EmitLLVM: case frontend::EmitLLVMOnly: diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index f85f0365616f9a..7476b1076d1038 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -53,6 +53,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { case DumpTokens: return std::make_unique(); case EmitAssembly: return std::make_unique(); case EmitBC: return std::make_unique(); + case EmitCIR: + llvm_unreachable("CIR suppport not built into clang"); case EmitHTML: return std::make_unique(); case EmitLLVM: return std::make_unique(); case EmitLLVMOnly: return std::make_unique(); From 326657f5679889e3374354ba3243e27bda2080f4 Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Mon, 29 Apr 2024 22:11:09 +0200 Subject: [PATCH 07/22] [Clang] Address post commit feedbacks in #89906 (#90495) * Fix a leak * Fix a maybe unused warning * Fix incorrect cxx_status entry --- clang/include/clang/Sema/DeclSpec.h | 8 ++++---- clang/lib/AST/DeclBase.cpp | 2 +- clang/www/cxx_status.html | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 760c7980be52bd..23bc780e04979d 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1811,15 +1811,15 @@ class DecompositionDeclarator { : Bindings(nullptr), NumBindings(0), DeleteBindings(false) {} DecompositionDeclarator(const DecompositionDeclarator &G) = delete; DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete; - ~DecompositionDeclarator() { - if (DeleteBindings) - delete[] Bindings; - } + ~DecompositionDeclarator() { clear(); } void clear() { LSquareLoc = RSquareLoc = SourceLocation(); if (DeleteBindings) delete[] Bindings; + else + llvm::for_each(llvm::MutableArrayRef(Bindings, NumBindings), + [](Binding &B) { B.Attrs.reset(); }); Bindings = nullptr; NumBindings = 0; DeleteBindings = false; diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index f341c74cf86e37..03e1055251c24f 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1115,7 +1115,7 @@ int64_t Decl::getID() const { const FunctionType *Decl::getFunctionType(bool BlocksToo) const { QualType Ty; - if (const auto *D = dyn_cast(this)) + if (isa(this)) return nullptr; else if (const auto *D = dyn_cast(this)) Ty = D->getType(); diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index d58c35b72c22bb..0996abc2405857 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -177,7 +177,7 @@

C++2c implementation status

Attributes for Structured Bindings P0609R3 - No + Clang 19 Module Declarations Shouldn’t be Macros @@ -187,7 +187,7 @@

C++2c implementation status

Trivial infinite loops are not Undefined Behavior P2809R3 (DR) - Clang 19 + No Erroneous behaviour for uninitialized reads From a5cc95147ed549e850b4e9641e84641e781e0ceb Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 29 Apr 2024 13:11:58 -0700 Subject: [PATCH 08/22] [BinaryFormat] Adjust OSABI functions and add unittests Adjust #89280: * ELFOSABI_LINUX is a historical alias that should not be used in new code. readelf -h displays "UNIX - GNU" instead of "Linux". * "OS" is inappropriate. Some values are architecture-specific, e.g. ELFOSABI_ARM. * Drop lowercase, which seems a job of the caller. Add some unittests. Pull Request: https://github.com/llvm/llvm-project/pull/90270 --- llvm/include/llvm/BinaryFormat/ELF.h | 9 +++--- llvm/lib/BinaryFormat/ELF.cpp | 15 +++++----- llvm/unittests/BinaryFormat/CMakeLists.txt | 1 + llvm/unittests/BinaryFormat/ELFTest.cpp | 32 ++++++++++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 llvm/unittests/BinaryFormat/ELFTest.cpp diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 56b5d4e399c636..f296acc2ca4bb9 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1939,11 +1939,12 @@ uint16_t convertArchNameToEMachine(StringRef Arch); /// Convert an ELF's e_machine value into an architecture name. StringRef convertEMachineToArchName(uint16_t EMachine); -/// Convert a OS into ELF's EI_OSABI value. -uint8_t convertOSToOSAbi(StringRef OS); +// Convert a lowercase string identifier into an OSABI value. +uint8_t convertNameToOSABI(StringRef Name); -/// Convert an ELF's e_machine value into an architecture name. -StringRef convertOSAbiToOS(uint8_t OSAbi); +// Convert an OSABI value into a string that identifies the OS- or ABI- +// specific ELF extension. +StringRef convertOSABIToName(uint8_t OSABI); } // end namespace ELF } // end namespace llvm diff --git a/llvm/lib/BinaryFormat/ELF.cpp b/llvm/lib/BinaryFormat/ELF.cpp index 8c10ed1a980bbc..9878f5769087ea 100644 --- a/llvm/lib/BinaryFormat/ELF.cpp +++ b/llvm/lib/BinaryFormat/ELF.cpp @@ -568,12 +568,11 @@ StringRef ELF::convertEMachineToArchName(uint16_t EMachine) { } } -uint8_t ELF::convertOSToOSAbi(StringRef OS) { - std::string LowerOS = OS.lower(); - return StringSwitch(LowerOS) +uint8_t ELF::convertNameToOSABI(StringRef Name) { + return StringSwitch(Name) .StartsWith("hpux", ELFOSABI_HPUX) .StartsWith("netbsd", ELFOSABI_NETBSD) - .StartsWith("linux", ELFOSABI_LINUX) + .StartsWith("gnu", ELFOSABI_GNU) .StartsWith("hurd", ELFOSABI_HURD) .StartsWith("solaris", ELFOSABI_SOLARIS) .StartsWith("aix", ELFOSABI_AIX) @@ -597,14 +596,14 @@ uint8_t ELF::convertOSToOSAbi(StringRef OS) { .Default(ELFOSABI_NONE); } -StringRef ELF::convertOSAbiToOS(uint8_t OSAbi) { - switch (OSAbi) { +StringRef ELF::convertOSABIToName(uint8_t OSABI) { + switch (OSABI) { case ELFOSABI_HPUX: return "hpux"; case ELFOSABI_NETBSD: return "netbsd"; - case ELFOSABI_LINUX: - return "linux"; + case ELFOSABI_GNU: + return "gnu"; case ELFOSABI_HURD: return "hurd"; case ELFOSABI_SOLARIS: diff --git a/llvm/unittests/BinaryFormat/CMakeLists.txt b/llvm/unittests/BinaryFormat/CMakeLists.txt index f0c42a0dd02b8e..40d3bc4dca0b66 100644 --- a/llvm/unittests/BinaryFormat/CMakeLists.txt +++ b/llvm/unittests/BinaryFormat/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(BinaryFormatTests DwarfTest.cpp + ELFTest.cpp MachOTest.cpp MsgPackDocumentTest.cpp MsgPackReaderTest.cpp diff --git a/llvm/unittests/BinaryFormat/ELFTest.cpp b/llvm/unittests/BinaryFormat/ELFTest.cpp new file mode 100644 index 00000000000000..5dbf6ff8d5c900 --- /dev/null +++ b/llvm/unittests/BinaryFormat/ELFTest.cpp @@ -0,0 +1,32 @@ +//===- ELFTest.cpp --------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/BinaryFormat/ELF.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::ELF; + +namespace { +TEST(ELFTest, OSABI) { + EXPECT_EQ(ELFOSABI_GNU, convertNameToOSABI("gnu")); + EXPECT_EQ(ELFOSABI_FREEBSD, convertNameToOSABI("freebsd")); + EXPECT_EQ(ELFOSABI_STANDALONE, convertNameToOSABI("standalone")); + EXPECT_EQ(ELFOSABI_NONE, convertNameToOSABI("none")); + // Test unrecognized strings. + EXPECT_EQ(ELFOSABI_NONE, convertNameToOSABI("")); + EXPECT_EQ(ELFOSABI_NONE, convertNameToOSABI("linux")); + + EXPECT_EQ("gnu", convertOSABIToName(ELFOSABI_GNU)); + EXPECT_EQ("freebsd", convertOSABIToName(ELFOSABI_FREEBSD)); + EXPECT_EQ("standalone", convertOSABIToName(ELFOSABI_STANDALONE)); + EXPECT_EQ("none", convertOSABIToName(ELFOSABI_NONE)); + // Test unrecognized values. + EXPECT_EQ("none", convertOSABIToName(0xfe)); +} +} // namespace From e5907c88594133e45b8d1d4e29702b96d7f45c77 Mon Sep 17 00:00:00 2001 From: Jorge Pinto Sousa Date: Mon, 29 Apr 2024 22:14:53 +0200 Subject: [PATCH 09/22] [NFC] Fix hasQualifier comment (#90485) operator bool from NestedNameSpecifierLoc and member function hasQualifier both do the same thing, returning true if the private data member Qualifier is not nullptr, so clearly one of the comments is wrong, and in this case it is the second one. fixes https://github.com/llvm/llvm-project/issues/90472 --- clang/include/clang/AST/NestedNameSpecifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index 7b0c21b9e7cfb1..a1d9e30e660d14 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -266,7 +266,7 @@ class NestedNameSpecifierLoc { explicit operator bool() const { return Qualifier; } /// Evaluates true when this nested-name-specifier location is - /// empty. + /// non-empty. bool hasQualifier() const { return Qualifier; } /// Retrieve the nested-name-specifier to which this instance From 8ba880b587074ad6c8624ed45ea2b289f653667f Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Mon, 29 Apr 2024 13:22:08 -0700 Subject: [PATCH 10/22] [Driver] Clean up denormal handling with fast-math-related options (#89477) This change cleans up the clang driver handling of umbrella options like -ffast-math, -funsafe-math-optimizations, and -ffp-model, and aligns the behavior of -ffp-model=fast with -ffast-math with regard to the linking of crtfastmath.o. We agreed in a previous review that the fast-math options should not attempt to change the -fdenormal-fp-math option, which is inherently target-specific. The clang user's manual claims that -ffp-model=fast "behaves identically to specifying both -ffast-math and -ffp-contract=fast." Since -ffast-math causes crtfastmath.o to be linked if it is available, that should also happen with -ffp-model=fast. I am going to be proposing further changes to -ffp-model=fast, decoupling it from -ffast-math and introducing a new -ffp-model=aggressive that matches the current behavior, but I wanted to solidfy the current behavior before I do that. --- clang/docs/UsersManual.rst | 15 +++++++++------ clang/lib/Driver/ToolChain.cpp | 13 +++++++++---- clang/lib/Driver/ToolChains/Clang.cpp | 20 +++----------------- clang/test/Driver/fp-model.c | 4 +++- clang/test/Driver/linux-ld.c | 3 +++ clang/test/Driver/solaris-ld.c | 3 +++ 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index a7fc7ec87a161f..6ba0a531fedf9b 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1452,8 +1452,6 @@ floating point semantic models: precise (the default), strict, and fast. "fenv_access", "off", "on", "off" "rounding_mode", "tonearest", "dynamic", "tonearest" "contract", "on", "off", "fast" - "denormal_fp_math", "IEEE", "IEEE", "IEEE" - "denormal_fp32_math", "IEEE","IEEE", "IEEE" "support_math_errno", "on", "on", "off" "no_honor_nans", "off", "off", "on" "no_honor_infinities", "off", "off", "on" @@ -1462,6 +1460,14 @@ floating point semantic models: precise (the default), strict, and fast. "allow_approximate_fns", "off", "off", "on" "allow_reassociation", "off", "off", "on" +The ``-ffp-model`` option does not modify the ``fdenormal-fp-math`` +setting, but it does have an impact on whether ``crtfastmath.o`` is +linked. Because linking ``crtfastmath.o`` has a global effect on the +program, and because the global denormal handling can be changed in +other ways, the state of ``fdenormal-fp-math`` handling cannot +be assumed in any function based on fp-model. See :ref:`crtfastmath.o` +for more details. + .. option:: -ffast-math Enable fast-math mode. This option lets the @@ -1537,7 +1543,6 @@ floating point semantic models: precise (the default), strict, and fast. Also, this option resets following options to their target-dependent defaults. * ``-f[no-]math-errno`` - * ``-fdenormal-fp-math=`` There is ambiguity about how ``-ffp-contract``, ``-ffast-math``, and ``-fno-fast-math`` behave when combined. To keep the value of @@ -1560,8 +1565,7 @@ floating point semantic models: precise (the default), strict, and fast. ``-ffp-contract`` setting is determined by the default value of ``-ffp-contract``. - Note: ``-fno-fast-math`` implies ``-fdenormal-fp-math=ieee``. - ``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code + Note: ``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code unless ``-mdaz-ftz`` is present. .. option:: -fdenormal-fp-math= @@ -1694,7 +1698,6 @@ floating point semantic models: precise (the default), strict, and fast. * ``-fsigned-zeros`` * ``-ftrapping-math`` * ``-ffp-contract=on`` - * ``-fdenormal-fp-math=ieee`` There is ambiguity about how ``-ffp-contract``, ``-funsafe-math-optimizations``, and ``-fno-unsafe-math-optimizations`` diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 341d6202a9ca3c..0e86bc07e0ea2c 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1316,14 +1316,19 @@ bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, // (to keep the linker options consistent with gcc and clang itself). if (Default && !isOptimizationLevelFast(Args)) { // Check if -ffast-math or -funsafe-math. - Arg *A = - Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, - options::OPT_funsafe_math_optimizations, - options::OPT_fno_unsafe_math_optimizations); + Arg *A = Args.getLastArg( + options::OPT_ffast_math, options::OPT_fno_fast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ); if (!A || A->getOption().getID() == options::OPT_fno_fast_math || A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) Default = false; + if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) { + StringRef Model = A->getValue(); + if (Model != "fast") + Default = false; + } } // Whatever decision came as a result of the above implicit settings, either diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 651a2b5aac368b..250dc078edf242 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2743,13 +2743,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, StringRef FPExceptionBehavior = ""; // -ffp-eval-method options: double, extended, source StringRef FPEvalMethod = ""; - const llvm::DenormalMode DefaultDenormalFPMath = + llvm::DenormalMode DenormalFPMath = TC.getDefaultDenormalModeForType(Args, JA); - const llvm::DenormalMode DefaultDenormalFP32Math = + llvm::DenormalMode DenormalFP32Math = TC.getDefaultDenormalModeForType(Args, JA, &llvm::APFloat::IEEEsingle()); - llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath; - llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math; // CUDA and HIP don't rely on the frontend to pass an ffp-contract option. // If one wasn't given by the user, don't pass it here. StringRef FPContract; @@ -2899,11 +2897,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, SignedZeros = true; // -fno_fast_math restores default denormal and fpcontract handling FPContract = "on"; - DenormalFPMath = llvm::DenormalMode::getIEEE(); - - // FIXME: The target may have picked a non-IEEE default mode here based on - // -cl-denorms-are-zero. Should the target consider -fp-model interaction? - DenormalFP32Math = llvm::DenormalMode::getIEEE(); StringRef Val = A->getValue(); if (OFastEnabled && !Val.equals("fast")) { @@ -3122,9 +3115,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, TrappingMath = true; FPExceptionBehavior = "strict"; - // The target may have opted to flush by default, so force IEEE. - DenormalFPMath = llvm::DenormalMode::getIEEE(); - DenormalFP32Math = llvm::DenormalMode::getIEEE(); if (!JA.isDeviceOffloading(Action::OFK_Cuda) && !JA.isOffloading(Action::OFK_HIP)) { if (LastSeenFfpContractOption != "") { @@ -3154,9 +3144,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, ReciprocalMath = false; ApproxFunc = false; SignedZeros = true; - // -fno_fast_math restores default denormal and fpcontract handling - DenormalFPMath = DefaultDenormalFPMath; - DenormalFP32Math = llvm::DenormalMode::getIEEE(); + // -fno_fast_math restores default fpcontract handling if (!JA.isDeviceOffloading(Action::OFK_Cuda) && !JA.isOffloading(Action::OFK_HIP)) { if (LastSeenFfpContractOption != "") { @@ -3171,8 +3159,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, // subsequent options conflict then emit warning diagnostic. if (HonorINFs && HonorNaNs && !AssociativeMath && !ReciprocalMath && SignedZeros && TrappingMath && RoundingFPMath && !ApproxFunc && - DenormalFPMath == llvm::DenormalMode::getIEEE() && - DenormalFP32Math == llvm::DenormalMode::getIEEE() && FPContract.equals("off")) // OK: Current Arg doesn't conflict with -ffp-model=strict ; diff --git a/clang/test/Driver/fp-model.c b/clang/test/Driver/fp-model.c index a464729edb45c3..9d12452399119b 100644 --- a/clang/test/Driver/fp-model.c +++ b/clang/test/Driver/fp-model.c @@ -64,7 +64,8 @@ // RUN: %clang -### -ffp-model=strict -fdenormal-fp-math=preserve-sign,preserve-sign -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=WARN10 %s -// WARN10: warning: overriding '-ffp-model=strict' option with '-fdenormal-fp-math=preserve-sign,preserve-sign' [-Woverriding-option] +// WARN10: "-cc1" +// WARN10-NOT: warning: overriding '-ffp-model=strict' option with '-fdenormal-fp-math=preserve-sign,preserve-sign' [-Woverriding-option] // RUN: %clang -### -ffp-model=fast -ffp-model=strict -c %s 2>&1 | FileCheck \ // RUN: --check-prefix=WARN11 %s @@ -128,6 +129,7 @@ // RUN: | FileCheck --check-prefix=CHECK-NO-EXCEPT %s // RUN: %clang -### -nostdinc -ffp-model=strict -Ofast -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-EXCEPT %s +// CHECK-NO-EXCEPT: "-cc1" // CHECK-NO-EXCEPT-NOT: "-ffp-exception-behavior=strict" // RUN: %clang -### -nostdinc -ffp-exception-behavior=strict -c %s 2>&1 \ diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index e2043ab22afcbf..28fb075a80dbbc 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1406,6 +1406,9 @@ // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -funsafe-math-optimizations\ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s +// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffp-model=fast \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast\ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s diff --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c index 6d74389e89222c..ce0728d392bf23 100644 --- a/clang/test/Driver/solaris-ld.c +++ b/clang/test/Driver/solaris-ld.c @@ -193,6 +193,9 @@ // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -ffast-math \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC32 %s +// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -ffp-model=fast \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC32 %s // CHECK-CRTFASTMATH-SPARC32: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-CRTFASTMATH-SPARC32: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtfastmath.o" // CHECK-NOCRTFASTMATH-SPARC32-NOT: crtfastmath.o From 975eca0e6a3459e59e96b0df33ea0cfbd157c597 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 29 Apr 2024 13:26:24 -0700 Subject: [PATCH 11/22] Add a new SBExpressionOptions::SetLanguage() API (NFCI) (#89981) that separates out language and version. To avoid reinventing the wheel and introducing subtle incompatibilities, this API uses the table of languages and versiond defined by the upcoming DWARF 6 standard (https://dwarfstd.org/languages-v6.html). While the DWARF 6 spec is not finialized, the list of languages is broadly considered stable. The primary motivation for this is to allow the Swift language plugin to switch between language dialects between, e.g., Swift 5.9 and 6.0 with out introducing a ton of new language codes. On the main branch this change is considered NFC. Depends on https://github.com/llvm/llvm-project/pull/89980 --- lldb/include/lldb/API/SBExpressionOptions.h | 5 ++ lldb/include/lldb/Expression/Expression.h | 7 +- .../lldb/Expression/LLVMUserExpression.h | 2 +- lldb/include/lldb/Expression/UserExpression.h | 33 ++++----- lldb/include/lldb/Symbol/TypeSystem.h | 10 ++- lldb/include/lldb/Target/StackFrame.h | 12 ++-- lldb/include/lldb/Target/Target.h | 19 ++++-- lldb/include/lldb/lldb-private-types.h | 19 ++++++ .../Python/lldbsuite/test/configuration.py | 1 + lldb/packages/Python/lldbsuite/test/dotest.py | 3 + .../Python/lldbsuite/test/dotest_args.py | 8 ++- .../Python/lldbsuite/test/lldbtest.py | 25 +++++-- lldb/source/API/CMakeLists.txt | 7 ++ lldb/source/API/SBExpressionOptions.cpp | 7 ++ lldb/source/API/SBFrame.cpp | 30 +++++---- lldb/source/Breakpoint/Watchpoint.cpp | 5 +- .../Commands/CommandObjectDWIMPrint.cpp | 2 +- lldb/source/Commands/CommandObjectType.cpp | 2 +- lldb/source/Expression/LLVMUserExpression.cpp | 2 +- lldb/source/Expression/UserExpression.cpp | 14 ++-- lldb/source/Expression/UtilityFunction.cpp | 4 +- .../Clang/ClangExpressionParser.cpp | 12 ++-- .../Clang/ClangUserExpression.cpp | 19 +++--- .../Clang/ClangUserExpression.h | 6 +- .../TypeSystem/Clang/TypeSystemClang.cpp | 2 +- .../TypeSystem/Clang/TypeSystemClang.h | 12 ++-- lldb/source/Target/Language.cpp | 34 ++++++++++ lldb/source/Target/StackFrame.cpp | 23 +++---- lldb/source/Target/Target.cpp | 21 +++--- lldb/test/API/lit.cfg.py | 3 + lldb/test/API/lit.site.cfg.py.in | 2 +- lldb/utils/TableGen/CMakeLists.txt | 1 + lldb/utils/TableGen/LLDBSBAPIDWARFEnum.cpp | 67 +++++++++++++++++++ lldb/utils/TableGen/LLDBTableGen.cpp | 9 ++- lldb/utils/TableGen/LLDBTableGenBackends.h | 1 + 35 files changed, 306 insertions(+), 123 deletions(-) create mode 100644 lldb/utils/TableGen/LLDBSBAPIDWARFEnum.cpp diff --git a/lldb/include/lldb/API/SBExpressionOptions.h b/lldb/include/lldb/API/SBExpressionOptions.h index e0ddfda5ba37a2..19c416d0f3bcbc 100644 --- a/lldb/include/lldb/API/SBExpressionOptions.h +++ b/lldb/include/lldb/API/SBExpressionOptions.h @@ -10,6 +10,7 @@ #define LLDB_API_SBEXPRESSIONOPTIONS_H #include "lldb/API/SBDefines.h" +#include "lldb/API/SBLanguages.h" #include @@ -67,6 +68,10 @@ class LLDB_API SBExpressionOptions { void SetTrapExceptions(bool trap_exceptions = true); void SetLanguage(lldb::LanguageType language); + /// Set the language using a pair of language code and version as + /// defined by the DWARF 6 specification. + /// WARNING: These codes may change until DWARF 6 is finalized. + void SetLanguage(SBSourceLanguageName name, uint32_t version); #ifndef SWIG void SetCancelCallback(lldb::ExpressionCancelCallback callback, void *baton); diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 3e61d78828bbbf..356fe4b82ae43a 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -47,11 +47,8 @@ class Expression { /// expression. Text() should contain the definition of this function. virtual const char *FunctionName() = 0; - /// Return the language that should be used when parsing. To use the - /// default, return eLanguageTypeUnknown. - virtual lldb::LanguageType Language() const { - return lldb::eLanguageTypeUnknown; - } + /// Return the language that should be used when parsing. + virtual SourceLanguage Language() const { return {}; } /// Return the Materializer that the parser should use when registering /// external values. diff --git a/lldb/include/lldb/Expression/LLVMUserExpression.h b/lldb/include/lldb/Expression/LLVMUserExpression.h index 7d32d17dbf544c..40b463933c07e8 100644 --- a/lldb/include/lldb/Expression/LLVMUserExpression.h +++ b/lldb/include/lldb/Expression/LLVMUserExpression.h @@ -52,7 +52,7 @@ class LLVMUserExpression : public UserExpression { }; LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, - llvm::StringRef prefix, lldb::LanguageType language, + llvm::StringRef prefix, SourceLanguage language, ResultType desired_type, const EvaluateExpressionOptions &options); ~LLVMUserExpression() override; diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h index b6cfeec7e89933..b04d00b72e8faa 100644 --- a/lldb/include/lldb/Expression/UserExpression.h +++ b/lldb/include/lldb/Expression/UserExpression.h @@ -56,7 +56,7 @@ class UserExpression : public Expression { /// If not eResultTypeAny, the type to use for the expression /// result. UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, - llvm::StringRef prefix, lldb::LanguageType language, + llvm::StringRef prefix, SourceLanguage language, ResultType desired_type, const EvaluateExpressionOptions &options); @@ -202,7 +202,7 @@ class UserExpression : public Expression { virtual bool IsParseCacheable() { return true; } /// Return the language that should be used when parsing. To use the /// default, return eLanguageTypeUnknown. - lldb::LanguageType Language() const override { return m_language; } + SourceLanguage Language() const override { return m_language; } /// Return the desired result type of the function, or eResultTypeAny if /// indifferent. @@ -315,19 +315,22 @@ class UserExpression : public Expression { lldb::ProcessSP &process_sp, lldb::StackFrameSP &frame_sp); - Address m_address; ///< The address the process is stopped in. - std::string m_expr_text; ///< The text of the expression, as typed by the user - std::string m_expr_prefix; ///< The text of the translation-level definitions, - ///as provided by the user - std::string m_fixed_text; ///< The text of the expression with fix-its applied - ///- this won't be set if the fixed text doesn't - ///parse. - lldb::LanguageType m_language; ///< The language to use when parsing - ///(eLanguageTypeUnknown means use defaults) - ResultType m_desired_type; ///< The type to coerce the expression's result to. - ///If eResultTypeAny, inferred from the expression. - EvaluateExpressionOptions - m_options; ///< Additional options provided by the user. + /// The address the process is stopped in. + Address m_address; + /// The text of the expression, as typed by the user. + std::string m_expr_text; + /// The text of the translation-level definitions, as provided by the user. + std::string m_expr_prefix; + /// The text of the expression with fix-its applied this won't be set if the + /// fixed text doesn't parse. + std::string m_fixed_text; + /// The language to use when parsing (unknown means use defaults). + SourceLanguage m_language; + /// The type to coerce the expression's result to. If eResultTypeAny, inferred + /// from the expression. + ResultType m_desired_type; + /// Additional options provided by the user. + EvaluateExpressionOptions m_options; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index ad3b853227a9f6..0924e21a6b54a4 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -483,12 +483,10 @@ class TypeSystem : public PluginInterface, return IsPointerOrReferenceType(type, nullptr); } - virtual UserExpression * - GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix, - lldb::LanguageType language, - Expression::ResultType desired_type, - const EvaluateExpressionOptions &options, - ValueObject *ctx_obj) { + virtual UserExpression *GetUserExpression( + llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options, ValueObject *ctx_obj) { return nullptr; } diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 6c18511c6e1ac3..52f0a1ee662176 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -1,3 +1,4 @@ + //===-- StackFrame.h --------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -446,13 +447,12 @@ class StackFrame : public ExecutionContextScope, /// Query this frame to determine what the default language should be when /// parsing expressions given the execution context. /// - /// \return - /// The language of the frame if known, else lldb::eLanguageTypeUnknown. - lldb::LanguageType GetLanguage(); + /// \return The language of the frame if known. + SourceLanguage GetLanguage(); - // similar to GetLanguage(), but is allowed to take a potentially incorrect - // guess if exact information is not available - lldb::LanguageType GuessLanguage(); + /// Similar to GetLanguage(), but is allowed to take a potentially incorrect + /// guess if exact information is not available. + SourceLanguage GuessLanguage(); /// Attempt to econstruct the ValueObject for a given raw address touched by /// the current instruction. The ExpressionPath should indicate how to get diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index cade60f3cc8cd9..7ad9f335860549 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -200,7 +200,7 @@ class TargetProperties : public Properties { bool GetBreakpointsConsultPlatformAvoidList(); - lldb::LanguageType GetLanguage() const; + SourceLanguage GetLanguage() const; llvm::StringRef GetExpressionPrefixContents(); @@ -310,9 +310,18 @@ class EvaluateExpressionOptions { m_execution_policy = policy; } - lldb::LanguageType GetLanguage() const { return m_language; } + SourceLanguage GetLanguage() const { return m_language; } - void SetLanguage(lldb::LanguageType language) { m_language = language; } + void SetLanguage(lldb::LanguageType language_type) { + m_language = SourceLanguage(language_type); + } + + /// Set the language using a pair of language code and version as + /// defined by the DWARF 6 specification. + /// WARNING: These codes may change until DWARF 6 is finalized. + void SetLanguage(uint16_t name, uint32_t version) { + m_language = SourceLanguage(name, version); + } bool DoesCoerceToId() const { return m_coerce_to_id; } @@ -445,7 +454,7 @@ class EvaluateExpressionOptions { private: ExecutionPolicy m_execution_policy = default_execution_policy; - lldb::LanguageType m_language = lldb::eLanguageTypeUnknown; + SourceLanguage m_language; std::string m_prefix; bool m_coerce_to_id = false; bool m_unwind_on_error = true; @@ -1160,7 +1169,7 @@ class Target : public std::enable_shared_from_this, UserExpression * GetUserExpressionForLanguage(llvm::StringRef expr, llvm::StringRef prefix, - lldb::LanguageType language, + SourceLanguage language, Expression::ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj, Status &error); diff --git a/lldb/include/lldb/lldb-private-types.h b/lldb/include/lldb/lldb-private-types.h index 7d301666df1a17..055eea9f6456d6 100644 --- a/lldb/include/lldb/lldb-private-types.h +++ b/lldb/include/lldb/lldb-private-types.h @@ -96,6 +96,25 @@ struct RegisterSet { const uint32_t *registers; }; +/// A type-erased pair of llvm::dwarf::SourceLanguageName and version. +struct SourceLanguage { + SourceLanguage() = default; + SourceLanguage(lldb::LanguageType language_type); + SourceLanguage(uint16_t name, uint32_t version) + : name(name), version(version) {} + SourceLanguage(std::optional> name_vers) + : name(name_vers ? name_vers->first : 0), + version(name_vers ? name_vers->second : 0) {} + operator bool() const { return name > 0; } + lldb::LanguageType AsLanguageType() const; + llvm::StringRef GetDescription() const; + bool IsC() const; + bool IsObjC() const; + bool IsCPlusPlus() const; + uint16_t name = 0; + uint32_t version = 0; +}; + struct OptionEnumValueElement { int64_t value; const char *string_value; diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py index 685f491c85fe19..dbd4a2d72a15d2 100644 --- a/lldb/packages/Python/lldbsuite/test/configuration.py +++ b/lldb/packages/Python/lldbsuite/test/configuration.py @@ -119,6 +119,7 @@ # LLDB library directory. lldb_libs_dir = None +lldb_obj_root = None libcxx_include_dir = None libcxx_include_target_dir = None diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 2ec4a840b91675..ebabf348643ef6 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -423,6 +423,7 @@ def parseOptionsAndInitTestdirs(): configuration.lldb_module_cache_dir = os.path.join( configuration.test_build_dir, "module-cache-lldb" ) + if args.clang_module_cache_dir: configuration.clang_module_cache_dir = args.clang_module_cache_dir else: @@ -432,6 +433,8 @@ def parseOptionsAndInitTestdirs(): if args.lldb_libs_dir: configuration.lldb_libs_dir = args.lldb_libs_dir + if args.lldb_obj_root: + configuration.lldb_obj_root = args.lldb_obj_root if args.enabled_plugins: configuration.enabled_plugins = args.enabled_plugins diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py index e4de786ec05489..8b00c7a4d56e77 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest_args.py +++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py @@ -236,11 +236,17 @@ def create_parser(): metavar="The clang module cache directory used by Clang", help="The clang module cache directory used in the Make files by Clang while building tests. Defaults to /module-cache-clang.", ) + group.add_argument( + "--lldb-obj-root", + dest="lldb_obj_root", + metavar="path", + help="The path to the LLDB object files.", + ) group.add_argument( "--lldb-libs-dir", dest="lldb_libs_dir", metavar="path", - help="The path to LLDB library directory (containing liblldb)", + help="The path to LLDB library directory (containing liblldb).", ) group.add_argument( "--enable-plugin", diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 7a7afec7345707..591e834c7cdf49 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1473,11 +1473,12 @@ def buildDriver(self, sources, exe_name): d = { "CXX_SOURCES": sources, "EXE": exe_name, - "CFLAGS_EXTRAS": "%s %s -I%s" + "CFLAGS_EXTRAS": "%s %s -I%s -I%s" % ( stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include"), + os.path.join(configuration.lldb_obj_root, "include"), ), "LD_EXTRAS": "-L%s -lliblldb" % lib_dir, } @@ -1485,11 +1486,12 @@ def buildDriver(self, sources, exe_name): d = { "CXX_SOURCES": sources, "EXE": exe_name, - "CFLAGS_EXTRAS": "%s %s -I%s" + "CFLAGS_EXTRAS": "%s %s -I%s -I%s" % ( stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include"), + os.path.join(configuration.lldb_obj_root, "include"), ), "LD_EXTRAS": "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir), } @@ -1508,7 +1510,8 @@ def buildLibrary(self, sources, lib_name): d = { "DYLIB_CXX_SOURCES": sources, "DYLIB_NAME": lib_name, - "CFLAGS_EXTRAS": "%s -stdlib=libc++" % stdflag, + "CFLAGS_EXTRAS": "%s -stdlib=libc++ -I%s" + % (stdflag, os.path.join(configuration.lldb_obj_root, "include")), "FRAMEWORK_INCLUDES": "-F%s" % self.framework_dir, "LD_EXTRAS": "%s -Wl,-rpath,%s -dynamiclib" % (self.lib_lldb, self.framework_dir), @@ -1517,16 +1520,24 @@ def buildLibrary(self, sources, lib_name): d = { "DYLIB_CXX_SOURCES": sources, "DYLIB_NAME": lib_name, - "CFLAGS_EXTRAS": "%s -I%s " - % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), + "CFLAGS_EXTRAS": "%s -I%s -I%s" + % ( + stdflag, + os.path.join(os.environ["LLDB_SRC"], "include"), + os.path.join(configuration.lldb_obj_root, "include"), + ), "LD_EXTRAS": "-shared -l%s\liblldb.lib" % lib_dir, } else: d = { "DYLIB_CXX_SOURCES": sources, "DYLIB_NAME": lib_name, - "CFLAGS_EXTRAS": "%s -I%s -fPIC" - % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")), + "CFLAGS_EXTRAS": "%s -I%s -I%s -fPIC" + % ( + stdflag, + os.path.join(os.environ["LLDB_SRC"], "include"), + os.path.join(configuration.lldb_obj_root, "include"), + ), "LD_EXTRAS": "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir), } if self.TraceOn(): diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index 57cc44f7646753..ad960403ae70bf 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -20,6 +20,10 @@ if(LLDB_ENABLE_LUA) set(lldb_lua_wrapper ${lua_bindings_dir}/LLDBWrapLua.cpp) endif() +lldb_tablegen(../../include/lldb/API/SBLanguages.h -gen-lldb-sbapi-dwarf-enum + SOURCE ${LLVM_MAIN_INCLUDE_DIR}/llvm/BinaryFormat/Dwarf.def + TARGET lldb-sbapi-dwarf-enums) + add_lldb_library(liblldb SHARED ${option_framework} SBAddress.cpp SBAttachInfo.cpp @@ -100,6 +104,9 @@ add_lldb_library(liblldb SHARED ${option_framework} ${lldb_python_wrapper} ${lldb_lua_wrapper} + DEPENDS + lldb-sbapi-dwarf-enums + LINK_LIBS lldbBreakpoint lldbCore diff --git a/lldb/source/API/SBExpressionOptions.cpp b/lldb/source/API/SBExpressionOptions.cpp index bd81a04596b10d..ce686112ff7197 100644 --- a/lldb/source/API/SBExpressionOptions.cpp +++ b/lldb/source/API/SBExpressionOptions.cpp @@ -156,6 +156,13 @@ void SBExpressionOptions::SetLanguage(lldb::LanguageType language) { m_opaque_up->SetLanguage(language); } +void SBExpressionOptions::SetLanguage(SBSourceLanguageName name, + uint32_t version) { + LLDB_INSTRUMENT_VA(this, name, version); + + m_opaque_up->SetLanguage(name, version); +} + void SBExpressionOptions::SetCancelCallback( lldb::ExpressionCancelCallback callback, void *baton) { LLDB_INSTRUMENT_VA(this, callback, baton); diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index a16bbc2ae7562d..47fc88625e30c5 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -1024,10 +1024,10 @@ SBValue SBFrame::EvaluateExpression(const char *expr) { options.SetFetchDynamicValue(fetch_dynamic_value); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - if (target->GetLanguage() != eLanguageTypeUnknown) - options.SetLanguage(target->GetLanguage()); - else - options.SetLanguage(frame->GetLanguage()); + SourceLanguage language = target->GetLanguage(); + if (!language) + language = frame->GetLanguage(); + options.SetLanguage((SBSourceLanguageName)language.name, language.version); return EvaluateExpression(expr, options); } else { Status error; @@ -1053,10 +1053,12 @@ SBFrame::EvaluateExpression(const char *expr, StackFrame *frame = exe_ctx.GetFramePtr(); Target *target = exe_ctx.GetTargetPtr(); - if (target && target->GetLanguage() != eLanguageTypeUnknown) - options.SetLanguage(target->GetLanguage()); - else if (frame) - options.SetLanguage(frame->GetLanguage()); + SourceLanguage language; + if (target) + language = target->GetLanguage(); + if (!language && frame) + language = frame->GetLanguage(); + options.SetLanguage((SBSourceLanguageName)language.name, language.version); return EvaluateExpression(expr, options); } @@ -1074,10 +1076,12 @@ SBValue SBFrame::EvaluateExpression(const char *expr, options.SetIgnoreBreakpoints(true); StackFrame *frame = exe_ctx.GetFramePtr(); Target *target = exe_ctx.GetTargetPtr(); - if (target && target->GetLanguage() != eLanguageTypeUnknown) - options.SetLanguage(target->GetLanguage()); - else if (frame) - options.SetLanguage(frame->GetLanguage()); + SourceLanguage language; + if (target) + language = target->GetLanguage(); + if (!language && frame) + language = frame->GetLanguage(); + options.SetLanguage((SBSourceLanguageName)language.name, language.version); return EvaluateExpression(expr, options); } @@ -1218,7 +1222,7 @@ lldb::LanguageType SBFrame::GuessLanguage() const { if (stop_locker.TryLock(&process->GetRunLock())) { frame = exe_ctx.GetFramePtr(); if (frame) { - return frame->GuessLanguage(); + return frame->GuessLanguage().AsLanguageType(); } } } diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp index a128ced5750449..edb1a0e93460c4 100644 --- a/lldb/source/Breakpoint/Watchpoint.cpp +++ b/lldb/source/Breakpoint/Watchpoint.cpp @@ -460,9 +460,8 @@ void Watchpoint::SetCondition(const char *condition) { // Pass nullptr for expr_prefix (no translation-unit level definitions). Status error; m_condition_up.reset(m_target.GetUserExpressionForLanguage( - condition, llvm::StringRef(), lldb::eLanguageTypeUnknown, - UserExpression::eResultTypeAny, EvaluateExpressionOptions(), nullptr, - error)); + condition, {}, {}, UserExpression::eResultTypeAny, + EvaluateExpressionOptions(), nullptr, error)); if (error.Fail()) { // FIXME: Log something... m_condition_up.reset(); diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index e1255f37d9bc58..f0b37e6832eab0 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -96,7 +96,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, // Either Swift was explicitly specified, or the frame is Swift. lldb::LanguageType language = m_expr_options.language; if (language == lldb::eLanguageTypeUnknown && frame) - language = frame->GuessLanguage(); + language = frame->GuessLanguage().AsLanguageType(); // Add a hint if object description was requested, but no description // function was implemented. diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 97489bdc2d9c28..46537dd1b98aaf 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -2509,7 +2509,7 @@ class CommandObjectTypeLookup : public CommandObjectRaw { if (!frame) return lang_type; - lang_type = frame->GuessLanguage(); + lang_type = frame->GuessLanguage().AsLanguageType(); if (lang_type != lldb::eLanguageTypeUnknown) return lang_type; diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp index 9c31cc84bf8f8b..1434011c80ad81 100644 --- a/lldb/source/Expression/LLVMUserExpression.cpp +++ b/lldb/source/Expression/LLVMUserExpression.cpp @@ -42,7 +42,7 @@ char LLVMUserExpression::ID; LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, - lldb::LanguageType language, + SourceLanguage language, ResultType desired_type, const EvaluateExpressionOptions &options) : UserExpression(exe_scope, expr, prefix, language, desired_type, options), diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index c181712a2f0b24..84578c7f9ad272 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -39,6 +39,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" +#include "llvm/BinaryFormat/Dwarf.h" using namespace lldb_private; @@ -46,8 +47,7 @@ char UserExpression::ID; UserExpression::UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, - lldb::LanguageType language, - ResultType desired_type, + SourceLanguage language, ResultType desired_type, const EvaluateExpressionOptions &options) : Expression(exe_scope), m_expr_text(std::string(expr)), m_expr_prefix(std::string(prefix)), m_language(language), @@ -176,7 +176,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); - lldb::LanguageType language = options.GetLanguage(); + SourceLanguage language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; @@ -242,7 +242,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, // If the language was not specified in the expression command, set it to the // language in the target's properties if specified, else default to the // langage for the frame. - if (language == lldb::eLanguageTypeUnknown) { + if (!language.name) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) @@ -384,7 +384,8 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); - result_valobj_sp->SetPreferredDisplayLanguage(language); + result_valobj_sp->SetPreferredDisplayLanguage( + language.AsLanguageType()); LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed " @@ -426,7 +427,8 @@ UserExpression::Execute(DiagnosticManager &diagnostic_manager, Target *target = exe_ctx.GetTargetPtr(); if (options.GetSuppressPersistentResult() && result_var && target) { if (auto *persistent_state = - target->GetPersistentExpressionStateForLanguage(m_language)) + target->GetPersistentExpressionStateForLanguage( + m_language.AsLanguageType())) persistent_state->RemovePersistentVariable(result_var); } return expr_result; diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp index d7a3c9d41d0484..7b34c2c2ff76d5 100644 --- a/lldb/source/Expression/UtilityFunction.cpp +++ b/lldb/source/Expression/UtilityFunction.cpp @@ -80,8 +80,8 @@ FunctionCaller *UtilityFunction::MakeFunctionCaller( name.append("-caller"); m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage( - Language(), return_type, impl_code_address, arg_value_list, name.c_str(), - error)); + Language().AsLanguageType(), return_type, impl_code_address, + arg_value_list, name.c_str(), error)); if (error.Fail()) { return nullptr; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index f48bdc730d9160..72c7cda13ecb70 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -392,8 +392,8 @@ ClangExpressionParser::ClangExpressionParser( // Make sure clang uses the same VFS as LLDB. m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); - lldb::LanguageType frame_lang = - expr.Language(); // defaults to lldb::eLanguageTypeUnknown + // Defaults to lldb::eLanguageTypeUnknown. + lldb::LanguageType frame_lang = expr.Language().AsLanguageType(); std::string abi; ArchSpec target_arch; @@ -410,7 +410,7 @@ ClangExpressionParser::ClangExpressionParser( // Make sure the user hasn't provided a preferred execution language with // `expression --language X -- ...` if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) - frame_lang = frame_sp->GetLanguage(); + frame_lang = frame_sp->GetLanguage().AsLanguageType(); if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) { LLDB_LOGF(log, "Frame has language of type %s", @@ -479,7 +479,7 @@ ClangExpressionParser::ClangExpressionParser( assert(m_compiler->hasTarget()); // 4. Set language options. - lldb::LanguageType language = expr.Language(); + lldb::LanguageType language = expr.Language().AsLanguageType(); LangOptions &lang_opts = m_compiler->getLangOpts(); switch (language) { @@ -1344,10 +1344,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( { auto lang = m_expr.Language(); LLDB_LOGF(log, "%s - Current expression language is %s\n", __FUNCTION__, - Language::GetNameForLanguageType(lang)); + lang.GetDescription().data()); lldb::ProcessSP process_sp = exe_ctx.GetProcessSP(); if (process_sp && lang != lldb::eLanguageTypeUnknown) { - auto runtime = process_sp->GetLanguageRuntime(lang); + auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType()); if (runtime) runtime->GetIRPasses(custom_passes); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 5776b1e94e0721..5ea7bc02a6e489 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -56,6 +56,7 @@ #include "clang/AST/DeclObjC.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/BinaryFormat/Dwarf.h" using namespace lldb_private; @@ -63,22 +64,21 @@ char ClangUserExpression::ID; ClangUserExpression::ClangUserExpression( ExecutionContextScope &exe_scope, llvm::StringRef expr, - llvm::StringRef prefix, lldb::LanguageType language, - ResultType desired_type, const EvaluateExpressionOptions &options, - ValueObject *ctx_obj) + llvm::StringRef prefix, SourceLanguage language, ResultType desired_type, + const EvaluateExpressionOptions &options, ValueObject *ctx_obj) : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type, options), m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel), m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) { - switch (m_language) { - case lldb::eLanguageTypeC_plus_plus: + switch (m_language.name) { + case llvm::dwarf::DW_LNAME_C_plus_plus: m_allow_cxx = true; break; - case lldb::eLanguageTypeObjC: + case llvm::dwarf::DW_LNAME_ObjC: m_allow_objc = true; break; - case lldb::eLanguageTypeObjC_plus_plus: + case llvm::dwarf::DW_LNAME_ObjC_plus_plus: default: m_allow_cxx = true; m_allow_objc = true; @@ -624,7 +624,8 @@ bool ClangUserExpression::TryParse( void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) { Log *log = GetLog(LLDBLog::Expressions); - CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx); + CppModuleConfiguration module_config = + GetModuleConfig(m_language.AsLanguageType(), exe_ctx); m_imported_cpp_modules = module_config.GetImportedModules(); m_include_directories = module_config.GetIncludeDirs(); @@ -734,7 +735,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (register_execution_unit) { if (auto *persistent_state = exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( - m_language)) + m_language.AsLanguageType())) persistent_state->RegisterExecutionUnit(m_execution_unit_sp); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index bc07cbcf9e646d..09604feea5dec4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -106,8 +106,8 @@ class ClangUserExpression : public LLVMUserExpression { /// definitions to be included when the expression is parsed. /// /// \param[in] language - /// If not eLanguageTypeUnknown, a language to use when parsing - /// the expression. Currently restricted to those languages + /// If not unknown, a language to use when parsing the + /// expression. Currently restricted to those languages /// supported by Clang. /// /// \param[in] desired_type @@ -122,7 +122,7 @@ class ClangUserExpression : public LLVMUserExpression { /// must be evaluated. For details see the comment to /// `UserExpression::Evaluate`. ClangUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, - llvm::StringRef prefix, lldb::LanguageType language, + llvm::StringRef prefix, SourceLanguage language, ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 8fc0f9103f5541..ec005ac46b34f3 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9596,7 +9596,7 @@ void ScratchTypeSystemClang::Dump(llvm::raw_ostream &output) { } UserExpression *ScratchTypeSystemClang::GetUserExpression( - llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, + llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language, Expression::ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj) { TargetSP target_sp = m_target_wp.lock(); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 62f14df7638dce..8a7d45254bcf52 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1280,12 +1280,12 @@ class ScratchTypeSystemClang : public TypeSystemClang { /// \see lldb_private::TypeSystem::Dump void Dump(llvm::raw_ostream &output) override; - UserExpression * - GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix, - lldb::LanguageType language, - Expression::ResultType desired_type, - const EvaluateExpressionOptions &options, - ValueObject *ctx_obj) override; + UserExpression *GetUserExpression(llvm::StringRef expr, + llvm::StringRef prefix, + SourceLanguage language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options, + ValueObject *ctx_obj) override; FunctionCaller *GetFunctionCaller(const CompilerType &return_type, const Address &function_address, diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp index 1542c8cb68ce65..d0bffe441f6395 100644 --- a/lldb/source/Target/Language.cpp +++ b/lldb/source/Target/Language.cpp @@ -19,6 +19,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/Stream.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Threading.h" using namespace lldb; @@ -532,3 +533,36 @@ Language::Language() = default; // Destructor Language::~Language() = default; + +SourceLanguage::SourceLanguage(lldb::LanguageType language_type) { + auto lname = + llvm::dwarf::toDW_LNAME((llvm::dwarf::SourceLanguage)language_type); + if (!lname) + return; + name = lname->first; + version = lname->second; +} + +lldb::LanguageType SourceLanguage::AsLanguageType() const { + if (auto lang = llvm::dwarf::toDW_LANG((llvm::dwarf::SourceLanguageName)name, + version)) + return (lldb::LanguageType)*lang; + return lldb::eLanguageTypeUnknown; +} + +llvm::StringRef SourceLanguage::GetDescription() const { + LanguageType type = AsLanguageType(); + if (type) + return Language::GetNameForLanguageType(type); + return llvm::dwarf::LanguageDescription( + (llvm::dwarf::SourceLanguageName)name); +} +bool SourceLanguage::IsC() const { return name == llvm::dwarf::DW_LNAME_C; } + +bool SourceLanguage::IsObjC() const { + return name == llvm::dwarf::DW_LNAME_ObjC; +} + +bool SourceLanguage::IsCPlusPlus() const { + return name == llvm::dwarf::DW_LNAME_C_plus_plus; +} diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 03a74f29e76e99..246871d5abaa52 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1203,26 +1203,23 @@ bool StackFrame::IsArtificial() const { return m_stack_frame_kind == StackFrame::Kind::Artificial; } -lldb::LanguageType StackFrame::GetLanguage() { +SourceLanguage StackFrame::GetLanguage() { CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit; if (cu) return cu->GetLanguage(); - return lldb::eLanguageTypeUnknown; + return {}; } -lldb::LanguageType StackFrame::GuessLanguage() { - LanguageType lang_type = GetLanguage(); +SourceLanguage StackFrame::GuessLanguage() { + SourceLanguage lang_type = GetLanguage(); if (lang_type == eLanguageTypeUnknown) { - SymbolContext sc = GetSymbolContext(eSymbolContextFunction - | eSymbolContextSymbol); - if (sc.function) { - lang_type = sc.function->GetMangled().GuessLanguage(); - } + SymbolContext sc = + GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol); + if (sc.function) + lang_type = LanguageType(sc.function->GetMangled().GuessLanguage()); else if (sc.symbol) - { - lang_type = sc.symbol->GetMangled().GuessLanguage(); - } + lang_type = SourceLanguage(sc.symbol->GetMangled().GuessLanguage()); } return lang_type; @@ -1302,7 +1299,7 @@ GetBaseExplainingDereference(const Instruction::Operand &operand, } return std::make_pair(nullptr, 0); } -} +} // namespace lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) { TargetSP target_sp = CalculateTarget(); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index aa4895bb5a6d65..82f3040e539a31 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -504,7 +504,7 @@ BreakpointSP Target::CreateBreakpoint( if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; if (language == lldb::eLanguageTypeUnknown) - language = GetLanguage(); + language = GetLanguage().AsLanguageType(); BreakpointResolverSP resolver_sp(new BreakpointResolverName( nullptr, func_name, func_name_type_mask, language, Breakpoint::Exact, @@ -530,7 +530,7 @@ Target::CreateBreakpoint(const FileSpecList *containingModules, if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; if (language == lldb::eLanguageTypeUnknown) - language = GetLanguage(); + language = GetLanguage().AsLanguageType(); BreakpointResolverSP resolver_sp( new BreakpointResolverName(nullptr, func_names, func_name_type_mask, @@ -559,7 +559,7 @@ Target::CreateBreakpoint(const FileSpecList *containingModules, skip_prologue = eLazyBoolNo; } if (language == lldb::eLanguageTypeUnknown) - language = GetLanguage(); + language = GetLanguage().AsLanguageType(); BreakpointResolverSP resolver_sp(new BreakpointResolverName( nullptr, func_names, num_names, func_name_type_mask, language, offset, @@ -2504,15 +2504,16 @@ Target::GetPersistentExpressionStateForLanguage(lldb::LanguageType language) { } UserExpression *Target::GetUserExpressionForLanguage( - llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, + llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language, Expression::ResultType desired_type, const EvaluateExpressionOptions &options, ValueObject *ctx_obj, Status &error) { - auto type_system_or_err = GetScratchTypeSystemForLanguage(language); + auto type_system_or_err = + GetScratchTypeSystemForLanguage(language.AsLanguageType()); if (auto err = type_system_or_err.takeError()) { error.SetErrorStringWithFormat( "Could not find type system for language %s: %s", - Language::GetNameForLanguageType(language), + Language::GetNameForLanguageType(language.AsLanguageType()), llvm::toString(std::move(err)).c_str()); return nullptr; } @@ -2521,7 +2522,7 @@ UserExpression *Target::GetUserExpressionForLanguage( if (!ts) { error.SetErrorStringWithFormat( "Type system for language %s is no longer live", - Language::GetNameForLanguageType(language)); + language.GetDescription().data()); return nullptr; } @@ -2530,7 +2531,7 @@ UserExpression *Target::GetUserExpressionForLanguage( if (!user_expr) error.SetErrorStringWithFormat( "Could not create an expression for language %s", - Language::GetNameForLanguageType(language)); + language.GetDescription().data()); return user_expr; } @@ -4646,9 +4647,9 @@ void TargetProperties::SetStandardErrorPath(llvm::StringRef path) { SetPropertyAtIndex(idx, path); } -LanguageType TargetProperties::GetLanguage() const { +SourceLanguage TargetProperties::GetLanguage() const { const uint32_t idx = ePropertyLanguage; - return GetPropertyAtIndexAs(idx, {}); + return {GetPropertyAtIndexAs(idx, {})}; } llvm::StringRef TargetProperties::GetExpressionPrefixContents() { diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index 9d6775917e1370..d934349fe3ca3d 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -239,6 +239,9 @@ def delete_module_cache(path): if is_configured("server"): dotest_cmd += ["--server", config.server] +if is_configured("lldb_obj_root"): + dotest_cmd += ["--lldb-obj-root", config.lldb_obj_root] + if is_configured("lldb_libs_dir"): dotest_cmd += ["--lldb-libs-dir", config.lldb_libs_dir] diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in index 053331dc4881f7..8b2d09ae41cd2a 100644 --- a/lldb/test/API/lit.site.cfg.py.in +++ b/lldb/test/API/lit.site.cfg.py.in @@ -8,7 +8,7 @@ config.llvm_include_dir = lit_config.substitute("@LLVM_INCLUDE_DIR@") config.llvm_shlib_dir = lit_config.substitute("@SHLIBDIR@") config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@") config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" -config.lldb_obj_root = "@LLDB_BINARY_DIR@" +config.lldb_obj_root = lit_config.substitute("@LLDB_BINARY_DIR@") config.lldb_src_root = "@LLDB_SOURCE_DIR@" config.lldb_libs_dir = lit_config.substitute("@LLDB_LIBS_DIR@") config.lldb_framework_dir = lit_config.substitute("@LLDB_FRAMEWORK_DIR@") diff --git a/lldb/utils/TableGen/CMakeLists.txt b/lldb/utils/TableGen/CMakeLists.txt index 47a6400b4287e2..68547fe13e1aeb 100644 --- a/lldb/utils/TableGen/CMakeLists.txt +++ b/lldb/utils/TableGen/CMakeLists.txt @@ -10,6 +10,7 @@ if (NOT DEFINED LLDB_TABLEGEN_EXE) add_tablegen(lldb-tblgen LLDB LLDBOptionDefEmitter.cpp LLDBPropertyDefEmitter.cpp + LLDBSBAPIDWARFEnum.cpp LLDBTableGen.cpp LLDBTableGenUtils.cpp ) diff --git a/lldb/utils/TableGen/LLDBSBAPIDWARFEnum.cpp b/lldb/utils/TableGen/LLDBSBAPIDWARFEnum.cpp new file mode 100644 index 00000000000000..084284ed6aa82a --- /dev/null +++ b/lldb/utils/TableGen/LLDBSBAPIDWARFEnum.cpp @@ -0,0 +1,67 @@ +//===- LLDBPropertyDefEmitter.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Produce the list of source languages header file fragment for the SBAPI. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +namespace lldb_private { +int EmitSBAPIDWARFEnum(int argc, char **argv) { + std::string InputFilename; + std::string OutputFilename; + std::string DepFilename; + // This command line option parser is as robust as the worst shell script. + for (int i = 0; i < argc; ++i) { + if (llvm::StringRef(argv[i]).ends_with("Dwarf.def")) + InputFilename = std::string(argv[i]); + if (llvm::StringRef(argv[i]) == "-o" && i + 1 < argc) + OutputFilename = std::string(argv[i + 1]); + if (llvm::StringRef(argv[i]) == "-d" && i + 1 < argc) + DepFilename = std::string(argv[i + 1]); + } + std::ifstream input(InputFilename); + std::ofstream output(OutputFilename); + output + << R"(//===-- SBLanguages.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_API_SBLANGUAGE_H +#define LLDB_API_SBLANGUAGE_H +/// Used by \ref SBExpressionOptions. +/// These enumerations use the same language enumerations as the DWARF +/// specification for ease of use and consistency. +enum SBSourceLanguageName : uint16_t { +)"; + std::string line; + std::regex macro_regex(R"(^ *HANDLE_DW_LNAME *\( *([^,]+), ([^,]+), )" + "\"(.*)\",.*\\).*", + std::regex::extended); + while (std::getline(input, line)) { + std::smatch match; + if (!std::regex_match(line, match, macro_regex)) + continue; + + output << " /// " << match[3] << ".\n"; + output << " eLanguageName" << match[2] << " = " << match[1] << ",\n"; + } + output << "};\n\n"; + output << "#endif\n"; + // Emit the dependencies file. + std::ofstream(DepFilename) << OutputFilename << ": " << InputFilename << '\n'; + return 0; +} +} // namespace lldb_private diff --git a/lldb/utils/TableGen/LLDBTableGen.cpp b/lldb/utils/TableGen/LLDBTableGen.cpp index abb6589f0ca681..75d16755604758 100644 --- a/lldb/utils/TableGen/LLDBTableGen.cpp +++ b/lldb/utils/TableGen/LLDBTableGen.cpp @@ -27,6 +27,7 @@ enum ActionType { GenOptionDefs, GenPropertyDefs, GenPropertyEnumDefs, + GenSBAPIDWARFEnum }; static cl::opt Action( @@ -40,6 +41,8 @@ static cl::opt Action( clEnumValN(GenPropertyDefs, "gen-lldb-property-defs", "Generate lldb property definitions"), clEnumValN(GenPropertyEnumDefs, "gen-lldb-property-enum-defs", + "Generate lldb property enum definitions"), + clEnumValN(GenSBAPIDWARFEnum, "gen-lldb-sbapi-dwarf-enum", "Generate lldb property enum definitions"))); static bool LLDBTableGenMain(raw_ostream &OS, RecordKeeper &Records) { @@ -59,6 +62,8 @@ static bool LLDBTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenPropertyEnumDefs: EmitPropertyEnumDefs(Records, OS); break; + case GenSBAPIDWARFEnum: + llvm_unreachable("already handled"); } return false; } @@ -67,9 +72,11 @@ int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); - llvm_shutdown_obj Y; + if (Action == GenSBAPIDWARFEnum) + return EmitSBAPIDWARFEnum(argc, argv); + return TableGenMain(argv[0], &LLDBTableGenMain); } diff --git a/lldb/utils/TableGen/LLDBTableGenBackends.h b/lldb/utils/TableGen/LLDBTableGenBackends.h index 88ae0888c22dc7..b60c4705de3ad9 100644 --- a/lldb/utils/TableGen/LLDBTableGenBackends.h +++ b/lldb/utils/TableGen/LLDBTableGenBackends.h @@ -32,6 +32,7 @@ namespace lldb_private { void EmitOptionDefs(RecordKeeper &RK, raw_ostream &OS); void EmitPropertyDefs(RecordKeeper &RK, raw_ostream &OS); void EmitPropertyEnumDefs(RecordKeeper &RK, raw_ostream &OS); +int EmitSBAPIDWARFEnum(int argc, char **argv); } // namespace lldb_private From 9d955a63c7b0d2d547a63d4074e03cd5ebd1f162 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Mon, 29 Apr 2024 15:31:34 -0500 Subject: [PATCH 12/22] [driver] Allow `ld` as a driver alias to lld (#90515) This adds a "hidden" alias kind that allows using LLD when symlinked as `ld`; however, it does not install `ld` as a symlink. This is to allow either using a mixed toolchain with both LLD and GNU ld, or a pure LLD toolchain where LLD has been installed (or symlinked) to `ld` for compatibility w/ older tools that expect `ld`. --- lld/tools/lld/CMakeLists.txt | 4 ++++ llvm/test/tools/llvm-driver/passthrough-lld.test | 2 ++ llvm/tools/llvm-driver/CMakeLists.txt | 5 +++++ utils/bazel/llvm-project-overlay/llvm/driver.bzl | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lld/tools/lld/CMakeLists.txt b/lld/tools/lld/CMakeLists.txt index 0f5daa78846bc7..8498a91597a930 100644 --- a/lld/tools/lld/CMakeLists.txt +++ b/lld/tools/lld/CMakeLists.txt @@ -42,3 +42,7 @@ endif() foreach(link ${LLD_SYMLINKS_TO_CREATE}) add_lld_symlink(${link} lld) endforeach() + +if(LLVM_TOOL_LLVM_DRIVER_BUILD) + set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_HIDDEN_TOOL_ALIASES_lld ld) +endif() diff --git a/llvm/test/tools/llvm-driver/passthrough-lld.test b/llvm/test/tools/llvm-driver/passthrough-lld.test index acd5f38784811c..b31fa4e483b92c 100644 --- a/llvm/test/tools/llvm-driver/passthrough-lld.test +++ b/llvm/test/tools/llvm-driver/passthrough-lld.test @@ -1,6 +1,8 @@ # REQUIRES: llvm-driver, lld # RUN: %llvm ld.lld --help | FileCheck %s +# RUN: %llvm ld --help | FileCheck %s # RUN: %llvm lld -flavor ld.lld --help | FileCheck %s +# RUN: %llvm ld -flavor ld.lld --help | FileCheck %s # CHECK: supported targets: elf diff --git a/llvm/tools/llvm-driver/CMakeLists.txt b/llvm/tools/llvm-driver/CMakeLists.txt index 83e084069b96ac..82d85c7230109c 100644 --- a/llvm/tools/llvm-driver/CMakeLists.txt +++ b/llvm/tools/llvm-driver/CMakeLists.txt @@ -13,6 +13,11 @@ foreach(tool ${LLVM_DRIVER_TOOLS}) string(REPLACE "llvm-" "" alias ${alias}) set(def_decl "${def_decl}LLVM_DRIVER_TOOL(\"${alias}\", ${tool_entry})\n") endforeach() + get_property(hidden_tool_aliases GLOBAL PROPERTY LLVM_DRIVER_HIDDEN_TOOL_ALIASES_${tool}) + foreach(alias ${hidden_tool_aliases}) + string(REPLACE "llvm-" "" alias ${alias}) + set(def_decl "${def_decl}LLVM_DRIVER_TOOL(\"${alias}\", ${tool_entry})\n") + endforeach() endforeach() file(WRITE diff --git a/utils/bazel/llvm-project-overlay/llvm/driver.bzl b/utils/bazel/llvm-project-overlay/llvm/driver.bzl index 888626d7cf8451..10796d91983433 100644 --- a/utils/bazel/llvm-project-overlay/llvm/driver.bzl +++ b/utils/bazel/llvm-project-overlay/llvm/driver.bzl @@ -37,7 +37,7 @@ _TOOLS = { # aliases for a given tool. _EXTRA_ALIASES = { "clang": ["clang++", "clang-cl", "clang-cpp"], - "lld": ["lld-link", "ld.lld", "ld64.lld", "wasm-ld"], + "lld": ["ld", "lld-link", "ld.lld", "ld64.lld", "wasm-ld"], "llvm-ar": ["ranlib", "lib", "dlltool"], "llvm-objcopy": ["bitcode-strip", "install-name-tool", "strip"], "llvm-objdump": ["otool"], From 35fa46a56ae2a220de514e5de5c5e6b4607f5ebb Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 29 Apr 2024 13:37:26 -0700 Subject: [PATCH 13/22] Improve comment --- lldb/source/Commands/CommandObjectDWIMPrint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index f0b37e6832eab0..57a372a762e150 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -93,7 +93,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, StackFrame *frame = m_exe_ctx.GetFramePtr(); - // Either Swift was explicitly specified, or the frame is Swift. + // Either the language was explicitly specified, or we check the frame. lldb::LanguageType language = m_expr_options.language; if (language == lldb::eLanguageTypeUnknown && frame) language = frame->GuessLanguage().AsLanguageType(); From 347a02b408567ba15fdc68646129c1f5de97ab7e Mon Sep 17 00:00:00 2001 From: Seth Pellegrino Date: Mon, 29 Apr 2024 13:41:57 -0700 Subject: [PATCH 14/22] [clang][NFC] Repair tests for __builtin_convertvector on big-endian Previously, the macro expansion to be explicit for the test cases had unintentionally forced the tests to always run in little-endian mode. This change restores the tests' endianness switch, and ensures that the tests always run on both a little- and big-endian platform. --- clang/test/Sema/constant_builtins_vector.cpp | 74 ++++++++++---------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp index 68620d436fc43e..ddb78696ce624d 100644 --- a/clang/test/Sema/constant_builtins_vector.cpp +++ b/clang/test/Sema/constant_builtins_vector.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension %s +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64-unknown-linux %s +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64le-unknown-linux %s #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define LITTLE_END 1 @@ -102,13 +104,13 @@ static_assert(__builtin_bit_cast( __builtin_shufflevector(from_vector4double_to_vector4char_var, from_vector4double_to_vector4char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector4double_to_vector4short_var, from_vector4double_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4float_to_vector4double_var = __builtin_convertvector((vector4float){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4float_to_vector4float_var = @@ -131,13 +133,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector4float_to_vector4char_var, from_vector4float_to_vector4char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector4float_to_vector4short_var, from_vector4float_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4long_to_vector4double_var = __builtin_convertvector((vector4long){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4long_to_vector4float_var = @@ -160,13 +162,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector4long_to_vector4char_var, from_vector4long_to_vector4char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector4long_to_vector4short_var, from_vector4long_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4int_to_vector4double_var = __builtin_convertvector((vector4int){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4int_to_vector4float_var = @@ -189,13 +191,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector4int_to_vector4char_var, from_vector4int_to_vector4char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector4int_to_vector4short_var, from_vector4int_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4short_to_vector4double_var = __builtin_convertvector((vector4short){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4short_to_vector4float_var = @@ -218,13 +220,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector4short_to_vector4char_var, from_vector4short_to_vector4char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector4short_to_vector4short_var, from_vector4short_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4char_to_vector4double_var = __builtin_convertvector((vector4char){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4char_to_vector4float_var = @@ -247,13 +249,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector4char_to_vector4char_var, from_vector4char_to_vector4char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector4char_to_vector4short_var, from_vector4char_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4BitInt8_to_vector4double_var = __builtin_convertvector((vector4BitInt8){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4BitInt8_to_vector4float_var = @@ -277,13 +279,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector4BitInt8_to_vector4char_var, from_vector4BitInt8_to_vector4char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector4BitInt8_to_vector4short_var, from_vector4BitInt8_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4BitInt32_to_vector4double_var = __builtin_convertvector((vector4BitInt32){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4BitInt32_to_vector4float_var = @@ -307,13 +309,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector4BitInt32_to_vector4char_var, from_vector4BitInt32_to_vector4char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector4BitInt32_to_vector4short_var, from_vector4BitInt32_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector4double from_vector4BitInt128_to_vector4double_var = __builtin_convertvector((vector4BitInt128){0, 1, 2, 3}, vector4double); constexpr vector4float from_vector4BitInt128_to_vector4float_var = @@ -337,13 +339,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector4BitInt128_to_vector4char_var, from_vector4BitInt128_to_vector4char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector4BitInt128_to_vector4short_var, from_vector4BitInt128_to_vector4short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); ; constexpr vector8double from_vector8double_to_vector8double_var = __builtin_convertvector((vector8double){0, 1, 2, 3, 4, 5, 6, 7}, @@ -377,13 +379,13 @@ static_assert(__builtin_bit_cast( __builtin_shufflevector(from_vector8double_to_vector8char_var, from_vector8double_to_vector8char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector8double_to_vector8short_var, from_vector8double_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8float_to_vector8double_var = __builtin_convertvector((vector8float){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -414,13 +416,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector8float_to_vector8char_var, from_vector8float_to_vector8char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector8float_to_vector8short_var, from_vector8float_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8long_to_vector8double_var = __builtin_convertvector((vector8long){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -449,13 +451,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector8long_to_vector8char_var, from_vector8long_to_vector8char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector8long_to_vector8short_var, from_vector8long_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8int_to_vector8double_var = __builtin_convertvector((vector8int){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -482,13 +484,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector8int_to_vector8char_var, from_vector8int_to_vector8char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector8int_to_vector8short_var, from_vector8int_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8short_to_vector8double_var = __builtin_convertvector((vector8short){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -519,13 +521,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector8short_to_vector8char_var, from_vector8short_to_vector8char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector8short_to_vector8short_var, from_vector8short_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8char_to_vector8double_var = __builtin_convertvector((vector8char){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -554,13 +556,13 @@ static_assert(__builtin_bit_cast(unsigned, __builtin_shufflevector( from_vector8char_to_vector8char_var, from_vector8char_to_vector8char_var, 0, 1, - 2, 3)) == (1 ? 0x03020100 : 0x00010203)); + 2, 3)) == (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast( unsigned long long, __builtin_shufflevector(from_vector8char_to_vector8short_var, from_vector8char_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8BitInt8_to_vector8double_var = __builtin_convertvector((vector8BitInt8){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -593,13 +595,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector8BitInt8_to_vector8char_var, from_vector8BitInt8_to_vector8char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector8BitInt8_to_vector8short_var, from_vector8BitInt8_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8BitInt32_to_vector8double_var = __builtin_convertvector((vector8BitInt32){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -632,13 +634,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector8BitInt32_to_vector8char_var, from_vector8BitInt32_to_vector8char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector8BitInt32_to_vector8short_var, from_vector8BitInt32_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); constexpr vector8double from_vector8BitInt128_to_vector8double_var = __builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7}, vector8double); @@ -671,13 +673,13 @@ static_assert(__builtin_bit_cast(unsigned, from_vector8BitInt128_to_vector8char_var, from_vector8BitInt128_to_vector8char_var, 0, 1, 2, 3)) == - (1 ? 0x03020100 : 0x00010203)); + (LITTLE_END ? 0x03020100 : 0x00010203)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_shufflevector( from_vector8BitInt128_to_vector8short_var, from_vector8BitInt128_to_vector8short_var, 0, 1, 2, 3)) == - (1 ? 0x0003000200010000 : 0x0000000100020003)); + (LITTLE_END ? 0x0003000200010000 : 0x0000000100020003)); ; #undef CHECK_ALL_COMBINATIONS #undef CHECK_TO_ALL_TYPES From 6f390ea60d987f6e1e027d1c72982c2eb7896005 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 29 Apr 2024 13:47:09 -0700 Subject: [PATCH 15/22] [Lex] Fix clang -Wparentheses after #89923 --- clang/lib/Lex/Pragma.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index ced407355e0015..10f0ab7180e62d 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1444,7 +1444,8 @@ struct PragmaWarningHandler : public PragmaHandler { .Case("once", PPCallbacks::PWS_Once) .Case("suppress", PPCallbacks::PWS_Suppress) .Default(-1); - if (SpecifierValid = (SpecifierInt != -1)) + SpecifierValid = SpecifierInt != -1; + if (SpecifierValid) Specifier = static_cast(SpecifierInt); From 5bbf1ea8f18d1f99637b7b8bf6b985c186c808f6 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 29 Apr 2024 14:23:08 -0700 Subject: [PATCH 16/22] [WebAssembly] Enable multivalue and reference-types in generic CPU config (#80923) This enables multivalue and reference-types in `-mcpu=generic` configuration. These proposals have been standardized and supported in all major browsers for several years at this point: https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md --- clang/docs/ReleaseNotes.rst | 5 +++++ clang/lib/Basic/Targets/WebAssembly.cpp | 20 ++++++++++++------- .../test/Preprocessor/wasm-target-features.c | 6 +++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 55e1670b7e2fa0..676f38a8e94c81 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -718,6 +718,11 @@ AIX Support WebAssembly Support ^^^^^^^^^^^^^^^^^^^ +The -mcpu=generic configuration now enables multivalue and reference-types.These +proposals are standardized and available in all major engines. Enabling +multivalue here only enables the language feature but does not turn on the +multivalue ABI (this enables non-ABI uses of multivalue, like exnref). + AVR Support ^^^^^^^^^^^ diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 3d76411f890a86..0db7b668d8a0ac 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -148,20 +148,26 @@ void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap &Features, bool WebAssemblyTargetInfo::initFeatureMap( llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector &FeaturesVec) const { - if (CPU == "bleeding-edge") { + auto addGenericFeatures = [&]() { + Features["multivalue"] = true; + Features["mutable-globals"] = true; + Features["reference-types"] = true; + Features["sign-ext"] = true; + }; + auto addBleedingEdgeFeatures = [&]() { + addGenericFeatures(); Features["atomics"] = true; Features["bulk-memory"] = true; Features["multimemory"] = true; - Features["mutable-globals"] = true; Features["nontrapping-fptoint"] = true; - Features["reference-types"] = true; - Features["sign-ext"] = true; Features["tail-call"] = true; Features["half-precision"] = true; setSIMDLevel(Features, SIMD128, true); - } else if (CPU == "generic") { - Features["mutable-globals"] = true; - Features["sign-ext"] = true; + }; + if (CPU == "generic") { + addGenericFeatures(); + } else if (CPU == "bleeding-edge") { + addBleedingEdgeFeatures(); } return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); diff --git a/clang/test/Preprocessor/wasm-target-features.c b/clang/test/Preprocessor/wasm-target-features.c index 32e24ad1b71656..19bd918543dfea 100644 --- a/clang/test/Preprocessor/wasm-target-features.c +++ b/clang/test/Preprocessor/wasm-target-features.c @@ -152,7 +152,9 @@ // RUN: -target wasm64-unknown-unknown -mcpu=generic \ // RUN: | FileCheck %s -check-prefix=GENERIC-INCLUDE // +// GENERIC-INCLUDE-DAG: #define __wasm_multivalue__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_mutable_globals__ 1{{$}} +// GENERIC-INCLUDE-DAG: #define __wasm_reference_types__ 1{{$}} // GENERIC-INCLUDE-DAG: #define __wasm_sign_ext__ 1{{$}} // // RUN: %clang -E -dM %s -o - 2>&1 \ @@ -167,9 +169,7 @@ // GENERIC-NOT: #define __wasm_exception_handling__ 1{{$}} // GENERIC-NOT: #define __wasm_extended_const__ 1{{$}} // GENERIC-NOT: #define __wasm_multimemory__ 1{{$}} -// GENERIC-NOT: #define __wasm_multivalue__ 1{{$}} // GENERIC-NOT: #define __wasm_nontrapping_fptoint__ 1{{$}} -// GENERIC-NOT: #define __wasm_reference_types__ 1{{$}} // GENERIC-NOT: #define __wasm_relaxed_simd__ 1{{$}} // GENERIC-NOT: #define __wasm_simd128__ 1{{$}} // GENERIC-NOT: #define __wasm_tail_call__ 1{{$}} @@ -184,6 +184,7 @@ // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_atomics__ 1{{$}} // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_bulk_memory__ 1{{$}} // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_multimemory__ 1{{$}} +// BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_multivalue__ 1{{$}} // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_mutable_globals__ 1{{$}} // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_nontrapping_fptoint__ 1{{$}} // BLEEDING-EDGE-INCLUDE-DAG: #define __wasm_reference_types__ 1{{$}} @@ -200,7 +201,6 @@ // // BLEEDING-EDGE-NOT: #define __wasm_exception_handling__ 1{{$}} // BLEEDING-EDGE-NOT: #define __wasm_extended_const__ 1{{$}} -// BLEEDING-EDGE-NOT: #define __wasm_multivalue__ 1{{$}} // BLEEDING-EDGE-NOT: #define __wasm_relaxed_simd__ 1{{$}} // RUN: %clang -E -dM %s -o - 2>&1 \ From 3a0d894fafddace75f03fa7df25022cadbe2dffc Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Mon, 29 Apr 2024 14:44:04 -0700 Subject: [PATCH 17/22] [BOLT] Add support for BOLT-reserved space in a binary (#90300) Allow the user to allocate space in a binary that could be used by BOLT for allocating new sections. The reservation is specified by two special symbols recognizable by BOLT: __bolt_reserved_{start,end}. The reserved space will be useful for optimizing the Linux kernel where we cannot allocate a new executable segment. However, the support is not limited to kernel binaries as some user-space application may find it useful too. --- bolt/include/bolt/Rewrite/RewriteInstance.h | 4 + bolt/lib/Rewrite/RewriteInstance.cpp | 88 +++++++++++++++------ 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index d37e6f5ed8595b..41a92e7ba01e84 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -422,6 +422,10 @@ class RewriteInstance { /// Section name used for extra BOLT code in addition to .text. static StringRef getBOLTTextSectionName() { return ".bolt.text"; } + /// Symbol markers for BOLT reserved area. + static StringRef getBOLTReservedStart() { return "__bolt_reserved_start"; } + static StringRef getBOLTReservedEnd() { return "__bolt_reserved_end"; } + /// Common section names. static StringRef getEHFrameSectionName() { return ".eh_frame"; } static StringRef getEHFrameHdrSectionName() { return ".eh_frame_hdr"; } diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 329649c1ca67c5..1c5ce5d0a6cd0b 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -1063,6 +1063,11 @@ void RewriteInstance::discoverFileObjects() { continue; } + if (SymName == getBOLTReservedStart() || SymName == getBOLTReservedEnd()) { + registerName(SymbolSize); + continue; + } + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: considering symbol " << UniqueName << " for function\n"); @@ -3594,6 +3599,26 @@ void RewriteInstance::updateMetadata() { void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) { BC->deregisterUnusedSections(); + // Check if the input has a space reserved for BOLT. + BinaryData *StartBD = BC->getBinaryDataByName(getBOLTReservedStart()); + BinaryData *EndBD = BC->getBinaryDataByName(getBOLTReservedEnd()); + if (!StartBD != !EndBD) { + BC->errs() << "BOLT-ERROR: one of the symbols is missing from the binary: " + << getBOLTReservedStart() << ", " << getBOLTReservedEnd() + << '\n'; + exit(1); + } + + if (StartBD) { + PHDRTableOffset = 0; + PHDRTableAddress = 0; + NewTextSegmentAddress = 0; + NewTextSegmentOffset = 0; + NextAvailableAddress = StartBD->getAddress(); + BC->outs() + << "BOLT-INFO: using reserved space for allocating new sections\n"; + } + // If no new .eh_frame was written, remove relocated original .eh_frame. BinarySection *RelocatedEHFrameSection = getSection(".relocated" + getEHFrameSectionName()); @@ -3613,6 +3638,18 @@ void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) { // Map the rest of the sections. mapAllocatableSections(MapSection); + + if (StartBD) { + const uint64_t ReservedSpace = EndBD->getAddress() - StartBD->getAddress(); + const uint64_t AllocatedSize = NextAvailableAddress - StartBD->getAddress(); + if (ReservedSpace < AllocatedSize) { + BC->errs() << "BOLT-ERROR: reserved space (" << ReservedSpace << " byte" + << (ReservedSpace == 1 ? "" : "s") + << ") is smaller than required for new allocations (" + << AllocatedSize << " bytes)\n"; + exit(1); + } + } } std::vector RewriteInstance::getCodeSections() { @@ -3854,7 +3891,7 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { // Add the new text section aggregating all existing code sections. // This is pseudo-section that serves a purpose of creating a corresponding // entry in section header table. - int64_t NewTextSectionSize = + const uint64_t NewTextSectionSize = NextAvailableAddress - NewTextSectionStartAddress; if (NewTextSectionSize) { const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, @@ -3937,7 +3974,7 @@ void RewriteInstance::mapAllocatableSections( if (PHDRTableAddress) { // Segment size includes the size of the PHDR area. NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress; - } else { + } else if (NewTextSegmentAddress) { // Existing PHDR table would be updated. NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress; } @@ -3976,7 +4013,7 @@ void RewriteInstance::patchELFPHDRTable() { assert(!PHDRTableAddress && "unexpected address for program header table"); PHDRTableOffset = Obj.getHeader().e_phoff; if (NewWritableSegmentSize) { - BC->errs() << "Unable to add writable segment with UseGnuStack option\n"; + BC->errs() << "BOLT-ERROR: unable to add writable segment\n"; exit(1); } } @@ -3986,7 +4023,7 @@ void RewriteInstance::patchELFPHDRTable() { if (!NewWritableSegmentSize) { if (PHDRTableAddress) NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress; - else + else if (NewTextSegmentAddress) NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress; } else { NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress; @@ -4020,8 +4057,10 @@ void RewriteInstance::patchELFPHDRTable() { }; auto writeNewSegmentPhdrs = [&]() { - ELF64LE::Phdr NewTextPhdr = createNewTextPhdr(); - OS.write(reinterpret_cast(&NewTextPhdr), sizeof(NewTextPhdr)); + if (PHDRTableAddress || NewTextSegmentSize) { + ELF64LE::Phdr NewPhdr = createNewTextPhdr(); + OS.write(reinterpret_cast(&NewPhdr), sizeof(NewPhdr)); + } if (NewWritableSegmentSize) { ELF64LEPhdrTy NewPhdr; @@ -4119,9 +4158,8 @@ void RewriteInstance::rewriteNoteSections() { const ELFFile &Obj = ELF64LEFile->getELFFile(); raw_fd_ostream &OS = Out->os(); - uint64_t NextAvailableOffset = getFileOffsetForAddress(NextAvailableAddress); - assert(NextAvailableOffset >= FirstNonAllocatableOffset && - "next available offset calculation failure"); + uint64_t NextAvailableOffset = std::max( + getFileOffsetForAddress(NextAvailableAddress), FirstNonAllocatableOffset); OS.seek(NextAvailableOffset); // Copy over non-allocatable section contents and update file offsets. @@ -4860,7 +4898,7 @@ void RewriteInstance::updateELFSymbolTable( ++NumHotDataSymsUpdated; } - if (*SymbolName == "_end") + if (*SymbolName == "_end" && NextAvailableAddress > Symbol.st_value) updateSymbolValue(*SymbolName, NextAvailableAddress); if (IsDynSym) @@ -4974,13 +5012,6 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile *File) { std::vector NewSectionIndex; getOutputSections(File, NewSectionIndex); - // Set pointer at the end of the output file, so we can pwrite old symbol - // tables if we need to. - uint64_t NextAvailableOffset = getFileOffsetForAddress(NextAvailableAddress); - assert(NextAvailableOffset >= FirstNonAllocatableOffset && - "next available offset calculation failure"); - Out->os().seek(NextAvailableOffset); - // Update dynamic symbol table. const ELFShdrTy *DynSymSection = nullptr; for (const ELFShdrTy &Section : cantFail(Obj.sections())) { @@ -4992,6 +5023,10 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile *File) { assert((DynSymSection || BC->IsStaticExecutable) && "dynamic symbol table expected"); if (DynSymSection) { + // Set pointer to the end of the section, so we can use pwrite to update + // the dynamic symbol table. + Out->os().seek(DynSymSection->sh_offset + DynSymSection->sh_size); + updateELFSymbolTable( File, /*IsDynSym=*/true, @@ -5545,10 +5580,10 @@ void RewriteInstance::rewriteFile() { auto Streamer = BC->createStreamer(OS); // Make sure output stream has enough reserved space, otherwise // pwrite() will fail. - uint64_t Offset = OS.seek(getFileOffsetForAddress(NextAvailableAddress)); - (void)Offset; - assert(Offset == getFileOffsetForAddress(NextAvailableAddress) && - "error resizing output file"); + uint64_t Offset = std::max(getFileOffsetForAddress(NextAvailableAddress), + FirstNonAllocatableOffset); + Offset = OS.seek(Offset); + assert((Offset != (uint64_t)-1) && "Error resizing output file"); // Overwrite functions with fixed output address. This is mostly used by // non-relocation mode, with one exception: injected functions are covered @@ -5780,7 +5815,7 @@ void RewriteInstance::writeEHFrameHeader() { std::vector NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader( RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses); - assert(Out->os().tell() == EHFrameHdrFileOffset && "offset mismatch"); + Out->os().seek(EHFrameHdrFileOffset); Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size()); const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, @@ -5800,6 +5835,15 @@ void RewriteInstance::writeEHFrameHeader() { NextAvailableAddress += EHFrameHdrSec.getOutputSize(); + if (const BinaryData *ReservedEnd = + BC->getBinaryDataByName(getBOLTReservedEnd())) { + if (NextAvailableAddress > ReservedEnd->getAddress()) { + BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName() + << " into reserved space\n"; + exit(1); + } + } + // Merge new .eh_frame with the relocated original so that gdb can locate all // FDEs. if (RelocatedEHFrameSection) { From 869ffcf3f6ca74c8a0ec6eb250d45e6ea0680c81 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 29 Apr 2024 14:54:10 -0700 Subject: [PATCH 18/22] [CodeGen][i386] Move -mregparm storage earlier and fix Runtime calls (#89707) When building the Linux kernel for i386, the -mregparm=3 option is enabled. Crashes were observed in the sanitizer handler functions, and the problem was found to be mismatched calling convention. As was fixed in commit c167c0a4dcdb ("[BuildLibCalls] infer inreg param attrs from NumRegisterParameters"), call arguments need to be marked as "in register" when -mregparm is set. Use the same helper developed there to update the function arguments. Since CreateRuntimeFunction() is actually part of CodeGenModule, storage of the -mregparm value is also moved to the constructor, as doing this in Release() is too late. Fixes: https://github.com/llvm/llvm-project/issues/89670 --- clang/lib/CodeGen/CodeGenModule.cpp | 15 ++++++++++----- clang/test/CodeGen/regparm-flag.c | 18 ++++++++++++++++++ .../llvm/Transforms/Utils/BuildLibCalls.h | 7 +++++++ llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 2 +- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d085e735ecb443..c8898ce196c1ed 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -73,6 +73,7 @@ #include "llvm/TargetParser/RISCVISAInfo.h" #include "llvm/TargetParser/Triple.h" #include "llvm/TargetParser/X86TargetParser.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" #include using namespace clang; @@ -442,6 +443,11 @@ CodeGenModule::CodeGenModule(ASTContext &C, } ModuleNameHash = llvm::getUniqueInternalLinkagePostfix(Path); } + + // Record mregparm value now so it is visible through all of codegen. + if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) + getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", + CodeGenOpts.NumRegisterParameters); } CodeGenModule::~CodeGenModule() {} @@ -980,11 +986,6 @@ void CodeGenModule::Release() { NMD->addOperand(MD); } - // Record mregparm value now so it is visible through rest of codegen. - if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) - getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", - CodeGenOpts.NumRegisterParameters); - if (CodeGenOpts.DwarfVersion) { getModule().addModuleFlag(llvm::Module::Max, "Dwarf Version", CodeGenOpts.DwarfVersion); @@ -4781,6 +4782,10 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, } } setDSOLocal(F); + // FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead + // of trying to approximate the attributes using the LLVM function + // signature. This requires revising the API of CreateRuntimeFunction(). + markRegisterParameterAttributes(F); } } diff --git a/clang/test/CodeGen/regparm-flag.c b/clang/test/CodeGen/regparm-flag.c index c35b53cd4e1990..d888c1e344c03b 100644 --- a/clang/test/CodeGen/regparm-flag.c +++ b/clang/test/CodeGen/regparm-flag.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 4 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME0 +// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 1 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME1 +// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 2 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME2 +// RUN: %clang_cc1 -triple i386-unknown-unknown -mregparm 3 -fsanitize=array-bounds %s -emit-llvm -o - | FileCheck %s --check-prefix=RUNTIME2 void f1(int a, int b, int c, int d, int e, int f, int g, int h); @@ -13,7 +17,21 @@ void f0(void) { f2(1, 2); } +struct has_array { + int a; + int b[4]; + int c; +}; + +int access(struct has_array *p, int index) +{ + return p->b[index]; +} + // CHECK: declare void @f1(i32 inreg noundef, i32 inreg noundef, i32 inreg noundef, i32 inreg noundef, // CHECK: i32 noundef, i32 noundef, i32 noundef, i32 noundef) // CHECK: declare void @f2(i32 noundef, i32 noundef) +// RUNTIME0: declare void @__ubsan_handle_out_of_bounds_abort(ptr, i32) +// RUNTIME1: declare void @__ubsan_handle_out_of_bounds_abort(ptr inreg, i32) +// RUNTIME2: declare void @__ubsan_handle_out_of_bounds_abort(ptr inreg, i32 inreg) diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h index 9ebb9500777421..429d6a2e05236f 100644 --- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -62,6 +62,13 @@ namespace llvm { LibFunc TheLibFunc, AttributeList AttributeList, FunctionType *Invalid, ArgsTy... Args) = delete; + // Handle -mregparm for the given function. + // Note that this function is a rough approximation that only works for simple + // function signatures; it does not apply other relevant attributes for + // function signatures, including sign/zero-extension for arguments and return + // values. + void markRegisterParameterAttributes(Function *F); + /// Check whether the library function is available on target and also that /// it in the current Module is a Function with the right type. bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index ed0ed345435c45..e97506b4bbd95d 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1255,7 +1255,7 @@ static void setRetExtAttr(Function &F, } // Modeled after X86TargetLowering::markLibCallAttributes. -static void markRegisterParameterAttributes(Function *F) { +void llvm::markRegisterParameterAttributes(Function *F) { if (!F->arg_size() || F->isVarArg()) return; From 028546cce2316a1074aa27001450295d856e1fdc Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 29 Apr 2024 15:08:35 -0700 Subject: [PATCH 19/22] Simplify condition (NFC) --- lldb/source/Expression/UserExpression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index 84578c7f9ad272..5658426c88912d 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -242,7 +242,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, // If the language was not specified in the expression command, set it to the // language in the target's properties if specified, else default to the // langage for the frame. - if (!language.name) { + if (!language) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) From 1f44a0b1ff2daebe10b9916da228f7c0ba66827c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 29 Apr 2024 22:08:05 +0000 Subject: [PATCH 20/22] Make minor improvements to the creduce wrapper script Use shlex.quote instead of pipes.quote. We don't need to support Python 2.7 anymore. Remove -fcolor-diagnostics first, because that can sometimes interfere with the interestingness test. --- clang/utils/creduce-clang-crash.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/utils/creduce-clang-crash.py b/clang/utils/creduce-clang-crash.py index 27361bb8850581..4d0c8224d8b499 100755 --- a/clang/utils/creduce-clang-crash.py +++ b/clang/utils/creduce-clang-crash.py @@ -15,7 +15,6 @@ import stat import sys import subprocess -import pipes import shlex import tempfile import shutil @@ -61,7 +60,7 @@ def check_cmd(cmd_name, cmd_dir, cmd_path=None): def quote_cmd(cmd): - return " ".join(pipes.quote(arg) for arg in cmd) + return " ".join(shlex.quote(arg) for arg in cmd) def write_to_script(text, filename): @@ -220,7 +219,7 @@ def write_interestingness_test(self): ) for msg in self.expected_output: - output += "grep -F %s t.log || exit 1\n" % pipes.quote(msg) + output += "grep -F %s t.log || exit 1\n" % shlex.quote(msg) write_to_script(output, self.testfile) self.check_interestingness() @@ -318,9 +317,17 @@ def simplify_clang_args(self): interestingness test takes to run. """ print("\nSimplifying the clang command...") + new_args = self.clang_args + + # Remove the color diagnostics flag to make it easier to match error + # text. + new_args = self.try_remove_args( + new_args, + msg="Removed -fcolor-diagnostics", + opts_equal=["-fcolor-diagnostics"], + ) # Remove some clang arguments to speed up the interestingness test - new_args = self.clang_args new_args = self.try_remove_args( new_args, msg="Removed debug info options", From d47c4984e9ea80ffd01efb084df9485d314d1d14 Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Mon, 29 Apr 2024 18:27:52 -0400 Subject: [PATCH 21/22] [AMDGPU][ISel] Add more trunc store actions regarding bf16 (#90493) --- llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 6 + ...bf16.ll => fp_trunc_store_fp32_to_bf16.ll} | 55 ++ .../AMDGPU/fp_trunc_store_fp64_to_bf16.ll | 663 ++++++++++++++++++ 3 files changed, 724 insertions(+) rename llvm/test/CodeGen/AMDGPU/{fp_trunc_store_bf16.ll => fp_trunc_store_fp32_to_bf16.ll} (89%) create mode 100644 llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp64_to_bf16.ll diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 7f4a2437f62eb4..3124fb23fb0be7 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -315,6 +315,7 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, setTruncStoreAction(MVT::f32, MVT::f16, Expand); setTruncStoreAction(MVT::v2f32, MVT::v2bf16, Expand); setTruncStoreAction(MVT::v2f32, MVT::v2f16, Expand); + setTruncStoreAction(MVT::v3f32, MVT::v3bf16, Expand); setTruncStoreAction(MVT::v3f32, MVT::v3f16, Expand); setTruncStoreAction(MVT::v4f32, MVT::v4bf16, Expand); setTruncStoreAction(MVT::v4f32, MVT::v4f16, Expand); @@ -330,6 +331,7 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, setTruncStoreAction(MVT::f64, MVT::f32, Expand); setTruncStoreAction(MVT::v2f64, MVT::v2f32, Expand); + setTruncStoreAction(MVT::v2f64, MVT::v2bf16, Expand); setTruncStoreAction(MVT::v2f64, MVT::v2f16, Expand); setTruncStoreAction(MVT::v3i32, MVT::v3i8, Expand); @@ -339,17 +341,21 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, setTruncStoreAction(MVT::v3i64, MVT::v3i8, Expand); setTruncStoreAction(MVT::v3i64, MVT::v3i1, Expand); setTruncStoreAction(MVT::v3f64, MVT::v3f32, Expand); + setTruncStoreAction(MVT::v3f64, MVT::v3bf16, Expand); setTruncStoreAction(MVT::v3f64, MVT::v3f16, Expand); setTruncStoreAction(MVT::v4i64, MVT::v4i32, Expand); setTruncStoreAction(MVT::v4i64, MVT::v4i16, Expand); setTruncStoreAction(MVT::v4f64, MVT::v4f32, Expand); + setTruncStoreAction(MVT::v4f64, MVT::v4bf16, Expand); setTruncStoreAction(MVT::v4f64, MVT::v4f16, Expand); setTruncStoreAction(MVT::v8f64, MVT::v8f32, Expand); + setTruncStoreAction(MVT::v8f64, MVT::v8bf16, Expand); setTruncStoreAction(MVT::v8f64, MVT::v8f16, Expand); setTruncStoreAction(MVT::v16f64, MVT::v16f32, Expand); + setTruncStoreAction(MVT::v16f64, MVT::v16bf16, Expand); setTruncStoreAction(MVT::v16f64, MVT::v16f16, Expand); setTruncStoreAction(MVT::v16i64, MVT::v16i16, Expand); setTruncStoreAction(MVT::v16i64, MVT::v16i16, Expand); diff --git a/llvm/test/CodeGen/AMDGPU/fp_trunc_store_bf16.ll b/llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp32_to_bf16.ll similarity index 89% rename from llvm/test/CodeGen/AMDGPU/fp_trunc_store_bf16.ll rename to llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp32_to_bf16.ll index 5aaff773689f96..2ccc0337b8aeba 100644 --- a/llvm/test/CodeGen/AMDGPU/fp_trunc_store_bf16.ll +++ b/llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp32_to_bf16.ll @@ -1,6 +1,27 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a %s -o - | FileCheck %s +define void @scalar(float %num, ptr addrspace(1) %p) { +; CHECK-LABEL: scalar: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v3, v2 +; CHECK-NEXT: v_mov_b32_e32 v2, v1 +; CHECK-NEXT: v_bfe_u32 v1, v0, 16, 1 +; CHECK-NEXT: s_movk_i32 s4, 0x7fff +; CHECK-NEXT: v_add3_u32 v1, v1, v0, s4 +; CHECK-NEXT: v_or_b32_e32 v4, 0x400000, v0 +; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v4, vcc +; CHECK-NEXT: global_store_short_d16_hi v[2:3], v0, off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc float %num to bfloat + store bfloat %conv, ptr addrspace(1) %p, align 8 + ret void +} + define void @v2(<2 x float> %num, ptr addrspace(1) %p) { ; CHECK-LABEL: v2: ; CHECK: ; %bb.0: ; %entry @@ -27,6 +48,40 @@ entry: ret void } +define void @v3(<3 x float> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v3: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v5, v4 +; CHECK-NEXT: v_mov_b32_e32 v4, v3 +; CHECK-NEXT: v_bfe_u32 v3, v0, 16, 1 +; CHECK-NEXT: s_movk_i32 s4, 0x7fff +; CHECK-NEXT: v_add3_u32 v3, v3, v0, s4 +; CHECK-NEXT: v_or_b32_e32 v6, 0x400000, v0 +; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; CHECK-NEXT: v_cndmask_b32_e32 v0, v3, v6, vcc +; CHECK-NEXT: v_bfe_u32 v3, v1, 16, 1 +; CHECK-NEXT: v_add3_u32 v3, v3, v1, s4 +; CHECK-NEXT: v_or_b32_e32 v6, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v1, v1 +; CHECK-NEXT: v_cndmask_b32_e32 v1, v3, v6, vcc +; CHECK-NEXT: s_mov_b32 s5, 0x7060302 +; CHECK-NEXT: v_perm_b32 v0, v1, v0, s5 +; CHECK-NEXT: v_bfe_u32 v1, v2, 16, 1 +; CHECK-NEXT: v_add3_u32 v1, v1, v2, s4 +; CHECK-NEXT: v_or_b32_e32 v3, 0x400000, v2 +; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v2, v2 +; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc +; CHECK-NEXT: global_store_short_d16_hi v[4:5], v1, off offset:4 +; CHECK-NEXT: global_store_dword v[4:5], v0, off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <3 x float> %num to <3 x bfloat> + store <3 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} + define void @v4(<4 x float> %num, ptr addrspace(1) %p) { ; CHECK-LABEL: v4: ; CHECK: ; %bb.0: ; %entry diff --git a/llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp64_to_bf16.ll b/llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp64_to_bf16.ll new file mode 100644 index 00000000000000..d824763c22e27a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/fp_trunc_store_fp64_to_bf16.ll @@ -0,0 +1,663 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a %s -o - | FileCheck %s + +define void @scalar(double %num, ptr addrspace(1) %p) { +; CHECK-LABEL: scalar: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v6, |v[0:1]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; CHECK-NEXT: v_and_b32_e32 v7, 1, v6 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v4, v6, v4 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; CHECK-NEXT: s_brev_b32 s4, 1 +; CHECK-NEXT: v_and_or_b32 v5, v1, s4, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: s_movk_i32 s4, 0x7fff +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s4 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v5, vcc +; CHECK-NEXT: global_store_short_d16_hi v[2:3], v0, off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc double %num to bfloat + store bfloat %conv, ptr addrspace(1) %p, align 8 + ret void +} + +define void @v2(<2 x double> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v2: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v8, |v[0:1]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[6:7], v8 +; CHECK-NEXT: v_and_b32_e32 v9, 1, v8 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[0:1]|, v[6:7] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[0:1]|, v[6:7] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v9 +; CHECK-NEXT: v_cndmask_b32_e64 v6, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v6, v8, v6 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v8, vcc +; CHECK-NEXT: s_brev_b32 s8, 1 +; CHECK-NEXT: v_and_or_b32 v7, v1, s8, v6 +; CHECK-NEXT: v_bfe_u32 v6, v6, 16, 1 +; CHECK-NEXT: s_movk_i32 s9, 0x7fff +; CHECK-NEXT: v_add3_u32 v6, v6, v7, s9 +; CHECK-NEXT: v_or_b32_e32 v7, 0x400000, v7 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v7, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v7, |v[2:3]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v7 +; CHECK-NEXT: v_and_b32_e32 v8, 1, v7 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v8 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v0, v7, v0 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v7, vcc +; CHECK-NEXT: v_and_or_b32 v1, v3, s8, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s9 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: s_mov_b32 s4, 0x7060302 +; CHECK-NEXT: v_perm_b32 v0, v0, v6, s4 +; CHECK-NEXT: global_store_dword v[4:5], v0, off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <2 x double> %num to <2 x bfloat> + store <2 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} + +define void @v3(<3 x double> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v3: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v10, |v[0:1]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[8:9], v10 +; CHECK-NEXT: v_and_b32_e32 v11, 1, v10 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[0:1]|, v[8:9] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[0:1]|, v[8:9] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v11 +; CHECK-NEXT: v_cndmask_b32_e64 v8, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v8, v10, v8 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; CHECK-NEXT: s_brev_b32 s8, 1 +; CHECK-NEXT: v_and_or_b32 v9, v1, s8, v8 +; CHECK-NEXT: v_bfe_u32 v8, v8, 16, 1 +; CHECK-NEXT: s_movk_i32 s9, 0x7fff +; CHECK-NEXT: v_add3_u32 v8, v8, v9, s9 +; CHECK-NEXT: v_or_b32_e32 v9, 0x400000, v9 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v9, |v[2:3]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v9 +; CHECK-NEXT: v_and_b32_e32 v10, 1, v9 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v10 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v0, v9, v0 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v9, vcc +; CHECK-NEXT: v_and_or_b32 v1, v3, s8, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s9 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: s_mov_b32 s4, 0x7060302 +; CHECK-NEXT: v_cvt_f32_f64_e64 v3, |v[4:5]| +; CHECK-NEXT: v_perm_b32 v2, v0, v8, s4 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v3 +; CHECK-NEXT: v_and_b32_e32 v8, 1, v3 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[4:5]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[4:5]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v8 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v0, v3, v0 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v3, vcc +; CHECK-NEXT: v_and_or_b32 v1, v5, s8, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s9 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[4:5], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: global_store_short_d16_hi v[6:7], v0, off offset:4 +; CHECK-NEXT: global_store_dword v[6:7], v2, off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <3 x double> %num to <3 x bfloat> + store <3 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} + +define void @v4(<4 x double> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v4: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v12, |v[4:5]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[10:11], v12 +; CHECK-NEXT: v_and_b32_e32 v13, 1, v12 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[4:5]|, v[10:11] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[4:5]|, v[10:11] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v13 +; CHECK-NEXT: v_cndmask_b32_e64 v10, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v10, v12, v10 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v10, v10, v12, vcc +; CHECK-NEXT: s_brev_b32 s8, 1 +; CHECK-NEXT: v_and_or_b32 v11, v5, s8, v10 +; CHECK-NEXT: v_bfe_u32 v10, v10, 16, 1 +; CHECK-NEXT: s_movk_i32 s9, 0x7fff +; CHECK-NEXT: v_add3_u32 v10, v10, v11, s9 +; CHECK-NEXT: v_or_b32_e32 v11, 0x400000, v11 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[4:5], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e32 v10, v10, v11, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v11, |v[6:7]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v11 +; CHECK-NEXT: v_and_b32_e32 v12, 1, v11 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v12 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v4, v11, v4 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v11, vcc +; CHECK-NEXT: v_and_or_b32 v5, v7, s8, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s9 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[6:7], v[6:7] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: s_mov_b32 s10, 0x7060302 +; CHECK-NEXT: v_perm_b32 v5, v4, v10, s10 +; CHECK-NEXT: v_cvt_f32_f64_e64 v4, |v[0:1]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[6:7], v4 +; CHECK-NEXT: v_and_b32_e32 v10, 1, v4 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[0:1]|, v[6:7] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[0:1]|, v[6:7] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v10 +; CHECK-NEXT: v_cndmask_b32_e64 v6, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v6, v4, v6 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc +; CHECK-NEXT: v_and_or_b32 v6, v1, s8, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v6, s9 +; CHECK-NEXT: v_or_b32_e32 v6, 0x400000, v6 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v6, |v[2:3]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v6 +; CHECK-NEXT: v_and_b32_e32 v7, 1, v6 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v0, v6, v0 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc +; CHECK-NEXT: v_and_or_b32 v1, v3, s8, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s9 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_perm_b32 v4, v0, v4, s10 +; CHECK-NEXT: global_store_dwordx2 v[8:9], v[4:5], off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <4 x double> %num to <4 x bfloat> + store <4 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} + +define void @v8(<8 x double> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v8: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v20, |v[12:13]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[18:19], v20 +; CHECK-NEXT: v_and_b32_e32 v21, 1, v20 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[12:13]|, v[18:19] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[12:13]|, v[18:19] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v21 +; CHECK-NEXT: v_cndmask_b32_e64 v18, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v18, v20, v18 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v18, v18, v20, vcc +; CHECK-NEXT: s_brev_b32 s8, 1 +; CHECK-NEXT: v_and_or_b32 v19, v13, s8, v18 +; CHECK-NEXT: v_bfe_u32 v18, v18, 16, 1 +; CHECK-NEXT: s_movk_i32 s9, 0x7fff +; CHECK-NEXT: v_add3_u32 v18, v18, v19, s9 +; CHECK-NEXT: v_or_b32_e32 v19, 0x400000, v19 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[12:13], v[12:13] +; CHECK-NEXT: v_cndmask_b32_e32 v18, v18, v19, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v19, |v[14:15]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[12:13], v19 +; CHECK-NEXT: v_and_b32_e32 v20, 1, v19 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[14:15]|, v[12:13] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[14:15]|, v[12:13] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v20 +; CHECK-NEXT: v_cndmask_b32_e64 v12, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v12, v19, v12 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v19, vcc +; CHECK-NEXT: v_and_or_b32 v13, v15, s8, v12 +; CHECK-NEXT: v_bfe_u32 v12, v12, 16, 1 +; CHECK-NEXT: v_add3_u32 v12, v12, v13, s9 +; CHECK-NEXT: v_or_b32_e32 v13, 0x400000, v13 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[14:15], v[14:15] +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v13, vcc +; CHECK-NEXT: s_mov_b32 s10, 0x7060302 +; CHECK-NEXT: v_perm_b32 v13, v12, v18, s10 +; CHECK-NEXT: v_cvt_f32_f64_e64 v12, |v[8:9]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[14:15], v12 +; CHECK-NEXT: v_and_b32_e32 v18, 1, v12 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[8:9]|, v[14:15] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[8:9]|, v[14:15] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v18 +; CHECK-NEXT: v_cndmask_b32_e64 v14, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v14, v12, v14 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v12, v14, v12, vcc +; CHECK-NEXT: v_and_or_b32 v14, v9, s8, v12 +; CHECK-NEXT: v_bfe_u32 v12, v12, 16, 1 +; CHECK-NEXT: v_add3_u32 v12, v12, v14, s9 +; CHECK-NEXT: v_or_b32_e32 v14, 0x400000, v14 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[8:9], v[8:9] +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v14, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v14, |v[10:11]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[8:9], v14 +; CHECK-NEXT: v_and_b32_e32 v15, 1, v14 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[10:11]|, v[8:9] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[10:11]|, v[8:9] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v15 +; CHECK-NEXT: v_cndmask_b32_e64 v8, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v8, v14, v8 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v14, vcc +; CHECK-NEXT: v_and_or_b32 v9, v11, s8, v8 +; CHECK-NEXT: v_bfe_u32 v8, v8, 16, 1 +; CHECK-NEXT: v_add3_u32 v8, v8, v9, s9 +; CHECK-NEXT: v_or_b32_e32 v9, 0x400000, v9 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[10:11], v[10:11] +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v10, |v[4:5]| +; CHECK-NEXT: v_perm_b32 v12, v8, v12, s10 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[8:9], v10 +; CHECK-NEXT: v_and_b32_e32 v11, 1, v10 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[4:5]|, v[8:9] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[4:5]|, v[8:9] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v11 +; CHECK-NEXT: v_cndmask_b32_e64 v8, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v8, v10, v8 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; CHECK-NEXT: v_and_or_b32 v9, v5, s8, v8 +; CHECK-NEXT: v_bfe_u32 v8, v8, 16, 1 +; CHECK-NEXT: v_add3_u32 v8, v8, v9, s9 +; CHECK-NEXT: v_or_b32_e32 v9, 0x400000, v9 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[4:5], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v9, |v[6:7]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v9 +; CHECK-NEXT: v_and_b32_e32 v10, 1, v9 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v10 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v4, v9, v4 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; CHECK-NEXT: v_and_or_b32 v5, v7, s8, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s9 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[6:7], v[6:7] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v6, |v[0:1]| +; CHECK-NEXT: v_perm_b32 v11, v4, v8, s10 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; CHECK-NEXT: v_and_b32_e32 v7, 1, v6 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v4, v6, v4 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; CHECK-NEXT: v_and_or_b32 v5, v1, s8, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s9 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v5, |v[2:3]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v5 +; CHECK-NEXT: v_and_b32_e32 v6, 1, v5 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v6 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v0, v5, v0 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; CHECK-NEXT: v_and_or_b32 v1, v3, s8, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s9 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_perm_b32 v10, v0, v4, s10 +; CHECK-NEXT: global_store_dwordx4 v[16:17], v[10:13], off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <8 x double> %num to <8 x bfloat> + store <8 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} + +define void @v16(<16 x double> %num, ptr addrspace(1) %p) { +; CHECK-LABEL: v16: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:8 +; CHECK-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 +; CHECK-NEXT: buffer_load_dword v31, off, s[0:3], s32 +; CHECK-NEXT: v_cvt_f32_f64_e64 v36, |v[12:13]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[34:35], v36 +; CHECK-NEXT: v_and_b32_e32 v37, 1, v36 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[6:7], |v[12:13]|, v[34:35] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[4:5], |v[12:13]|, v[34:35] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v37 +; CHECK-NEXT: v_cndmask_b32_e64 v34, -1, 1, s[6:7] +; CHECK-NEXT: v_add_u32_e32 v34, v36, v34 +; CHECK-NEXT: s_or_b64 vcc, s[4:5], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v34, v34, v36, vcc +; CHECK-NEXT: s_brev_b32 s4, 1 +; CHECK-NEXT: v_and_or_b32 v35, v13, s4, v34 +; CHECK-NEXT: v_bfe_u32 v34, v34, 16, 1 +; CHECK-NEXT: s_movk_i32 s5, 0x7fff +; CHECK-NEXT: v_add3_u32 v34, v34, v35, s5 +; CHECK-NEXT: v_or_b32_e32 v35, 0x400000, v35 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[12:13], v[12:13] +; CHECK-NEXT: v_cndmask_b32_e32 v34, v34, v35, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v35, |v[14:15]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[12:13], v35 +; CHECK-NEXT: v_and_b32_e32 v36, 1, v35 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[8:9], |v[14:15]|, v[12:13] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[6:7], |v[14:15]|, v[12:13] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v36 +; CHECK-NEXT: v_cndmask_b32_e64 v12, -1, 1, s[8:9] +; CHECK-NEXT: v_add_u32_e32 v12, v35, v12 +; CHECK-NEXT: s_or_b64 vcc, s[6:7], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v35, vcc +; CHECK-NEXT: v_and_or_b32 v13, v15, s4, v12 +; CHECK-NEXT: v_bfe_u32 v12, v12, 16, 1 +; CHECK-NEXT: v_add3_u32 v12, v12, v13, s5 +; CHECK-NEXT: v_or_b32_e32 v13, 0x400000, v13 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[14:15], v[14:15] +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v13, vcc +; CHECK-NEXT: s_mov_b32 s6, 0x7060302 +; CHECK-NEXT: v_perm_b32 v13, v12, v34, s6 +; CHECK-NEXT: v_cvt_f32_f64_e64 v12, |v[8:9]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[14:15], v12 +; CHECK-NEXT: v_and_b32_e32 v34, 1, v12 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[8:9]|, v[14:15] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[8:9]|, v[14:15] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v34 +; CHECK-NEXT: v_cndmask_b32_e64 v14, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v14, v12, v14 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v12, v14, v12, vcc +; CHECK-NEXT: v_and_or_b32 v14, v9, s4, v12 +; CHECK-NEXT: v_bfe_u32 v12, v12, 16, 1 +; CHECK-NEXT: v_add3_u32 v12, v12, v14, s5 +; CHECK-NEXT: v_or_b32_e32 v14, 0x400000, v14 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[8:9], v[8:9] +; CHECK-NEXT: v_cndmask_b32_e32 v12, v12, v14, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v14, |v[10:11]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[8:9], v14 +; CHECK-NEXT: v_and_b32_e32 v15, 1, v14 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[10:11]|, v[8:9] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[10:11]|, v[8:9] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v15 +; CHECK-NEXT: v_cndmask_b32_e64 v8, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v8, v14, v8 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v14, vcc +; CHECK-NEXT: v_and_or_b32 v9, v11, s4, v8 +; CHECK-NEXT: v_bfe_u32 v8, v8, 16, 1 +; CHECK-NEXT: v_add3_u32 v8, v8, v9, s5 +; CHECK-NEXT: v_or_b32_e32 v9, 0x400000, v9 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[10:11], v[10:11] +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v10, |v[4:5]| +; CHECK-NEXT: v_perm_b32 v12, v8, v12, s6 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[8:9], v10 +; CHECK-NEXT: v_and_b32_e32 v11, 1, v10 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[4:5]|, v[8:9] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[4:5]|, v[8:9] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v11 +; CHECK-NEXT: v_cndmask_b32_e64 v8, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v8, v10, v8 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; CHECK-NEXT: v_and_or_b32 v9, v5, s4, v8 +; CHECK-NEXT: v_bfe_u32 v8, v8, 16, 1 +; CHECK-NEXT: v_add3_u32 v8, v8, v9, s5 +; CHECK-NEXT: v_or_b32_e32 v9, 0x400000, v9 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[4:5], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e32 v8, v8, v9, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v9, |v[6:7]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v9 +; CHECK-NEXT: v_and_b32_e32 v10, 1, v9 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[6:7]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v10 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v4, v9, v4 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; CHECK-NEXT: v_and_or_b32 v5, v7, s4, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s5 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[6:7], v[6:7] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v6, |v[0:1]| +; CHECK-NEXT: v_perm_b32 v11, v4, v8, s6 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; CHECK-NEXT: v_and_b32_e32 v7, 1, v6 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[0:1]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v4, v6, v4 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; CHECK-NEXT: v_and_or_b32 v5, v1, s4, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s5 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v5, |v[2:3]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v5 +; CHECK-NEXT: v_and_b32_e32 v6, 1, v5 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[2:3]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v6 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v5, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; CHECK-NEXT: v_and_or_b32 v1, v3, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v2, |v[28:29]| +; CHECK-NEXT: v_perm_b32 v10, v0, v4, s6 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v2 +; CHECK-NEXT: v_and_b32_e32 v3, 1, v2 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[28:29]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[28:29]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v3 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v2, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; CHECK-NEXT: v_and_or_b32 v1, v29, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[28:29], v[28:29] +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: v_cvt_f32_f64_e64 v3, |v[30:31]| +; CHECK-NEXT: v_cndmask_b32_e32 v2, v0, v1, vcc +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v3 +; CHECK-NEXT: v_and_b32_e32 v4, 1, v3 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[30:31]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[30:31]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v4 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v3, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v3, vcc +; CHECK-NEXT: v_and_or_b32 v1, v31, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[30:31], v[30:31] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_perm_b32 v3, v0, v2, s6 +; CHECK-NEXT: v_cvt_f32_f64_e64 v2, |v[24:25]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v2 +; CHECK-NEXT: v_and_b32_e32 v4, 1, v2 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[24:25]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[24:25]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v4 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v2, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; CHECK-NEXT: v_and_or_b32 v1, v25, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[24:25], v[24:25] +; CHECK-NEXT: v_cvt_f32_f64_e64 v4, |v[26:27]| +; CHECK-NEXT: v_cndmask_b32_e32 v2, v0, v1, vcc +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v4 +; CHECK-NEXT: v_and_b32_e32 v5, 1, v4 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[26:27]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[26:27]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v5 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v4, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc +; CHECK-NEXT: v_and_or_b32 v1, v27, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[26:27], v[26:27] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_cvt_f32_f64_e64 v4, |v[20:21]| +; CHECK-NEXT: v_perm_b32 v2, v0, v2, s6 +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v4 +; CHECK-NEXT: v_and_b32_e32 v5, 1, v4 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[20:21]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[20:21]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v5 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v4, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc +; CHECK-NEXT: v_and_or_b32 v1, v21, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[20:21], v[20:21] +; CHECK-NEXT: v_cvt_f32_f64_e64 v5, |v[22:23]| +; CHECK-NEXT: v_cndmask_b32_e32 v4, v0, v1, vcc +; CHECK-NEXT: v_cvt_f64_f32_e32 v[0:1], v5 +; CHECK-NEXT: v_and_b32_e32 v6, 1, v5 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[22:23]|, v[0:1] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[22:23]|, v[0:1] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v6 +; CHECK-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v0, v5, v0 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; CHECK-NEXT: v_and_or_b32 v1, v23, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v1, s5 +; CHECK-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[22:23], v[22:23] +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; CHECK-NEXT: v_perm_b32 v1, v0, v4, s6 +; CHECK-NEXT: v_cvt_f32_f64_e64 v0, |v[16:17]| +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v0 +; CHECK-NEXT: v_and_b32_e32 v6, 1, v0 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[16:17]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[16:17]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v6 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v4, v0, v4 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v0, vcc +; CHECK-NEXT: v_and_or_b32 v4, v17, s4, v0 +; CHECK-NEXT: v_bfe_u32 v0, v0, 16, 1 +; CHECK-NEXT: v_add3_u32 v0, v0, v4, s5 +; CHECK-NEXT: v_or_b32_e32 v4, 0x400000, v4 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[16:17], v[16:17] +; CHECK-NEXT: v_cvt_f32_f64_e64 v6, |v[18:19]| +; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc +; CHECK-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; CHECK-NEXT: v_and_b32_e32 v7, 1, v6 +; CHECK-NEXT: v_cmp_gt_f64_e64 s[10:11], |v[18:19]|, v[4:5] +; CHECK-NEXT: v_cmp_nlg_f64_e64 s[8:9], |v[18:19]|, v[4:5] +; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; CHECK-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[10:11] +; CHECK-NEXT: v_add_u32_e32 v4, v6, v4 +; CHECK-NEXT: s_or_b64 vcc, s[8:9], vcc +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; CHECK-NEXT: v_and_or_b32 v5, v19, s4, v4 +; CHECK-NEXT: v_bfe_u32 v4, v4, 16, 1 +; CHECK-NEXT: v_add3_u32 v4, v4, v5, s5 +; CHECK-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; CHECK-NEXT: v_cmp_u_f64_e32 vcc, v[18:19], v[18:19] +; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; CHECK-NEXT: v_perm_b32 v0, v4, v0, s6 +; CHECK-NEXT: global_store_dwordx4 v[32:33], v[0:3], off offset:16 +; CHECK-NEXT: global_store_dwordx4 v[32:33], v[10:13], off +; CHECK-NEXT: s_waitcnt vmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %conv = fptrunc <16 x double> %num to <16 x bfloat> + store <16 x bfloat> %conv, ptr addrspace(1) %p, align 8 + ret void +} From 79ca5236c3b4f458c3aa0a41dc7e5ece45c2d0f9 Mon Sep 17 00:00:00 2001 From: Michael Halkenhaeuser Date: Mon, 29 Apr 2024 09:55:31 -0400 Subject: [PATCH 22/22] [offload] Fix missing reference decrement introduced by merge resolution Added line which has been dropped from the 'deinitRuntime()' during merge-conflict resolution. Change-Id: Iee2c8b2fe63d8cd36cdb9befca2e8c93384087d9 --- offload/src/OffloadRTL.cpp | 1 + offload/src/interface.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/offload/src/OffloadRTL.cpp b/offload/src/OffloadRTL.cpp index 8d732f94b677d3..56c378acebdf40 100644 --- a/offload/src/OffloadRTL.cpp +++ b/offload/src/OffloadRTL.cpp @@ -54,6 +54,7 @@ void deinitRuntime() { PM = nullptr; } + RefCount--; } // HACK: These depricated device stubs still needs host versions for fallback diff --git a/offload/src/interface.cpp b/offload/src/interface.cpp index 6efc734fad21a5..1af787ac5f53ce 100644 --- a/offload/src/interface.cpp +++ b/offload/src/interface.cpp @@ -478,8 +478,8 @@ EXTERN void __tgt_push_mapper_component(void *RtMapperHandle, void *Base, } EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) { - OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); assert(PM && "Runtime not initialized"); + OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); std::atomic &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); for (auto &R : PM->pluginAdaptors()) @@ -487,8 +487,8 @@ EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) { } EXTERN int __tgt_print_device_info(int64_t DeviceId) { - OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); assert(PM && "Runtime not initialized"); + OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); auto DeviceOrErr = PM->getDevice(DeviceId); if (!DeviceOrErr) FATAL_MESSAGE(DeviceId, "%s", toString(DeviceOrErr.takeError()).c_str());