Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 1 | //===--- Driver.cpp - Clang GCC Compatible Driver -----------------------*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 10 | #include "clang/Driver/Driver.h" |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 11 | |
Daniel Dunbar | d6f0e37 | 2009-03-04 20:49:20 +0000 | [diff] [blame] | 12 | #include "clang/Driver/Arg.h" |
| 13 | #include "clang/Driver/ArgList.h" |
| 14 | #include "clang/Driver/Compilation.h" |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 15 | #include "clang/Driver/HostInfo.h" |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 16 | #include "clang/Driver/Option.h" |
Daniel Dunbar | d6f0e37 | 2009-03-04 20:49:20 +0000 | [diff] [blame] | 17 | #include "clang/Driver/Options.h" |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 18 | |
| 19 | #include "llvm/Support/raw_ostream.h" |
Daniel Dunbar | d6f0e37 | 2009-03-04 20:49:20 +0000 | [diff] [blame] | 20 | using namespace clang::driver; |
| 21 | |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 22 | Driver::Driver(const char *_Name, const char *_Dir, |
| 23 | const char *_DefaultHostTriple) |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 24 | : Opts(new OptTable()), |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 25 | Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple), |
| 26 | Host(0), |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 27 | CCCIsCXX(false), CCCEcho(false), |
| 28 | CCCNoClang(false), CCCNoClangCXX(false), CCCNoClangCPP(false) |
| 29 | { |
Daniel Dunbar | d6f0e37 | 2009-03-04 20:49:20 +0000 | [diff] [blame] | 30 | |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 31 | } |
| 32 | |
| 33 | Driver::~Driver() { |
Daniel Dunbar | d6f0e37 | 2009-03-04 20:49:20 +0000 | [diff] [blame] | 34 | delete Opts; |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 35 | } |
| 36 | |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 37 | ArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) { |
| 38 | ArgList *Args = new ArgList(ArgBegin, ArgEnd); |
| 39 | |
| 40 | unsigned Index = 0, End = ArgEnd - ArgBegin; |
| 41 | while (Index < End) { |
| 42 | unsigned Prev = Index; |
| 43 | Arg *A = getOpts().ParseOneArg(*Args, Index, End); |
| 44 | if (A) |
| 45 | Args->append(A); |
| 46 | |
| 47 | assert(Index > Prev && "Parser failed to consume argument."); |
| 48 | } |
| 49 | |
| 50 | return Args; |
| 51 | } |
| 52 | |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 53 | Compilation *Driver::BuildCompilation(int argc, const char **argv) { |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 54 | // FIXME: This stuff needs to go into the Compilation, not the |
| 55 | // driver. |
| 56 | bool CCCPrintOptions = false, CCCPrintPhases = false; |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 57 | |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 58 | const char **Start = argv + 1, **End = argv + argc; |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 59 | const char *HostTriple = DefaultHostTriple.c_str(); |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 60 | |
| 61 | // Read -ccc args. |
| 62 | // |
| 63 | // FIXME: We need to figure out where this behavior should |
| 64 | // live. Most of it should be outside in the client; the parts that |
| 65 | // aren't should have proper options, either by introducing new ones |
| 66 | // or by overloading gcc ones like -V or -b. |
| 67 | for (; Start != End && memcmp(*Start, "-ccc-", 5) == 0; ++Start) { |
| 68 | const char *Opt = *Start + 5; |
| 69 | |
| 70 | if (!strcmp(Opt, "print-options")) { |
| 71 | CCCPrintOptions = true; |
| 72 | } else if (!strcmp(Opt, "print-phases")) { |
| 73 | CCCPrintPhases = true; |
| 74 | } else if (!strcmp(Opt, "cxx")) { |
| 75 | CCCIsCXX = true; |
| 76 | } else if (!strcmp(Opt, "echo")) { |
| 77 | CCCEcho = true; |
| 78 | |
| 79 | } else if (!strcmp(Opt, "no-clang")) { |
| 80 | CCCNoClang = true; |
| 81 | } else if (!strcmp(Opt, "no-clang-cxx")) { |
| 82 | CCCNoClangCXX = true; |
| 83 | } else if (!strcmp(Opt, "no-clang-cpp")) { |
| 84 | CCCNoClangCPP = true; |
| 85 | } else if (!strcmp(Opt, "clang-archs")) { |
| 86 | assert(Start+1 < End && "FIXME: -ccc- argument handling."); |
| 87 | const char *Cur = *++Start; |
| 88 | |
| 89 | for (;;) { |
| 90 | const char *Next = strchr(Cur, ','); |
| 91 | |
| 92 | if (Next) { |
| 93 | CCCClangArchs.insert(std::string(Cur, Next)); |
| 94 | Cur = Next + 1; |
| 95 | } else { |
| 96 | CCCClangArchs.insert(std::string(Cur)); |
| 97 | break; |
| 98 | } |
| 99 | } |
| 100 | |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 101 | } else if (!strcmp(Opt, "host-triple")) { |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 102 | assert(Start+1 < End && "FIXME: -ccc- argument handling."); |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 103 | HostTriple = *++Start; |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 104 | |
| 105 | } else { |
| 106 | // FIXME: Error handling. |
| 107 | llvm::errs() << "invalid option: " << *Start << "\n"; |
| 108 | exit(1); |
| 109 | } |
| 110 | } |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 111 | |
| 112 | Host = Driver::GetHostInfo(HostTriple); |
| 113 | |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 114 | ArgList *Args = ParseArgStrings(Start, End); |
| 115 | |
| 116 | // FIXME: This behavior shouldn't be here. |
| 117 | if (CCCPrintOptions) { |
| 118 | PrintOptions(Args); |
| 119 | exit(0); |
| 120 | } |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 121 | |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 122 | assert(0 && "FIXME: Implement"); |
| 123 | |
| 124 | return new Compilation(); |
| 125 | } |
| 126 | |
| 127 | void Driver::PrintOptions(const ArgList *Args) { |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 128 | unsigned i = 0; |
Daniel Dunbar | b282ced | 2009-03-10 20:52:46 +0000 | [diff] [blame] | 129 | for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 130 | it != ie; ++it, ++i) { |
| 131 | Arg *A = *it; |
| 132 | llvm::errs() << "Option " << i << " - " |
| 133 | << "Name: \"" << A->getOption().getName() << "\", " |
| 134 | << "Values: {"; |
| 135 | for (unsigned j = 0; j < A->getNumValues(); ++j) { |
| 136 | if (j) |
| 137 | llvm::errs() << ", "; |
| 138 | llvm::errs() << '"' << A->getValue(*Args, j) << '"'; |
| 139 | } |
| 140 | llvm::errs() << "}\n"; |
Daniel Dunbar | 7dc2a04 | 2009-03-05 06:38:47 +0000 | [diff] [blame] | 141 | } |
Daniel Dunbar | 63c4da9 | 2009-03-02 19:59:07 +0000 | [diff] [blame] | 142 | } |
Daniel Dunbar | d25acaa | 2009-03-10 23:41:59 +0000 | [diff] [blame^] | 143 | |
| 144 | HostInfo *Driver::GetHostInfo(const char *Triple) { |
| 145 | // Dice into arch, platform, and OS. This matches |
| 146 | // arch,platform,os = '(.*?)-(.*?)-(.*?)' |
| 147 | // and missing fields are left empty. |
| 148 | std::string Arch, Platform, OS; |
| 149 | |
| 150 | if (const char *ArchEnd = strchr(Triple, '-')) { |
| 151 | Arch = std::string(Triple, ArchEnd); |
| 152 | |
| 153 | if (const char *PlatformEnd = strchr(ArchEnd+1, '-')) { |
| 154 | Platform = std::string(ArchEnd+1, PlatformEnd); |
| 155 | OS = PlatformEnd+1; |
| 156 | } else |
| 157 | Platform = ArchEnd+1; |
| 158 | } else |
| 159 | Arch = Triple; |
| 160 | |
| 161 | if (memcmp(&Platform[0], "darwin", 6) == 0) |
| 162 | return new DarwinHostInfo(Arch.c_str(), Platform.c_str(), OS.c_str()); |
| 163 | |
| 164 | return new UnknownHostInfo(Arch.c_str(), Platform.c_str(), OS.c_str()); |
| 165 | } |