rs_cc_options.cpp revision 7ac9d0de26d325071ad3f26f8d34514efca2d3d6
1/*
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
22#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;
89    std::unique_ptr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable());
90    std::unique_ptr<llvm::opt::InputArgList> Args(OptParser->ParseArgs(
91        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
120    Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);
121
122    if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
123      switch (A->getOption().getID()) {
124        case OPT_M: {
125          Opts.mEmitDependency = true;
126          Opts.mOutputType = slang::Slang::OT_Dependency;
127          break;
128        }
129        case OPT_MD: {
130          Opts.mEmitDependency = true;
131          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
162    if (Opts.mEmitDependency &&
163        ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
164         (Opts.mOutputType != slang::Slang::OT_Dependency)))
165      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
189    if (Args->hasArg(OPT_reflect_cpp)) {
190      Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
191      // mJavaReflectionPathBase can be set for C++ reflected builds.
192      // Set it to the standard mBitcodeOutputDir (via -o) by default.
193      if (Opts.mJavaReflectionPathBase.empty()) {
194        Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
195      }
196    }
197
198    Opts.mDependencyOutputDir =
199        Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
200    Opts.mAdditionalDepTargets =
201        Args->getAllArgValues(OPT_additional_dep_target);
202
203    Opts.mShowHelp = Args->hasArg(OPT_help);
204    Opts.mShowVersion = Args->hasArg(OPT_version);
205    Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
206    Opts.mVerbose = Args->hasArg(OPT_verbose);
207
208    // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.
209    Opts.mEmit3264 = Args->hasArg(OPT_emit_32_64);
210    if (Opts.mEmit3264) {
211      Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
212    }
213
214    size_t OptLevel =
215        clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine);
216
217    Opts.mOptimizationLevel =
218        OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive;
219
220    Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api,
221                                                RS_VERSION, DiagEngine);
222
223    if (Opts.mTargetAPI == 0) {
224      Opts.mTargetAPI = UINT_MAX;
225    }
226  }
227}
228