blob: 1e60c6e49a84a0d036c8bb4af29f4235744ca93b [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
24#include "clang/Driver/Arg.h"
25#include "clang/Driver/ArgList.h"
26#include "clang/Driver/DriverDiagnostic.h"
27#include "clang/Driver/Option.h"
28#include "clang/Driver/OptTable.h"
29
30#include "clang/Frontend/DiagnosticOptions.h"
31#include "clang/Frontend/TextDiagnosticPrinter.h"
Stephen Hines8f4d9722011-12-05 14:14:42 -080032#include "clang/Frontend/Utils.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070033
Stephen Hinese639eb52010-11-08 19:27:20 -080034#include "llvm/ADT/SmallVector.h"
Loganbe274822011-02-16 22:02:54 +080035#include "llvm/ADT/IntrusiveRefCntPtr.h"
36#include "llvm/ADT/OwningPtr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080037
38#include "llvm/Support/CommandLine.h"
39#include "llvm/Support/ManagedStatic.h"
40#include "llvm/Support/MemoryBuffer.h"
Loganbe274822011-02-16 22:02:54 +080041#include "llvm/Support/Path.h"
Stephen Hinesba7c6dc2011-09-07 19:57:04 -070042#include "llvm/Support/raw_ostream.h"
Loganbe274822011-02-16 22:02:54 +080043#include "llvm/Support/system_error.h"
mkopec1c460b372012-01-09 11:21:50 -050044#include "llvm/Target/TargetMachine.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080045
46#include "slang.h"
Stephen Hines6e6578a2011-02-07 18:05:48 -080047#include "slang_assert.h"
Stephen Hines8f4d9722011-12-05 14:14:42 -080048#include "slang_diagnostic_buffer.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070049#include "slang_rs.h"
50#include "slang_rs_reflect_utils.h"
51
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070052// Class under clang::driver used are enumerated here.
Stephen Hinese639eb52010-11-08 19:27:20 -080053using clang::driver::arg_iterator;
54using clang::driver::options::DriverOption;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070055using clang::driver::Arg;
56using clang::driver::ArgList;
57using clang::driver::InputArgList;
58using clang::driver::Option;
59using clang::driver::OptTable;
Shih-wei Liao43730fe2012-08-02 23:06:18 -070060using namespace clang::driver::options;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070061
62// SaveStringInSet, ExpandArgsFromBuf and ExpandArgv are all copied from
63// $(CLANG_ROOT)/tools/driver/driver.cpp for processing argc/argv passed in
64// main().
65static inline const char *SaveStringInSet(std::set<std::string> &SavedStrings,
66 llvm::StringRef S) {
67 return SavedStrings.insert(S).first->c_str();
68}
69static void ExpandArgsFromBuf(const char *Arg,
70 llvm::SmallVectorImpl<const char*> &ArgVector,
71 std::set<std::string> &SavedStrings);
72static void ExpandArgv(int argc, const char **argv,
73 llvm::SmallVectorImpl<const char*> &ArgVector,
74 std::set<std::string> &SavedStrings);
75
76enum {
77 OPT_INVALID = 0, // This is not an option ID.
78#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
79 HELPTEXT, METAVAR) OPT_##ID,
80#include "RSCCOptions.inc"
81 LastOption
82#undef OPTION
83};
84
85static const OptTable::Info RSCCInfoTable[] = {
86#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
87 HELPTEXT, METAVAR) \
Shih-wei Liao43730fe2012-08-02 23:06:18 -070088 { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070089 OPT_##GROUP, OPT_##ALIAS },
90#include "RSCCOptions.inc"
91};
92
93class RSCCOptTable : public OptTable {
94 public:
95 RSCCOptTable()
96 : OptTable(RSCCInfoTable,
97 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {
98 }
99};
100
101OptTable *createRSCCOptTable() {
102 return new RSCCOptTable();
103}
104
105///////////////////////////////////////////////////////////////////////////////
106
107class RSCCOptions {
108 public:
109 // The include search paths
110 std::vector<std::string> mIncludePaths;
111
112 // The output directory, if any.
113 std::string mOutputDir;
114
115 // The output type
Stephen Hinese639eb52010-11-08 19:27:20 -0800116 slang::Slang::OutputType mOutputType;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700117
118 unsigned mAllowRSPrefix : 1;
119
Stephen Hinesb7d12692011-09-02 18:16:19 -0700120 // The name of the target triple to compile for.
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700121 std::string mTriple;
122
Stephen Hinesb7d12692011-09-02 18:16:19 -0700123 // The name of the target CPU to generate code for.
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700124 std::string mCPU;
125
126 // The list of target specific features to enable or disable -- this should
127 // be a list of strings starting with by '+' or '-'.
128 std::vector<std::string> mFeatures;
129
130 std::string mJavaReflectionPathBase;
131
132 std::string mJavaReflectionPackageName;
133
Stephen Hines0a813a32012-08-03 16:52:40 -0700134 std::string mRSPackageName;
135
Stephen Hinese639eb52010-11-08 19:27:20 -0800136 slang::BitCodeStorageType mBitcodeStorage;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700137
138 unsigned mOutputDep : 1;
139
140 std::string mOutputDepDir;
141
142 std::vector<std::string> mAdditionalDepTargets;
143
144 unsigned mShowHelp : 1; // Show the -help text.
145 unsigned mShowVersion : 1; // Show the -version text.
146
Stephen Hines2e35b132011-07-22 02:50:19 -0700147 unsigned int mTargetAPI;
148
mkopec1c460b372012-01-09 11:21:50 -0500149 // Enable emission of debugging symbols
150 unsigned mDebugEmission : 1;
151
152 // The optimization level used in CodeGen, and encoded in emitted bitcode
153 llvm::CodeGenOpt::Level mOptimizationLevel;
154
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700155 RSCCOptions() {
Stephen Hinese639eb52010-11-08 19:27:20 -0800156 mOutputType = slang::Slang::OT_Bitcode;
Stephen Hinesb7d12692011-09-02 18:16:19 -0700157 // Triple/CPU/Features must be hard-coded to our chosen portable ABI.
158 mTriple = "armv7-none-linux-gnueabi";
159 mCPU = "";
160 slangAssert(mFeatures.empty());
Stephen Hines18ca8cf2011-10-21 14:56:40 -0700161 mFeatures.push_back("+long64");
Stephen Hinese639eb52010-11-08 19:27:20 -0800162 mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700163 mOutputDep = 0;
164 mShowHelp = 0;
165 mShowVersion = 0;
Stephen Hines2e35b132011-07-22 02:50:19 -0700166 mTargetAPI = RS_VERSION;
mkopec1c460b372012-01-09 11:21:50 -0500167 mDebugEmission = 0;
168 mOptimizationLevel = llvm::CodeGenOpt::Aggressive;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700169 }
170};
171
172// ParseArguments -
173static void ParseArguments(llvm::SmallVectorImpl<const char*> &ArgVector,
174 llvm::SmallVectorImpl<const char*> &Inputs,
175 RSCCOptions &Opts,
Logan Chien9207a2e2011-10-21 15:39:28 +0800176 clang::DiagnosticsEngine &DiagEngine) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700177 if (ArgVector.size() > 1) {
178 const char **ArgBegin = ArgVector.data() + 1;
179 const char **ArgEnd = ArgVector.data() + ArgVector.size();
180 unsigned MissingArgIndex, MissingArgCount;
181 llvm::OwningPtr<OptTable> OptParser(createRSCCOptTable());
182 llvm::OwningPtr<InputArgList> Args(
183 OptParser->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
184
185 // Check for missing argument error.
186 if (MissingArgCount)
Logan Chien9207a2e2011-10-21 15:39:28 +0800187 DiagEngine.Report(clang::diag::err_drv_missing_argument)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700188 << Args->getArgString(MissingArgIndex) << MissingArgCount;
189
Stephen Hines8f4d9722011-12-05 14:14:42 -0800190 clang::DiagnosticOptions DiagOpts;
191 DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
192 DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
193 clang::ProcessWarningOptions(DiagEngine, DiagOpts);
194
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700195 // Issue errors on unknown arguments.
196 for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
197 ie = Args->filtered_end(); it != ie; ++it)
Logan Chien9207a2e2011-10-21 15:39:28 +0800198 DiagEngine.Report(clang::diag::err_drv_unknown_argument)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700199 << (*it)->getAsString(*Args);
200
201 for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
202 it != ie; ++it) {
203 const Arg *A = *it;
204 if (A->getOption().getKind() == Option::InputClass)
205 Inputs.push_back(A->getValue(*Args));
206 }
207
208 Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
209
210 Opts.mOutputDir = Args->getLastArgValue(OPT_o);
211
212 if (const Arg *A = Args->getLastArg(OPT_M_Group)) {
213 switch (A->getOption().getID()) {
214 case OPT_M: {
215 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800216 Opts.mOutputType = slang::Slang::OT_Dependency;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700217 break;
218 }
219 case OPT_MD: {
220 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800221 Opts.mOutputType = slang::Slang::OT_Bitcode;
Patrick Scott190ac892010-10-21 14:47:31 -0400222 break;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700223 }
224 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800225 slangAssert(false && "Invalid option in M group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700226 }
227 }
228 }
229
230 if (const Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
231 switch (A->getOption().getID()) {
232 case OPT_emit_asm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800233 Opts.mOutputType = slang::Slang::OT_Assembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700234 break;
235 }
236 case OPT_emit_llvm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800237 Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700238 break;
239 }
240 case OPT_emit_bc: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800241 Opts.mOutputType = slang::Slang::OT_Bitcode;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700242 break;
243 }
244 case OPT_emit_nothing: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800245 Opts.mOutputType = slang::Slang::OT_Nothing;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700246 break;
247 }
248 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800249 slangAssert(false && "Invalid option in output type group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700250 }
251 }
252 }
253
Zonr Change8c263a2010-10-12 00:35:29 +0800254 if (Opts.mOutputDep &&
Stephen Hinese639eb52010-11-08 19:27:20 -0800255 ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
256 (Opts.mOutputType != slang::Slang::OT_Dependency)))
Logan Chien9207a2e2011-10-21 15:39:28 +0800257 DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700258 << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
259 << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
260
261 Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
262
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700263 Opts.mJavaReflectionPathBase =
264 Args->getLastArgValue(OPT_java_reflection_path_base);
265 Opts.mJavaReflectionPackageName =
266 Args->getLastArgValue(OPT_java_reflection_package_name);
267
Stephen Hines0a813a32012-08-03 16:52:40 -0700268 Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
269
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700270 llvm::StringRef BitcodeStorageValue =
271 Args->getLastArgValue(OPT_bitcode_storage);
272 if (BitcodeStorageValue == "ar")
Stephen Hinese639eb52010-11-08 19:27:20 -0800273 Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700274 else if (BitcodeStorageValue == "jc")
Stephen Hinese639eb52010-11-08 19:27:20 -0800275 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700276 else if (!BitcodeStorageValue.empty())
Logan Chien9207a2e2011-10-21 15:39:28 +0800277 DiagEngine.Report(clang::diag::err_drv_invalid_value)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700278 << OptParser->getOptionName(OPT_bitcode_storage)
279 << BitcodeStorageValue;
280
Stephen Hines5c25c512012-02-27 12:58:17 -0800281 if (Args->hasArg(OPT_reflect_cpp)) {
282 Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
Tim Murrayb2fbbb92012-09-28 14:17:30 -0700283 // mJavaReflectionPathBase isn't set for C++ reflected builds
284 // set it to mOutputDir so we can use the path sanely from
285 // RSReflectionBase later on
286 Opts.mJavaReflectionPathBase = Opts.mOutputDir;
Stephen Hines5c25c512012-02-27 12:58:17 -0800287 }
288
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700289 Opts.mOutputDepDir =
290 Args->getLastArgValue(OPT_output_dep_dir, Opts.mOutputDir);
291 Opts.mAdditionalDepTargets =
292 Args->getAllArgValues(OPT_additional_dep_target);
293
294 Opts.mShowHelp = Args->hasArg(OPT_help);
295 Opts.mShowVersion = Args->hasArg(OPT_version);
mkopec1c460b372012-01-09 11:21:50 -0500296 Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
297
298 size_t OptLevel = Args->getLastArgIntValue(OPT_optimization_level,
299 3,
300 DiagEngine);
301
302 Opts.mOptimizationLevel = OptLevel == 0 ? llvm::CodeGenOpt::None
303 : llvm::CodeGenOpt::Aggressive;
Stephen Hines2e35b132011-07-22 02:50:19 -0700304
305 Opts.mTargetAPI = Args->getLastArgIntValue(OPT_target_api,
306 RS_VERSION,
Logan Chien9207a2e2011-10-21 15:39:28 +0800307 DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700308 }
309
310 return;
311}
312
313static const char *DetermineOutputFile(const std::string &OutputDir,
314 const char *InputFile,
Stephen Hinese639eb52010-11-08 19:27:20 -0800315 slang::Slang::OutputType OutputType,
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700316 std::set<std::string> &SavedStrings) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800317 if (OutputType == slang::Slang::OT_Nothing)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700318 return "/dev/null";
319
320 std::string OutputFile(OutputDir);
321
322 // Append '/' to Opts.mOutputDir if not presents
323 if (!OutputFile.empty() &&
Raphael8d5a2f62011-02-08 00:15:05 -0800324 (OutputFile[OutputFile.size() - 1]) != OS_PATH_SEPARATOR)
325 OutputFile.append(1, OS_PATH_SEPARATOR);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700326
Stephen Hinese639eb52010-11-08 19:27:20 -0800327 if (OutputType == slang::Slang::OT_Dependency) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700328 // The build system wants the .d file name stem to be exactly the same as
329 // the source .rs file, instead of the .bc file.
Stephen Hinese639eb52010-11-08 19:27:20 -0800330 OutputFile.append(slang::RSSlangReflectUtils::GetFileNameStem(InputFile));
331 } else {
332 OutputFile.append(
333 slang::RSSlangReflectUtils::BCFileNameFromRSFileName(InputFile));
334 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700335
Stephen Hinese639eb52010-11-08 19:27:20 -0800336 switch (OutputType) {
337 case slang::Slang::OT_Dependency: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700338 OutputFile.append(".d");
339 break;
340 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800341 case slang::Slang::OT_Assembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700342 OutputFile.append(".S");
343 break;
344 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800345 case slang::Slang::OT_LLVMAssembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700346 OutputFile.append(".ll");
347 break;
348 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800349 case slang::Slang::OT_Object: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700350 OutputFile.append(".o");
351 break;
352 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800353 case slang::Slang::OT_Bitcode: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700354 OutputFile.append(".bc");
355 break;
356 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800357 case slang::Slang::OT_Nothing:
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700358 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800359 slangAssert(false && "Invalid output type!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700360 }
361 }
362
363 return SaveStringInSet(SavedStrings, OutputFile);
364}
365
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700366#define str(s) #s
367#define wrap_str(s) str(s)
368static void llvm_rs_cc_VersionPrinter() {
369 llvm::raw_ostream &OS = llvm::outs();
370 OS << "llvm-rs-cc: Renderscript compiler\n"
371 << " (http://developer.android.com/guide/topics/renderscript)\n"
372 << " based on LLVM (http://llvm.org):\n";
373 OS << " Built " << __DATE__ << " (" << __TIME__ ").\n";
374 OS << " Target APIs: " << SLANG_MINIMUM_TARGET_API << " - "
375 << SLANG_MAXIMUM_TARGET_API;
376 OS << "\n Build type: " << wrap_str(TARGET_BUILD_VARIANT);
377#ifndef __DISABLE_ASSERTS
378 OS << " with assertions";
379#endif
380 OS << ".\n";
381 return;
382}
Stephen Hines8f4d9722011-12-05 14:14:42 -0800383#undef wrap_str
384#undef str
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700385
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700386int main(int argc, const char **argv) {
387 std::set<std::string> SavedStrings;
388 llvm::SmallVector<const char*, 256> ArgVector;
389 RSCCOptions Opts;
390 llvm::SmallVector<const char*, 16> Inputs;
391 std::string Argv0;
392
393 atexit(llvm::llvm_shutdown);
394
395 ExpandArgv(argc, argv, ArgVector, SavedStrings);
396
397 // Argv0
Logan Chien6f4e0a92011-03-10 01:10:25 +0800398 Argv0 = llvm::sys::path::stem(ArgVector[0]);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700399
400 // Setup diagnostic engine
Stephen Hines8f4d9722011-12-05 14:14:42 -0800401 slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
Loganbe274822011-02-16 22:02:54 +0800402
403 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
404 new clang::DiagnosticIDs());
405
Logan Chien9207a2e2011-10-21 15:39:28 +0800406 clang::DiagnosticsEngine DiagEngine(DiagIDs, DiagClient, true);
407
Stephen Hinese639eb52010-11-08 19:27:20 -0800408 slang::Slang::GlobalInitialization();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700409
Logan Chien9207a2e2011-10-21 15:39:28 +0800410 ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700411
412 // Exits when there's any error occurred during parsing the arguments
Stephen Hines8f4d9722011-12-05 14:14:42 -0800413 if (DiagEngine.hasErrorOccurred()) {
414 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700415 return 1;
Stephen Hines8f4d9722011-12-05 14:14:42 -0800416 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700417
418 if (Opts.mShowHelp) {
419 llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
420 OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
Stephen Hinesb7d12692011-09-02 18:16:19 -0700421 "Renderscript source compiler");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700422 return 0;
423 }
424
425 if (Opts.mShowVersion) {
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700426 llvm_rs_cc_VersionPrinter();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700427 return 0;
428 }
429
430 // No input file
431 if (Inputs.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800432 DiagEngine.Report(clang::diag::err_drv_no_input_files);
Stephen Hines8f4d9722011-12-05 14:14:42 -0800433 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700434 return 1;
435 }
436
Zonr Changcf6af6a2010-10-12 12:38:51 +0800437 // Prepare input data for RS compiler.
438 std::list<std::pair<const char*, const char*> > IOFiles;
439 std::list<std::pair<const char*, const char*> > DepFiles;
440
Stephen Hinese639eb52010-11-08 19:27:20 -0800441 llvm::OwningPtr<slang::SlangRS> Compiler(new slang::SlangRS());
Zonr Chang641558f2010-10-12 21:07:06 +0800442
Stephen Hines8f4d9722011-12-05 14:14:42 -0800443 Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures, &DiagEngine,
444 DiagClient);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700445
446 for (int i = 0, e = Inputs.size(); i != e; i++) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800447 const char *InputFile = Inputs[i];
448 const char *OutputFile =
449 DetermineOutputFile(Opts.mOutputDir, InputFile,
450 Opts.mOutputType, SavedStrings);
451
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700452 if (Opts.mOutputDep) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800453 const char *BCOutputFile, *DepOutputFile;
Zonr Change8c263a2010-10-12 00:35:29 +0800454
Stephen Hinese639eb52010-11-08 19:27:20 -0800455 if (Opts.mOutputType == slang::Slang::OT_Bitcode)
Zonr Change8c263a2010-10-12 00:35:29 +0800456 BCOutputFile = OutputFile;
457 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800458 BCOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
459 InputFile,
460 slang::Slang::OT_Bitcode,
461 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800462
Stephen Hinese639eb52010-11-08 19:27:20 -0800463 if (Opts.mOutputType == slang::Slang::OT_Dependency)
Zonr Changcf6af6a2010-10-12 12:38:51 +0800464 DepOutputFile = OutputFile;
465 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800466 DepOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
467 InputFile,
468 slang::Slang::OT_Dependency,
469 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800470
471 DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700472 }
Zonr Changcf6af6a2010-10-12 12:38:51 +0800473
474 IOFiles.push_back(std::make_pair(InputFile, OutputFile));
475 }
476
477 // Let's rock!
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800478 int CompileFailed = !Compiler->compile(IOFiles,
479 DepFiles,
480 Opts.mIncludePaths,
481 Opts.mAdditionalDepTargets,
482 Opts.mOutputType,
483 Opts.mBitcodeStorage,
484 Opts.mAllowRSPrefix,
485 Opts.mOutputDep,
Stephen Hines2e35b132011-07-22 02:50:19 -0700486 Opts.mTargetAPI,
mkopec1c460b372012-01-09 11:21:50 -0500487 Opts.mDebugEmission,
488 Opts.mOptimizationLevel,
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800489 Opts.mJavaReflectionPathBase,
Stephen Hines0a813a32012-08-03 16:52:40 -0700490 Opts.mJavaReflectionPackageName,
491 Opts.mRSPackageName);
Stephen Hines5c25c512012-02-27 12:58:17 -0800492
Stephen Hinesc632be22011-09-23 15:53:16 -0700493 Compiler->reset();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700494
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800495 return CompileFailed;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700496}
497
498///////////////////////////////////////////////////////////////////////////////
499
500// ExpandArgsFromBuf -
501static void ExpandArgsFromBuf(const char *Arg,
502 llvm::SmallVectorImpl<const char*> &ArgVector,
503 std::set<std::string> &SavedStrings) {
504 const char *FName = Arg + 1;
Loganbe274822011-02-16 22:02:54 +0800505 llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
506 if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
507 // Unable to open the file
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700508 ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
509 return;
510 }
511
512 const char *Buf = MemBuf->getBufferStart();
513 char InQuote = ' ';
514 std::string CurArg;
515
516 for (const char *P = Buf; ; ++P) {
517 if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
518 if (!CurArg.empty()) {
519 if (CurArg[0] != '@') {
520 ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
521 } else {
522 ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
523 }
524
525 CurArg = "";
526 }
527 if (*P == '\0')
528 break;
529 else
530 continue;
531 }
532
533 if (isspace(*P)) {
534 if (InQuote != ' ')
535 CurArg.push_back(*P);
536 continue;
537 }
538
539 if (*P == '"' || *P == '\'') {
540 if (InQuote == *P)
541 InQuote = ' ';
542 else if (InQuote == ' ')
543 InQuote = *P;
544 else
545 CurArg.push_back(*P);
546 continue;
547 }
548
549 if (*P == '\\') {
550 ++P;
551 if (*P != '\0')
552 CurArg.push_back(*P);
553 continue;
554 }
555 CurArg.push_back(*P);
556 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700557}
558
559// ExpandArgsFromBuf -
560static void ExpandArgv(int argc, const char **argv,
561 llvm::SmallVectorImpl<const char*> &ArgVector,
562 std::set<std::string> &SavedStrings) {
563 for (int i = 0; i < argc; ++i) {
564 const char *Arg = argv[i];
565 if (Arg[0] != '@') {
566 ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
567 continue;
568 }
569
570 ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
571 }
572}