[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-13 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos created 
https://github.com/llvm/llvm-project/pull/108585

Replace code that relies on iterators by LLVM helper functions that take 
ranges. This makes the code simpler and more readable.

>From a2438ce9a61d8e80aa32fa58ca5368a64deacd52 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 13:56:31 +0100
Subject: [PATCH] [ADT] Use range-based helper functions in SmallSet

Replace code that relies on iterators by LLVM helper functions that take
ranges. This makes the code simpler and more readable.
---
 llvm/include/llvm/ADT/SmallSet.h | 36 +---
 1 file changed, 10 insertions(+), 26 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 630c98504261aa..d5f64e4f20f854 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -139,10 +139,6 @@ class SmallSet {
   SmallVector Vector;
   std::set Set;
 
-  using VIterator = typename SmallVector::const_iterator;
-  using SIterator = typename std::set::const_iterator;
-  using mutable_iterator = typename SmallVector::iterator;
-
   // In small mode SmallPtrSet uses linear search for the elements, so it is
   // not a good idea to choose this value too high. You may consider using a
   // DenseSet<> instead if you expect many elements in the set.
@@ -163,13 +159,7 @@ class SmallSet {
   }
 
   /// count - Return 1 if the element is in the set, 0 otherwise.
-  size_type count(const T &V) const {
-if (isSmall()) {
-  // Since the collection is small, just do a linear search.
-  return vfind(V) == Vector.end() ? 0 : 1;
-}
-return Set.count(V);
-  }
+  size_type count(const T &V) const { return contains(V) ? 1 : 0; }
 
   /// insert - Insert an element into the set if it isn't already there.
   /// Returns a pair. The first value of it is an iterator to the inserted
@@ -181,7 +171,7 @@ class SmallSet {
   return std::make_pair(const_iterator(I), Inserted);
 }
 
-VIterator I = vfind(V);
+auto I = llvm::find(Vector, V);
 if (I != Vector.end())// Don't reinsert if it already exists.
   return std::make_pair(const_iterator(I), false);
 if (Vector.size() < N) {
@@ -206,11 +196,12 @@ class SmallSet {
   bool erase(const T &V) {
 if (!isSmall())
   return Set.erase(V);
-for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V) {
-Vector.erase(I);
-return true;
-  }
+
+auto It = llvm::find(Vector, V);
+if (It != Vector.end()) {
+  Vector.erase(It);
+  return true;
+}
 return false;
   }
 
@@ -234,19 +225,12 @@ class SmallSet {
   /// Check if the SmallSet contains the given element.
   bool contains(const T &V) const {
 if (isSmall())
-  return vfind(V) != Vector.end();
-return Set.find(V) != Set.end();
+  return llvm::is_contained(Vector, V);
+return llvm::is_contained(Set, V);
   }
 
 private:
   bool isSmall() const { return Set.empty(); }
-
-  VIterator vfind(const T &V) const {
-for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V)
-return I;
-return Vector.end();
-  }
 };
 
 /// If this set is of pointer values, transparently switch over to using

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Add more useful methods to SmallSet API (PR #108601)

2024-09-13 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos created 
https://github.com/llvm/llvm-project/pull/108601

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.

>From d05069198321f3bab9de7db65f48f3c2b15b34bc Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 14:00:32 +0100
Subject: [PATCH] [ADT] Add more useful methods to SmallSet API

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.
---
 llvm/include/llvm/ADT/SmallSet.h| 21 --
 llvm/unittests/ADT/SmallSetTest.cpp | 60 +
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index c864eda8f8..2e26ad65eb2dd6 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -14,14 +14,13 @@
 #ifndef LLVM_ADT_SMALLSET_H
 #define LLVM_ADT_SMALLSET_H
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/iterator.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/type_traits.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -151,6 +150,22 @@ class SmallSet {
   using const_iterator = SmallSetIterator;
 
   SmallSet() = default;
+  SmallSet(const SmallSet &) = default;
+  SmallSet(SmallSet &&) = default;
+
+  template  SmallSet(IterT Begin, IterT End) {
+this->insert(Begin, End);
+  }
+
+  template 
+  explicit SmallSet(const iterator_range &R) {
+this->insert(R.begin(), R.end());
+  }
+
+  SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
+
+  SmallSet &operator=(const SmallSet &) = default;
+  SmallSet &operator=(SmallSet &&) = default;
 
   [[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
 
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index b50b368ae66361..ced1ba5dce34d8 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -17,6 +17,66 @@
 
 using namespace llvm;
 
+TEST(SmallSetTest, ConstructorIteratorPair) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S(std::begin(L), std::end(L));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorRange) {
+  auto L = {1, 2, 3, 4, 5};
+
+  SmallSet S(llvm::make_range(std::begin(L), std::end(L)));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorInitializerList) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S = {1, 2, 3, 4, 5};
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, CopyConstructor) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveConstructor) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
+TEST(SmallSet, CopyAssignment) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T;
+  T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveAssignment) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T;
+  T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
 TEST(SmallSetTest, Insert) {
 
   SmallSet s1;

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-17 Thread Victor Campos via llvm-branch-commits

vhscampos wrote:

> I'm slightly opposed to this change because it pulls in STLExtras.h. Yes, it 
> is already included, but it would be better to avoid including it.

Why is including `STLExtras.h` a problem?

https://github.com/llvm/llvm-project/pull/108585
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-17 Thread Victor Campos via llvm-branch-commits


@@ -234,19 +225,12 @@ class SmallSet {
   /// Check if the SmallSet contains the given element.
   bool contains(const T &V) const {
 if (isSmall())
-  return vfind(V) != Vector.end();
-return Set.find(V) != Set.end();
+  return llvm::is_contained(Vector, V);
+return llvm::is_contained(Set, V);

vhscampos wrote:

Thanks for pointing that out. I've checked and `llvm::is_contained` indeed does 
a linear scan on a `std::set` because the latter does not have a `contains` 
method before C++20.

https://github.com/llvm/llvm-project/pull/108585
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-17 Thread Victor Campos via llvm-branch-commits


@@ -234,19 +225,12 @@ class SmallSet {
   /// Check if the SmallSet contains the given element.
   bool contains(const T &V) const {
 if (isSmall())
-  return vfind(V) != Vector.end();
-return Set.find(V) != Set.end();
+  return llvm::is_contained(Vector, V);
+return llvm::is_contained(Set, V);

vhscampos wrote:

My bad. @kuhar is right. It calls `std::set::find` which is as good as it gets 
with `std::set`.

https://github.com/llvm/llvm-project/pull/108585
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use perfect forwarding in SmallSet::insert() (PR #108590)

2024-09-17 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108590

>From e0295a14694c5bba65a873914eb700b201e94b6a Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 13:57:42 +0100
Subject: [PATCH 1/3] [ADT] Use perfect forwarding in SmallSet::insert()

Previously this method took arguments by const-ref. This patch changes
the implementation to take perfectly forwarded arguments in the form of
a universal reference. Now, the insertion method will take advantage of
arguments passed as rvalue, potentially leading to performance
improvements.
---
 llvm/include/llvm/ADT/SmallSet.h | 47 +++-
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index d5f64e4f20f854..c864eda8f8 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -165,26 +165,10 @@ class SmallSet {
   /// Returns a pair. The first value of it is an iterator to the inserted
   /// element or the existing element in the set. The second value is true
   /// if the element is inserted (it was not in the set before).
-  std::pair insert(const T &V) {
-if (!isSmall()) {
-  auto [I, Inserted] = Set.insert(V);
-  return std::make_pair(const_iterator(I), Inserted);
-}
+  std::pair insert(const T &V) { return insertImpl(V); }
 
-auto I = llvm::find(Vector, V);
-if (I != Vector.end())// Don't reinsert if it already exists.
-  return std::make_pair(const_iterator(I), false);
-if (Vector.size() < N) {
-  Vector.push_back(V);
-  return std::make_pair(const_iterator(std::prev(Vector.end())), true);
-}
-
-// Otherwise, grow from vector to set.
-while (!Vector.empty()) {
-  Set.insert(Vector.back());
-  Vector.pop_back();
-}
-return std::make_pair(const_iterator(Set.insert(V).first), true);
+  std::pair insert(T &&V) {
+return insertImpl(std::move(V));
   }
 
   template 
@@ -231,6 +215,31 @@ class SmallSet {
 
 private:
   bool isSmall() const { return Set.empty(); }
+
+  template 
+  std::pair insertImpl(ArgType &&V) {
+static_assert(std::is_convertible_v,
+  "ArgType must be convertible to T!");
+if (!isSmall()) {
+  auto [I, Inserted] = Set.insert(std::forward(V));
+  return std::make_pair(const_iterator(I), Inserted);
+}
+
+auto I = llvm::find(Vector, V);
+if (I != Vector.end()) // Don't reinsert if it already exists.
+  return std::make_pair(const_iterator(I), false);
+if (Vector.size() < N) {
+  Vector.push_back(std::forward(V));
+  return std::make_pair(const_iterator(std::prev(Vector.end())), true);
+}
+
+// Otherwise, grow from vector to set.
+Set.insert(std::make_move_iterator(Vector.begin()),
+   std::make_move_iterator(Vector.end()));
+Vector.clear();
+return std::make_pair(
+const_iterator(Set.insert(std::forward(V)).first), true);
+  }
 };
 
 /// If this set is of pointer values, transparently switch over to using

>From 47c7444d4391d3bcbead2bb86a09ae051e0c4802 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 17 Sep 2024 13:11:00 +0100
Subject: [PATCH 2/3] Add test for SmallSet::insert perfect forwarding

---
 llvm/unittests/ADT/SmallSetTest.cpp | 34 +
 1 file changed, 34 insertions(+)

diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index b50b368ae66361..0fb20b19df9254 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -41,6 +41,40 @@ TEST(SmallSetTest, Insert) {
   EXPECT_EQ(0u, s1.count(4));
 }
 
+TEST(SmallSetTest, InsertPerfectFwd) {
+  struct Value {
+int Key;
+bool Moved;
+
+Value(int Key) : Key(Key), Moved(false) {}
+Value(const Value &) = default;
+Value(Value &&Other) : Key(Other.Key), Moved(false) { Other.Moved = true; }
+bool operator==(const Value &Other) const { return Key == Other.Key; }
+bool operator<(const Value &Other) const { return Key < Other.Key; }
+  };
+
+  {
+SmallSet S;
+Value V1(1), V2(2);
+
+S.insert(V1);
+EXPECT_EQ(V1.Moved, false);
+
+S.insert(std::move(V2));
+EXPECT_EQ(V2.Moved, true);
+  }
+  {
+SmallSet S;
+Value V1(1), V2(2);
+
+S.insert(V1);
+EXPECT_EQ(V1.Moved, false);
+
+S.insert(std::move(V2));
+EXPECT_EQ(V2.Moved, true);
+  }
+}
+
 TEST(SmallSetTest, Grow) {
   SmallSet s1;
 

>From a2eb49509529eb0a04346e50f64aa071b91e8c93 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 17 Sep 2024 13:16:24 +0100
Subject: [PATCH 3/3] Style changes

---
 llvm/include/llvm/ADT/SmallSet.h | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index c864eda8f8..2beaf2b92c028b 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -222,23 +222,22 

[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-17 Thread Victor Campos via llvm-branch-commits

vhscampos wrote:

Given that this change isn't exactly agreeable, I plan to change it to a PR to 
make SmallSet not use `STLExtras.h` at all.

https://github.com/llvm/llvm-project/pull/108585
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] 7996b49 - Revert "[ARM] Improve codegen of volatile load/store of i64"

2020-02-08 Thread Victor Campos via llvm-branch-commits

Author: Victor Campos
Date: 2020-02-08T13:36:47Z
New Revision: 7996b49053f0508717f4a081d197ddc3073f4b5f

URL: 
https://github.com/llvm/llvm-project/commit/7996b49053f0508717f4a081d197ddc3073f4b5f
DIFF: 
https://github.com/llvm/llvm-project/commit/7996b49053f0508717f4a081d197ddc3073f4b5f.diff

LOG: Revert "[ARM] Improve codegen of volatile load/store of i64"

This reverts commit 60e0120c913dd1d4bfe33769e1f000a076249a42.

Added: 


Modified: 
llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/lib/Target/ARM/ARMISelLowering.h
llvm/lib/Target/ARM/ARMInstrInfo.td
llvm/lib/Target/ARM/ARMInstrThumb2.td

Removed: 
llvm/test/CodeGen/ARM/i64_volatile_load_store.ll



diff  --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp 
b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 2c3ac816219f..de4377ec5a47 100644
--- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -1952,24 +1952,6 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
   MI.eraseFromParent();
   return true;
 }
-case ARM::LOADDUAL:
-case ARM::STOREDUAL: {
-  Register PairReg = MI.getOperand(0).getReg();
-
-  MachineInstrBuilder MIB =
-  BuildMI(MBB, MBBI, MI.getDebugLoc(),
-  TII->get(Opcode == ARM::LOADDUAL ? ARM::LDRD : ARM::STRD))
-  .addReg(TRI->getSubReg(PairReg, ARM::gsub_0),
-  Opcode == ARM::LOADDUAL ? RegState::Define : 0)
-  .addReg(TRI->getSubReg(PairReg, ARM::gsub_1),
-  Opcode == ARM::LOADDUAL ? RegState::Define : 0);
-  for (unsigned i = 1; i < MI.getNumOperands(); i++)
-MIB.add(MI.getOperand(i));
-  MIB.add(predOps(ARMCC::AL));
-  MIB.cloneMemRefs(MI);
-  MI.eraseFromParent();
-  return true;
-}
   }
 }
 

diff  --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp 
b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 76a9ac12062d..9b06987178d8 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -145,8 +145,6 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
 
   // Thumb 2 Addressing Modes:
   bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
-  template 
-  bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, SDValue &OffImm);
   bool SelectT2AddrModeImm8(SDValue N, SDValue &Base,
 SDValue &OffImm);
   bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N,
@@ -1296,33 +1294,6 @@ bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N,
   return true;
 }
 
-template 
-bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, SDValue &Base,
-   SDValue &OffImm) {
-  if (N.getOpcode() == ISD::SUB || CurDAG->isBaseWithConstantOffset(N)) {
-int RHSC;
-if (isScaledConstantInRange(N.getOperand(1), 1 << Shift, -255, 256, RHSC)) 
{
-  Base = N.getOperand(0);
-  if (Base.getOpcode() == ISD::FrameIndex) {
-int FI = cast(Base)->getIndex();
-Base = CurDAG->getTargetFrameIndex(
-FI, TLI->getPointerTy(CurDAG->getDataLayout()));
-  }
-
-  if (N.getOpcode() == ISD::SUB)
-RHSC = -RHSC;
-  OffImm =
-  CurDAG->getTargetConstant(RHSC * (1 << Shift), SDLoc(N), MVT::i32);
-  return true;
-}
-  }
-
-  // Base only.
-  Base = N;
-  OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
-  return true;
-}
-
 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N,
SDValue &Base, SDValue &OffImm) {
   // Match simple R - imm8 operands.
@@ -3515,26 +3486,6 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
 CurDAG->RemoveDeadNode(N);
 return;
   }
-  case ARMISD::LDRD: {
-if (Subtarget->isThumb2())
-  break; // TableGen handles isel in this case.
-SDValue Base, RegOffset, ImmOffset;
-const SDValue &Chain = N->getOperand(0);
-const SDValue &Addr = N->getOperand(1);
-SelectAddrMode3(Addr, Base, RegOffset, ImmOffset);
-SDValue Ops[] = {Base, RegOffset, ImmOffset, Chain};
-SDNode *New = CurDAG->getMachineNode(ARM::LOADDUAL, dl,
- {MVT::Untyped, MVT::Other}, Ops);
-SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32,
-SDValue(New, 0));
-SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32,
-SDValue(New, 0));
-ReplaceUses(SDValue(N, 0), Lo);
-ReplaceUses(SDValue(N, 1), Hi);
-ReplaceUses(SDValue(N, 2), SDValue(New, 1));
-CurDAG->RemoveDeadNode(N);
-return;
-  }
   case ARMISD::LOOP_DEC: {
 SDValue Ops[] = { N->getOperand(1),
   N->getOperand(2),

diff  --git a/llvm/lib/Target/ARM/ARMI

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-10-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos ready_for_review 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-10-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos ready_for_review 
https://github.com/llvm/llvm-project/pull/110658
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-10-24 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From 829fad54c1b1ee204633e4c1d7dcef3657c179cd Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 14 ++
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 23 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 0cb7c0c0ae04f7..1fff1fa3edd052 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5684,6 +5684,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 4df31770950858..19f5f59897eda2 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,16 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void
+processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,
+ const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -232,6 +242,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (ABIArg) {
 Result.push_back(ABIArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -285,6 +297,8 @@ static void getARMMultilibFlags(const Driver &D,
   if (BranchProtectionArg) {
 Result.push_back(BranchProtectionArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 4bb62665ad8981..6bf50cd0976a6b 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -82,3 +82,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-11-04 Thread Victor Campos via llvm-branch-commits


@@ -196,6 +196,16 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void
+processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,

vhscampos wrote:

Fixed

https://github.com/llvm/llvm-project/pull/110658
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Victor Campos via llvm-branch-commits


@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Prefix + Unclaimed).str();
+else
+  D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+  << (custom_flag::Prefix + Unclaimed).str()
+  << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+class ValueNameToDetailMap {
+  SmallVector> Mapping;
+
+public:
+  template 
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+  const CustomFlagDeclarationPtr &Decl = *DeclIt;
+  for (const auto &Value : Decl->ValueList)
+Mapping.emplace_back(Value.Name, &Value);
+}
+  }
+
+  const CustomFlagValueDetail *get(StringRef Key) const {
+auto Iter = llvm::find_if(
+Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector
+  ClaimedCustomFlagValues;
+  SmallVector UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+  CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+if (!Flag.starts_with(custom_flag::Prefix)) {
+  Result.push_back(Flag.str());
+  continue;
+}
+
+StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+const custom_flag::CustomFlagValueDetail *Detail =
+ValueNameToValueDetail.get(CustomFlagValueStr);
+if (Detail)
+  ClaimedCustomFlagValues.push_back(Detail);
+else
+  UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  llvm::SmallSet
+  TriggeredCustomFlagDecls;
+
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+  continue;
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+  }

vhscampos wrote:

Fixed

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Victor Campos via llvm-branch-commits


@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;

vhscampos wrote:

Fixed

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From f2525efdd1f70c59923220b787be005903bdced5 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/2] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td  |   6 +
 clang/include/clang/Driver/Multilib.h |   3 +
 clang/lib/Driver/Driver.cpp   |   4 +-
 clang/lib/Driver/Multilib.cpp | 137 +-
 .../baremetal-multilib-custom-flags.yaml  |  57 
 5 files changed, 201 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 65551bd7761a9d..6874614557f837 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 0662feb114c796..d0a3dd827e3531 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,6 +163,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
   llvm::SmallVectorImpl &) const;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 9878a9dad78d40..cee10d36070616 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2324,9 +2324,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
   }
 
   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
-for (const Multilib &Multilib : TC.getMultilibs())
-  if (!Multilib.isError())
-llvm::outs() << Multilib << "\n";
+llvm::outs() << TC.getMultilibs();
 return false;
   }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 236074478e7d84..adabf21057eb35 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -12,6 +12,7 @@
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Pref

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-04 Thread Victor Campos via llvm-branch-commits


@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Prefix + Unclaimed).str();
+else
+  D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+  << (custom_flag::Prefix + Unclaimed).str()
+  << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+class ValueNameToDetailMap {
+  SmallVector> Mapping;
+
+public:
+  template 
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+  const CustomFlagDeclarationPtr &Decl = *DeclIt;
+  for (const auto &Value : Decl->ValueList)
+Mapping.emplace_back(Value.Name, &Value);
+}
+  }
+
+  const CustomFlagValueDetail *get(StringRef Key) const {
+auto Iter = llvm::find_if(
+Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector
+  ClaimedCustomFlagValues;
+  SmallVector UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+  CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+if (!Flag.starts_with(custom_flag::Prefix)) {
+  Result.push_back(Flag.str());
+  continue;
+}
+
+StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+const custom_flag::CustomFlagValueDetail *Detail =
+ValueNameToValueDetail.get(CustomFlagValueStr);
+if (Detail)
+  ClaimedCustomFlagValues.push_back(Detail);
+else
+  UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  llvm::SmallSet
+  TriggeredCustomFlagDecls;
+
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+  continue;
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+  }

vhscampos wrote:

If the added comments aren't still good enough to improve clarity, please let 
me know

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-11-05 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos created 
https://github.com/llvm/llvm-project/pull/114998

None

>From 02161c1c4754b15450ae81538c22b77501a809ca Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 116 
 1 file changed, 116 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..7c165d149d7a4c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,104 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  ExtraBuildArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* ExtraBuildArgs: a list of strings corresponding to the extra build arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
+Use of ``-print-multi-lib`` by build systems
+
+
+Some library build systems use the ``-print-multi-lib`` command-line option to
+query what library variants are shipped or supported by the target compiler and
+what command-line options should be used to build the variants.
+
+In this use case, a build system queries the target toolchain about what 
library
+variants should be built. With this information in hand, the build system may
+launch the build of each variant using the collected command-line arguments.
+
+For example, in *newlib*, multithreading is enabled by default and can be
+disabled by defining the ``__SINGLE_THREAD__`` macro. Therefore a multilib YAML
+file that is used to drive a *newlib* build must encode this information in the
+output of ``-print-multi-lib``.
+
+To account for this use case, custom flag values may specify the
+*ExtraBuildArgs* field. This optional field is a list of strings to be printed
+alongside the other command-line arguments in the output of
+``-print-multi-lib``. In the example of *newlib* and its multithreading 
support,
+a variant specific for single threaded execution should list
+``-D__SINGLE_THREAD__`` in its corresponding flag value's *ExtraBuildArgs*
+field.
+
+Since this information is specific for users of ``-print-multi-lib``, that is,
+for *builders* of library variants, it has no relevance in library *selection*.
+
 Stability
 =
 
@@ -222,6 +320,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# Li

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-05 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From f2525efdd1f70c59923220b787be005903bdced5 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/3] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td  |   6 +
 clang/include/clang/Driver/Multilib.h |   3 +
 clang/lib/Driver/Driver.cpp   |   4 +-
 clang/lib/Driver/Multilib.cpp | 137 +-
 .../baremetal-multilib-custom-flags.yaml  |  57 
 5 files changed, 201 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 65551bd7761a9d..6874614557f837 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 0662feb114c796..d0a3dd827e3531 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,6 +163,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
   llvm::SmallVectorImpl &) const;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 9878a9dad78d40..cee10d36070616 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2324,9 +2324,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
   }
 
   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
-for (const Multilib &Multilib : TC.getMultilibs())
-  if (!Multilib.isError())
-llvm::outs() << Multilib << "\n";
+llvm::outs() << TC.getMultilibs();
 return false;
   }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 236074478e7d84..adabf21057eb35 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -12,6 +12,7 @@
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Pref

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-05 Thread Victor Campos via llvm-branch-commits

vhscampos wrote:

FYI I added a test for `-print-multi-lib` and its interaction with 
`ExtraBuildArgs`.

https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-11-04 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From 4f85ea57b021362f2a1bff12f720c8991093 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH 1/2] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 14 ++
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 23 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 0cb7c0c0ae04f7..1fff1fa3edd052 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5684,6 +5684,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 4df31770950858..19f5f59897eda2 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,16 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void
+processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,
+ const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -232,6 +242,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (ABIArg) {
 Result.push_back(ABIArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -285,6 +297,8 @@ static void getARMMultilibFlags(const Driver &D,
   if (BranchProtectionArg) {
 Result.push_back(BranchProtectionArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 4bb62665ad8981..6bf50cd0976a6b 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -82,3 +82,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

>From ee2d268d6ab0f231da471875194744b2fb5d32be Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 4 Nov 2024 13:45:58 +
Subject: [PATCH 2/2] Renamed function

---
 clang/lib/Driver/ToolChain.cpp | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 19f5f59897eda2..b9ddb65d2ef886 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,9 +196,8 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
-static void
-processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,
- const llvm::opt::ArgList &Args) {
+static void processMultilibCusto

[llvm-branch-commits] [llvm] [ADT] Use perfect forwarding in SmallSet::insert() (PR #108590)

2024-09-24 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108590

>From 964abdd8e2c5d9089b831ad242452cb83605db3a Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 13:57:42 +0100
Subject: [PATCH 1/3] [ADT] Use perfect forwarding in SmallSet::insert()

Previously this method took arguments by const-ref. This patch changes
the implementation to take perfectly forwarded arguments in the form of
a universal reference. Now, the insertion method will take advantage of
arguments passed as rvalue, potentially leading to performance
improvements.
---
 llvm/include/llvm/ADT/SmallSet.h | 47 +++-
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 8d7511bf0bc8d9..49e641a07eda3f 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -161,26 +161,10 @@ class SmallSet {
   /// Returns a pair. The first value of it is an iterator to the inserted
   /// element or the existing element in the set. The second value is true
   /// if the element is inserted (it was not in the set before).
-  std::pair insert(const T &V) {
-if (!isSmall()) {
-  auto [I, Inserted] = Set.insert(V);
-  return std::make_pair(const_iterator(I), Inserted);
-}
+  std::pair insert(const T &V) { return insertImpl(V); }
 
-auto I = std::find(Vector.begin(), Vector.end(), V);
-if (I != Vector.end())// Don't reinsert if it already exists.
-  return std::make_pair(const_iterator(I), false);
-if (Vector.size() < N) {
-  Vector.push_back(V);
-  return std::make_pair(const_iterator(std::prev(Vector.end())), true);
-}
-
-// Otherwise, grow from vector to set.
-while (!Vector.empty()) {
-  Set.insert(Vector.back());
-  Vector.pop_back();
-}
-return std::make_pair(const_iterator(Set.insert(V).first), true);
+  std::pair insert(T &&V) {
+return insertImpl(std::move(V));
   }
 
   template 
@@ -226,6 +210,31 @@ class SmallSet {
 
 private:
   bool isSmall() const { return Set.empty(); }
+
+  template 
+  std::pair insertImpl(ArgType &&V) {
+static_assert(std::is_convertible_v,
+  "ArgType must be convertible to T!");
+if (!isSmall()) {
+  auto [I, Inserted] = Set.insert(std::forward(V));
+  return std::make_pair(const_iterator(I), Inserted);
+}
+
+auto I = std::find(Vector.begin(), Vector.end(), V);
+if (I != Vector.end()) // Don't reinsert if it already exists.
+  return std::make_pair(const_iterator(I), false);
+if (Vector.size() < N) {
+  Vector.push_back(std::forward(V));
+  return std::make_pair(const_iterator(std::prev(Vector.end())), true);
+}
+
+// Otherwise, grow from vector to set.
+Set.insert(std::make_move_iterator(Vector.begin()),
+   std::make_move_iterator(Vector.end()));
+Vector.clear();
+return std::make_pair(
+const_iterator(Set.insert(std::forward(V)).first), true);
+  }
 };
 
 /// If this set is of pointer values, transparently switch over to using

>From 7970dad69c790748f0ffcd5c45d5961c178bef8b Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 17 Sep 2024 13:11:00 +0100
Subject: [PATCH 2/3] Add test for SmallSet::insert perfect forwarding

---
 llvm/unittests/ADT/SmallSetTest.cpp | 34 +
 1 file changed, 34 insertions(+)

diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index b50b368ae66361..0fb20b19df9254 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -41,6 +41,40 @@ TEST(SmallSetTest, Insert) {
   EXPECT_EQ(0u, s1.count(4));
 }
 
+TEST(SmallSetTest, InsertPerfectFwd) {
+  struct Value {
+int Key;
+bool Moved;
+
+Value(int Key) : Key(Key), Moved(false) {}
+Value(const Value &) = default;
+Value(Value &&Other) : Key(Other.Key), Moved(false) { Other.Moved = true; }
+bool operator==(const Value &Other) const { return Key == Other.Key; }
+bool operator<(const Value &Other) const { return Key < Other.Key; }
+  };
+
+  {
+SmallSet S;
+Value V1(1), V2(2);
+
+S.insert(V1);
+EXPECT_EQ(V1.Moved, false);
+
+S.insert(std::move(V2));
+EXPECT_EQ(V2.Moved, true);
+  }
+  {
+SmallSet S;
+Value V1(1), V2(2);
+
+S.insert(V1);
+EXPECT_EQ(V1.Moved, false);
+
+S.insert(std::move(V2));
+EXPECT_EQ(V2.Moved, true);
+  }
+}
+
 TEST(SmallSetTest, Grow) {
   SmallSet s1;
 

>From 8a9e20edaa526a88f4e16eea03f0aca511805965 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 17 Sep 2024 13:16:24 +0100
Subject: [PATCH 3/3] Style changes

---
 llvm/include/llvm/ADT/SmallSet.h | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 49e641a07eda3f..56259ea7cf9d0f 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/ll

[llvm-branch-commits] [llvm] [ADT] Add more useful methods to SmallSet API (PR #108601)

2024-09-24 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108601

>From 12b657a4761351d52fccb93ce52e64c3c1b1e91f Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 14:00:32 +0100
Subject: [PATCH] [ADT] Add more useful methods to SmallSet API

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.
---
 llvm/include/llvm/ADT/SmallSet.h| 17 
 llvm/unittests/ADT/SmallSetTest.cpp | 60 +
 2 files changed, 77 insertions(+)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 56259ea7cf9d0f..431fdee56c20e0 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/iterator.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -147,6 +148,22 @@ class SmallSet {
   using const_iterator = SmallSetIterator;
 
   SmallSet() = default;
+  SmallSet(const SmallSet &) = default;
+  SmallSet(SmallSet &&) = default;
+
+  template  SmallSet(IterT Begin, IterT End) {
+this->insert(Begin, End);
+  }
+
+  template 
+  explicit SmallSet(const iterator_range &R) {
+this->insert(R.begin(), R.end());
+  }
+
+  SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
+
+  SmallSet &operator=(const SmallSet &) = default;
+  SmallSet &operator=(SmallSet &&) = default;
 
   [[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
 
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index 0fb20b19df9254..8219bf6f4b4c55 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -17,6 +17,66 @@
 
 using namespace llvm;
 
+TEST(SmallSetTest, ConstructorIteratorPair) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S(std::begin(L), std::end(L));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorRange) {
+  auto L = {1, 2, 3, 4, 5};
+
+  SmallSet S(llvm::make_range(std::begin(L), std::end(L)));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorInitializerList) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S = {1, 2, 3, 4, 5};
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, CopyConstructor) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveConstructor) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
+TEST(SmallSet, CopyAssignment) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T;
+  T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveAssignment) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T;
+  T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
 TEST(SmallSetTest, Insert) {
 
   SmallSet s1;

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Add more useful methods to SmallSet API (PR #108601)

2024-09-24 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108601

>From 12b657a4761351d52fccb93ce52e64c3c1b1e91f Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 14:00:32 +0100
Subject: [PATCH 1/2] [ADT] Add more useful methods to SmallSet API

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.
---
 llvm/include/llvm/ADT/SmallSet.h| 17 
 llvm/unittests/ADT/SmallSetTest.cpp | 60 +
 2 files changed, 77 insertions(+)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 56259ea7cf9d0f..431fdee56c20e0 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/iterator.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -147,6 +148,22 @@ class SmallSet {
   using const_iterator = SmallSetIterator;
 
   SmallSet() = default;
+  SmallSet(const SmallSet &) = default;
+  SmallSet(SmallSet &&) = default;
+
+  template  SmallSet(IterT Begin, IterT End) {
+this->insert(Begin, End);
+  }
+
+  template 
+  explicit SmallSet(const iterator_range &R) {
+this->insert(R.begin(), R.end());
+  }
+
+  SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
+
+  SmallSet &operator=(const SmallSet &) = default;
+  SmallSet &operator=(SmallSet &&) = default;
 
   [[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
 
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index 0fb20b19df9254..8219bf6f4b4c55 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -17,6 +17,66 @@
 
 using namespace llvm;
 
+TEST(SmallSetTest, ConstructorIteratorPair) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S(std::begin(L), std::end(L));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorRange) {
+  auto L = {1, 2, 3, 4, 5};
+
+  SmallSet S(llvm::make_range(std::begin(L), std::end(L)));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorInitializerList) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S = {1, 2, 3, 4, 5};
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, CopyConstructor) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveConstructor) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
+TEST(SmallSet, CopyAssignment) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T;
+  T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveAssignment) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T;
+  T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
 TEST(SmallSetTest, Insert) {
 
   SmallSet s1;

>From d122983eb4f1f66da2a4a6b5bcdb9c8171d18205 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 24 Sep 2024 17:43:42 +0100
Subject: [PATCH 2/2] fixup! [ADT] Add more useful methods to SmallSet API

---
 llvm/include/llvm/ADT/SmallSet.h|  4 ++--
 llvm/unittests/ADT/SmallSetTest.cpp | 34 +++--
 2 files changed, 15 insertions(+), 23 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 431fdee56c20e0..1b8ad542846630 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -152,12 +152,12 @@ class SmallSet {
   SmallSet(SmallSet &&) = default;
 
   template  SmallSet(IterT Begin, IterT End) {
-this->insert(Begin, End);
+insert(Begin, End);
   }
 
   template 
   explicit SmallSet(const iterator_range &R) {
-this->insert(R.begin(), R.end());
+insert(R.begin(), R.end());
   }
 
   SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index 8219bf6f4b4c55..2feb0b1feb421b 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -12,49 +12,44 @@
 
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
 
 using namespace llvm;
 
 TEST(SmallSetTest, ConstructorIteratorPair) {
-  auto L = {1, 2, 3, 4, 5};
+  std::initializer_list L = {1, 2, 3, 4, 5};
   SmallSet S(std::begin(L), std::end(L));
-  for (int Value : L)
-EXPECT_TRUE(S.contains(Value));
+  EXPECT_THAT(S, testing::UnorderedElementsAreArray(L));
 }
 
 TEST(SmallSet, ConstructorRange) {
-  auto L = {1, 2, 3, 4, 5};
+  std::initializer_list L = {1, 2, 3, 4, 5};
 
   SmallSet S

[llvm-branch-commits] [llvm] [ADT] Add more useful methods to SmallSet API (PR #108601)

2024-09-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108601

>From 12b657a4761351d52fccb93ce52e64c3c1b1e91f Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 14:00:32 +0100
Subject: [PATCH 1/3] [ADT] Add more useful methods to SmallSet API

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.
---
 llvm/include/llvm/ADT/SmallSet.h| 17 
 llvm/unittests/ADT/SmallSetTest.cpp | 60 +
 2 files changed, 77 insertions(+)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 56259ea7cf9d0f..431fdee56c20e0 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/iterator.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -147,6 +148,22 @@ class SmallSet {
   using const_iterator = SmallSetIterator;
 
   SmallSet() = default;
+  SmallSet(const SmallSet &) = default;
+  SmallSet(SmallSet &&) = default;
+
+  template  SmallSet(IterT Begin, IterT End) {
+this->insert(Begin, End);
+  }
+
+  template 
+  explicit SmallSet(const iterator_range &R) {
+this->insert(R.begin(), R.end());
+  }
+
+  SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
+
+  SmallSet &operator=(const SmallSet &) = default;
+  SmallSet &operator=(SmallSet &&) = default;
 
   [[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
 
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index 0fb20b19df9254..8219bf6f4b4c55 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -17,6 +17,66 @@
 
 using namespace llvm;
 
+TEST(SmallSetTest, ConstructorIteratorPair) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S(std::begin(L), std::end(L));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorRange) {
+  auto L = {1, 2, 3, 4, 5};
+
+  SmallSet S(llvm::make_range(std::begin(L), std::end(L)));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorInitializerList) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S = {1, 2, 3, 4, 5};
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, CopyConstructor) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveConstructor) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
+TEST(SmallSet, CopyAssignment) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T;
+  T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveAssignment) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T;
+  T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
 TEST(SmallSetTest, Insert) {
 
   SmallSet s1;

>From d122983eb4f1f66da2a4a6b5bcdb9c8171d18205 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 24 Sep 2024 17:43:42 +0100
Subject: [PATCH 2/3] fixup! [ADT] Add more useful methods to SmallSet API

---
 llvm/include/llvm/ADT/SmallSet.h|  4 ++--
 llvm/unittests/ADT/SmallSetTest.cpp | 34 +++--
 2 files changed, 15 insertions(+), 23 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 431fdee56c20e0..1b8ad542846630 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -152,12 +152,12 @@ class SmallSet {
   SmallSet(SmallSet &&) = default;
 
   template  SmallSet(IterT Begin, IterT End) {
-this->insert(Begin, End);
+insert(Begin, End);
   }
 
   template 
   explicit SmallSet(const iterator_range &R) {
-this->insert(R.begin(), R.end());
+insert(R.begin(), R.end());
   }
 
   SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index 8219bf6f4b4c55..2feb0b1feb421b 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -12,49 +12,44 @@
 
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
 
 using namespace llvm;
 
 TEST(SmallSetTest, ConstructorIteratorPair) {
-  auto L = {1, 2, 3, 4, 5};
+  std::initializer_list L = {1, 2, 3, 4, 5};
   SmallSet S(std::begin(L), std::end(L));
-  for (int Value : L)
-EXPECT_TRUE(S.contains(Value));
+  EXPECT_THAT(S, testing::UnorderedElementsAreArray(L));
 }
 
 TEST(SmallSet, ConstructorRange) {
-  auto L = {1, 2, 3, 4, 5};
+  std::initializer_list L = {1, 2, 3, 4, 5};
 
   SmallSet S

[llvm-branch-commits] [llvm] [ADT] Use range-based helper functions in SmallSet (PR #108585)

2024-09-20 Thread Victor Campos via llvm-branch-commits

vhscampos wrote:

New PR: https://github.com/llvm/llvm-project/pull/109412

https://github.com/llvm/llvm-project/pull/108585
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [ADT] Simplify SmallSet (PR #109412)

2024-09-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos created 
https://github.com/llvm/llvm-project/pull/109412

- Remove dependence on `STLExtras.h`.
- Remove unused header inclusions.
- Make `count` use `contains` for deduplication.
- Replace hand-written linear scans on Vector by `std::find`.

>From 3d83c5456c35f891aefa65f7cc6b37795af99c32 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 20 Sep 2024 11:43:18 +0100
Subject: [PATCH] [ADT] Simplify SmallSet

- Remove dependence on `STLExtras.h`.
- Remove unused header inclusions.
- Make `count` use `contains` for deduplication.
- Replace hand-written linear scans on Vector by `std::find`.
---
 clang/lib/Basic/TargetID.cpp |  1 +
 llvm/include/llvm/ADT/SmallSet.h | 37 +++-
 2 files changed, 9 insertions(+), 29 deletions(-)

diff --git a/clang/lib/Basic/TargetID.cpp b/clang/lib/Basic/TargetID.cpp
index 3c06d9bad1dc0d..fa1bfec2aacb9c 100644
--- a/clang/lib/Basic/TargetID.cpp
+++ b/clang/lib/Basic/TargetID.cpp
@@ -7,6 +7,7 @@
 
//===--===//
 
 #include "clang/Basic/TargetID.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/TargetParser.h"
diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 630c98504261aa..8d7511bf0bc8d9 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -16,14 +16,10 @@
 
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/iterator.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/type_traits.h"
 #include 
 #include 
 #include 
-#include 
 #include 
 
 namespace llvm {
@@ -139,10 +135,6 @@ class SmallSet {
   SmallVector Vector;
   std::set Set;
 
-  using VIterator = typename SmallVector::const_iterator;
-  using SIterator = typename std::set::const_iterator;
-  using mutable_iterator = typename SmallVector::iterator;
-
   // In small mode SmallPtrSet uses linear search for the elements, so it is
   // not a good idea to choose this value too high. You may consider using a
   // DenseSet<> instead if you expect many elements in the set.
@@ -163,13 +155,7 @@ class SmallSet {
   }
 
   /// count - Return 1 if the element is in the set, 0 otherwise.
-  size_type count(const T &V) const {
-if (isSmall()) {
-  // Since the collection is small, just do a linear search.
-  return vfind(V) == Vector.end() ? 0 : 1;
-}
-return Set.count(V);
-  }
+  size_type count(const T &V) const { return contains(V) ? 1 : 0; }
 
   /// insert - Insert an element into the set if it isn't already there.
   /// Returns a pair. The first value of it is an iterator to the inserted
@@ -181,7 +167,7 @@ class SmallSet {
   return std::make_pair(const_iterator(I), Inserted);
 }
 
-VIterator I = vfind(V);
+auto I = std::find(Vector.begin(), Vector.end(), V);
 if (I != Vector.end())// Don't reinsert if it already exists.
   return std::make_pair(const_iterator(I), false);
 if (Vector.size() < N) {
@@ -206,11 +192,11 @@ class SmallSet {
   bool erase(const T &V) {
 if (!isSmall())
   return Set.erase(V);
-for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V) {
-Vector.erase(I);
-return true;
-  }
+auto I = std::find(Vector.begin(), Vector.end(), V);
+if (I != Vector.end()) {
+  Vector.erase(I);
+  return true;
+}
 return false;
   }
 
@@ -234,19 +220,12 @@ class SmallSet {
   /// Check if the SmallSet contains the given element.
   bool contains(const T &V) const {
 if (isSmall())
-  return vfind(V) != Vector.end();
+  return std::find(Vector.begin(), Vector.end(), V) != Vector.end();
 return Set.find(V) != Set.end();
   }
 
 private:
   bool isSmall() const { return Set.empty(); }
-
-  VIterator vfind(const T &V) const {
-for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V)
-return I;
-return Vector.end();
-  }
 };
 
 /// If this set is of pointer values, transparently switch over to using

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use perfect forwarding in SmallSet::insert() (PR #108590)

2024-09-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/108590
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Use perfect forwarding in SmallSet::insert() (PR #108590)

2024-09-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108590

>From a2438ce9a61d8e80aa32fa58ca5368a64deacd52 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 13:56:31 +0100
Subject: [PATCH 1/4] [ADT] Use range-based helper functions in SmallSet

Replace code that relies on iterators by LLVM helper functions that take
ranges. This makes the code simpler and more readable.
---
 llvm/include/llvm/ADT/SmallSet.h | 36 +---
 1 file changed, 10 insertions(+), 26 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 630c98504261aa..d5f64e4f20f854 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -139,10 +139,6 @@ class SmallSet {
   SmallVector Vector;
   std::set Set;
 
-  using VIterator = typename SmallVector::const_iterator;
-  using SIterator = typename std::set::const_iterator;
-  using mutable_iterator = typename SmallVector::iterator;
-
   // In small mode SmallPtrSet uses linear search for the elements, so it is
   // not a good idea to choose this value too high. You may consider using a
   // DenseSet<> instead if you expect many elements in the set.
@@ -163,13 +159,7 @@ class SmallSet {
   }
 
   /// count - Return 1 if the element is in the set, 0 otherwise.
-  size_type count(const T &V) const {
-if (isSmall()) {
-  // Since the collection is small, just do a linear search.
-  return vfind(V) == Vector.end() ? 0 : 1;
-}
-return Set.count(V);
-  }
+  size_type count(const T &V) const { return contains(V) ? 1 : 0; }
 
   /// insert - Insert an element into the set if it isn't already there.
   /// Returns a pair. The first value of it is an iterator to the inserted
@@ -181,7 +171,7 @@ class SmallSet {
   return std::make_pair(const_iterator(I), Inserted);
 }
 
-VIterator I = vfind(V);
+auto I = llvm::find(Vector, V);
 if (I != Vector.end())// Don't reinsert if it already exists.
   return std::make_pair(const_iterator(I), false);
 if (Vector.size() < N) {
@@ -206,11 +196,12 @@ class SmallSet {
   bool erase(const T &V) {
 if (!isSmall())
   return Set.erase(V);
-for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V) {
-Vector.erase(I);
-return true;
-  }
+
+auto It = llvm::find(Vector, V);
+if (It != Vector.end()) {
+  Vector.erase(It);
+  return true;
+}
 return false;
   }
 
@@ -234,19 +225,12 @@ class SmallSet {
   /// Check if the SmallSet contains the given element.
   bool contains(const T &V) const {
 if (isSmall())
-  return vfind(V) != Vector.end();
-return Set.find(V) != Set.end();
+  return llvm::is_contained(Vector, V);
+return llvm::is_contained(Set, V);
   }
 
 private:
   bool isSmall() const { return Set.empty(); }
-
-  VIterator vfind(const T &V) const {
-for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
-  if (*I == V)
-return I;
-return Vector.end();
-  }
 };
 
 /// If this set is of pointer values, transparently switch over to using

>From e0295a14694c5bba65a873914eb700b201e94b6a Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 13:57:42 +0100
Subject: [PATCH 2/4] [ADT] Use perfect forwarding in SmallSet::insert()

Previously this method took arguments by const-ref. This patch changes
the implementation to take perfectly forwarded arguments in the form of
a universal reference. Now, the insertion method will take advantage of
arguments passed as rvalue, potentially leading to performance
improvements.
---
 llvm/include/llvm/ADT/SmallSet.h | 47 +++-
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index d5f64e4f20f854..c864eda8f8 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -165,26 +165,10 @@ class SmallSet {
   /// Returns a pair. The first value of it is an iterator to the inserted
   /// element or the existing element in the set. The second value is true
   /// if the element is inserted (it was not in the set before).
-  std::pair insert(const T &V) {
-if (!isSmall()) {
-  auto [I, Inserted] = Set.insert(V);
-  return std::make_pair(const_iterator(I), Inserted);
-}
+  std::pair insert(const T &V) { return insertImpl(V); }
 
-auto I = llvm::find(Vector, V);
-if (I != Vector.end())// Don't reinsert if it already exists.
-  return std::make_pair(const_iterator(I), false);
-if (Vector.size() < N) {
-  Vector.push_back(V);
-  return std::make_pair(const_iterator(std::prev(Vector.end())), true);
-}
-
-// Otherwise, grow from vector to set.
-while (!Vector.empty()) {
-  Set.insert(Vector.back());
-  Vector.pop_back();
-}
-return std::make_pair(const_iterator(Set.insert(V).first), true);

[llvm-branch-commits] [llvm] [ADT] Add more useful methods to SmallSet API (PR #108601)

2024-09-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/108601

>From d05069198321f3bab9de7db65f48f3c2b15b34bc Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 9 Aug 2024 14:00:32 +0100
Subject: [PATCH 1/2] [ADT] Add more useful methods to SmallSet API

This patch adds useful methods to the SmallSet API:

 - Constructor that takes pair of iterators.
 - Constructor that takes a range.
 - Constructor that takes an initializer list.
 - Copy constructor.
 - Move constructor.
 - Copy assignment operator.
 - Move assignment operator.
---
 llvm/include/llvm/ADT/SmallSet.h| 21 --
 llvm/unittests/ADT/SmallSetTest.cpp | 60 +
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index c864eda8f8..2e26ad65eb2dd6 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -14,14 +14,13 @@
 #ifndef LLVM_ADT_SMALLSET_H
 #define LLVM_ADT_SMALLSET_H
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/iterator.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/type_traits.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -151,6 +150,22 @@ class SmallSet {
   using const_iterator = SmallSetIterator;
 
   SmallSet() = default;
+  SmallSet(const SmallSet &) = default;
+  SmallSet(SmallSet &&) = default;
+
+  template  SmallSet(IterT Begin, IterT End) {
+this->insert(Begin, End);
+  }
+
+  template 
+  explicit SmallSet(const iterator_range &R) {
+this->insert(R.begin(), R.end());
+  }
+
+  SmallSet(std::initializer_list L) { this->insert(L.begin(), L.end()); }
+
+  SmallSet &operator=(const SmallSet &) = default;
+  SmallSet &operator=(SmallSet &&) = default;
 
   [[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
 
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp 
b/llvm/unittests/ADT/SmallSetTest.cpp
index b50b368ae66361..ced1ba5dce34d8 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -17,6 +17,66 @@
 
 using namespace llvm;
 
+TEST(SmallSetTest, ConstructorIteratorPair) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S(std::begin(L), std::end(L));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorRange) {
+  auto L = {1, 2, 3, 4, 5};
+
+  SmallSet S(llvm::make_range(std::begin(L), std::end(L)));
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, ConstructorInitializerList) {
+  auto L = {1, 2, 3, 4, 5};
+  SmallSet S = {1, 2, 3, 4, 5};
+  for (int Value : L)
+EXPECT_TRUE(S.contains(Value));
+}
+
+TEST(SmallSet, CopyConstructor) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveConstructor) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
+TEST(SmallSet, CopyAssignment) {
+  SmallSet S = {1, 2, 3};
+  SmallSet T;
+  T = S;
+
+  EXPECT_EQ(S, T);
+}
+
+TEST(SmallSet, MoveAssignment) {
+  auto L = {1, 2, 3};
+  SmallSet S = L;
+  SmallSet T;
+  T = std::move(S);
+
+  EXPECT_TRUE(T.size() == L.size());
+  for (int Value : L) {
+EXPECT_TRUE(T.contains(Value));
+  }
+}
+
 TEST(SmallSetTest, Insert) {
 
   SmallSet s1;

>From 09a354280c76973b0fb5ed546f9566ca65b9e730 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Fri, 20 Sep 2024 14:16:49 +0100
Subject: [PATCH 2/2] fixup! [ADT] Add more useful methods to SmallSet API

Remove inclusion of STLExtras.h
---
 llvm/include/llvm/ADT/SmallSet.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index 2e26ad65eb2dd6..459099154a4ded 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -14,7 +14,6 @@
 #ifndef LLVM_ADT_SMALLSET_H
 #define LLVM_ADT_SMALLSET_H
 
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/iterator.h"

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-10-01 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 1d394d0cbfb4a47d77f466b265671d0c13ebbb3b Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed in
the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value  fed into the library selection mechanism.

A warning is shown if the flag's value is invalid. The closest valid
value is suggested (string edit distance).

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td  |  3 +
 clang/include/clang/Driver/Multilib.h |  3 +
 clang/lib/Driver/Multilib.cpp | 77 ++-
 .../baremetal-multilib-custom-flags.yaml  | 57 ++
 4 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 97573fcf20c1fb..2a724e2f483970 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,9 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 53ab51a33eea67..88115fa7c31eee 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -150,6 +150,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
   llvm::SmallVectorImpl &) const;
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 4175bc13834ed2..0e3f305848c974 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -11,6 +11,7 @@
 #include "clang/Basic/Version.h"
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -96,9 +97,83 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls,
+const StringRef MultilibFlagOptionStr) {
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (StringRef FlagValue : Decl.Values) {
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValue, /*AllowReplacements=*/false);
+if (!BestCandidate || EditDistance < BestCandidate->EditDistance) {
+  BestCandidate = {std::move(FlagValue), EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  continue;
+D.Diag(clang::diag::warn_drv_unsupported_opt_with_suggestion)
+<< (MultilibFlagOptionStr + Unclaimed).str()
+<< (MultilibFlagOptionStr + BestCandidate->FlagValue).str();
+  }
+}
+
+Multilib::flags_list
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  constexpr StringRef MultilibFlagOptionStr = "-fmultilib-flag=";
+  SmallVector CustomFlags;
+
+  for (StringRef Flag : Flags) {
+if (Flag.starts_with(MultilibFlagOptionStr))
+  CustomFlags.push_back(std::move(Flag));
+else
+  Result.push_back(Flag.str());
+  }
+
+  SmallVector UnclaimedCustomFlagValues;
+  llvm::SmallSet TriggeredCustomFlagDecls;
+
+  for (StringRef Flag : llvm::reverse(CustomFlags)) {
+StringRef CustomFlagValue = Flag.drop_front(MultilibFlagOptionStr.size());
+bool Claimed = false;
+for (const CustomFlagDeclaration &Decl : CustomFlagDecls) {
+  if (llvm::i

[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-10-01 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From 002079817c4d849973941795bb4d19bd822112d5 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 14 ++
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 23 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 607ff47a857b8f..30ef1c3bea023e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5658,6 +5658,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 16f9b629fc538c..70e9d82f596772 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,16 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void
+processARMAArch64MultilibCustomFlags(Multilib::flags_list &List,
+ const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -227,6 +237,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (BranchProtectionArg) {
 Result.push_back(BranchProtectionArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -280,6 +292,8 @@ static void getARMMultilibFlags(const Driver &D,
   if (BranchProtectionArg) {
 Result.push_back(BranchProtectionArg->getAsString(Args));
   }
+
+  processARMAArch64MultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 0116c7f5a03b9a..9502eab9eb7457 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -77,3 +77,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-10-24 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 838993d1fa75688a91a5734ed7a6bd379da9f6e3 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 .../clang/Basic/DiagnosticDriverKinds.td  |   6 +
 clang/include/clang/Driver/Multilib.h |   3 +
 clang/lib/Driver/Driver.cpp   |   4 +-
 clang/lib/Driver/Multilib.cpp | 137 +-
 .../baremetal-multilib-custom-flags.yaml  |  57 
 5 files changed, 201 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 65551bd7761a9d..6874614557f837 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -14,6 +14,12 @@ def err_drv_no_such_file_with_suggestion : Error<
 def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
 def err_drv_unsupported_opt_with_suggestion : Error<
   "unsupported option '%0'; did you mean '%1'?">;
+def warn_drv_unsupported_opt : Warning<
+  "unsupported option '%0'">,
+  InGroup;
+def warn_drv_unsupported_opt_with_suggestion : Warning<
+  "unsupported option '%0'; did you mean '%1'?">,
+  InGroup;
 def err_drv_unsupported_opt_for_target : Error<
   "unsupported option '%0' for target '%1'">;
 def err_drv_unsupported_opt_for_language_mode : Error<
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 333b1d2b555bd9..f99d4e6313ff26 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,6 +163,9 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  Multilib::flags_list
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
   llvm::SmallVectorImpl &) const;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 9878a9dad78d40..cee10d36070616 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2324,9 +2324,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
   }
 
   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
-for (const Multilib &Multilib : TC.getMultilibs())
-  if (!Multilib.isError())
-llvm::outs() << Multilib << "\n";
+llvm::outs() << TC.getMultilibs();
 return false;
   }
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 81fe97517b0f91..a4a4a74a9c7ad4 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -12,6 +12,7 @@
 #include "clang/Driver/Driver.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -95,9 +96,113 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
+static void WarnUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) 
{
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::warn_drv_unsupported_opt)
+  << (custom_flag::Prefix +

[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-11-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From be0d5d6ee15e22b78a6fe671dc4f665680fd2aa5 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/2] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From a940ccd9eec0f683df9f41f2a9e218df76357364 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/2] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From 7b8f0d9a968eba4d85cf1d6a4ebc93f5e6dfbd2b Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 12 
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 21 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index f2f9c20c9bc264..4ec23b270f2e6b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5704,6 +5704,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 0d426a467e9a3b..bb8a4d6915e641 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,15 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void processMultilibCustomFlags(Multilib::flags_list &List,
+   const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -246,6 +255,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (ABIArg) {
 Result.push_back(ABIArg->getAsString(Args));
   }
+
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -313,6 +324,7 @@ static void getARMMultilibFlags(const Driver &D,
 if (Endian->getOption().matches(options::OPT_mbig_endian))
   Result.push_back(Endian->getAsString(Args));
   }
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 5bf6dca5096a73..cf9522aa068524 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -90,3 +90,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110658
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 391e7c9a0236b71caaa7db699ee8becaefec5cfd Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From b2de2588d108fa19a957a1525a63d522dee93769 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 142 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 329 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index 9177d56718ee77..40e2b9546cead5 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -463,7 +463,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 69d0b9b31714ff..d9398208fbea49 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a0f4329e36136b..360f6519360d44 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1252,8 +1252,9 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
 
   // All arguments, from both config file and command line.
-  InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
-  : std::move(*CLOptions));
+  auto UArgs = std::make_unique(std::move(HasConfigFile ? 
std::move(*CfgOption

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-11-20 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/114998
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From b2de2588d108fa19a957a1525a63d522dee93769 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/3] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 142 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 329 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index 9177d56718ee77..40e2b9546cead5 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -463,7 +463,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 69d0b9b31714ff..d9398208fbea49 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a0f4329e36136b..360f6519360d44 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1252,8 +1252,9 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
 
   // All arguments, from both config file and command line.
-  InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
-  : std::move(*CLOptions));
+  auto UArgs = std::make_unique(std::move(HasConfigFile ? 
std::move(*CfgOp

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-11-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From b2de2588d108fa19a957a1525a63d522dee93769 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/2] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 142 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 329 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index 9177d56718ee77..40e2b9546cead5 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -463,7 +463,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 69d0b9b31714ff..d9398208fbea49 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a0f4329e36136b..360f6519360d44 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1252,8 +1252,9 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
 
   // All arguments, from both config file and command line.
-  InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
-  : std::move(*CLOptions));
+  auto UArgs = std::make_unique(std::move(HasConfigFile ? 
std::move(*CfgOp

[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-11-25 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 1e4516b64005507d4e778847c7a3d5ec0b4b0fe1 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/2] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From 3425219671b230901510d03a5fbf8b1891969da8 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/2] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-12-11 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From 17265b1f8b175acda38e225b044cadcc845666ff Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 12 
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 21 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 88862ae9edb29d..29ddbc627a9f9f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5721,6 +5721,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 9f174fbda398b5..57fa57914c0a32 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,15 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void processMultilibCustomFlags(Multilib::flags_list &List,
+   const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -246,6 +255,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (ABIArg) {
 Result.push_back(ABIArg->getAsString(Args));
   }
+
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -313,6 +324,7 @@ static void getARMMultilibFlags(const Driver &D,
 if (Endian->getOption().matches(options::OPT_mbig_endian))
   Result.push_back(Endian->getAsString(Args));
   }
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 5bf6dca5096a73..cf9522aa068524 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -90,3 +90,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-12-11 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 2fe418964fff9e03861650afb89a81ac80f1413d Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/4] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 141 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 328 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index c23d037e725bb9..80be9261ec40f7 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -466,7 +466,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 1dab45c062aeec..36bdfdb6157b0b 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fb73b62cf2daed..761876b9fcc53b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1272,8 +1272,8 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
 
   // All arguments, from both config file and command line.
-  InputArgList Args =
-  HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
+  auto UArgs = std::make_unique(HasConfigFileHead ? 
std::move(*CfgOptionsHead) : std::move(*CLOptions));
+  InputArgList &Args =

[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-12-11 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 9fcdd1760ea664a618a2c05a18e777940a9d49b6 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/3] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From 5799eb81ac94ec4131af146bfacdf44a9bebdd71 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/3] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-12-11 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Add -fmultilib-flag command-line option (PR #110658)

2024-12-10 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110658

>From c0bb75d7ba6292a0267d71026324164a11910ce8 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 12 
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 21 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index f2f9c20c9bc264..4ec23b270f2e6b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5704,6 +5704,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 0d426a467e9a3b..bb8a4d6915e641 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,15 @@ bool ToolChain::defaultToIEEELongDouble() const {
   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
 }
 
+static void processMultilibCustomFlags(Multilib::flags_list &List,
+   const llvm::opt::ArgList &Args) {
+  for (const Arg *MultilibFlagArg :
+   Args.filtered(options::OPT_fmultilib_flag)) {
+List.push_back(MultilibFlagArg->getAsString(Args));
+MultilibFlagArg->claim();
+  }
+}
+
 static void getAArch64MultilibFlags(const Driver &D,
   const llvm::Triple &Triple,
   const llvm::opt::ArgList &Args,
@@ -246,6 +255,8 @@ static void getAArch64MultilibFlags(const Driver &D,
   if (ABIArg) {
 Result.push_back(ABIArg->getAsString(Args));
   }
+
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getARMMultilibFlags(const Driver &D,
@@ -313,6 +324,7 @@ static void getARMMultilibFlags(const Driver &D,
 if (Endian->getOption().matches(options::OPT_mbig_endian))
   Result.push_back(Endian->getAsString(Args));
   }
+  processMultilibCustomFlags(Result, Args);
 }
 
 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 5bf6dca5096a73..cf9522aa068524 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -90,3 +90,10 @@
 // CHECK-RV32E-ORDER: --target=riscv32-unknown-none-elf
 // CHECK-RV32E-ORDER: -mabi=ilp32e
 // CHECK-RV32E-ORDER: 
-march=rv32e{{[0-9]+p[0-9]+}}_c{{[0-9]+p[0-9]+}}_zicsr{{[0-9]+p[0-9]+}}
+
+// RUN: %clang -print-multi-flags-experimental --target=armv8m.main-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-ARM-MULTILIB-CUSTOM-FLAG %s
+// RUN: %clang -print-multi-flags-experimental --target=aarch64-none-eabi 
-fmultilib-flag=foo -fmultilib-flag=bar | FileCheck 
--check-prefixes=CHECK-MULTILIB-CUSTOM-FLAG,CHECK-AARCH64-MULTILIB-CUSTOM-FLAG 
%s
+// CHECK-ARM-MULTILIB-CUSTOM-FLAG: --target=thumbv8m.main-unknown-none-eabi
+// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
+// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2024-12-10 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 6f607d96dfc02223ab22fa743796a5af6c14e3f1 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/3] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From 4dbb33c9b35eb19ae10b6f39ffaba76eb5a367f0 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/3] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2024-12-10 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 96e089e5b075cf5376109cae6eadea9b4b9a054d Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 9 Dec 2024 09:36:52 +
Subject: [PATCH 1/6] Change in specification: DriverArgs now MacroDefines

We've decided to restrict the driver arguments that can be specified to
only macro definitions. Hence this patch adjusts the YAML parsing for
that.
---
 clang/include/clang/Driver/Multilib.h|  2 +-
 clang/lib/Driver/Multilib.cpp|  2 +-
 .../baremetal-multilib-custom-flags-parsing.yaml | 12 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 69d0b9b31714ff..1dab45c062aeec 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -107,7 +107,7 @@ using DeclarationPtr = std::shared_ptr;
 
 struct ValueDetail {
   std::string Name;
-  std::optional> DriverArgs;
+  std::optional> MacroDefines;
   DeclarationPtr Decl;
 };
 
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 0d7d590a0eed8b..b4b5dbd1bdb5e3 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -269,7 +269,7 @@ struct 
llvm::yaml::MappingContextTraits &) {
 io.mapRequired("Name", V.Name);
-io.mapOptional("DriverArgs", V.DriverArgs);
+io.mapOptional("MacroDefines", V.MacroDefines);
   }
   static std::string validate(IO &io, custom_flag::ValueDetail &V,
   llvm::SmallSet &NameSet) {
diff --git a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml 
b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
index dc4d1b31a71165..fe6a9a8d7f1ee7 100644
--- a/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
+++ b/clang/test/Driver/baremetal-multilib-custom-flags-parsing.yaml
@@ -1,8 +1,8 @@
 # RUN: split-file %s %t
 
-# RUN: %clang --target=arm-none-eabi 
--multi-lib-config=%t/multilib-without-extra-build-args.yaml %s -### -o 
/dev/null 2>&1 \
+# RUN: %clang --target=arm-none-eabi 
--multi-lib-config=%t/multilib-without-macro-defines.yaml %s -### -o /dev/null 
2>&1 \
 # RUN: | FileCheck %s
-# RUN: %clang --target=arm-none-eabi 
--multi-lib-config=%t/multilib-with-extra-build-args.yaml %s -### -o /dev/null 
2>&1 \
+# RUN: %clang --target=arm-none-eabi 
--multi-lib-config=%t/multilib-with-macro-defines.yaml %s -### -o /dev/null 
2>&1 \
 # RUN: | FileCheck %s
 # CHECK-NOT: error:
 
@@ -27,7 +27,7 @@
 # CHECK-DUPLICATE-FLAG-VALUE-NAME:  error: duplicate custom flag value 
name: "value-name"
 # CHECK-DUPLICATE-FLAG-VALUE-NAME-NEXT: - Name: value-name
 
-#--- multilib-without-extra-build-args.yaml
+#--- multilib-without-macro-defines.yaml
 ---
 MultilibVersion: 1.0
 
@@ -42,7 +42,7 @@ Flags:
 - Name: b
 Default: a
 
-#--- multilib-with-extra-build-args.yaml
+#--- multilib-with-macro-defines.yaml
 ---
 MultilibVersion: 1.0
 
@@ -54,9 +54,9 @@ Flags:
   - Name: flag
 Values:
 - Name: a
-  DriverArgs: [-DFEATURE_A]
+  MacroDefines: [FEATURE_A]
 - Name: b
-  DriverArgs: [-DFEATURE_B]
+  MacroDefines: [FEATURE_B]
 Default: a
 
 #--- missing-flag-name.yaml

>From c0bb75d7ba6292a0267d71026324164a11910ce8 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:01 +0100
Subject: [PATCH 2/6] [Multilib] Add -fmultilib-flag command-line option

This option is passed through to the multilib system. It is then used in
conjunction with other options to select the proper library variant.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Options.td   |  2 ++
 clang/lib/Driver/ToolChain.cpp  | 12 
 clang/test/Driver/print-multi-selection-flags.c |  7 +++
 3 files changed, 21 insertions(+)

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index f2f9c20c9bc264..4ec23b270f2e6b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5704,6 +5704,8 @@ def print_multi_directory : Flag<["-", "--"], 
"print-multi-directory">;
 def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
 def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
   HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+  Visibility<[ClangOption]>;
 def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
   Flags<[Unsupported]>;
 def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 0d426a467e9a3b..bb8a4d6915e641 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +

[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2025-01-08 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 9fcdd1760ea664a618a2c05a18e777940a9d49b6 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/4] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From 5799eb81ac94ec4131af146bfacdf44a9bebdd71 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/4] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2025-01-08 Thread Victor Campos via llvm-branch-commits


@@ -122,6 +122,76 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  MacroDefines: [__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag Values (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a

vhscampos wrote:

Thanks. FIxed.

https://github.com/llvm/llvm-project/pull/114998
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2025-01-14 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos edited 
https://github.com/llvm/llvm-project/pull/110659
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Add documentation for Multilib custom flags (PR #114998)

2025-01-14 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/114998

>From 7fd397e918ba2663c7342bc1653c9ccbc5be9d96 Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Tue, 5 Nov 2024 14:22:06 +
Subject: [PATCH 1/4] Add documentation for Multilib custom flags

---
 clang/docs/Multilib.rst | 90 +
 1 file changed, 90 insertions(+)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 7637d0db9565b8..85cb789b9847ac 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -122,6 +122,78 @@ subclass and a suitable base multilib variant is present 
then the
 It is the responsibility of layered multilib authors to ensure that headers and
 libraries in each layer are complete enough to mask any incompatibilities.
 
+Multilib custom flags
+=
+
+Introduction
+
+
+The multilib mechanism supports library variants that correspond to target,
+code generation or language command-line flags. Examples include ``--target``,
+``-mcpu``, ``-mfpu``, ``-mbranch-protection``, ``-fno-rtti``. However, some 
library
+variants are particular to features that do not correspond to any command-line
+option. Multithreading and semihosting, for instance, have no associated
+compiler option.
+
+In order to support the selection of variants for which no compiler option
+exists, the multilib specification includes the concept of *custom flags*.
+These flags have no impact on code generation and are only used in the multilib
+processing.
+
+Multilib custom flags follow this format in the driver invocation:
+
+::
+
+  -fmultilib-flag=
+
+They are fed into the multilib system alongside the remaining flags.
+
+Custom flag declarations
+
+
+Custom flags can be declared in the YAML file under the *Flags* section.
+
+.. code-block:: yaml
+
+  Flags:
+  - Name: multithreaded
+Values:
+- Name: no-multithreaded
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+Default: no-multithreaded
+
+* Name: the name to categorize a flag.
+* Values: a list of flag *Value*s (defined below).
+* Default: it specifies the name of the value this flag should take if not
+  specified in the command-line invocation. It must be one value from the 
Values
+  field.
+
+A Default value is useful to save users from specifying custom flags that have 
a
+most commonly used value.
+
+Each flag *Value* is defined as:
+
+* Name: name of the value. This is the string to be used in
+  ``-fmultilib-flag=``.
+* DriverArgs: a list of strings corresponding to the extra driver arguments
+  used to build a library variant that's in accordance to this specific custom
+  flag value. These arguments are fed back into the driver if this flag *Value*
+  is enabled.
+
+The namespace of flag values is common across all flags. This means that flag
+value names must be unique.
+
+Usage of custom flags in the *Variants* specifications
+--
+
+Library variants should list their requirement on one or more custom flags like
+they do for any other flag. Each requirement must be listed as
+``-fmultilib-flag=``.
+
+A variant that does not specify a requirement on one particular flag can be
+matched against any value of that flag.
+
 Stability
 =
 
@@ -222,6 +294,24 @@ For a more comprehensive example see
 # Flags is a list of one or more strings.
 Flags: [--target=thumbv7m-none-eabi]
 
+  # Custom flag declarations. Each item is a different declaration.
+  Flags:
+# Name of the flag
+  - Name: multithreaded
+# List of custom flag values
+Values:
+  # Name of the custom flag value. To be used in -fmultilib-flag=.
+- Name: no-multithreaded
+  # Extra driver arguments to be printed with -print-multi-lib. Useful for
+  # specifying extra arguments for building the the associated library
+  # variant(s).
+  DriverArgs: [-D__SINGLE_THREAD__]
+- Name: multithreaded
+# Default flag value. If no value for this flag declaration is used in the
+# command-line, the multilib system will use this one. Must be equal to one
+# of the flag value names from this flag declaration.
+Default: no-multithreaded
+
 Design principles
 =
 

>From 27217d74b6be78263e2365ed74600953fc3f353c Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Mon, 25 Nov 2024 15:07:57 +
Subject: [PATCH 2/4] Fix doc build warning

---
 clang/docs/Multilib.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/Multilib.rst b/clang/docs/Multilib.rst
index 85cb789b9847ac..48d84087dda01c 100644
--- a/clang/docs/Multilib.rst
+++ b/clang/docs/Multilib.rst
@@ -164,7 +164,7 @@ Custom flags can be declared in the YAML file under the 
*Flags* section.
 Default: no-multithreaded
 
 * Name: the name to categorize a flag.
-* Values: a list of flag *Value*s (defined below).
+* Values: a list of flag Values (defined b

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2025-01-09 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 2fe418964fff9e03861650afb89a81ac80f1413d Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/6] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 141 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 328 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index c23d037e725bb9..80be9261ec40f7 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -466,7 +466,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 1dab45c062aeec..36bdfdb6157b0b 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fb73b62cf2daed..761876b9fcc53b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1272,8 +1272,8 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
 
   // All arguments, from both config file and command line.
-  InputArgList Args =
-  HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
+  auto UArgs = std::make_unique(HasConfigFileHead ? 
std::move(*CfgOptionsHead) : std::move(*CLOptions));
+  InputArgList &Args =

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2025-01-09 Thread Victor Campos via llvm-branch-commits

https://github.com/vhscampos updated 
https://github.com/llvm/llvm-project/pull/110659

>From 2fe418964fff9e03861650afb89a81ac80f1413d Mon Sep 17 00:00:00 2001
From: Victor Campos 
Date: Thu, 26 Sep 2024 14:44:33 +0100
Subject: [PATCH 1/5] [Multilib] Custom flags processing for library selection

Select library variants in the multilib system using the flags passed
following the '-fmultilib-flag=' format.

Multilib flags that were not passed in the command-line have their
default value fed into the library selection mechanism.

A warning is shown if the flag's value name is invalid. If the wrong
name is close enough to any valid one, according to edit distance, the
closest valid value name is suggested.

Details about this change can be found in this thread:
https://discourse.llvm.org/t/rfc-multilib-custom-flags/81058
---
 clang/include/clang/Driver/Driver.h   |   2 +-
 clang/include/clang/Driver/Multilib.h |  11 +-
 clang/include/clang/Driver/ToolChain.h|   7 +
 clang/lib/Driver/Driver.cpp   | 141 ++
 clang/lib/Driver/Multilib.cpp | 136 -
 clang/lib/Driver/ToolChains/BareMetal.cpp |  22 ++-
 clang/lib/Driver/ToolChains/BareMetal.h   |   5 +
 .../baremetal-multilib-custom-flags.yaml  |  79 ++
 8 files changed, 328 insertions(+), 75 deletions(-)
 create mode 100644 clang/test/Driver/baremetal-multilib-custom-flags.yaml

diff --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index c23d037e725bb9..80be9261ec40f7 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -466,7 +466,7 @@ class Driver {
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
   bool UseDriverMode,
-  bool &ContainsError);
+  bool &ContainsError) const;
 
   /// BuildInputs - Construct the list of inputs and their types from
   /// the given arguments.
diff --git a/clang/include/clang/Driver/Multilib.h 
b/clang/include/clang/Driver/Multilib.h
index 1dab45c062aeec..36bdfdb6157b0b 100644
--- a/clang/include/clang/Driver/Multilib.h
+++ b/clang/include/clang/Driver/Multilib.h
@@ -163,9 +163,18 @@ class MultilibSet {
   const_iterator begin() const { return Multilibs.begin(); }
   const_iterator end() const { return Multilibs.end(); }
 
+  /// Process custom flags from \p Flags and returns an expanded flags list and
+  /// a list of extra compilation arguments.
+  /// Returns a pair where:
+  ///  - first: the new flags list including custom flags after processing.
+  ///  - second: the extra compilation arguments to be fed to the driver.
+  std::pair>
+  processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const;
+
   /// Select compatible variants, \returns false if none are compatible
   bool select(const Driver &D, const Multilib::flags_list &Flags,
-  llvm::SmallVectorImpl &) const;
+  llvm::SmallVectorImpl &,
+  llvm::SmallVector * = nullptr) const;
 
   unsigned size() const { return Multilibs.size(); }
 
diff --git a/clang/include/clang/Driver/ToolChain.h 
b/clang/include/clang/Driver/ToolChain.h
index 5347e29be91439..25f51b7de3e9f5 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -686,6 +686,13 @@ class ToolChain {
   /// Add warning options that need to be passed to cc1 for this target.
   virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
 
+  // Get the list of extra driver arguments strings requested by the multilib
+  // configuration.
+  virtual SmallVector
+  getMultilibDriverArgsStr(llvm::opt::ArgList &Args) const {
+return {};
+  };
+
   // GetRuntimeLibType - Determine the runtime library type to use with the
   // given compilation arguments.
   virtual RuntimeLibType
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fb73b62cf2daed..761876b9fcc53b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -262,7 +262,7 @@ void Driver::setDriverMode(StringRef Value) {
 }
 
 InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings,
- bool UseDriverMode, bool &ContainsError) {
+ bool UseDriverMode, bool &ContainsError) 
const {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
   ContainsError = false;
 
@@ -1272,8 +1272,8 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   bool HasConfigFileTail = !ContainsError && CfgOptionsTail;
 
   // All arguments, from both config file and command line.
-  InputArgList Args =
-  HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);
+  auto UArgs = std::make_unique(HasConfigFileHead ? 
std::move(*CfgOptionsHead) : std::move(*CLOptions));
+  InputArgList &Args =

[llvm-branch-commits] [clang] [Multilib] Custom flags processing for library selection (PR #110659)

2025-01-09 Thread Victor Campos via llvm-branch-commits


@@ -92,12 +93,141 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
 
 void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
 
-bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
- llvm::SmallVectorImpl &Selected) const {
-  llvm::StringSet<> FlagSet(expandFlags(Flags));
+static void DiagnoseUnclaimedMultilibCustomFlags(
+const Driver &D, const SmallVector &UnclaimedCustomFlagValues,
+const SmallVector &CustomFlagDecls) {
+  struct EditDistanceInfo {
+StringRef FlagValue;
+unsigned EditDistance;
+  };
+  const unsigned MaxEditDistance = 5;
+
+  for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
+std::optional BestCandidate;
+for (const auto &Decl : CustomFlagDecls) {
+  for (const auto &Value : Decl->ValueList) {
+const std::string &FlagValueName = Value.Name;
+unsigned EditDistance =
+Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
+/*MaxEditDistance=*/MaxEditDistance);
+if (!BestCandidate || (EditDistance <= MaxEditDistance &&
+   EditDistance < BestCandidate->EditDistance)) {
+  BestCandidate = {FlagValueName, EditDistance};
+}
+  }
+}
+if (!BestCandidate)
+  D.Diag(clang::diag::err_drv_unsupported_opt)
+  << (custom_flag::Prefix + Unclaimed).str();
+else
+  D.Diag(clang::diag::err_drv_unsupported_opt_with_suggestion)
+  << (custom_flag::Prefix + Unclaimed).str()
+  << (custom_flag::Prefix + BestCandidate->FlagValue).str();
+  }
+}
+
+namespace clang::driver::custom_flag {
+// Map implemented using linear searches as the expected size is too small for
+// the overhead of a search tree or a hash table.
+class ValueNameToDetailMap {
+  SmallVector> Mapping;
+
+public:
+  template 
+  ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
+for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
+  const DeclarationPtr &Decl = *DeclIt;
+  for (const auto &Value : Decl->ValueList)
+Mapping.emplace_back(Value.Name, &Value);
+}
+  }
+
+  const ValueDetail *get(StringRef Key) const {
+auto Iter = llvm::find_if(
+Mapping, [&](const auto &Pair) { return Pair.first == Key; });
+return Iter != Mapping.end() ? Iter->second : nullptr;
+  }
+};
+} // namespace clang::driver::custom_flag
+
+std::pair>
+MultilibSet::processCustomFlags(const Driver &D,
+const Multilib::flags_list &Flags) const {
+  Multilib::flags_list Result;
+  SmallVector MacroDefines;
+
+  // Custom flag values detected in the flags list
+  SmallVector ClaimedCustomFlagValues;
+
+  // Arguments to -fmultilib-flag= that don't correspond to any valid
+  // custom flag value. An error will be printed out for each of these.
+  SmallVector UnclaimedCustomFlagValueStrs;
+
+  const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
+  CustomFlagDecls.begin(), CustomFlagDecls.end());
+
+  for (StringRef Flag : Flags) {
+if (!Flag.starts_with(custom_flag::Prefix)) {
+  Result.push_back(Flag.str());
+  continue;
+}
+
+StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
+const custom_flag::ValueDetail *Detail =
+ValueNameToValueDetail.get(CustomFlagValueStr);
+if (Detail)
+  ClaimedCustomFlagValues.push_back(Detail);
+else
+  UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
+  }
+
+  // Set of custom flag declarations for which a value was passed in the flags
+  // list. This is used to, firstly, detect multiple values for the same flag
+  // declaration (in this case, the last one wins), and secondly, to detect
+  // which declarations had no value passed in (in this case, the default value
+  // is selected).
+  llvm::SmallSet TriggeredCustomFlagDecls;
+
+  // Detect multiple values for the same flag declaration. Last one wins.
+  for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
+if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
+  continue;
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
+if (CustomFlagValue->MacroDefines)
+  MacroDefines.append(CustomFlagValue->MacroDefines->begin(),
+  CustomFlagValue->MacroDefines->end());
+  }
+
+  // Detect flag declarations with no value passed in. Select default value.
+  for (const auto &Decl : CustomFlagDecls) {
+if (TriggeredCustomFlagDecls.contains(Decl))
+  continue;
+custom_flag::ValueDetail &CustomFlagValue =
+Decl->ValueList[*Decl->DefaultValueIdx];
+Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
+if (CustomFlagValue.MacroDefines)
+  MacroDefines.append(CustomFlagValue.MacroDefines->begin(),
+  CustomFlagValue.MacroDefines->