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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44551 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index f26fb99..5a27d8f 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -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");