blob: 4b29ae394cf84d716851b321b9bcd8b6efb69dab [file] [log] [blame]
Daniel Dunbar63c4da92009-03-02 19:59:07 +00001//===--- 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 Dunbar63c4da92009-03-02 19:59:07 +000010#include "clang/Driver/Driver.h"
Daniel Dunbar63c4da92009-03-02 19:59:07 +000011
Daniel Dunbard6f0e372009-03-04 20:49:20 +000012#include "clang/Driver/Arg.h"
13#include "clang/Driver/ArgList.h"
14#include "clang/Driver/Compilation.h"
Daniel Dunbard25acaa2009-03-10 23:41:59 +000015#include "clang/Driver/HostInfo.h"
Daniel Dunbar7dc2a042009-03-05 06:38:47 +000016#include "clang/Driver/Option.h"
Daniel Dunbard6f0e372009-03-04 20:49:20 +000017#include "clang/Driver/Options.h"
Daniel Dunbar7dc2a042009-03-05 06:38:47 +000018
19#include "llvm/Support/raw_ostream.h"
Daniel Dunbard6f0e372009-03-04 20:49:20 +000020using namespace clang::driver;
21
Daniel Dunbard25acaa2009-03-10 23:41:59 +000022Driver::Driver(const char *_Name, const char *_Dir,
23 const char *_DefaultHostTriple)
Daniel Dunbarb282ced2009-03-10 20:52:46 +000024 : Opts(new OptTable()),
Daniel Dunbard25acaa2009-03-10 23:41:59 +000025 Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
26 Host(0),
Daniel Dunbarb282ced2009-03-10 20:52:46 +000027 CCCIsCXX(false), CCCEcho(false),
28 CCCNoClang(false), CCCNoClangCXX(false), CCCNoClangCPP(false)
29{
Daniel Dunbard6f0e372009-03-04 20:49:20 +000030
Daniel Dunbar63c4da92009-03-02 19:59:07 +000031}
32
33Driver::~Driver() {
Daniel Dunbard6f0e372009-03-04 20:49:20 +000034 delete Opts;
Daniel Dunbar63c4da92009-03-02 19:59:07 +000035}
36
Daniel Dunbar7dc2a042009-03-05 06:38:47 +000037ArgList *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 Dunbar63c4da92009-03-02 19:59:07 +000053Compilation *Driver::BuildCompilation(int argc, const char **argv) {
Daniel Dunbarb282ced2009-03-10 20:52:46 +000054 // FIXME: This stuff needs to go into the Compilation, not the
55 // driver.
56 bool CCCPrintOptions = false, CCCPrintPhases = false;
Daniel Dunbar7dc2a042009-03-05 06:38:47 +000057
Daniel Dunbarb282ced2009-03-10 20:52:46 +000058 const char **Start = argv + 1, **End = argv + argc;
Daniel Dunbard25acaa2009-03-10 23:41:59 +000059 const char *HostTriple = DefaultHostTriple.c_str();
Daniel Dunbarb282ced2009-03-10 20:52:46 +000060
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 Dunbard25acaa2009-03-10 23:41:59 +0000101 } else if (!strcmp(Opt, "host-triple")) {
Daniel Dunbarb282ced2009-03-10 20:52:46 +0000102 assert(Start+1 < End && "FIXME: -ccc- argument handling.");
Daniel Dunbard25acaa2009-03-10 23:41:59 +0000103 HostTriple = *++Start;
Daniel Dunbarb282ced2009-03-10 20:52:46 +0000104
105 } else {
106 // FIXME: Error handling.
107 llvm::errs() << "invalid option: " << *Start << "\n";
108 exit(1);
109 }
110 }
Daniel Dunbard25acaa2009-03-10 23:41:59 +0000111
112 Host = Driver::GetHostInfo(HostTriple);
113
Daniel Dunbarb282ced2009-03-10 20:52:46 +0000114 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 Dunbard25acaa2009-03-10 23:41:59 +0000121
Daniel Dunbarb282ced2009-03-10 20:52:46 +0000122 assert(0 && "FIXME: Implement");
123
124 return new Compilation();
125}
126
127void Driver::PrintOptions(const ArgList *Args) {
Daniel Dunbar7dc2a042009-03-05 06:38:47 +0000128 unsigned i = 0;
Daniel Dunbarb282ced2009-03-10 20:52:46 +0000129 for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
Daniel Dunbar7dc2a042009-03-05 06:38:47 +0000130 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 Dunbar7dc2a042009-03-05 06:38:47 +0000141 }
Daniel Dunbar63c4da92009-03-02 19:59:07 +0000142}
Daniel Dunbard25acaa2009-03-10 23:41:59 +0000143
144HostInfo *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}