blob: ff37dd09cf3c494e73948fc21c6b3ee181336370 [file] [log] [blame]
Stephen Hines8b5c5c62014-06-06 18:03:18 -07001/*
2 * Copyright 2014, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "clang/Basic/DiagnosticOptions.h"
18#include "clang/Driver/DriverDiagnostic.h"
19#include "clang/Driver/Options.h"
20#include "clang/Frontend/Utils.h"
21
Stephen Hines8b5c5c62014-06-06 18:03:18 -070022#include "llvm/Option/Arg.h"
23#include "llvm/Option/ArgList.h"
24#include "llvm/Option/Option.h"
25#include "llvm/Option/OptTable.h"
26
27#include "rs_cc_options.h"
28#include "slang.h"
29#include "slang_assert.h"
30
31#include <cstdlib>
32#include <string>
33#include <utility>
34#include <vector>
35
36enum {
37 OPT_INVALID = 0, // This is not an option ID.
38#define PREFIX(NAME, VALUE)
39#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
40 HELPTEXT, METAVAR) \
41 OPT_##ID,
42#include "RSCCOptions.inc"
43 LastOption
44#undef OPTION
45#undef PREFIX
46};
47
48#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
49#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
50 HELPTEXT, METAVAR)
51#include "RSCCOptions.inc"
52#undef OPTION
53#undef PREFIX
54
55static const llvm::opt::OptTable::Info RSCCInfoTable[] = {
56#define PREFIX(NAME, VALUE)
57#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
58 HELPTEXT, METAVAR) \
59 { \
60 PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
61 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS \
62 } \
63 ,
64#include "RSCCOptions.inc"
65#undef OPTION
66#undef PREFIX
67};
68
69namespace {
70
71class RSCCOptTable : public llvm::opt::OptTable {
72 public:
73 RSCCOptTable()
74 : OptTable(RSCCInfoTable,
75 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {}
76};
77}
78
79llvm::opt::OptTable *slang::createRSCCOptTable() { return new RSCCOptTable(); }
80
81void slang::ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector,
82 llvm::SmallVectorImpl<const char *> &Inputs,
83 slang::RSCCOptions &Opts,
84 clang::DiagnosticsEngine &DiagEngine) {
85 if (ArgVector.size() > 1) {
86 const char **ArgBegin = ArgVector.data() + 1;
87 const char **ArgEnd = ArgVector.data() + ArgVector.size();
88 unsigned MissingArgIndex, MissingArgCount;
Stephen Hines7ac9d0d2014-07-15 16:50:03 -070089 std::unique_ptr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable());
90 std::unique_ptr<llvm::opt::InputArgList> Args(OptParser->ParseArgs(
Stephen Hines8b5c5c62014-06-06 18:03:18 -070091 ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
92
93 // Check for missing argument error.
94 if (MissingArgCount)
95 DiagEngine.Report(clang::diag::err_drv_missing_argument)
96 << Args->getArgString(MissingArgIndex) << MissingArgCount;
97
98 clang::DiagnosticOptions DiagOpts;
99 DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
100 DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
101 clang::ProcessWarningOptions(DiagEngine, DiagOpts);
102
103 // Issue errors on unknown arguments.
104 for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
105 ie = Args->filtered_end();
106 it != ie; ++it)
107 DiagEngine.Report(clang::diag::err_drv_unknown_argument)
108 << (*it)->getAsString(*Args);
109
110 for (llvm::opt::ArgList::const_iterator it = Args->begin(),
111 ie = Args->end();
112 it != ie; ++it) {
113 const llvm::opt::Arg *A = *it;
114 if (A->getOption().getKind() == llvm::opt::Option::InputClass)
115 Inputs.push_back(A->getValue());
116 }
117
118 Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
119
Stephen Hines7f5704e2014-06-10 18:06:50 -0700120 Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700121
122 if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
123 switch (A->getOption().getID()) {
124 case OPT_M: {
Stephen Hines7f5704e2014-06-10 18:06:50 -0700125 Opts.mEmitDependency = true;
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700126 Opts.mOutputType = slang::Slang::OT_Dependency;
127 break;
128 }
129 case OPT_MD: {
Stephen Hines7f5704e2014-06-10 18:06:50 -0700130 Opts.mEmitDependency = true;
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700131 Opts.mOutputType = slang::Slang::OT_Bitcode;
132 break;
133 }
134 default: { slangAssert(false && "Invalid option in M group!"); }
135 }
136 }
137
138 if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
139 switch (A->getOption().getID()) {
140 case OPT_emit_asm: {
141 Opts.mOutputType = slang::Slang::OT_Assembly;
142 break;
143 }
144 case OPT_emit_llvm: {
145 Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
146 break;
147 }
148 case OPT_emit_bc: {
149 Opts.mOutputType = slang::Slang::OT_Bitcode;
150 break;
151 }
152 case OPT_emit_nothing: {
153 Opts.mOutputType = slang::Slang::OT_Nothing;
154 break;
155 }
156 default: {
157 slangAssert(false && "Invalid option in output type group!");
158 }
159 }
160 }
161
Stephen Hines7f5704e2014-06-10 18:06:50 -0700162 if (Opts.mEmitDependency &&
163 ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
164 (Opts.mOutputType != slang::Slang::OT_Dependency)))
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700165 DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
166 << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
167 << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
168
169 Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
170
171 Opts.mJavaReflectionPathBase =
172 Args->getLastArgValue(OPT_java_reflection_path_base);
173 Opts.mJavaReflectionPackageName =
174 Args->getLastArgValue(OPT_java_reflection_package_name);
175
176 Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
177
178 llvm::StringRef BitcodeStorageValue =
179 Args->getLastArgValue(OPT_bitcode_storage);
180 if (BitcodeStorageValue == "ar")
181 Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
182 else if (BitcodeStorageValue == "jc")
183 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
184 else if (!BitcodeStorageValue.empty())
185 DiagEngine.Report(clang::diag::err_drv_invalid_value)
186 << OptParser->getOptionName(OPT_bitcode_storage)
187 << BitcodeStorageValue;
188
Stephen Hines5984fc02014-09-10 02:43:45 -0700189 llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64);
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700190 if (Args->hasArg(OPT_reflect_cpp)) {
191 Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
192 // mJavaReflectionPathBase can be set for C++ reflected builds.
Stephen Hines7f5704e2014-06-10 18:06:50 -0700193 // Set it to the standard mBitcodeOutputDir (via -o) by default.
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700194 if (Opts.mJavaReflectionPathBase.empty()) {
Stephen Hines7f5704e2014-06-10 18:06:50 -0700195 Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700196 }
Stephen Hines5984fc02014-09-10 02:43:45 -0700197
198 // Check for bitwidth arguments.
199 if (lastBitwidthArg) {
200 if (lastBitwidthArg->getOption().matches(OPT_m32)) {
201 Opts.mBitWidth = 32;
202 } else {
203 Opts.mBitWidth = 64;
204 }
205 }
206 } else if (lastBitwidthArg) {
207 // -m32/-m64 are forbidden for non-C++ reflection paths.
208 DiagEngine.Report(DiagEngine.getCustomDiagID(
209 clang::DiagnosticsEngine::Error,
210 "cannot use -m32/-m64 without specifying C++ reflection (-reflect-c++)"));
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700211 }
212
Stephen Hines7f5704e2014-06-10 18:06:50 -0700213 Opts.mDependencyOutputDir =
214 Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700215 Opts.mAdditionalDepTargets =
216 Args->getAllArgValues(OPT_additional_dep_target);
217
218 Opts.mShowHelp = Args->hasArg(OPT_help);
219 Opts.mShowVersion = Args->hasArg(OPT_version);
220 Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700221 Opts.mVerbose = Args->hasArg(OPT_verbose);
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700222
Stephen Hines9ae18b22014-06-10 23:53:00 -0700223 // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.
Stephen Hines9ae18b22014-06-10 23:53:00 -0700224
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700225 size_t OptLevel =
226 clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine);
227
228 Opts.mOptimizationLevel =
229 OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive;
230
231 Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api,
232 RS_VERSION, DiagEngine);
Chris Wailesc9454af2014-06-13 17:25:40 -0700233
234 if (Opts.mTargetAPI == 0) {
235 Opts.mTargetAPI = UINT_MAX;
236 }
Stephen Hinesdd22d5c2014-08-14 16:32:50 -0700237
Stephen Hines5984fc02014-09-10 02:43:45 -0700238 Opts.mEmit3264 = (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != slang::BCST_CPP_CODE);
Stephen Hinesdd22d5c2014-08-14 16:32:50 -0700239 if (Opts.mEmit3264) {
Stephen Hinesdd22d5c2014-08-14 16:32:50 -0700240 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
Stephen Hinesdd22d5c2014-08-14 16:32:50 -0700241 }
Stephen Hines8b5c5c62014-06-06 18:03:18 -0700242 }
243}