[llvm] [llvm] Add a new `Triple::str(N)` method (PR #145150)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 20 22:42:25 PDT 2025
https://github.com/royitaqi created https://github.com/llvm/llvm-project/pull/145150
# Change
Adds a new `Triple::str(N)` method, which returns the triple string but only keep the first N components. See method doc for details.
Note that the return type is `StringRef`. This is different from the existing methods, where `std::string` is returned by `Triple::str()` and `Triple::getTriple()`. The reason for `StringRef` is performance - it's unnecessary to create a new `std::string` object, which copies the content of the triple string.
# Usage
This method can be used to generate a triple which has less trailing components (e.g. to remove the "object format" component). This can be for edit or display purposes.
# Alternatives
**Alternative 1**: Add the same method but return `std::string` for consistency with the existing methods. However, we probably don't want to make unnecessary copies just to make the API look more consistent.
**Alternative 2**: Add a new method called `Triple::clone(N = 5)`, which will return a new triple with the triple string that would be returned by `Triple::str(N)`. However, the user might not want to construct a new triple object, or maybe they want to normalize it before creating such object. `Triple::str(N)` is more flexible.
# Tests
Added `TripleTest::StrFirstN`.
>From 7cf98d07d2cfd3642744ec8d7b691a57357f87a7 Mon Sep 17 00:00:00 2001
From: Roy Shi <royshi at meta.com>
Date: Fri, 20 Jun 2025 22:04:06 -0700
Subject: [PATCH] Add a new Triple::clone() method
---
llvm/include/llvm/TargetParser/Triple.h | 21 +++++
llvm/lib/TargetParser/Triple.cpp | 24 ++++++
llvm/unittests/TargetParser/TripleTest.cpp | 93 ++++++++++++++++++++++
3 files changed, 138 insertions(+)
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 7fd5278f1ed53..6b9e80dc8743a 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -463,6 +463,27 @@ class Triple {
const std::string &str() const { return Data; }
+ /// Return the triple string but only keep the first \p N components.
+ ///
+ /// The returned string will preserve the first \p N components exactly the
+ /// same as the original (including the leading "-" and the value, empty or
+ /// not).
+ ///
+ /// E.g. Triple("arm64-apple-ios").str(5) == "arm64-apple-ios"
+ /// E.g. Triple("arm64-apple-ios--").str(5) == "arm64-apple-ios--"
+ /// E.g. Triple("arm64-apple-ios--").str(4) == "arm64-apple-ios-"
+ /// E.g. Triple("arm64-apple-ios--").str(3) == "arm64-apple-ios"
+ /// E.g. Triple("arm64-apple-ios--").str(2) == "arm64-apple"
+ /// E.g. Triple("arm64-apple-ios--").str(1) == "arm64"
+ /// E.g. Triple("arm64-apple-ios--").str(0) == ""
+ ///
+ /// This method does not normalize any triple strings. Clients that need to
+ /// handle the non-canonical triples that users often specify should use the
+ /// normalize method.
+ ///
+ /// \returns the (shorterned) triple string.
+ StringRef str(size_t N) const;
+
const std::string &getTriple() const { return Data; }
/// Whether the triple is empty / default constructed.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 6a559ff023caa..0fdb62c473e73 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -2107,6 +2107,30 @@ std::string Triple::merge(const Triple &Other) const {
return Other.str();
}
+StringRef Triple::str(size_t N) const {
+ // If empty, return empty
+ if (N == 0 || Data == "")
+ return "";
+
+ // If keeping all components, return a full clone
+ if (N >= 5)
+ return Data;
+
+ // Find the N-th separator (which is after the N'th component)
+ size_t p = StringRef::npos;
+ for (uint32_t i = 0; i < N; ++i) {
+ p = Data.find('-', p + 1);
+ if (p == StringRef::npos)
+ break;
+ }
+
+ // Create a triple
+ if (p == StringRef::npos)
+ return Data;
+ else
+ return StringRef(Data).substr(0, p);
+}
+
bool Triple::isMacOSXVersionLT(unsigned Major, unsigned Minor,
unsigned Micro) const {
assert(isMacOSX() && "Not an OS X triple!");
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index bbd12e6d0e412..ba91e91d08a21 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -2926,4 +2926,97 @@ TEST(TripleTest, isCompatibleWith) {
EXPECT_TRUE(DoTest(C.B, C.A, C.Result));
}
}
+
+TEST(TripleTest, StrFirstN) {
+ // Empty triple
+ {
+ llvm::Triple triple;
+ ASSERT_EQ(triple.str(), "");
+ ASSERT_EQ(triple.str(5), "");
+ }
+
+ // Normal triple with 3 components
+ {
+ llvm::Triple triple("arm64-apple-ios");
+ ASSERT_EQ(triple.str(), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(5), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(4), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(3), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(2), "arm64-apple");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Normal triple with 4 components
+ {
+ llvm::Triple triple("arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(), "arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(5), "arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(4), "arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(3), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(2), "arm64-apple");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Normal triple with 5 components
+ {
+ llvm::Triple triple("arm64-apple-ios-simulator-macho");
+ ASSERT_EQ(triple.str(), "arm64-apple-ios-simulator-macho");
+ ASSERT_EQ(triple.str(5), "arm64-apple-ios-simulator-macho");
+ ASSERT_EQ(triple.str(4), "arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(3), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(2), "arm64-apple");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Empty vendor and os
+ {
+ llvm::Triple triple("arm64---simulator-macho");
+ ASSERT_EQ(triple.str(), "arm64---simulator-macho");
+ ASSERT_EQ(triple.str(5), "arm64---simulator-macho");
+ ASSERT_EQ(triple.str(4), "arm64---simulator");
+ ASSERT_EQ(triple.str(3), "arm64--");
+ ASSERT_EQ(triple.str(2), "arm64-");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Empty environment
+ {
+ llvm::Triple triple("arm64-apple-ios-");
+ ASSERT_EQ(triple.str(), "arm64-apple-ios-");
+ ASSERT_EQ(triple.str(5), "arm64-apple-ios-");
+ ASSERT_EQ(triple.str(4), "arm64-apple-ios-");
+ ASSERT_EQ(triple.str(3), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(2), "arm64-apple");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Empty object format
+ {
+ llvm::Triple triple("arm64-apple-ios-simulator-");
+ ASSERT_EQ(triple.str(), "arm64-apple-ios-simulator-");
+ ASSERT_EQ(triple.str(5), "arm64-apple-ios-simulator-");
+ ASSERT_EQ(triple.str(4), "arm64-apple-ios-simulator");
+ ASSERT_EQ(triple.str(3), "arm64-apple-ios");
+ ASSERT_EQ(triple.str(2), "arm64-apple");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+
+ // Empty environment, but has object format
+ {
+ llvm::Triple triple("arm64----macho");
+ ASSERT_EQ(triple.str(), "arm64----macho");
+ ASSERT_EQ(triple.str(5), "arm64----macho");
+ ASSERT_EQ(triple.str(4), "arm64---");
+ ASSERT_EQ(triple.str(3), "arm64--");
+ ASSERT_EQ(triple.str(2), "arm64-");
+ ASSERT_EQ(triple.str(1), "arm64");
+ ASSERT_EQ(triple.str(0), "");
+ }
+}
} // end anonymous namespace
More information about the llvm-commits
mailing list