1/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  // NOLINT
18#define _FRAMEWORKS_COMPILE_SLANG_SLANG_H_
19
20#include <cstdio>
21#include <list>
22#include <string>
23#include <utility>
24#include <vector>
25
26#include "llvm/ADT/StringMap.h"
27
28#include "slang_rs_reflect_utils.h"
29#include "slang_version.h"
30
31// Terrible workaround for TargetOptions.h not using llvm::RefCountedBase!
32#include "llvm/ADT/IntrusiveRefCntPtr.h"
33using llvm::RefCountedBase;
34
35#include "clang/Basic/LangOptions.h"
36#include "clang/Basic/TargetOptions.h"
37#include "clang/Frontend/CodeGenOptions.h"
38#include "clang/Lex/ModuleLoader.h"
39
40#include "llvm/ADT/StringRef.h"
41
42#include "llvm/Target/TargetMachine.h"
43
44#include "slang_diagnostic_buffer.h"
45#include "slang_pragma_list.h"
46
47namespace llvm {
48  class tool_output_file;
49}
50
51namespace clang {
52  class ASTConsumer;
53  class ASTContext;
54  class Backend;
55  class CodeGenOptions;
56  class Diagnostic;
57  class DiagnosticsEngine;
58  class FileManager;
59  class FileSystemOptions;
60  class HeaderSearchOptions;
61  class LangOptions;
62  class PCHContainerOperations;
63  class Preprocessor;
64  class PreprocessorOptions;
65  class SourceManager;
66  class TargetInfo;
67}  // namespace clang
68
69namespace slang {
70
71class ReflectionState;
72class RSCCOptions;
73class RSContext;
74class RSExportRecordType;
75
76llvm::LLVMContext &getGlobalLLVMContext();
77
78class Slang : public clang::ModuleLoader {
79 public:
80  enum OutputType {
81    OT_Dependency,
82    OT_Assembly,
83    OT_LLVMAssembly,
84    OT_Bitcode,
85    OT_Nothing,
86    OT_Object,
87
88    OT_Default = OT_Bitcode
89  };
90
91 private:
92  // Language options (define the language feature for compiler such as C99)
93  clang::LangOptions LangOpts;
94  // Code generation options for the compiler
95  clang::CodeGenOptions CodeGenOpts;
96
97  // Returns true if this is a Filterscript file.
98  static bool isFilterscript(const char *Filename);
99
100  // Diagnostics Engine (Producer and Diagnostics Reporter)
101  clang::DiagnosticsEngine *mDiagEngine;
102
103  // Diagnostics Consumer
104  // NOTE: The ownership is taken by mDiagEngine after creation.
105  DiagnosticBuffer *mDiagClient;
106
107  // The target being compiled for
108  std::shared_ptr<clang::TargetOptions> mTargetOpts;
109  std::unique_ptr<clang::TargetInfo> mTarget;
110  void createTarget(uint32_t BitWidth);
111
112  // File manager (for prepocessor doing the job such as header file search)
113  std::unique_ptr<clang::FileManager> mFileMgr;
114  std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
115  void createFileManager();
116
117  // Source manager (responsible for the source code handling)
118  std::unique_ptr<clang::SourceManager> mSourceMgr;
119  void createSourceManager();
120
121  // Preprocessor (source code preprocessor)
122  std::unique_ptr<clang::Preprocessor> mPP;
123  void createPreprocessor();
124
125  // AST context (the context to hold long-lived AST nodes)
126  std::unique_ptr<clang::ASTContext> mASTContext;
127  void createASTContext();
128
129  // AST consumer, responsible for code generation
130  std::unique_ptr<clang::ASTConsumer> mBackend;
131
132  // Options for includes
133  llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> mHSOpts;
134
135  // Options for the preprocessor (but not header includes)
136  llvm::IntrusiveRefCntPtr<clang::PreprocessorOptions> mPPOpts;
137
138  // Module provider (probably not necessary, but keeps us more consistent
139  // with regular Clang.
140  std::shared_ptr<clang::PCHContainerOperations> mPCHContainerOperations;
141
142  // File names
143  std::string mInputFileName;
144  std::string mOutputFileName;
145  std::string mOutput32FileName;
146
147  std::string mDepOutputFileName;
148  std::string mDepTargetBCFileName;
149  std::vector<std::string> mAdditionalDepTargets;
150
151  OutputType mOT;
152
153  // Output stream
154  std::unique_ptr<llvm::tool_output_file> mOS;
155
156  // Dependency output stream
157  std::unique_ptr<llvm::tool_output_file> mDOS;
158
159  std::vector<std::string> mIncludePaths;
160
161  // Context for Renderscript
162  RSContext *mRSContext;
163
164  bool mAllowRSPrefix;
165
166  unsigned int mTargetAPI;
167
168  bool mVerbose;
169
170  bool mIsFilterscript;
171
172  // Collect generated filenames (without the .java) for dependency generation
173  std::vector<std::string> mGeneratedFileNames;
174
175  PragmaList mPragmas;
176
177  // FIXME: Should be std::list<RSExportable *> here. But currently we only
178  //        check ODR on record type.
179  //
180  // ReflectedDefinitions maps record type name to a pair:
181  //  <its RSExportRecordType instance,
182  //   the first file contains this record type definition>
183  typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
184  typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
185  ReflectedDefinitionListTy ReflectedDefinitions;
186
187  bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
188                                   const std::string &PackageName,
189                                   const std::string *LicenseNote);
190
191  // CurInputFile is the pointer to a char array holding the input filename
192  // and is valid before compile() ends.
193  bool checkODR(const char *CurInputFile);
194
195  clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
196  clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
197  clang::FileManager &getFileManager() { return *mFileMgr; }
198  clang::SourceManager &getSourceManager() { return *mSourceMgr; }
199  clang::Preprocessor &getPreprocessor() { return *mPP; }
200  clang::ASTContext &getASTContext() { return *mASTContext; }
201  clang::HeaderSearchOptions &getHeaderSearchOpts() { return *mHSOpts; }
202  clang::PreprocessorOptions &getPreprocessorOpts() { return *mPPOpts; }
203
204  inline clang::TargetOptions const &getTargetOptions() const
205    { return *mTargetOpts.get(); }
206
207  void initPreprocessor();
208  void initASTContext();
209
210  clang::ASTConsumer *createBackend(const RSCCOptions &Opts,
211                                    const clang::CodeGenOptions &CodeGenOpts,
212                                    llvm::raw_ostream *OS,
213                                    OutputType OT);
214
215 public:
216  static const llvm::StringRef PragmaMetadataName;
217
218  static void GlobalInitialization();
219
220  static bool IsRSHeaderFile(const char *File);
221  // FIXME: Determine whether a location is in RS header (i.e., one of the RS
222  //        built-in APIs) should only need its names (we need a "list" of RS
223  //        built-in APIs).
224  static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
225                                  const clang::SourceManager &SourceMgr);
226
227  Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
228        DiagnosticBuffer *DiagClient);
229
230  virtual ~Slang();
231
232  bool setInputSource(llvm::StringRef InputFile);
233
234  std::string const &getInputFileName() const { return mInputFileName; }
235
236  void setIncludePaths(const std::vector<std::string> &IncludePaths) {
237    mIncludePaths = IncludePaths;
238  }
239
240  void setOutputType(OutputType OT) { mOT = OT; }
241
242  bool setOutput(const char *OutputFile);
243
244  bool setDepOutput(const char *OutputFile);
245
246  void setDepTargetBC(const char *TargetBCFile) {
247    mDepTargetBCFileName = TargetBCFile;
248  }
249
250  void setAdditionalDepTargets(
251      std::vector<std::string> const &AdditionalDepTargets) {
252    mAdditionalDepTargets = AdditionalDepTargets;
253  }
254
255  void appendGeneratedFileName(std::string const &GeneratedFileName) {
256    mGeneratedFileNames.push_back(GeneratedFileName);
257  }
258
259  int generateDepFile(bool PhonyTarget);
260
261  int compile(const RSCCOptions &Opts);
262
263  char const *getErrorMessage() { return mDiagClient->str().c_str(); }
264
265  void setDebugMetadataEmission(bool EmitDebug);
266
267  void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
268
269  // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
270  // all given input files are successfully compiled without errors.
271  //
272  // @IOFiles - List of pairs of <input file path, output file path>.
273  //
274  // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
275  //             target>. If @OutputDep is true, this parameter must be given
276  //             with the same number of pairs given in @IOFiles.
277  //
278  // @Opts - Selection of options defined from invoking llvm-rs-cc
279  //
280  // @Reflection - Carries reflection information from 32-bit compile to 64-bit compile.
281  bool
282  compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
283          const std::list<std::pair<const char *, const char *>> &IOFiles32,
284          const std::list<std::pair<const char *, const char *>> &DepFiles,
285          const RSCCOptions &Opts,
286          clang::DiagnosticOptions &DiagOpts,
287          ReflectionState *Reflection);
288
289  clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
290                                     clang::ModuleIdPath Path,
291                                     clang::Module::NameVisibilityKind VK,
292                                     bool IsInclusionDirective) override;
293
294  void makeModuleVisible(clang::Module *Mod,
295                         clang::Module::NameVisibilityKind Visibility,
296                         clang::SourceLocation ImportLoc) override {}
297
298  clang::GlobalModuleIndex *
299  loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override {
300    // We don't support C++ modules for RenderScript.
301    return nullptr;
302  }
303
304  bool lookupMissingImports(llvm::StringRef Name,
305                            clang::SourceLocation TriggerLoc) override {
306    // We don't support C++ modules for RenderScript.
307    return false;
308  }
309};
310
311} // namespace slang
312
313#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
314