slang.h revision 3fe4027f9acbc5047f8e7ca8f1575e3a6af76cf8
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_recorder.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 LangOptions;
61  class Preprocessor;
62  class SourceManager;
63  class TargetInfo;
64}  // namespace clang
65
66namespace slang {
67
68class RSCCOptions;
69class RSContext;
70class RSExportRecordType;
71
72class Slang : public clang::ModuleLoader {
73 public:
74  enum OutputType {
75    OT_Dependency,
76    OT_Assembly,
77    OT_LLVMAssembly,
78    OT_Bitcode,
79    OT_Nothing,
80    OT_Object,
81
82    OT_Default = OT_Bitcode
83  };
84
85 private:
86  // Language options (define the language feature for compiler such as C99)
87  clang::LangOptions LangOpts;
88  // Code generation options for the compiler
89  clang::CodeGenOptions CodeGenOpts;
90
91  // Returns true if this is a Filterscript file.
92  static bool isFilterscript(const char *Filename);
93
94  // Diagnostics Engine (Producer and Diagnostics Reporter)
95  clang::DiagnosticsEngine *mDiagEngine;
96
97  // Diagnostics Consumer
98  // NOTE: The ownership is taken by mDiagEngine after creation.
99  DiagnosticBuffer *mDiagClient;
100
101  // The target being compiled for
102  std::shared_ptr<clang::TargetOptions> mTargetOpts;
103  std::unique_ptr<clang::TargetInfo> mTarget;
104  void createTarget(uint32_t BitWidth);
105
106  // File manager (for prepocessor doing the job such as header file search)
107  std::unique_ptr<clang::FileManager> mFileMgr;
108  std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
109  void createFileManager();
110
111  // Source manager (responsible for the source code handling)
112  std::unique_ptr<clang::SourceManager> mSourceMgr;
113  void createSourceManager();
114
115  // Preprocessor (source code preprocessor)
116  std::unique_ptr<clang::Preprocessor> mPP;
117  void createPreprocessor();
118
119  // AST context (the context to hold long-lived AST nodes)
120  std::unique_ptr<clang::ASTContext> mASTContext;
121  void createASTContext();
122
123  // AST consumer, responsible for code generation
124  std::unique_ptr<clang::ASTConsumer> mBackend;
125
126  // File names
127  std::string mInputFileName;
128  std::string mOutputFileName;
129  std::string mOutput32FileName;
130
131  std::string mDepOutputFileName;
132  std::string mDepTargetBCFileName;
133  std::vector<std::string> mAdditionalDepTargets;
134
135  OutputType mOT;
136
137  // Output stream
138  std::unique_ptr<llvm::tool_output_file> mOS;
139
140  // Dependency output stream
141  std::unique_ptr<llvm::tool_output_file> mDOS;
142
143  std::vector<std::string> mIncludePaths;
144
145  // Context for Renderscript
146  RSContext *mRSContext;
147
148  bool mAllowRSPrefix;
149
150  unsigned int mTargetAPI;
151
152  bool mVerbose;
153
154  bool mIsFilterscript;
155
156  // Collect generated filenames (without the .java) for dependency generation
157  std::vector<std::string> mGeneratedFileNames;
158
159  PragmaList mPragmas;
160
161  // FIXME: Should be std::list<RSExportable *> here. But currently we only
162  //        check ODR on record type.
163  //
164  // ReflectedDefinitions maps record type name to a pair:
165  //  <its RSExportRecordType instance,
166  //   the first file contains this record type definition>
167  typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy;
168  typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy;
169  ReflectedDefinitionListTy ReflectedDefinitions;
170
171  bool generateJavaBitcodeAccessor(const std::string &OutputPathBase,
172                                   const std::string &PackageName,
173                                   const std::string *LicenseNote);
174
175  // CurInputFile is the pointer to a char array holding the input filename
176  // and is valid before compile() ends.
177  bool checkODR(const char *CurInputFile);
178
179  clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
180  clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
181  clang::FileManager &getFileManager() { return *mFileMgr; }
182  clang::SourceManager &getSourceManager() { return *mSourceMgr; }
183  clang::Preprocessor &getPreprocessor() { return *mPP; }
184  clang::ASTContext &getASTContext() { return *mASTContext; }
185
186  inline clang::TargetOptions const &getTargetOptions() const
187    { return *mTargetOpts.get(); }
188
189  void initPreprocessor();
190  void initASTContext();
191
192  clang::ASTConsumer *createBackend(const RSCCOptions &Opts,
193                                    const clang::CodeGenOptions &CodeGenOpts,
194                                    llvm::raw_ostream *OS,
195                                    OutputType OT);
196
197 public:
198  static const llvm::StringRef PragmaMetadataName;
199
200  static void GlobalInitialization();
201
202  static bool IsRSHeaderFile(const char *File);
203  // FIXME: Determine whether a location is in RS header (i.e., one of the RS
204  //        built-in APIs) should only need its names (we need a "list" of RS
205  //        built-in APIs).
206  static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
207                                  const clang::SourceManager &SourceMgr);
208
209  Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
210        DiagnosticBuffer *DiagClient);
211
212  virtual ~Slang();
213
214  bool setInputSource(llvm::StringRef InputFile);
215
216  std::string const &getInputFileName() const { return mInputFileName; }
217
218  void setIncludePaths(const std::vector<std::string> &IncludePaths) {
219    mIncludePaths = IncludePaths;
220  }
221
222  void setOutputType(OutputType OT) { mOT = OT; }
223
224  bool setOutput(const char *OutputFile);
225
226  bool setDepOutput(const char *OutputFile);
227
228  void setDepTargetBC(const char *TargetBCFile) {
229    mDepTargetBCFileName = TargetBCFile;
230  }
231
232  void setAdditionalDepTargets(
233      std::vector<std::string> const &AdditionalDepTargets) {
234    mAdditionalDepTargets = AdditionalDepTargets;
235  }
236
237  void appendGeneratedFileName(std::string const &GeneratedFileName) {
238    mGeneratedFileNames.push_back(GeneratedFileName);
239  }
240
241  int generateDepFile(bool PhonyTarget);
242
243  int compile(const RSCCOptions &Opts);
244
245  char const *getErrorMessage() { return mDiagClient->str().c_str(); }
246
247  void setDebugMetadataEmission(bool EmitDebug);
248
249  void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
250
251  // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if
252  // all given input files are successfully compiled without errors.
253  //
254  // @IOFiles - List of pairs of <input file path, output file path>.
255  //
256  // @DepFiles - List of pairs of <output dep. file path, dependent bitcode
257  //             target>. If @OutputDep is true, this parameter must be given
258  //             with the same number of pairs given in @IOFiles.
259  //
260  // @Opts - Selection of options defined from invoking llvm-rs-cc
261  bool
262  compile(const std::list<std::pair<const char *, const char *>> &IOFiles64,
263          const std::list<std::pair<const char *, const char *>> &IOFiles32,
264          const std::list<std::pair<const char *, const char *>> &DepFiles,
265          const RSCCOptions &Opts,
266          clang::DiagnosticOptions &DiagOpts);
267
268  clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc,
269                                     clang::ModuleIdPath Path,
270                                     clang::Module::NameVisibilityKind VK,
271                                     bool IsInclusionDirective) override;
272
273  void makeModuleVisible(clang::Module *Mod,
274                         clang::Module::NameVisibilityKind Visibility,
275                         clang::SourceLocation ImportLoc,
276                         bool Complain = false) override {}
277
278  clang::GlobalModuleIndex *
279  loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override {
280    // We don't support C++ modules for RenderScript.
281    return nullptr;
282  }
283
284  bool lookupMissingImports(llvm::StringRef Name,
285                            clang::SourceLocation TriggerLoc) override {
286    // We don't support C++ modules for RenderScript.
287    return false;
288  }
289};
290
291} // namespace slang
292
293#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
294