rs_cc_options.cpp revision 7f5704efe0c59d5599f1ac7056976225dbfab946
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/ADT/OwningPtr.h"
23#include "llvm/Option/Arg.h"
24#include "llvm/Option/ArgList.h"
25#include "llvm/Option/Option.h"
26#include "llvm/Option/OptTable.h"
27
28#include "rs_cc_options.h"
29#include "slang.h"
30#include "slang_assert.h"
31
32#include <cstdlib>
33#include <string>
34#include <utility>
35#include <vector>
36
37enum {
38  OPT_INVALID = 0,  // This is not an option ID.
39#define PREFIX(NAME, VALUE)
40#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
41               HELPTEXT, METAVAR)                                             \
42  OPT_##ID,
43#include "RSCCOptions.inc"
44  LastOption
45#undef OPTION
46#undef PREFIX
47};
48
49#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
50#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
51               HELPTEXT, METAVAR)
52#include "RSCCOptions.inc"
53#undef OPTION
54#undef PREFIX
55
56static const llvm::opt::OptTable::Info RSCCInfoTable[] = {
57#define PREFIX(NAME, VALUE)
58#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
59               HELPTEXT, METAVAR)                                              \
60  {                                                                            \
61    PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
62        PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS                      \
63  }                                                                            \
64  ,
65#include "RSCCOptions.inc"
66#undef OPTION
67#undef PREFIX
68};
69
70namespace {
71
72class RSCCOptTable : public llvm::opt::OptTable {
73 public:
74  RSCCOptTable()
75      : OptTable(RSCCInfoTable,
76                 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {}
77};
78}
79
80llvm::opt::OptTable *slang::createRSCCOptTable() { return new RSCCOptTable(); }
81
82void slang::ParseArguments(llvm::SmallVectorImpl<const char *> &ArgVector,
83                           llvm::SmallVectorImpl<const char *> &Inputs,
84                           slang::RSCCOptions &Opts,
85                           clang::DiagnosticsEngine &DiagEngine) {
86  if (ArgVector.size() > 1) {
87    const char **ArgBegin = ArgVector.data() + 1;
88    const char **ArgEnd = ArgVector.data() + ArgVector.size();
89    unsigned MissingArgIndex, MissingArgCount;
90    llvm::OwningPtr<llvm::opt::OptTable> OptParser(slang::createRSCCOptTable());
91    llvm::OwningPtr<llvm::opt::InputArgList> Args(OptParser->ParseArgs(
92        ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
93
94    // Check for missing argument error.
95    if (MissingArgCount)
96      DiagEngine.Report(clang::diag::err_drv_missing_argument)
97          << Args->getArgString(MissingArgIndex) << MissingArgCount;
98
99    clang::DiagnosticOptions DiagOpts;
100    DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
101    DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
102    clang::ProcessWarningOptions(DiagEngine, DiagOpts);
103
104    // Issue errors on unknown arguments.
105    for (llvm::opt::arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
106                                 ie = Args->filtered_end();
107         it != ie; ++it)
108      DiagEngine.Report(clang::diag::err_drv_unknown_argument)
109          << (*it)->getAsString(*Args);
110
111    for (llvm::opt::ArgList::const_iterator it = Args->begin(),
112                                            ie = Args->end();
113         it != ie; ++it) {
114      const llvm::opt::Arg *A = *it;
115      if (A->getOption().getKind() == llvm::opt::Option::InputClass)
116        Inputs.push_back(A->getValue());
117    }
118
119    Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
120
121    Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);
122
123    if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
124      switch (A->getOption().getID()) {
125        case OPT_M: {
126          Opts.mEmitDependency = true;
127          Opts.mOutputType = slang::Slang::OT_Dependency;
128          break;
129        }
130        case OPT_MD: {
131          Opts.mEmitDependency = true;
132          Opts.mOutputType = slang::Slang::OT_Bitcode;
133          break;
134        }
135        default: { slangAssert(false && "Invalid option in M group!"); }
136      }
137    }
138
139    if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
140      switch (A->getOption().getID()) {
141        case OPT_emit_asm: {
142          Opts.mOutputType = slang::Slang::OT_Assembly;
143          break;
144        }
145        case OPT_emit_llvm: {
146          Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
147          break;
148        }
149        case OPT_emit_bc: {
150          Opts.mOutputType = slang::Slang::OT_Bitcode;
151          break;
152        }
153        case OPT_emit_nothing: {
154          Opts.mOutputType = slang::Slang::OT_Nothing;
155          break;
156        }
157        default: {
158          slangAssert(false && "Invalid option in output type group!");
159        }
160      }
161    }
162
163    if (Opts.mEmitDependency &&
164        ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
165         (Opts.mOutputType != slang::Slang::OT_Dependency)))
166      DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
167          << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
168          << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
169
170    Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
171
172    Opts.mJavaReflectionPathBase =
173        Args->getLastArgValue(OPT_java_reflection_path_base);
174    Opts.mJavaReflectionPackageName =
175        Args->getLastArgValue(OPT_java_reflection_package_name);
176
177    Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
178
179    llvm::StringRef BitcodeStorageValue =
180        Args->getLastArgValue(OPT_bitcode_storage);
181    if (BitcodeStorageValue == "ar")
182      Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
183    else if (BitcodeStorageValue == "jc")
184      Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
185    else if (!BitcodeStorageValue.empty())
186      DiagEngine.Report(clang::diag::err_drv_invalid_value)
187          << OptParser->getOptionName(OPT_bitcode_storage)
188          << BitcodeStorageValue;
189
190    if (Args->hasArg(OPT_reflect_cpp)) {
191      Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
192      // mJavaReflectionPathBase can be set for C++ reflected builds.
193      // Set it to the standard mBitcodeOutputDir (via -o) by default.
194      if (Opts.mJavaReflectionPathBase.empty()) {
195        Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
196      }
197    }
198
199    Opts.mDependencyOutputDir =
200        Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
201    Opts.mAdditionalDepTargets =
202        Args->getAllArgValues(OPT_additional_dep_target);
203
204    Opts.mShowHelp = Args->hasArg(OPT_help);
205    Opts.mShowVersion = Args->hasArg(OPT_version);
206    Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
207
208    size_t OptLevel =
209        clang::getLastArgIntValue(*Args, OPT_optimization_level, 3, DiagEngine);
210
211    Opts.mOptimizationLevel =
212        OptLevel == 0 ? llvm::CodeGenOpt::None : llvm::CodeGenOpt::Aggressive;
213
214    Opts.mTargetAPI = clang::getLastArgIntValue(*Args, OPT_target_api,
215                                                RS_VERSION, DiagEngine);
216  }
217}
218