blob: f49c641c1997dbdf9624455bdb53de0bfd7c13ba [file] [log] [blame]
Daniel Dunbarbe6ef382009-11-19 07:19:04 +00001//===--- CC1Options.cpp - Clang CC1 Options Table -----------------------*-===//
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
10#include "clang/Driver/CC1Options.h"
Daniel Dunbarf7535122009-11-20 01:46:44 +000011#include "clang/Driver/ArgList.h"
12#include "clang/Driver/Arg.h"
Daniel Dunbarbe6ef382009-11-19 07:19:04 +000013#include "clang/Driver/OptTable.h"
14#include "clang/Driver/Option.h"
Daniel Dunbar84e8a242009-11-19 20:54:59 +000015#include "clang/Frontend/CompilerInvocation.h"
Daniel Dunbarf7535122009-11-20 01:46:44 +000016#include "llvm/ADT/OwningPtr.h"
Daniel Dunbarf5835ea2009-11-22 22:08:20 +000017#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar84e8a242009-11-19 20:54:59 +000018#include "llvm/ADT/SmallVector.h"
Daniel Dunbarf7535122009-11-20 01:46:44 +000019#include "llvm/Support/raw_ostream.h"
20#include "llvm/System/Host.h"
Daniel Dunbarbe6ef382009-11-19 07:19:04 +000021
22using namespace clang::driver;
23using namespace clang::driver::options;
24using namespace clang::driver::cc1options;
25
26static OptTable::Info CC1InfoTable[] = {
Daniel Dunbarbe6ef382009-11-19 07:19:04 +000027#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
28 HELPTEXT, METAVAR) \
29 { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
30 OPT_##GROUP, OPT_##ALIAS },
31#include "clang/Driver/CC1Options.inc"
32};
33
34namespace {
35
36class CC1OptTable : public OptTable {
37public:
38 CC1OptTable()
39 : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {}
40};
41
42}
43
44OptTable *clang::driver::createCC1OptTable() {
45 return new CC1OptTable();
46}
Daniel Dunbar84e8a242009-11-19 20:54:59 +000047
48//
49
50using namespace clang;
51
Daniel Dunbarf7535122009-11-20 01:46:44 +000052static llvm::StringRef getLastArgValue(ArgList &Args, cc1options::ID ID,
53 llvm::StringRef Default = "") {
54 if (Arg *A = Args.getLastArg(ID))
55 return A->getValue(Args);
56 return Default;
57}
58
Daniel Dunbar69fd86d2009-11-20 17:23:30 +000059static int getLastArgIntValue(ArgList &Args, cc1options::ID ID,
60 int Default = 0) {
61 Arg *A = Args.getLastArg(ID);
62 if (!A)
63 return Default;
64
65 int Res = Default;
66 // FIXME: What to do about argument parsing errors?
67 if (llvm::StringRef(A->getValue(Args)).getAsInteger(10, Res))
68 llvm::errs() << "error: invalid integral argument in '"
69 << A->getAsString(Args) << "'\n";
70
71 return Res;
72}
73
Daniel Dunbarf7535122009-11-20 01:46:44 +000074static std::vector<std::string>
75getAllArgValues(ArgList &Args, cc1options::ID ID) {
76 llvm::SmallVector<const char *, 16> Values;
77 Args.AddAllArgValues(Values, ID);
78 return std::vector<std::string>(Values.begin(), Values.end());
79}
80
Daniel Dunbar69fd86d2009-11-20 17:23:30 +000081//
82
Daniel Dunbarf5835ea2009-11-22 22:08:20 +000083static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args) {
84 Opts.AnalysisList.clear();
85#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \
86 if (Args.hasArg(cc1options::OPT_analysis_##NAME)) \
87 Opts.AnalysisList.push_back(NAME);
88#include "clang/Frontend/Analyses.def"
89
90 if (Arg *A = Args.getLastArg(cc1options::OPT_analyzer_store)) {
91 llvm::StringRef Name = A->getValue(Args);
92 AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
93#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
94 .Case(CMDFLAG, NAME##Model)
95#include "clang/Frontend/Analyses.def"
96 .Default(NumStores);
97 // FIXME: Error handling.
98 if (Value == NumStores)
99 llvm::errs() << "error: invalid analysis store '" << Name << "'\n";
100 else
101 Opts.AnalysisStoreOpt = Value;
102 }
103
104 if (Arg *A = Args.getLastArg(cc1options::OPT_analyzer_constraints)) {
105 llvm::StringRef Name = A->getValue(Args);
106 AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
107#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
108 .Case(CMDFLAG, NAME##Model)
109#include "clang/Frontend/Analyses.def"
110 .Default(NumConstraints);
111 // FIXME: Error handling.
112 if (Value == NumConstraints)
113 llvm::errs() << "error: invalid analysis constraints '" << Name << "'\n";
114 else
115 Opts.AnalysisConstraintsOpt = Value;
116 }
117
118 if (Arg *A = Args.getLastArg(cc1options::OPT_analyzer_output)) {
119 llvm::StringRef Name = A->getValue(Args);
120 AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
121#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
122 .Case(CMDFLAG, PD_##NAME)
123#include "clang/Frontend/Analyses.def"
124 .Default(NUM_ANALYSIS_DIAG_CLIENTS);
125 // FIXME: Error handling.
126 if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
127 llvm::errs() << "error: invalid analysis output '" << Name << "'\n";
128 else
129 Opts.AnalysisDiagOpt = Value;
130 }
131
132 Opts.VisualizeEGDot =
133 Args.hasArg(cc1options::OPT_analyzer_viz_egraph_graphviz);
134 Opts.VisualizeEGUbi =
135 Args.hasArg(cc1options::OPT_analyzer_viz_egraph_ubigraph);
136 Opts.AnalyzeAll = Args.hasArg(cc1options::OPT_analyzer_opt_analyze_headers);
137 Opts.AnalyzerDisplayProgress =
138 Args.hasArg(cc1options::OPT_analyzer_display_progress);
139 Opts.PurgeDead = !Args.hasArg(cc1options::OPT_analyzer_no_purge_dead);
140 Opts.EagerlyAssume = Args.hasArg(cc1options::OPT_analyzer_eagerly_assume);
141 Opts.AnalyzeSpecificFunction =
142 getLastArgValue(Args, cc1options::OPT_analyze_function);
143 Opts.EnableExperimentalChecks =
144 Args.hasArg(cc1options::OPT_analyzer_experimental_checks);
145 Opts.EnableExperimentalInternalChecks =
146 Args.hasArg(cc1options::OPT_analyzer_experimental_internal_checks);
147 Opts.TrimGraph = Args.hasArg(cc1options::OPT_trim_egraph);
148}
149
Daniel Dunbar69fd86d2009-11-20 17:23:30 +0000150static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args) {
151 // -Os implies -O2
152 if (Args.hasArg(cc1options::OPT_Os))
153 Opts.OptimizationLevel = 2;
154 else
155 Opts.OptimizationLevel = getLastArgIntValue(Args, cc1options::OPT_O);
156
157 // FIXME: What to do about argument parsing errors?
158 if (Opts.OptimizationLevel > 3) {
159 llvm::errs() << "error: invalid optimization level '"
160 << Opts.OptimizationLevel << "' (out of range)\n";
161 Opts.OptimizationLevel = 3;
162 }
163
164 // We must always run at least the always inlining pass.
165 Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
166 : CodeGenOptions::OnlyAlwaysInlining;
167
168 Opts.DebugInfo = Args.hasArg(cc1options::OPT_g);
169 Opts.DisableLLVMOpts = Args.hasArg(cc1options::OPT_disable_llvm_optzns);
170 Opts.DisableRedZone = Args.hasArg(cc1options::OPT_disable_red_zone);
171 Opts.MergeAllConstants = !Args.hasArg(cc1options::OPT_fno_merge_all_constants);
172 Opts.NoCommon = Args.hasArg(cc1options::OPT_fno_common);
173 Opts.NoImplicitFloat = Args.hasArg(cc1options::OPT_no_implicit_float);
174 Opts.OptimizeSize = Args.hasArg(cc1options::OPT_Os);
175 Opts.SimplifyLibCalls = 1;
176 Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
177
178 // FIXME: Implement!
179 // FIXME: Eliminate this dependency?
180// if (Lang.NoBuiltin)
181// Opts.SimplifyLibCalls = 0;
182// if (Lang.CPlusPlus)
183// Opts.NoCommon = 1;
184// Opts.TimePasses = TimePasses;
185
186 // FIXME: Put elsewhere?
187#ifdef NDEBUG
188 Opts.VerifyModule = 0;
189#endif
190}
191
Daniel Dunbara764eef2009-11-20 23:28:07 +0000192static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
193 ArgList &Args) {
194 Opts.OutputFile = getLastArgValue(Args, cc1options::OPT_dependency_file);
195 Opts.Targets = getAllArgValues(Args, cc1options::OPT_MT);
196 Opts.IncludeSystemHeaders = Args.hasArg(cc1options::OPT_sys_header_deps);
197 Opts.UsePhonyTargets = Args.hasArg(cc1options::OPT_MP);
198}
199
Daniel Dunbarf7535122009-11-20 01:46:44 +0000200static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
201 Opts.ABI = getLastArgValue(Args, cc1options::OPT_target_abi);
202 Opts.CPU = getLastArgValue(Args, cc1options::OPT_mcpu);
203 Opts.Triple = getLastArgValue(Args, cc1options::OPT_triple);
204 Opts.Features = getAllArgValues(Args, cc1options::OPT_target_feature);
205
206 // Use the host triple if unspecified.
207 if (Opts.Triple.empty())
208 Opts.Triple = llvm::sys::getHostTriple();
209}
210
Daniel Dunbar69fd86d2009-11-20 17:23:30 +0000211//
212
Daniel Dunbar84e8a242009-11-19 20:54:59 +0000213void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Daniel Dunbara6046392009-11-20 22:47:55 +0000214 const char **ArgBegin,
215 const char **ArgEnd) {
Daniel Dunbarf7535122009-11-20 01:46:44 +0000216 // Parse the arguments.
217 llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
218 unsigned MissingArgIndex, MissingArgCount;
219 llvm::OwningPtr<InputArgList> InputArgs(
Daniel Dunbara6046392009-11-20 22:47:55 +0000220 Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
Daniel Dunbarf7535122009-11-20 01:46:44 +0000221
222 // Check for missing argument error.
223 if (MissingArgCount) {
224 // FIXME: Use proper diagnostics!
225 llvm::errs() << "error: argument to '"
226 << InputArgs->getArgString(MissingArgIndex)
227 << "' is missing (expected " << MissingArgCount
228 << " value )\n";
229 }
230
Daniel Dunbarf5835ea2009-11-22 22:08:20 +0000231 ParseAnalyzerArgs(Res.getAnalyzerOpts(), *InputArgs);
Daniel Dunbara764eef2009-11-20 23:28:07 +0000232 ParseCodeGenArgs(Res.getCodeGenOpts(), *InputArgs);
233 ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *InputArgs);
Daniel Dunbarf7535122009-11-20 01:46:44 +0000234 ParseTargetArgs(Res.getTargetOpts(), *InputArgs);
Daniel Dunbar84e8a242009-11-19 20:54:59 +0000235}