1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
20a813a3ef2a82f19d7eab9e23ae8493197143803Stephen Hines * Copyright 2010-2012, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
178b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines#include "clang/Basic/DiagnosticOptions.h"
18b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao#include "clang/Driver/DriverDiagnostic.h"
19a1f95ee8df425089100148a42954cf61dc285015Stephen Hines#include "clang/Driver/Options.h"
20b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao#include "clang/Frontend/TextDiagnosticPrinter.h"
218f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines#include "clang/Frontend/Utils.h"
22b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
23e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/ADT/SmallVector.h"
24be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "llvm/ADT/IntrusiveRefCntPtr.h"
25b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
26a1f95ee8df425089100148a42954cf61dc285015Stephen Hines#include "llvm/Option/OptTable.h"
27e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Support/CommandLine.h"
28e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Support/ManagedStatic.h"
29e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Support/MemoryBuffer.h"
30be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "llvm/Support/Path.h"
31ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines#include "llvm/Support/raw_ostream.h"
32c460b37ffb50819a32c2a8967754b6f784b28263mkopec#include "llvm/Target/TargetMachine.h"
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
348b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines#include "rs_cc_options.h"
35e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang.h"
366e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
378f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines#include "slang_diagnostic_buffer.h"
38e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang_rs.h"
39e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "slang_rs_reflect_utils.h"
40b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
418b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines#include <list>
428b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines#include <set>
438b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines#include <string>
44b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
45b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao// SaveStringInSet, ExpandArgsFromBuf and ExpandArgv are all copied from
46b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao// $(CLANG_ROOT)/tools/driver/driver.cpp for processing argc/argv passed in
47b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao// main().
48b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic inline const char *SaveStringInSet(std::set<std::string> &SavedStrings,
49b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                                          llvm::StringRef S) {
50b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  return SavedStrings.insert(S).first->c_str();
51b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao}
52b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic void ExpandArgsFromBuf(const char *Arg,
53b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                              llvm::SmallVectorImpl<const char*> &ArgVector,
54b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                              std::set<std::string> &SavedStrings);
55b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic void ExpandArgv(int argc, const char **argv,
56b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                       llvm::SmallVectorImpl<const char*> &ArgVector,
57b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                       std::set<std::string> &SavedStrings);
58b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
59b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic const char *DetermineOutputFile(const std::string &OutputDir,
609ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                       const std::string &PathSuffix,
61b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                                       const char *InputFile,
62e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                       slang::Slang::OutputType OutputType,
63b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                                       std::set<std::string> &SavedStrings) {
64e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (OutputType == slang::Slang::OT_Nothing)
65b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return "/dev/null";
66b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
67b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  std::string OutputFile(OutputDir);
68b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
697f5704efe0c59d5599f1ac7056976225dbfab946Stephen Hines  // Append '/' to Opts.mBitcodeOutputDir if not presents
70b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  if (!OutputFile.empty() &&
718d5a2f6ab321615bfb3a46f68aff0b643a71caa0Raphael      (OutputFile[OutputFile.size() - 1]) != OS_PATH_SEPARATOR)
728d5a2f6ab321615bfb3a46f68aff0b643a71caa0Raphael    OutputFile.append(1, OS_PATH_SEPARATOR);
73b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
749ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (!PathSuffix.empty()) {
759ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    OutputFile.append(PathSuffix);
769ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    OutputFile.append(1, OS_PATH_SEPARATOR);
779ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
789ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
79e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (OutputType == slang::Slang::OT_Dependency) {
80b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    // The build system wants the .d file name stem to be exactly the same as
81b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    // the source .rs file, instead of the .bc file.
82e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    OutputFile.append(slang::RSSlangReflectUtils::GetFileNameStem(InputFile));
83e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  } else {
84e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    OutputFile.append(
85e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines        slang::RSSlangReflectUtils::BCFileNameFromRSFileName(InputFile));
86e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  }
87b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
88e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  switch (OutputType) {
89e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_Dependency: {
90b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      OutputFile.append(".d");
91b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      break;
92b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
93e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_Assembly: {
94b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      OutputFile.append(".S");
95b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      break;
96b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
97e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_LLVMAssembly: {
98b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      OutputFile.append(".ll");
99b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      break;
100b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
101e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_Object: {
102b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      OutputFile.append(".o");
103b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      break;
104b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
105e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_Bitcode: {
106b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      OutputFile.append(".bc");
107b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      break;
108b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
109e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    case slang::Slang::OT_Nothing:
110b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    default: {
1116e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Invalid output type!");
112b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
113b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
114b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
115b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  return SaveStringInSet(SavedStrings, OutputFile);
116b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao}
117b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
1189ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hinestypedef std::list<std::pair<const char*, const char*> > NamePairList;
1199ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1209ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines/*
1219ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * Compile the Inputs.
1229ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines *
1239ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * Returns 0 on success and nonzero on failure.
1249ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines *
1259ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * IOFiles - list of (foo.rs, foo.bc) pairs of input/output files.
1269ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * IOFiles32 - list of input/output pairs for 32-bit compilation.
1279ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * Inputs - input filenames.
1289ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * Opts - options controlling compilation.
1299ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * DiagEngine - Clang diagnostic engine (for creating diagnostics).
1309ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * DiagClient - Slang diagnostic consumer (collects and displays diagnostics).
1319ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * SavedStrings - expanded strings copied from argv source input files.
1329ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines *
1339ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * We populate IOFiles dynamically while working through the list of Inputs.
1349ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * On any 64-bit compilation, we pass back in the 32-bit pairs of files as
1359ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * IOFiles32. This allows the 64-bit compiler to later bundle up both the
1369ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * 32-bit and 64-bit bitcode outputs to be included in the final reflected
1379ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines * source code that is emitted.
1389ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines */
1399ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hinesstatic int compileFiles(NamePairList *IOFiles, NamePairList *IOFiles32,
1409ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    const llvm::SmallVector<const char*, 16> &Inputs, slang::RSCCOptions &Opts,
1419ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    clang::DiagnosticsEngine *DiagEngine, slang::DiagnosticBuffer *DiagClient,
1429ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    std::set<std::string> *SavedStrings) {
1439ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  NamePairList DepFiles;
1449ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  std::string PathSuffix = "";
1452d504fd03c66be56ac3b4bb62c78cc72c75dd8b6Stephen Hines  bool CompileSecondTimeFor64Bit = false;
1469ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1479ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  // In our mixed 32/64-bit path, we need to suffix our files differently for
1489ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  // both 32-bit and 64-bit versions.
1499ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (Opts.mEmit3264) {
1509ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    if (Opts.mBitWidth == 64) {
1519ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      PathSuffix = "bc64";
1522d504fd03c66be56ac3b4bb62c78cc72c75dd8b6Stephen Hines      CompileSecondTimeFor64Bit = true;
1539ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    } else {
1549ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      PathSuffix = "bc32";
1559ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    }
1569ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
1579ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1589ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  for (int i = 0, e = Inputs.size(); i != e; i++) {
1599ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    const char *InputFile = Inputs[i];
1609ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1619ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    const char *BCOutputFile = DetermineOutputFile(Opts.mBitcodeOutputDir,
1629ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                                   PathSuffix, InputFile,
1639ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                                   slang::Slang::OT_Bitcode,
1649ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                                   *SavedStrings);
1659ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    const char *OutputFile = BCOutputFile;
1669ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1679ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    if (Opts.mEmitDependency) {
1689ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      // The dependency file is always emitted without a PathSuffix.
1699ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      // Collisions between 32-bit and 64-bit files don't make a difference,
1709ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      // because they share the same sources/dependencies.
1719ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      const char *DepOutputFile =
1729ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines          DetermineOutputFile(Opts.mDependencyOutputDir, "", InputFile,
1739ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                              slang::Slang::OT_Dependency, *SavedStrings);
1749ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      if (Opts.mOutputType == slang::Slang::OT_Dependency) {
1759ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines        OutputFile = DepOutputFile;
1769ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      }
1779ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1789ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
1799ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    }
1809ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1819ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    IOFiles->push_back(std::make_pair(InputFile, OutputFile));
1829ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  }
1839ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
1847ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines  std::unique_ptr<slang::SlangRS> Compiler(new slang::SlangRS());
1859ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  Compiler->init(Opts.mBitWidth, DiagEngine, DiagClient);
1869ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  int CompileFailed = !Compiler->compile(*IOFiles, *IOFiles32, DepFiles, Opts);
1872d504fd03c66be56ac3b4bb62c78cc72c75dd8b6Stephen Hines  // We suppress warnings (via reset) if we are doing a second compilation.
1882d504fd03c66be56ac3b4bb62c78cc72c75dd8b6Stephen Hines  Compiler->reset(CompileSecondTimeFor64Bit);
1899ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  return CompileFailed;
1909ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines}
1919ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines
192ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines#define str(s) #s
193ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines#define wrap_str(s) str(s)
194ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hinesstatic void llvm_rs_cc_VersionPrinter() {
195ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  llvm::raw_ostream &OS = llvm::outs();
196ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << "llvm-rs-cc: Renderscript compiler\n"
197ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines     << "  (http://developer.android.com/guide/topics/renderscript)\n"
198ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines     << "  based on LLVM (http://llvm.org):\n";
199ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << "  Built " << __DATE__ << " (" << __TIME__ ").\n";
200ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << "  Target APIs: " << SLANG_MINIMUM_TARGET_API << " - "
201ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines     << SLANG_MAXIMUM_TARGET_API;
202ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << "\n  Build type: " << wrap_str(TARGET_BUILD_VARIANT);
203ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines#ifndef __DISABLE_ASSERTS
204ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << " with assertions";
205ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines#endif
206ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines  OS << ".\n";
207ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines}
2088f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines#undef wrap_str
2098f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines#undef str
210ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines
211b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaoint main(int argc, const char **argv) {
212b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  std::set<std::string> SavedStrings;
213b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  llvm::SmallVector<const char*, 256> ArgVector;
2148b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines  slang::RSCCOptions Opts;
215b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  llvm::SmallVector<const char*, 16> Inputs;
216b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  std::string Argv0;
217b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
2189ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  llvm::llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
219b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
220b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  ExpandArgv(argc, argv, ArgVector, SavedStrings);
221b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
222b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  // Argv0
2236f4e0a9955a53a6f715af7e674e68ed15270a47cLogan Chien  Argv0 = llvm::sys::path::stem(ArgVector[0]);
224b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
225b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  // Setup diagnostic engine
2268f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines  slang::DiagnosticBuffer *DiagClient = new slang::DiagnosticBuffer();
227be27482cdeaf08576bc39b72a15d35d13014a636Logan
228be27482cdeaf08576bc39b72a15d35d13014a636Logan  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
229be27482cdeaf08576bc39b72a15d35d13014a636Logan    new clang::DiagnosticIDs());
230be27482cdeaf08576bc39b72a15d35d13014a636Logan
23123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
23223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    new clang::DiagnosticOptions());
23323c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::DiagnosticsEngine DiagEngine(DiagIDs, &*DiagOpts, DiagClient, true);
2349207a2e495c8363606861e4f034504ec5c153dabLogan Chien
235e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  slang::Slang::GlobalInitialization();
236b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
2378b5c5c6566078d49c4dcd8d8c7a6364c33c09037Stephen Hines  slang::ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
238b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
239b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  // Exits when there's any error occurred during parsing the arguments
2408f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines  if (DiagEngine.hasErrorOccurred()) {
2418f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines    llvm::errs() << DiagClient->str();
242b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return 1;
2438f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines  }
244b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
245b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  if (Opts.mShowHelp) {
2467ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines    std::unique_ptr<llvm::opt::OptTable> OptTbl(slang::createRSCCOptTable());
247b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
248b7d1269f983f28d9fe625a96439fa88b39dc96f6Stephen Hines                      "Renderscript source compiler");
249b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return 0;
250b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
251b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
252b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  if (Opts.mShowVersion) {
253ba7c6dc08e1ab8486ccaf842e8ae87dc5c99d8cfStephen Hines    llvm_rs_cc_VersionPrinter();
254b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return 0;
255b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
256b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
257b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  // No input file
258b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  if (Inputs.empty()) {
2599207a2e495c8363606861e4f034504ec5c153dabLogan Chien    DiagEngine.Report(clang::diag::err_drv_no_input_files);
2608f4d972ef6c6796ffdde603e456979a7004d1e20Stephen Hines    llvm::errs() << DiagClient->str();
261b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return 1;
262b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
263b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
264cf6af6abc1de499920571308b14a27e19cf57097Zonr Chang  // Prepare input data for RS compiler.
2659ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  NamePairList IOFiles64;
2669ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  NamePairList IOFiles32;
267b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
2689ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  int CompileFailed = compileFiles(&IOFiles32, &IOFiles32, Inputs, Opts,
2699ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                   &DiagEngine, DiagClient, &SavedStrings);
270cf6af6abc1de499920571308b14a27e19cf57097Zonr Chang
2719ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  // Handle the 64-bit case too!
2729ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines  if (Opts.mEmit3264 && !CompileFailed) {
2739ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    Opts.mBitWidth = 64;
2749ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines    CompileFailed = compileFiles(&IOFiles64, &IOFiles32, Inputs, Opts,
2759ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines                                 &DiagEngine, DiagClient, &SavedStrings);
276cf6af6abc1de499920571308b14a27e19cf57097Zonr Chang  }
277cf6af6abc1de499920571308b14a27e19cf57097Zonr Chang
278d7f0ea21058abbdd1edfd3df65762fa3c91cb224Stephen Hines  return CompileFailed;
279b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao}
280b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
281b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao///////////////////////////////////////////////////////////////////////////////
282b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
283b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao// ExpandArgsFromBuf -
284b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic void ExpandArgsFromBuf(const char *Arg,
285b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                              llvm::SmallVectorImpl<const char*> &ArgVector,
286b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                              std::set<std::string> &SavedStrings) {
287b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  const char *FName = Arg + 1;
2887ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MBOrErr =
2897ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines      llvm::MemoryBuffer::getFile(FName);
2907ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines  if (MBOrErr.getError()) {
291be27482cdeaf08576bc39b72a15d35d13014a636Logan    // Unable to open the file
292b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
293b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    return;
294b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
2957ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines  std::unique_ptr<llvm::MemoryBuffer> MemBuf = std::move(MBOrErr.get());
296b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
297b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  const char *Buf = MemBuf->getBufferStart();
298b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  char InQuote = ' ';
299b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  std::string CurArg;
300b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
301b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  for (const char *P = Buf; ; ++P) {
302b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
303b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      if (!CurArg.empty()) {
304b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        if (CurArg[0] != '@') {
305b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao          ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
306b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        } else {
307b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao          ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
308b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        }
309b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
310b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        CurArg = "";
311b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      }
312b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      if (*P == '\0')
313b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        break;
314b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      else
315b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        continue;
316b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
317b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
318b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    if (isspace(*P)) {
319b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      if (InQuote != ' ')
320b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        CurArg.push_back(*P);
321b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      continue;
322b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
323b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
324b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    if (*P == '"' || *P == '\'') {
325b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      if (InQuote == *P)
326b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        InQuote = ' ';
327b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      else if (InQuote == ' ')
328b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        InQuote = *P;
329b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      else
330b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        CurArg.push_back(*P);
331b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      continue;
332b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
333b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
334b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    if (*P == '\\') {
335b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      ++P;
336b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      if (*P != '\0')
337b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        CurArg.push_back(*P);
338b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      continue;
339b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
340b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    CurArg.push_back(*P);
341b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
342b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao}
343b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
344b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao// ExpandArgsFromBuf -
345b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liaostatic void ExpandArgv(int argc, const char **argv,
346b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                       llvm::SmallVectorImpl<const char*> &ArgVector,
347b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao                       std::set<std::string> &SavedStrings) {
348b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  for (int i = 0; i < argc; ++i) {
349b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    const char *Arg = argv[i];
350b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    if (Arg[0] != '@') {
351b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
352b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao      continue;
353b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
354b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao
355b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
356b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao  }
357b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao}
358