blob: 08e25e741bc689bb9486cac8b26afd99e8fa8d9a [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;
283 }
284
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700285 Opts.mOutputDepDir =
286 Args->getLastArgValue(OPT_output_dep_dir, Opts.mOutputDir);
287 Opts.mAdditionalDepTargets =
288 Args->getAllArgValues(OPT_additional_dep_target);
289
290 Opts.mShowHelp = Args->hasArg(OPT_help);
291 Opts.mShowVersion = Args->hasArg(OPT_version);
mkopec1c460b372012-01-09 11:21:50 -0500292 Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
293
294 size_t OptLevel = Args->getLastArgIntValue(OPT_optimization_level,
295 3,
296 DiagEngine);
297
298 Opts.mOptimizationLevel = OptLevel == 0 ? llvm::CodeGenOpt::None
299 : llvm::CodeGenOpt::Aggressive;
Stephen Hines2e35b132011-07-22 02:50:19 -0700300
301 Opts.mTargetAPI = Args->getLastArgIntValue(OPT_target_api,
302 RS_VERSION,
Logan Chien9207a2e2011-10-21 15:39:28 +0800303 DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700304 }
305
306 return;
307}
308
309static const char *DetermineOutputFile(const std::string &OutputDir,
310 const char *InputFile,
Stephen Hinese639eb52010-11-08 19:27:20 -0800311 slang::Slang::OutputType OutputType,
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700312 std::set<std::string> &SavedStrings) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800313 if (OutputType == slang::Slang::OT_Nothing)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700314 return "/dev/null";
315
316 std::string OutputFile(OutputDir);
317
318 // Append '/' to Opts.mOutputDir if not presents
319 if (!OutputFile.empty() &&
Raphael8d5a2f62011-02-08 00:15:05 -0800320 (OutputFile[OutputFile.size() - 1]) != OS_PATH_SEPARATOR)
321 OutputFile.append(1, OS_PATH_SEPARATOR);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700322
Stephen Hinese639eb52010-11-08 19:27:20 -0800323 if (OutputType == slang::Slang::OT_Dependency) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700324 // The build system wants the .d file name stem to be exactly the same as
325 // the source .rs file, instead of the .bc file.
Stephen Hinese639eb52010-11-08 19:27:20 -0800326 OutputFile.append(slang::RSSlangReflectUtils::GetFileNameStem(InputFile));
327 } else {
328 OutputFile.append(
329 slang::RSSlangReflectUtils::BCFileNameFromRSFileName(InputFile));
330 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700331
Stephen Hinese639eb52010-11-08 19:27:20 -0800332 switch (OutputType) {
333 case slang::Slang::OT_Dependency: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700334 OutputFile.append(".d");
335 break;
336 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800337 case slang::Slang::OT_Assembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700338 OutputFile.append(".S");
339 break;
340 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800341 case slang::Slang::OT_LLVMAssembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700342 OutputFile.append(".ll");
343 break;
344 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800345 case slang::Slang::OT_Object: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700346 OutputFile.append(".o");
347 break;
348 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800349 case slang::Slang::OT_Bitcode: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700350 OutputFile.append(".bc");
351 break;
352 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800353 case slang::Slang::OT_Nothing:
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700354 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800355 slangAssert(false && "Invalid output type!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700356 }
357 }
358
359 return SaveStringInSet(SavedStrings, OutputFile);
360}
361
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700362#define str(s) #s
363#define wrap_str(s) str(s)
364static void llvm_rs_cc_VersionPrinter() {
365 llvm::raw_ostream &OS = llvm::outs();
366 OS << "llvm-rs-cc: Renderscript compiler\n"
367 << " (http://developer.android.com/guide/topics/renderscript)\n"
368 << " based on LLVM (http://llvm.org):\n";
369 OS << " Built " << __DATE__ << " (" << __TIME__ ").\n";
370 OS << " Target APIs: " << SLANG_MINIMUM_TARGET_API << " - "
371 << SLANG_MAXIMUM_TARGET_API;
372 OS << "\n Build type: " << wrap_str(TARGET_BUILD_VARIANT);
373#ifndef __DISABLE_ASSERTS
374 OS << " with assertions";
375#endif
376 OS << ".\n";
377 return;
378}
Stephen Hines8f4d9722011-12-05 14:14:42 -0800379#undef wrap_str
380#undef str
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700381
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700382int main(int argc, const char **argv) {
383 std::set<std::string> SavedStrings;
384 llvm::SmallVector<const char*, 256> ArgVector;
385 RSCCOptions Opts;
386 llvm::SmallVector<const char*, 16> Inputs;
387 std::string Argv0;
388
389 atexit(llvm::llvm_shutdown);
390
391 ExpandArgv(argc, argv, ArgVector, SavedStrings);
392
393 // Argv0
Logan Chien6f4e0a92011-03-10 01:10:25 +0800394 Argv0 = llvm::sys::path::stem(ArgVector[0]);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700395
396 // Setup diagnostic engine
Stephen Hines8f4d9722011-12-05 14:14:42 -0800397 slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
Loganbe274822011-02-16 22:02:54 +0800398
399 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
400 new clang::DiagnosticIDs());
401
Logan Chien9207a2e2011-10-21 15:39:28 +0800402 clang::DiagnosticsEngine DiagEngine(DiagIDs, DiagClient, true);
403
Stephen Hinese639eb52010-11-08 19:27:20 -0800404 slang::Slang::GlobalInitialization();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700405
Logan Chien9207a2e2011-10-21 15:39:28 +0800406 ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700407
408 // Exits when there's any error occurred during parsing the arguments
Stephen Hines8f4d9722011-12-05 14:14:42 -0800409 if (DiagEngine.hasErrorOccurred()) {
410 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700411 return 1;
Stephen Hines8f4d9722011-12-05 14:14:42 -0800412 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700413
414 if (Opts.mShowHelp) {
415 llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
416 OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
Stephen Hinesb7d12692011-09-02 18:16:19 -0700417 "Renderscript source compiler");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700418 return 0;
419 }
420
421 if (Opts.mShowVersion) {
Stephen Hinesba7c6dc2011-09-07 19:57:04 -0700422 llvm_rs_cc_VersionPrinter();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700423 return 0;
424 }
425
426 // No input file
427 if (Inputs.empty()) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800428 DiagEngine.Report(clang::diag::err_drv_no_input_files);
Stephen Hines8f4d9722011-12-05 14:14:42 -0800429 llvm::errs() << DiagClient->str();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700430 return 1;
431 }
432
Zonr Changcf6af6a2010-10-12 12:38:51 +0800433 // Prepare input data for RS compiler.
434 std::list<std::pair<const char*, const char*> > IOFiles;
435 std::list<std::pair<const char*, const char*> > DepFiles;
436
Stephen Hinese639eb52010-11-08 19:27:20 -0800437 llvm::OwningPtr<slang::SlangRS> Compiler(new slang::SlangRS());
Zonr Chang641558f2010-10-12 21:07:06 +0800438
Stephen Hines8f4d9722011-12-05 14:14:42 -0800439 Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures, &DiagEngine,
440 DiagClient);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700441
442 for (int i = 0, e = Inputs.size(); i != e; i++) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800443 const char *InputFile = Inputs[i];
444 const char *OutputFile =
445 DetermineOutputFile(Opts.mOutputDir, InputFile,
446 Opts.mOutputType, SavedStrings);
447
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700448 if (Opts.mOutputDep) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800449 const char *BCOutputFile, *DepOutputFile;
Zonr Change8c263a2010-10-12 00:35:29 +0800450
Stephen Hinese639eb52010-11-08 19:27:20 -0800451 if (Opts.mOutputType == slang::Slang::OT_Bitcode)
Zonr Change8c263a2010-10-12 00:35:29 +0800452 BCOutputFile = OutputFile;
453 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800454 BCOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
455 InputFile,
456 slang::Slang::OT_Bitcode,
457 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800458
Stephen Hinese639eb52010-11-08 19:27:20 -0800459 if (Opts.mOutputType == slang::Slang::OT_Dependency)
Zonr Changcf6af6a2010-10-12 12:38:51 +0800460 DepOutputFile = OutputFile;
461 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800462 DepOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
463 InputFile,
464 slang::Slang::OT_Dependency,
465 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800466
467 DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700468 }
Zonr Changcf6af6a2010-10-12 12:38:51 +0800469
470 IOFiles.push_back(std::make_pair(InputFile, OutputFile));
471 }
472
473 // Let's rock!
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800474 int CompileFailed = !Compiler->compile(IOFiles,
475 DepFiles,
476 Opts.mIncludePaths,
477 Opts.mAdditionalDepTargets,
478 Opts.mOutputType,
479 Opts.mBitcodeStorage,
480 Opts.mAllowRSPrefix,
481 Opts.mOutputDep,
Stephen Hines2e35b132011-07-22 02:50:19 -0700482 Opts.mTargetAPI,
mkopec1c460b372012-01-09 11:21:50 -0500483 Opts.mDebugEmission,
484 Opts.mOptimizationLevel,
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800485 Opts.mJavaReflectionPathBase,
Stephen Hines0a813a32012-08-03 16:52:40 -0700486 Opts.mJavaReflectionPackageName,
487 Opts.mRSPackageName);
Stephen Hines5c25c512012-02-27 12:58:17 -0800488
Stephen Hinesc632be22011-09-23 15:53:16 -0700489 Compiler->reset();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700490
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800491 return CompileFailed;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700492}
493
494///////////////////////////////////////////////////////////////////////////////
495
496// ExpandArgsFromBuf -
497static void ExpandArgsFromBuf(const char *Arg,
498 llvm::SmallVectorImpl<const char*> &ArgVector,
499 std::set<std::string> &SavedStrings) {
500 const char *FName = Arg + 1;
Loganbe274822011-02-16 22:02:54 +0800501 llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
502 if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
503 // Unable to open the file
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700504 ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
505 return;
506 }
507
508 const char *Buf = MemBuf->getBufferStart();
509 char InQuote = ' ';
510 std::string CurArg;
511
512 for (const char *P = Buf; ; ++P) {
513 if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
514 if (!CurArg.empty()) {
515 if (CurArg[0] != '@') {
516 ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
517 } else {
518 ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
519 }
520
521 CurArg = "";
522 }
523 if (*P == '\0')
524 break;
525 else
526 continue;
527 }
528
529 if (isspace(*P)) {
530 if (InQuote != ' ')
531 CurArg.push_back(*P);
532 continue;
533 }
534
535 if (*P == '"' || *P == '\'') {
536 if (InQuote == *P)
537 InQuote = ' ';
538 else if (InQuote == ' ')
539 InQuote = *P;
540 else
541 CurArg.push_back(*P);
542 continue;
543 }
544
545 if (*P == '\\') {
546 ++P;
547 if (*P != '\0')
548 CurArg.push_back(*P);
549 continue;
550 }
551 CurArg.push_back(*P);
552 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700553}
554
555// ExpandArgsFromBuf -
556static void ExpandArgv(int argc, const char **argv,
557 llvm::SmallVectorImpl<const char*> &ArgVector,
558 std::set<std::string> &SavedStrings) {
559 for (int i = 0; i < argc; ++i) {
560 const char *Arg = argv[i];
561 if (Arg[0] != '@') {
562 ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
563 continue;
564 }
565
566 ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
567 }
568}