[llvm-commits] [llvm] r68252 - in /llvm/trunk: include/llvm/ADT/Triple.h lib/Support/Triple.cpp unittests/ADT/TripleTest.cpp

Daniel Dunbar daniel at zuster.org
Wed Apr 1 14:53:24 PDT 2009


Author: ddunbar
Date: Wed Apr  1 16:53:23 2009
New Revision: 68252

URL: http://llvm.org/viewvc/llvm-project?rev=68252&view=rev
Log:
Add llvm::Triple class for abstracting access to target triples.
 - The code is silly, I'm just amusing myself. Rewrite to be efficient
   if you like. :)

Also, if you wish to debate the proper names of the triple components
I'm all ears.

Added:
    llvm/trunk/include/llvm/ADT/Triple.h
    llvm/trunk/lib/Support/Triple.cpp
    llvm/trunk/unittests/ADT/TripleTest.cpp

Added: llvm/trunk/include/llvm/ADT/Triple.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Triple.h?rev=68252&view=auto

==============================================================================
--- llvm/trunk/include/llvm/ADT/Triple.h (added)
+++ llvm/trunk/include/llvm/ADT/Triple.h Wed Apr  1 16:53:23 2009
@@ -0,0 +1,196 @@
+//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_TRIPLE_H
+#define LLVM_ADT_TRIPLE_H
+
+#include <string>
+
+namespace llvm {
+
+/// Triple - Helper class for working with target triples.
+///
+/// Target triples are strings in the format of:
+///   ARCHITECTURE-VENDOR-OPERATING_SYSTEM
+/// or
+///   ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT
+///
+/// This class is used for clients which want to support arbitrary
+/// target triples, but also want to implement certain special
+/// behavior for particular targets. This class isolates the mapping
+/// from the components of the target triple to well known IDs.
+///
+/// See autoconf/config.guess for a glimpse into what they look like
+/// in practice.
+class Triple {
+public:
+  enum ArchType {
+    UnknownArch,
+    
+    x86,    // i?86
+    ppc,    // powerpc
+    ppc64,  // powerpc64
+    x86_64, // amd64, x86_64
+
+    InvalidArch
+  };
+  enum VendorType {
+    UnknownVendor,
+
+    Apple, 
+    PC
+  };
+  enum OSType {
+    UnknownOS,
+
+    Darwin,
+    FreeBSD,
+    Linux
+  };
+  
+private:
+  std::string Data;
+
+  /// The parsed arch type (or InvalidArch if uninitialized).
+  mutable ArchType Arch;
+
+  /// The parsed vendor type.
+  mutable VendorType Vendor;
+
+  /// The parsed OS type.
+  mutable OSType OS;
+
+  bool isInitialized() const { return Arch != InvalidArch; }
+  void Parse() const;
+
+public:
+  /// @name Constructors
+  /// @{
+  
+  Triple() : Data(""), Arch(InvalidArch) {}
+  explicit Triple(const char *Str) : Data(Str), Arch(InvalidArch) {}
+
+  /// @}
+  /// @name Typed Component Access
+  /// @{
+  
+  /// getArch - Get the parsed architecture type of this triple.
+  ArchType getArch() const { 
+    if (!isInitialized()) Parse(); 
+    return Arch;
+  }
+  
+  /// getVendor - Get the parsed vendor type of this triple.
+  VendorType getVendor() const { 
+    if (!isInitialized()) Parse(); 
+    return Vendor;
+  }
+  
+  /// getOS - Get the parsed operating system type of this triple.
+  OSType getOS() const { 
+    if (!isInitialized()) Parse(); 
+    return OS;
+  }
+
+  /// hasEnvironment - Does this triple have the optional environment
+  /// (fourth) component?
+  bool hasEnvironment() const {
+    return getEnvironmentName() != "";
+  }
+
+  /// @}
+  /// @name Direct Component Access
+  /// @{
+
+  const std::string &getTriple() const { return Data; }
+
+  // FIXME: Invent a lightweight string representation for these to
+  // use.
+
+  /// getArchName - Get the architecture (first) component of the
+  /// triple.
+  std::string getArchName() const;
+
+  /// getVendorName - Get the vendor (second) component of the triple.
+  std::string getVendorName() const;
+
+  /// getOSName - Get the operating system (third) component of the
+  /// triple.
+  std::string getOSName() const;
+
+  /// getEnvironmentName - Get the optional environment (fourth)
+  /// component of the triple, or "" if empty.
+  std::string getEnvironmentName() const;
+
+  /// getOSAndEnvironmentName - Get the operating system and optional
+  /// environment components as a single string (separated by a '-'
+  /// if the environment component is present).
+  std::string getOSAndEnvironmentName() const;
+
+  /// @}
+  /// @name Mutators
+  /// @{
+
+  /// setArch - Set the architecture (first) component of the triple
+  /// to a known type.
+  void setArch(ArchType Kind);
+
+  /// setVendor - Set the vendor (second) component of the triple to a
+  /// known type.
+  void setVendor(VendorType Kind);
+
+  /// setOS - Set the operating system (third) component of the triple
+  /// to a known type.
+  void setOS(OSType Kind);
+
+  /// setTriple - Set all components to the new triple \arg Str.
+  void setTriple(const std::string &Str);
+
+  /// setArchName - Set the architecture (first) component of the
+  /// triple by name.
+  void setArchName(const std::string &Str);
+
+  /// setVendorName - Set the vendor (second) component of the triple
+  /// by name.
+  void setVendorName(const std::string &Str);
+
+  /// setOSName - Set the operating system (third) component of the
+  /// triple by name.
+  void setOSName(const std::string &Str);
+
+  /// setEnvironmentName - Set the optional environment (fourth)
+  /// component of the triple by name.
+  void setEnvironmentName(const std::string &Str);
+
+  /// setOSAndEnvironmentName - Set the operating system and optional
+  /// environment components with a single string.
+  void setOSAndEnvironmentName(const std::string &Str);
+
+  /// @}
+  /// @name Static helpers for IDs.
+  /// @{
+
+  /// getArchTypeName - Get the canonical name for the \arg Kind
+  /// architecture.
+  static const char *getArchTypeName(ArchType Kind);
+
+  /// getVendorTypeName - Get the canonical name for the \arg Kind
+  /// vendor.
+  static const char *getVendorTypeName(VendorType Kind);
+
+  /// getOSTypeName - Get the canonical name for the \arg Kind vendor.
+  static const char *getOSTypeName(OSType Kind);
+
+  /// @}
+};
+
+} // End llvm namespace
+
+
+#endif

Added: llvm/trunk/lib/Support/Triple.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Triple.cpp?rev=68252&view=auto

==============================================================================
--- llvm/trunk/lib/Support/Triple.cpp (added)
+++ llvm/trunk/lib/Support/Triple.cpp Wed Apr  1 16:53:23 2009
@@ -0,0 +1,183 @@
+//===--- Triple.cpp - Target triple helper class --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Triple.h"
+#include <cassert>
+using namespace llvm;
+
+//
+
+const char *Triple::getArchTypeName(ArchType Kind) {
+  switch (Kind) {
+  case InvalidArch: return "<invalid>";
+  case UnknownArch: return "unknown";
+
+  case x86: return "i386";
+  case x86_64: return "x86_64";
+  case ppc: return "powerpc";
+  case ppc64: return "powerpc64";
+  }
+
+  return "<invalid>";
+}
+
+const char *Triple::getVendorTypeName(VendorType Kind) {
+  switch (Kind) {
+  case UnknownVendor: return "unknown";
+
+  case Apple: return "apple";
+  case PC: return "PC";
+  }
+
+  return "<invalid>";
+}
+
+const char *Triple::getOSTypeName(OSType Kind) {
+  switch (Kind) {
+  case UnknownOS: return "unknown";
+
+  case Darwin: return "darwin";
+  case FreeBSD: return "freebsd";
+  case Linux: return "linux";
+  }
+
+  return "<invalid>";
+}
+
+//
+
+void Triple::Parse() const {
+  assert(!isInitialized() && "Invalid parse call.");
+
+  std::string ArchName = getArchName();
+  if (ArchName.size() == 4 && ArchName[0] == 'i' && 
+      ArchName[2] == '8' && ArchName[3] == '6')
+    Arch = x86;
+  else if (ArchName == "amd64" || ArchName == "x86_64")
+    Arch = x86_64;
+  else if (ArchName == "powerpc")
+    Arch = ppc;
+  else if (ArchName == "powerpc64")
+    Arch = ppc64;
+  else
+    Arch = UnknownArch;
+
+  std::string VendorName = getVendorName();
+  if (VendorName == "apple")
+    Vendor = Apple;
+  else if (VendorName == "pc")
+    Vendor = PC;
+  else
+    Vendor = UnknownVendor;
+
+  std::string OSName = getOSName();
+  if (memcmp(&OSName[0], "darwin", 6) == 0)
+    OS = Darwin;
+  else if (memcmp(&OSName[0], "freebsd", 7) == 0)
+    OS = FreeBSD;
+  else if (memcmp(&OSName[0], "linux", 5) == 0)
+    OS = Linux;
+  else
+    OS = UnknownOS;
+
+  assert(isInitialized() && "Failed to initialize!");
+}
+
+static std::string extract(const std::string &A,
+                           std::string::size_type begin,
+                           std::string::size_type end) {
+  if (begin == std::string::npos)
+    return "";
+  if (end == std::string::npos)
+    return A.substr(begin);
+  return A.substr(begin, end - begin);
+}
+
+static std::string extract1(const std::string &A,
+                           std::string::size_type begin,
+                           std::string::size_type end) {
+  if (begin == std::string::npos || begin == end)
+    return "";
+  return extract(A, begin + 1, end);
+}
+
+std::string Triple::getArchName() const {
+  std::string Tmp = Data;
+  return extract(Tmp, 0, Tmp.find('-'));
+}
+
+std::string Triple::getVendorName() const {
+  std::string Tmp = Data;
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  return extract(Tmp, 0, Tmp.find('-'));
+}
+
+std::string Triple::getOSName() const {
+  std::string Tmp = Data;
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  return extract(Tmp, 0, Tmp.find('-'));
+}
+
+std::string Triple::getEnvironmentName() const {
+  std::string Tmp = Data;
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  return extract(Tmp, 0, std::string::npos);
+}
+
+std::string Triple::getOSAndEnvironmentName() const {
+  std::string Tmp = Data;
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  Tmp = extract1(Tmp, Tmp.find('-'), std::string::npos);
+  return extract(Tmp, 0, std::string::npos);
+}
+
+void Triple::setTriple(const std::string &Str) {
+  Data = Str;
+  Arch = InvalidArch;
+}
+
+void Triple::setArch(ArchType Kind) {
+  setArchName(getArchTypeName(Kind));
+}
+
+void Triple::setVendor(VendorType Kind) {
+  setVendorName(getVendorTypeName(Kind));
+}
+
+void Triple::setOS(OSType Kind) {
+  setOSName(getOSTypeName(Kind));
+}
+
+void Triple::setArchName(const std::string &Str) {
+  setTriple(Str + "-" + getVendorName() + "-" + getOSAndEnvironmentName());
+}
+
+void Triple::setVendorName(const std::string &Str) {
+  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
+}
+
+void Triple::setOSName(const std::string &Str) {
+  if (hasEnvironment())
+    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
+              "-" + getEnvironmentName());
+  else
+    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
+}
+
+void Triple::setEnvironmentName(const std::string &Str) {
+  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + 
+            "-" + Str);
+}
+
+void Triple::setOSAndEnvironmentName(const std::string &Str) {
+  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
+}

Added: llvm/trunk/unittests/ADT/TripleTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/TripleTest.cpp?rev=68252&view=auto

==============================================================================
--- llvm/trunk/unittests/ADT/TripleTest.cpp (added)
+++ llvm/trunk/unittests/ADT/TripleTest.cpp Wed Apr  1 16:53:23 2009
@@ -0,0 +1,137 @@
+//===----------- Triple.cpp - Triple unit tests ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(TripleTest, BasicParsing) {
+  Triple T;
+
+  T = Triple("");
+  EXPECT_EQ(T.getArchName(), "");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("-");
+  EXPECT_EQ(T.getArchName(), "");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("--");
+  EXPECT_EQ(T.getArchName(), "");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("---");
+  EXPECT_EQ(T.getArchName(), "");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("----");
+  EXPECT_EQ(T.getArchName(), "");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "-");
+
+  T = Triple("a");
+  EXPECT_EQ(T.getArchName(), "a");
+  EXPECT_EQ(T.getVendorName(), "");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("a-b");
+  EXPECT_EQ(T.getArchName(), "a");
+  EXPECT_EQ(T.getVendorName(), "b");
+  EXPECT_EQ(T.getOSName(), "");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("a-b-c");
+  EXPECT_EQ(T.getArchName(), "a");
+  EXPECT_EQ(T.getVendorName(), "b");
+  EXPECT_EQ(T.getOSName(), "c");
+  EXPECT_EQ(T.getEnvironmentName(), "");
+
+  T = Triple("a-b-c-d");
+  EXPECT_EQ(T.getArchName(), "a");
+  EXPECT_EQ(T.getVendorName(), "b");
+  EXPECT_EQ(T.getOSName(), "c");
+  EXPECT_EQ(T.getEnvironmentName(), "d");
+}
+
+TEST(TripleTest, ParsedIDs) {
+  Triple T;
+
+  T = Triple("i386-apple-darwin");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::Apple);
+  EXPECT_EQ(T.getOS(), Triple::Darwin);
+
+  T = Triple("x86_64-pc-linux-gnu");
+  EXPECT_EQ(T.getArch(), Triple::x86_64);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getOS(), Triple::Linux);
+
+  T = Triple("powerpc-dunno-notsure");
+  EXPECT_EQ(T.getArch(), Triple::ppc);
+  EXPECT_EQ(T.getVendor(), Triple::UnknownVendor);
+  EXPECT_EQ(T.getOS(), Triple::UnknownOS);
+
+  T = Triple("huh");
+  EXPECT_EQ(T.getArch(), Triple::UnknownArch);
+}
+
+TEST(TripleTest, MutateName) {
+  Triple T;
+  EXPECT_EQ(T.getArch(), Triple::UnknownArch);
+  EXPECT_EQ(T.getVendor(), Triple::UnknownVendor);
+  EXPECT_EQ(T.getOS(), Triple::UnknownOS);
+
+  T.setArchName("i386");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getTriple(), "i386--");
+
+  T.setVendorName("pc");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getTriple(), "i386-pc-");
+
+  T.setOSName("linux");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getOS(), Triple::Linux);
+  EXPECT_EQ(T.getTriple(), "i386-pc-linux");
+
+  T.setEnvironmentName("gnu");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getOS(), Triple::Linux);
+  EXPECT_EQ(T.getTriple(), "i386-pc-linux-gnu");
+
+  T.setOSName("freebsd");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getOS(), Triple::FreeBSD);
+  EXPECT_EQ(T.getTriple(), "i386-pc-freebsd-gnu");
+
+  T.setOSAndEnvironmentName("darwin");
+  EXPECT_EQ(T.getArch(), Triple::x86);
+  EXPECT_EQ(T.getVendor(), Triple::PC);
+  EXPECT_EQ(T.getOS(), Triple::Darwin);
+  EXPECT_EQ(T.getTriple(), "i386-pc-darwin");
+}
+
+}





More information about the llvm-commits mailing list