[cfe-commits] r44551 - in /cfe/trunk: Basic/TargetInfo.cpp Driver/Targets.cpp Driver/clang.cpp Driver/clang.h include/clang/Basic/TargetInfo.h test/Parser/portability.c

Ted Kremenek kremenek at apple.com
Mon Dec 3 14:06:57 PST 2007


Author: kremenek
Date: Mon Dec  3 16:06:55 2007
New Revision: 44551

URL: http://llvm.org/viewvc/llvm-project?rev=44551&view=rev
Log:
Implemented initial support for "-triple" option to the clang driver. This
replaces the functionality previously provided by just "-arch" (which is still
supported but has different semantics).

The new behavior is as follows:

(1) If the user does not specify -triple:

   (a) If no -arch options are specified, the target triple used is the host
   triple (in llvm/Config/config.h).
   
   (b) If one or more -arch's are specified (and no -triple), then there is
       one triple for each -arch, where the specified arch is substituted
       for the arch in the host triple.  Example:
          host triple = i686-apple-darwin9
          command: clang  -arch ppc -arch ppc64 ...
          triples used: ppc-apple-darwin9  ppc64-apple-darwin9
          
(2) The user does specify a -triple (only one allowed):

  (a) If no -arch options are specified, the triple specified by -triple
      is used.  E.g clang -triple i686-apple-darwin9
      
  (b) If one or more -arch options are specified, then the triple specified
      by -triple is used as the primary target, and the arch's specified
      by -arch are used to create secondary targets.  For example:
      
      clang -triple i686-apple-darwin9 -arch ppc -arch ppc64
      
      has the following targets:
         i686-apple-darwin9  (primary target)
         ppc-apple-darwin9
         ppc64-apple-darwin9


Other changes related to the changes to the driver:

- TargetInfoImpl now includes the triple string.

- TargetInfo::getTargetTriple returns the triple for its primary target.

- test case test/Parser/portability.c has been updated because "-arch linux" is
  no longer valid ("linux" is an OS, not an arch); instead we use a bogus
  architecture "bogusW16W16" where WCharWidth=16 and WCharAlign=16.

Modified:
    cfe/trunk/Basic/TargetInfo.cpp
    cfe/trunk/Driver/Targets.cpp
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/Driver/clang.h
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/test/Parser/portability.c

Modified: cfe/trunk/Basic/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Basic/TargetInfo.cpp?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/Basic/TargetInfo.cpp (original)
+++ cfe/trunk/Basic/TargetInfo.cpp Mon Dec  3 16:06:55 2007
@@ -52,6 +52,10 @@
 
 //===----------------------------------------------------------------------===//
 
+const char* TargetInfo::getTargetTriple() const {
+  return PrimaryTarget->getTargetTriple();
+}
+
 /// DiagnoseNonPortability - When a use of a non-portable target feature is
 /// used, this method emits the diagnostic and marks the translation unit as
 /// non-portable.

Modified: cfe/trunk/Driver/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/Targets.cpp?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/Driver/Targets.cpp (original)
+++ cfe/trunk/Driver/Targets.cpp Mon Dec  3 16:06:55 2007
@@ -18,24 +18,10 @@
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/CommandLine.h"
-using namespace clang;
-
-/// Note: a hard coded list of targets is clearly silly, these should be
-/// dynamicly registered and loadable with "-load".
-enum SupportedTargets {
-  target_ppc, target_ppc64,
-  target_i386, target_x86_64,
-  target_linux_i386
-};
+#include <algorithm>
+#include <cctype>
 
-static llvm::cl::list<SupportedTargets>
-Archs("arch", llvm::cl::desc("Architectures to compile for"),
-llvm::cl::values(clEnumValN(target_ppc,       "ppc",   "32-bit Darwin PowerPC"),
-                 clEnumValN(target_ppc64,     "ppc64", "64-bit Darwin PowerPC"),
-                 clEnumValN(target_i386,      "i386",  "32-bit Darwin X86"),
-                 clEnumValN(target_x86_64,    "x86_64","64-bit Darwin X86"),
-                 clEnumValN(target_linux_i386,"linux", "Linux i386"),
-                 clEnumValEnd));
+using namespace clang;
 
 //===----------------------------------------------------------------------===//
 //  Common code shared among targets.
@@ -55,6 +41,8 @@
 namespace {
 class DarwinTargetInfo : public TargetInfoImpl {
 public:
+  DarwinTargetInfo(const std::string& triple) : TargetInfoImpl(triple) {}
+  
   virtual void getTargetDefines(std::vector<char> &Defs) const {
 // FIXME: we need a real target configuration system.  For now, only define
 // __APPLE__ if the host has it.
@@ -504,6 +492,8 @@
 namespace {
 class DarwinPPCTargetInfo : public DarwinTargetInfo {
 public:
+  DarwinPPCTargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
+  
   virtual void getTargetDefines(std::vector<char> &Defines) const {
     DarwinTargetInfo::getTargetDefines(Defines);
     getPowerPCDefines(Defines, false);
@@ -536,6 +526,8 @@
 namespace {
 class DarwinPPC64TargetInfo : public DarwinTargetInfo {
 public:
+  DarwinPPC64TargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
+  
   virtual void getTargetDefines(std::vector<char> &Defines) const {
     DarwinTargetInfo::getTargetDefines(Defines);
     getPowerPCDefines(Defines, true);
@@ -568,6 +560,8 @@
 namespace {
 class DarwinI386TargetInfo : public DarwinTargetInfo {
 public:
+  DarwinI386TargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {}
+  
   virtual void getTargetDefines(std::vector<char> &Defines) const {
     DarwinTargetInfo::getTargetDefines(Defines);
     getX86Defines(Defines, false);
@@ -600,6 +594,8 @@
 namespace {
 class DarwinX86_64TargetInfo : public DarwinTargetInfo {
 public:
+  DarwinX86_64TargetInfo(const std::string& triple) :DarwinTargetInfo(triple) {}
+  
   virtual void getTargetDefines(std::vector<char> &Defines) const {
     DarwinTargetInfo::getTargetDefines(Defines);
     getX86Defines(Defines, true);
@@ -632,7 +628,7 @@
 namespace {
 class LinuxTargetInfo : public DarwinTargetInfo {
 public:
-  LinuxTargetInfo() {
+  LinuxTargetInfo(const std::string& triple) : DarwinTargetInfo(triple) {
     // Note: I have no idea if this is right, just for testing.
     WCharWidth = 16;
     WCharAlign = 16;
@@ -672,48 +668,52 @@
 // Driver code
 //===----------------------------------------------------------------------===//
 
+static bool IsX86(const std::string& TT) {
+  return (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
+          TT[4] == '-' && TT[1] - '3' < 6);
+}
+
 /// CreateTarget - Create the TargetInfoImpl object for the specified target
 /// enum value.
-static TargetInfoImpl *CreateTarget(SupportedTargets T) {
-  switch (T) {
-  default: assert(0 && "Unknown target!");
-  case target_ppc:        return new DarwinPPCTargetInfo();
-  case target_ppc64:      return new DarwinPPC64TargetInfo();
-  case target_i386:       return new DarwinI386TargetInfo();
-  case target_x86_64:     return new DarwinX86_64TargetInfo();
-  case target_linux_i386: return new LinuxTargetInfo();
+static TargetInfoImpl *CreateTarget(const std::string& T) {
+  if (T.find("darwin") != std::string::npos) {
+    if (T.find("ppc-") == 0)
+      return new DarwinPPCTargetInfo(T);
+    else if (T.find("ppc64-") == 0)
+      return new DarwinPPC64TargetInfo(T);
+    else if (T.find("x86_64-") == 0)
+      return new DarwinX86_64TargetInfo(T);
+    else if (IsX86(T))
+      return new DarwinI386TargetInfo(T);
+    else if (T.find("bogusW16W16-") == 0) // For testing portability.
+      return new LinuxTargetInfo(T);
+  }
+  else { 
+    // Make a copy of the triple that is all lowercase.
+    std::string T_lower(T);    
+    std::transform(T_lower.begin(), T_lower.end(),
+                   T_lower.begin(), (int(*)(int)) std::tolower);
+
+    if (T_lower.find("linux") != std::string::npos && IsX86(T))
+      return new LinuxTargetInfo(T);
   }
+  
+  assert (false && "Unknown target!");
 }
 
 /// CreateTargetInfo - Return the set of target info objects as specified by
 /// the -arch command line option.
-TargetInfo *clang::CreateTargetInfo(Diagnostic &Diags) {
-  // If the user didn't specify at least one architecture, auto-sense the
-  // current host.  TODO: This is a hack. :)
-  if (Archs.empty()) {
-#ifndef __APPLE__
-    // Assume non-apple = i386 for now.
-    Archs.push_back(target_i386);
-#elif (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
-      defined(__ppc64__)
-    Archs.push_back(target_ppc64);
-#elif defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
-    Archs.push_back(target_ppc);
-#elif defined(__x86_64__)
-    Archs.push_back(target_x86_64);
-#elif defined(__i386__) || defined(i386) || defined(_M_IX86)
-    Archs.push_back(target_i386);
-#else
-    // Don't know what this is!
-    return 0;
-#endif
-  }
+TargetInfo *clang::CreateTargetInfo(const std::vector<std::string>& triples, 
+                                    Diagnostic &Diags) {
 
+  assert (!triples.empty() && "No target triple.");
+  
   // Create the primary target and target info.
-  TargetInfo *TI = new TargetInfo(CreateTarget(Archs[0]), &Diags);
+  TargetInfo *TI = new TargetInfo(CreateTarget(triples[0]), &Diags);
   
   // Add all secondary targets.
-  for (unsigned i = 1, e = Archs.size(); i != e; ++i)
-    TI->AddSecondaryTarget(CreateTarget(Archs[i]));
+  for (unsigned i = 1, e = triples.size(); i != e; ++i)
+    TI->AddSecondaryTarget(CreateTarget(triples[i]));
+  
   return TI;
 }

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Mon Dec  3 16:06:55 2007
@@ -36,6 +36,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/System/Signals.h"
+#include "llvm/Config/config.h"
 #include <memory>
 using namespace clang;
 
@@ -390,6 +391,67 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Target Triple Processing.
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<std::string>
+TargetTriple("triple",
+  llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9)."));
+
+static llvm::cl::list<std::string>
+Archs("arch",
+  llvm::cl::desc("Specify target architecture (e.g. i686)."));
+
+namespace {
+  class TripleProcessor {
+    llvm::StringMap<char> TriplesProcessed;
+    std::vector<std::string>& triples;
+  public:
+    TripleProcessor(std::vector<std::string>& t) :  triples(t) {}
+    
+    void addTriple(const std::string& t) {
+      if (TriplesProcessed.find(t.c_str(),t.c_str()+t.size()) ==
+          TriplesProcessed.end()) {
+        triples.push_back(t);
+        TriplesProcessed.GetOrCreateValue(t.c_str(),t.c_str()+t.size());
+      }
+    }
+  };
+}
+
+static void CreateTargetTriples(std::vector<std::string>& triples) {
+  std::string base_triple;
+  
+  // Initialize base triple.  If a -triple option has been specified, use
+  // that triple.  Otherwise, default to the host triple.
+  if (TargetTriple.getValue().empty())
+    base_triple = LLVM_HOSTTRIPLE;
+  else
+    base_triple = TargetTriple.getValue();
+  
+  // Decompose the base triple into "arch" and suffix.
+  std::string::size_type firstDash = base_triple.find("-");
+  
+  // FIXME: Make this a diagnostic.
+  assert (firstDash != std::string::npos);
+  
+  std::string suffix(base_triple,firstDash+1);
+  // FIXME: Make this a diagnostic.
+  assert (!suffix.empty());
+
+  // Create triple cacher.
+  TripleProcessor tp(triples);
+
+  // Add the primary triple to our set of triples if we are using the
+  // host-triple with no archs or using a specified target triple.
+  if (!TargetTriple.getValue().empty() || Archs.empty())
+    tp.addTriple(base_triple);
+           
+  for (unsigned i = 0, e = Archs.size(); i !=e; ++i)
+    tp.addTriple(Archs[i] + "-" + suffix);
+}
+
+//===----------------------------------------------------------------------===//
 // Preprocessor Initialization
 //===----------------------------------------------------------------------===//
 
@@ -914,7 +976,19 @@
   // Get information about the targets being compiled for.  Note that this
   // pointer and the TargetInfoImpl objects are never deleted by this toy
   // driver.
-  TargetInfo *Target = CreateTargetInfo(Diags);
+  TargetInfo *Target;
+  
+  { // Create triples, and create the TargetInfo.
+    std::vector<std::string> triples;
+    CreateTargetTriples(triples);
+    fprintf(stderr, "Targets:");
+    for (std::vector<std::string>::iterator I = triples.begin(), E = triples.end(); I !=E ; ++I)
+      fprintf (stderr, " %s", I->c_str());
+    fprintf(stderr,"\n");
+      
+    Target = CreateTargetInfo(triples,Diags);
+  }
+  
   if (Target == 0) {
     fprintf(stderr,
             "Sorry, don't know what target this is, please use -arch.\n");

Modified: cfe/trunk/Driver/clang.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.h?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.h (original)
+++ cfe/trunk/Driver/clang.h Mon Dec  3 16:06:55 2007
@@ -14,6 +14,9 @@
 #ifndef LLVM_CLANG_CLANG_H
 #define LLVM_CLANG_CLANG_H
 
+#include <vector>
+#include <string>
+
 namespace clang {
 class Preprocessor;
 struct LangOptions;
@@ -33,7 +36,8 @@
 
 /// CreateTargetInfo - Return the set of target info objects as specified by
 /// the -arch command line option.
-TargetInfo *CreateTargetInfo(Diagnostic &Diags);
+TargetInfo *CreateTargetInfo(const std::vector<std::string>& triples,
+                             Diagnostic &Diags);
 
 /// EmitLLVMFromASTs - Implement -emit-llvm, which generates llvm IR from C.
 void EmitLLVMFromASTs(Preprocessor &PP, unsigned MainFileID,

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Mon Dec  3 16:06:55 2007
@@ -245,11 +245,10 @@
     return static_cast<unsigned>(Size);
   }
 
-  const char *getTargetTriple() {
-    // FIXME !
-    return "i686-apple-darwin9";
-  }
-  const char *getTargetDescription() {
+  /// getTargetTriple - Return the target triple of the primary target.
+  const char *getTargetTriple() const;
+  
+  const char *getTargetDescription() const {
     // FIXME !
     // Hard code darwin-x86 for now.
     return "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:\
@@ -270,10 +269,17 @@
 protected:
   unsigned WCharWidth;    /// sizeof(wchar_t) in bits.  Default value is 32.
   unsigned WCharAlign;    /// alignof(wchar_t) in bits.  Default value is 32.
+  std::string Triple;
 public:
-  TargetInfoImpl() : WCharWidth(32), WCharAlign(32) {}
+  TargetInfoImpl(const std::string& triple) 
+    : WCharWidth(32), WCharAlign(32), Triple(triple) {}
+  
   virtual ~TargetInfoImpl() {}
   
+  /// getTargetTriple - Return the string representing the target triple this
+  ///  TargetInfoImpl object was created from.
+  const char* getTargetTriple() const { return Triple.c_str(); }
+  
   /// getTargetDefines - Return a list of the target-specific #define values set
   /// when compiling to this target.  Each string should be of the form
   /// "#define X Y\n".

Modified: cfe/trunk/test/Parser/portability.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/portability.c?rev=44551&r1=44550&r2=44551&view=diff

==============================================================================
--- cfe/trunk/test/Parser/portability.c (original)
+++ cfe/trunk/test/Parser/portability.c Mon Dec  3 16:06:55 2007
@@ -1,4 +1,4 @@
-// RUN: clang -arch ppc -arch linux -fsyntax-only %s 2>&1 | grep note | wc -l | grep 1
+// RUN: clang -arch ppc -arch bogusW16W16 -fsyntax-only %s 2>&1 | grep note | wc -l | grep 1
 
 // wchar_t varies across targets.
 void *X = L"foo";





More information about the cfe-commits mailing list