blob: 40209e0b41e1d4ff47da3e67390444d97fbedc0d [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hines0a813a32012-08-03 16:52:40 -07002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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
Stephen Hinese639eb52010-11-08 19:27:20 -080017#include <cstdlib>
18#include <list>
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070019#include <set>
20#include <string>
Stephen Hinese639eb52010-11-08 19:27:20 -080021#include <utility>
22#include <vector>
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070023
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070024#include "clang/Driver/DriverDiagnostic.h"
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070025#include "clang/Driver/Options.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070026
Stephen Hines23c43582013-01-09 20:02:04 -080027#include "clang/Basic/DiagnosticOptions.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070028#include "clang/Frontend/TextDiagnosticPrinter.h"
Stephen Hines8f4d9722011-12-05 14:14:42 -080029#include "clang/Frontend/Utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070030
Stephen Hinese639eb52010-11-08 19:27:20 -080031#include "llvm/ADT/SmallVector.h"
Loganbe274822011-02-16 22:02:54 +080032#include "llvm/ADT/IntrusiveRefCntPtr.h"
33#include "llvm/ADT/OwningPtr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080034
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070035#include "llvm/Option/Arg.h"
36#include "llvm/Option/ArgList.h"
37#include "llvm/Option/Option.h"
38#include "llvm/Option/OptTable.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080039#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/ManagedStatic.h"
41#include "llvm/Support/MemoryBuffer.h"
Loganbe274822011-02-16 22:02:54 +080042#include "llvm/Support/Path.h"
Stephen Hinesba7c6dc2011-09-07 19:57:04 -070043#include "llvm/Support/raw_ostream.h"
Loganbe274822011-02-16 22:02:54 +080044#include "llvm/Support/system_error.h"
mkopec1c460b372012-01-09 11:21:50 -050045#include "llvm/Target/TargetMachine.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080046
47#include "slang.h"
Stephen Hines6e6578a2011-02-07 18:05:48 -080048#include "slang_assert.h"
Stephen Hines8f4d9722011-12-05 14:14:42 -080049#include "slang_diagnostic_buffer.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070050#include "slang_rs.h"
51#include "slang_rs_reflect_utils.h"
52
Stephen Hinese639eb52010-11-08 19:27:20 -080053using clang::driver::options::DriverOption;
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070054using llvm::opt::arg_iterator;
55using llvm::opt::Arg;
56using llvm::opt::ArgList;
57using llvm::opt::InputArgList;
58using llvm::opt::Option;
59using llvm::opt::OptTable;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070060
61// SaveStringInSet, ExpandArgsFromBuf and ExpandArgv are all copied from
62// $(CLANG_ROOT)/tools/driver/driver.cpp for processing argc/argv passed in
63// main().
64static inline const char *SaveStringInSet(std::set<std::string> &SavedStrings,
65 llvm::StringRef S) {
66 return SavedStrings.insert(S).first->c_str();
67}
68static void ExpandArgsFromBuf(const char *Arg,
69 llvm::SmallVectorImpl<const char*> &ArgVector,
70 std::set<std::string> &SavedStrings);
71static void ExpandArgv(int argc, const char **argv,
72 llvm::SmallVectorImpl<const char*> &ArgVector,
73 std::set<std::string> &SavedStrings);
74
75enum {
76 OPT_INVALID = 0, // This is not an option ID.
Stephen Hines23c43582013-01-09 20:02:04 -080077#define PREFIX(NAME, VALUE)
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070078#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070079 HELPTEXT, METAVAR) OPT_##ID,
80#include "RSCCOptions.inc"
81 LastOption
82#undef OPTION
Stephen Hines23c43582013-01-09 20:02:04 -080083#undef PREFIX
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070084};
85
Stephen Hines23c43582013-01-09 20:02:04 -080086#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070087#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
Stephen Hines23c43582013-01-09 20:02:04 -080088 HELPTEXT, METAVAR)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070089#include "RSCCOptions.inc"
Stephen Hines23c43582013-01-09 20:02:04 -080090#undef OPTION
91#undef PREFIX
92
93static const OptTable::Info RSCCInfoTable[] = {
94#define PREFIX(NAME, VALUE)
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070095#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
Stephen Hines23c43582013-01-09 20:02:04 -080096 HELPTEXT, METAVAR) \
97 { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
Stephen Hinesa1f95ee2013-08-09 01:26:08 -070098 FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
Stephen Hines23c43582013-01-09 20:02:04 -080099#include "RSCCOptions.inc"
100#undef OPTION
101#undef PREFIX
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700102};
103
104class RSCCOptTable : public OptTable {
105 public:
106 RSCCOptTable()
107 : OptTable(RSCCInfoTable,
108 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {
109 }
110};
111
112OptTable *createRSCCOptTable() {
113 return new RSCCOptTable();
114}
115
116///////////////////////////////////////////////////////////////////////////////
117
118class RSCCOptions {
119 public:
120 // The include search paths
121 std::vector<std::string> mIncludePaths;
122
123 // The output directory, if any.
124 std::string mOutputDir;
125
126 // The output type
Stephen Hinese639eb52010-11-08 19:27:20 -0800127 slang::Slang::OutputType mOutputType;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700128
129 unsigned mAllowRSPrefix : 1;
130
Stephen Hinesb7d12692011-09-02 18:16:19 -0700131 // The name of the target triple to compile for.
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700132 std::string mTriple;
133
Stephen Hinesb7d12692011-09-02 18:16:19 -0700134 // The name of the target CPU to generate code for.
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700135 std::string mCPU;
136
137 // The list of target specific features to enable or disable -- this should
138 // be a list of strings starting with by '+' or '-'.
139 std::vector<std::string> mFeatures;
140
141 std::string mJavaReflectionPathBase;
142
143 std::string mJavaReflectionPackageName;
144
Stephen Hines0a813a32012-08-03 16:52:40 -0700145 std::string mRSPackageName;
146
Stephen Hinese639eb52010-11-08 19:27:20 -0800147 slang::BitCodeStorageType mBitcodeStorage;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700148
149 unsigned mOutputDep : 1;
150
151 std::string mOutputDepDir;
152
153 std::vector<std::string> mAdditionalDepTargets;
154
155 unsigned mShowHelp : 1; // Show the -help text.
156 unsigned mShowVersion : 1; // Show the -version text.
157
Stephen Hines2e35b132011-07-22 02:50:19 -0700158 unsigned int mTargetAPI;
159
mkopec1c460b372012-01-09 11:21:50 -0500160 // Enable emission of debugging symbols
161 unsigned mDebugEmission : 1;
162
163 // The optimization level used in CodeGen, and encoded in emitted bitcode
164 llvm::CodeGenOpt::Level mOptimizationLevel;
165
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700166 RSCCOptions() {
Stephen Hinese639eb52010-11-08 19:27:20 -0800167 mOutputType = slang::Slang::OT_Bitcode;
Stephen Hinesb7d12692011-09-02 18:16:19 -0700168 // Triple/CPU/Features must be hard-coded to our chosen portable ABI.
169 mTriple = "armv7-none-linux-gnueabi";
170 mCPU = "";
171 slangAssert(mFeatures.empty());
Stephen Hines18ca8cf2011-10-21 14:56:40 -0700172 mFeatures.push_back("+long64");
Stephen Hinese639eb52010-11-08 19:27:20 -0800173 mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700174 mOutputDep = 0;
175 mShowHelp = 0;
176 mShowVersion = 0;
Stephen Hines2e35b132011-07-22 02:50:19 -0700177 mTargetAPI = RS_VERSION;
mkopec1c460b372012-01-09 11:21:50 -0500178 mDebugEmission = 0;
179 mOptimizationLevel = llvm::CodeGenOpt::Aggressive;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700180 }
181};
182
183// ParseArguments -
184static void ParseArguments(llvm::SmallVectorImpl<const char*> &ArgVector,
185 llvm::SmallVectorImpl<const char*> &Inputs,
186 RSCCOptions &Opts,
Logan Chien9207a2e2011-10-21 15:39:28 +0800187 clang::DiagnosticsEngine &DiagEngine) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700188 if (ArgVector.size() > 1) {
189 const char **ArgBegin = ArgVector.data() + 1;
190 const char **ArgEnd = ArgVector.data() + ArgVector.size();
191 unsigned MissingArgIndex, MissingArgCount;
192 llvm::OwningPtr<OptTable> OptParser(createRSCCOptTable());
193 llvm::OwningPtr<InputArgList> Args(
194 OptParser->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
195
196 // Check for missing argument error.
197 if (MissingArgCount)
Logan Chien9207a2e2011-10-21 15:39:28 +0800198 DiagEngine.Report(clang::diag::err_drv_missing_argument)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700199 << Args->getArgString(MissingArgIndex) << MissingArgCount;
200
Stephen Hines8f4d9722011-12-05 14:14:42 -0800201 clang::DiagnosticOptions DiagOpts;
202 DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
203 DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
204 clang::ProcessWarningOptions(DiagEngine, DiagOpts);
205
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700206 // Issue errors on unknown arguments.
207 for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
208 ie = Args->filtered_end(); it != ie; ++it)
Logan Chien9207a2e2011-10-21 15:39:28 +0800209 DiagEngine.Report(clang::diag::err_drv_unknown_argument)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700210 << (*it)->getAsString(*Args);
211
212 for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
213 it != ie; ++it) {
214 const Arg *A = *it;
215 if (A->getOption().getKind() == Option::InputClass)
Stephen Hines23c43582013-01-09 20:02:04 -0800216 Inputs.push_back(A->getValue());
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700217 }
218
219 Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
220
221 Opts.mOutputDir = Args->getLastArgValue(OPT_o);
222
223 if (const Arg *A = Args->getLastArg(OPT_M_Group)) {
224 switch (A->getOption().getID()) {
225 case OPT_M: {
226 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800227 Opts.mOutputType = slang::Slang::OT_Dependency;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700228 break;
229 }
230 case OPT_MD: {
231 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800232 Opts.mOutputType = slang::Slang::OT_Bitcode;
Patrick Scott190ac892010-10-21 14:47:31 -0400233 break;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700234 }
235 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800236 slangAssert(false && "Invalid option in M group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700237 }
238 }
239 }
240
241 if (const Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
242 switch (A->getOption().getID()) {
243 case OPT_emit_asm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800244 Opts.mOutputType = slang::Slang::OT_Assembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700245 break;
246 }
247 case OPT_emit_llvm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800248 Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700249 break;
250 }
251 case OPT_emit_bc: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800252 Opts.mOutputType = slang::Slang::OT_Bitcode;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700253 break;
254 }
255 case OPT_emit_nothing: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800256 Opts.mOutputType = slang::Slang::OT_Nothing;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700257 break;
258 }
259 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800260 slangAssert(false && "Invalid option in output type group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700261 }
262 }
263 }
264
Zonr Change8c263a2010-10-12 00:35:29 +0800265 if (Opts.mOutputDep &&
Stephen Hinese639eb52010-11-08 19:27:20 -0800266 ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
267 (Opts.mOutputType != slang::Slang::OT_Dependency)))
Logan Chien9207a2e2011-10-21 15:39:28 +0800268 DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700269 << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
270 << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
271
272 Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
273
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700274 Opts.mJavaReflectionPathBase =
275 Args->getLastArgValue(OPT_java_reflection_path_base);
276 Opts.mJavaReflectionPackageName =
277 Args->getLastArgValue(OPT_java_reflection_package_name);
278
Stephen Hines0a813a32012-08-03 16:52:40 -0700279 Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
280
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700281 llvm::StringRef BitcodeStorageValue =
282 Args->getLastArgValue(OPT_bitcode_storage);
283 if (BitcodeStorageValue == "ar")
Stephen Hinese639eb52010-11-08 19:27:20 -0800284 Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700285 else if (BitcodeStorageValue == "jc")
Stephen Hinese639eb52010-11-08 19:27:20 -0800286 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700287 else if (!BitcodeStorageValue.empty())
Logan Chien9207a2e2011-10-21 15:39:28 +0800288 DiagEngine.Report(clang::diag::err_drv_invalid_value)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700289 << OptParser->getOptionName(OPT_bitcode_storage)
290 << BitcodeStorageValue;
291
Stephen Hines5c25c512012-02-27 12:58:17 -0800292 if (Args->hasArg(OPT_reflect_cpp)) {
293 Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
Stephen Hines476d4f52013-11-17 23:26:38 -0800294 // mJavaReflectionPathBase can be set for C++ reflected builds.
295 // Set it to the standard mOutputDir (via -o) by default.
296 if (Opts.mJavaReflectionPathBase.empty()) {
297 Opts.mJavaReflectionPathBase = Opts.mOutputDir;
298 }
Stephen Hines5c25c512012-02-27 12:58:17 -0800299 }
300
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700301 Opts.mOutputDepDir =
302 Args->getLastArgValue(OPT_output_dep_dir, Opts.mOutputDir);
303 Opts.mAdditionalDepTargets =
304 Args->getAllArgValues(OPT_additional_dep_target);
305
306 Opts.mShowHelp = Args->hasArg(OPT_help);
307 Opts.mShowVersion = Args->hasArg(OPT_version);
mkopec1c460b372012-01-09 11:21:50 -0500308 Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
309
Stephen Hinesa1f95ee2013-08-09 01:26:08 -0700310 size_t OptLevel = clang::getLastArgIntValue(*Args,
311 OPT_optimization_level,
312 3,
313 DiagEngine);
mkopec1c460b372012-01-09 11:21:50 -0500314
315 Opts.mOptimizationLevel = OptLevel == 0 ? llvm::CodeGenOpt::None
316 : llvm::CodeGenOpt::Aggressive;
Stephen Hines2e35b132011-07-22 02:50:19 -0700317
Stephen Hinesa1f95ee2013-08-09 01:26:08 -0700318 Opts.mTargetAPI = clang::getLastArgIntValue(*Args,
319 OPT_target_api,
320 RS_VERSION,
321 DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700322 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700323}
324
325static const char *DetermineOutputFile(const std::string &OutputDir,
326 const char *InputFile,
Stephen Hinese639eb52010-11-08 19:27:20 -0800327 slang::Slang::OutputType OutputType,
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700328 std::set<std::string> &SavedStrings) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800329 if (OutputType == slang::Slang::OT_Nothing)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700330 return "/dev/null";
331
332 std::string OutputFile(OutputDir);
333
334 // Append '/' to Opts.mOutputDir if not presents
335 if (!OutputFile.empty() &&
Raphael8d5a2f62011-02-08 00:15:05 -0800336 (OutputFile[OutputFile.size() - 1]) != OS_PATH_SEPARATOR)
337 OutputFile.append(1, OS_PATH_SEPARATOR);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700338
Stephen Hinese639eb52010-11-08 19:27:20 -0800339 if (OutputType == slang::Slang::OT_Dependency) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700340 // The build system wants the .d file name stem to be exactly the same as
341 // the source .rs file, instead of the .bc file.
Stephen Hinese639eb52010-11-08 19:27:20 -0800342 OutputFile.append(slang::RSSlangReflectUtils::GetFileNameStem(InputFile));
343 } else {
344 OutputFile.append(
345 slang::RSSlangReflectUtils::BCFileNameFromRSFileName(InputFile));
346 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700347
Stephen Hinese639eb52010-11-08 19:27:20 -0800348 switch (OutputType) {
349 case slang::Slang::OT_Dependency: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700350 OutputFile.append(".d");
351 break;
352 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800353 case slang::Slang::OT_Assembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700354 OutputFile.append(".S");
355 break;
356 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800357 case slang::Slang::OT_LLVMAssembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700358 OutputFile.append(".ll");
359 break;
360 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800361 case slang::Slang::OT_Object: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700362 OutputFile.append(".o");
363 break;
364 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800365 case slang::Slang::OT_Bitcode: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700366 OutputFile.append(".bc");
367 break;
368 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800369 case slang::Slang::OT_Nothing:
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700370 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800371 slangAssert(false && "Invalid output type!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700372 }
373 }
374
375 return SaveStringInSet(SavedStrings, OutputFile);
376}
377
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700378#define str(s) #s
379#define wrap_str(s) str(s)
380static void llvm_rs_cc_VersionPrinter() {
381 llvm::raw_ostream &OS = llvm::outs();
382 OS << "llvm-rs-cc: Renderscript compiler\n"
383 << " (http://developer.android.com/guide/topics/renderscript)\n"
384 << " based on LLVM (http://llvm.org):\n";
385 OS << " Built " << __DATE__ << " (" << __TIME__ ").\n";
386 OS << " Target APIs: " << SLANG_MINIMUM_TARGET_API << " - "
387 << SLANG_MAXIMUM_TARGET_API;
388 OS << "\n Build type: " << wrap_str(TARGET_BUILD_VARIANT);
389#ifndef __DISABLE_ASSERTS
390 OS << " with assertions";
391#endif
392 OS << ".\n";
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700393}
Stephen Hines8f4d9722011-12-05 14:14:42 -0800394#undef wrap_str
395#undef str
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700396
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700397int main(int argc, const char **argv) {
398 std::set<std::string> SavedStrings;
399 llvm::SmallVector<const char*, 256> ArgVector;
400 RSCCOptions Opts;
401 llvm::SmallVector<const char*, 16> Inputs;
402 std::string Argv0;
403
404 atexit(llvm::llvm_shutdown);
405
406 ExpandArgv(argc, argv, ArgVector, SavedStrings);
407
408 // Argv0
Logan Chien6f4e0a92011-03-10 01:10:25 +0800409 Argv0 = llvm::sys::path::stem(ArgVector[0]);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700410
411 // Setup diagnostic engine
Stephen Hines8f4d9722011-12-05 14:14:42 -0800412 slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
Loganbe274822011-02-16 22:02:54 +0800413
414 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
415 new clang::DiagnosticIDs());
416
Stephen Hines23c43582013-01-09 20:02:04 -0800417 llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
418 new clang::DiagnosticOptions());
419 clang::DiagnosticsEngine DiagEngine(DiagIDs, &*DiagOpts, DiagClient, true);
Logan Chien9207a2e2011-10-21 15:39:28 +0800420
Stephen Hinese639eb52010-11-08 19:27:20 -0800421 slang::Slang::GlobalInitialization();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700422
Logan Chien9207a2e2011-10-21 15:39:28 +0800423 ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700424
425 // Exits when there's any error occurred during parsing the arguments
Stephen Hines8f4d9722011-12-05 14:14:42 -0800426 if (DiagEngine.hasErrorOccurred()) {
427 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700428 return 1;
Stephen Hines8f4d9722011-12-05 14:14:42 -0800429 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700430
431 if (Opts.mShowHelp) {
432 llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
433 OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
Stephen Hinesb7d12692011-09-02 18:16:19 -0700434 "Renderscript source compiler");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700435 return 0;
436 }
437
438 if (Opts.mShowVersion) {
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700439 llvm_rs_cc_VersionPrinter();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700440 return 0;
441 }
442
443 // No input file
444 if (Inputs.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800445 DiagEngine.Report(clang::diag::err_drv_no_input_files);
Stephen Hines8f4d9722011-12-05 14:14:42 -0800446 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700447 return 1;
448 }
449
Zonr Changcf6af6a2010-10-12 12:38:51 +0800450 // Prepare input data for RS compiler.
451 std::list<std::pair<const char*, const char*> > IOFiles;
452 std::list<std::pair<const char*, const char*> > DepFiles;
453
Stephen Hinese639eb52010-11-08 19:27:20 -0800454 llvm::OwningPtr<slang::SlangRS> Compiler(new slang::SlangRS());
Zonr Chang641558f2010-10-12 21:07:06 +0800455
Stephen Hines8f4d9722011-12-05 14:14:42 -0800456 Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures, &DiagEngine,
457 DiagClient);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700458
459 for (int i = 0, e = Inputs.size(); i != e; i++) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800460 const char *InputFile = Inputs[i];
461 const char *OutputFile =
462 DetermineOutputFile(Opts.mOutputDir, InputFile,
463 Opts.mOutputType, SavedStrings);
464
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700465 if (Opts.mOutputDep) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800466 const char *BCOutputFile, *DepOutputFile;
Zonr Change8c263a2010-10-12 00:35:29 +0800467
Stephen Hinese639eb52010-11-08 19:27:20 -0800468 if (Opts.mOutputType == slang::Slang::OT_Bitcode)
Zonr Change8c263a2010-10-12 00:35:29 +0800469 BCOutputFile = OutputFile;
470 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800471 BCOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
472 InputFile,
473 slang::Slang::OT_Bitcode,
474 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800475
Stephen Hinese639eb52010-11-08 19:27:20 -0800476 if (Opts.mOutputType == slang::Slang::OT_Dependency)
Zonr Changcf6af6a2010-10-12 12:38:51 +0800477 DepOutputFile = OutputFile;
478 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800479 DepOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
480 InputFile,
481 slang::Slang::OT_Dependency,
482 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800483
484 DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700485 }
Zonr Changcf6af6a2010-10-12 12:38:51 +0800486
487 IOFiles.push_back(std::make_pair(InputFile, OutputFile));
488 }
489
490 // Let's rock!
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800491 int CompileFailed = !Compiler->compile(IOFiles,
492 DepFiles,
493 Opts.mIncludePaths,
494 Opts.mAdditionalDepTargets,
495 Opts.mOutputType,
496 Opts.mBitcodeStorage,
497 Opts.mAllowRSPrefix,
498 Opts.mOutputDep,
Stephen Hines2e35b132011-07-22 02:50:19 -0700499 Opts.mTargetAPI,
mkopec1c460b372012-01-09 11:21:50 -0500500 Opts.mDebugEmission,
501 Opts.mOptimizationLevel,
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800502 Opts.mJavaReflectionPathBase,
Stephen Hines0a813a32012-08-03 16:52:40 -0700503 Opts.mJavaReflectionPackageName,
504 Opts.mRSPackageName);
Stephen Hines5c25c512012-02-27 12:58:17 -0800505
Stephen Hinesc632be22011-09-23 15:53:16 -0700506 Compiler->reset();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700507
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800508 return CompileFailed;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700509}
510
511///////////////////////////////////////////////////////////////////////////////
512
513// ExpandArgsFromBuf -
514static void ExpandArgsFromBuf(const char *Arg,
515 llvm::SmallVectorImpl<const char*> &ArgVector,
516 std::set<std::string> &SavedStrings) {
517 const char *FName = Arg + 1;
Stephen Hines75d47182014-05-28 09:43:18 -0700518 std::unique_ptr<llvm::MemoryBuffer> MemBuf;
Loganbe274822011-02-16 22:02:54 +0800519 if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
520 // Unable to open the file
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700521 ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
522 return;
523 }
524
525 const char *Buf = MemBuf->getBufferStart();
526 char InQuote = ' ';
527 std::string CurArg;
528
529 for (const char *P = Buf; ; ++P) {
530 if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
531 if (!CurArg.empty()) {
532 if (CurArg[0] != '@') {
533 ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
534 } else {
535 ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
536 }
537
538 CurArg = "";
539 }
540 if (*P == '\0')
541 break;
542 else
543 continue;
544 }
545
546 if (isspace(*P)) {
547 if (InQuote != ' ')
548 CurArg.push_back(*P);
549 continue;
550 }
551
552 if (*P == '"' || *P == '\'') {
553 if (InQuote == *P)
554 InQuote = ' ';
555 else if (InQuote == ' ')
556 InQuote = *P;
557 else
558 CurArg.push_back(*P);
559 continue;
560 }
561
562 if (*P == '\\') {
563 ++P;
564 if (*P != '\0')
565 CurArg.push_back(*P);
566 continue;
567 }
568 CurArg.push_back(*P);
569 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700570}
571
572// ExpandArgsFromBuf -
573static void ExpandArgv(int argc, const char **argv,
574 llvm::SmallVectorImpl<const char*> &ArgVector,
575 std::set<std::string> &SavedStrings) {
576 for (int i = 0; i < argc; ++i) {
577 const char *Arg = argv[i];
578 if (Arg[0] != '@') {
579 ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
580 continue;
581 }
582
583 ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
584 }
585}