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 <string>
22#include <vector>
23
24// Terrible workaround for TargetOptions.h not using llvm::RefCountedBase!
25#include "llvm/ADT/IntrusiveRefCntPtr.h"
26using llvm::RefCountedBase;
27
28#include "clang/Basic/TargetOptions.h"
29#include "clang/Lex/ModuleLoader.h"
30
31#include "llvm/ADT/StringRef.h"
32
33#include "llvm/Target/TargetMachine.h"
34
35#include "slang_diagnostic_buffer.h"
36#include "slang_pragma_recorder.h"
37
38namespace llvm {
39  class tool_output_file;
40}
41
42namespace clang {
43  class ASTConsumer;
44  class ASTContext;
45  class Backend;
46  class CodeGenOptions;
47  class Diagnostic;
48  class DiagnosticsEngine;
49  class FileManager;
50  class FileSystemOptions;
51  class LangOptions;
52  class Preprocessor;
53  class SourceManager;
54  class TargetInfo;
55}  // namespace clang
56
57namespace slang {
58
59class Slang : public clang::ModuleLoader {
60  static clang::LangOptions LangOpts;
61  static clang::CodeGenOptions CodeGenOpts;
62
63  static bool GlobalInitialized;
64
65  static void LLVMErrorHandler(void *UserData, const std::string &Message,
66                               bool GenCrashDialog);
67
68 public:
69  enum OutputType {
70    OT_Dependency,
71    OT_Assembly,
72    OT_LLVMAssembly,
73    OT_Bitcode,
74    OT_Nothing,
75    OT_Object,
76
77    OT_Default = OT_Bitcode
78  };
79
80 private:
81  bool mInitialized;
82
83  // Diagnostics Mediator (An interface for both Producer and Consumer)
84  std::unique_ptr<clang::Diagnostic> mDiag;
85
86  // Diagnostics Engine (Producer and Diagnostics Reporter)
87  clang::DiagnosticsEngine *mDiagEngine;
88
89  // Diagnostics Consumer
90  // NOTE: The ownership is taken by mDiagEngine after creation.
91  DiagnosticBuffer *mDiagClient;
92
93  // The target being compiled for
94  std::shared_ptr<clang::TargetOptions> mTargetOpts;
95  std::unique_ptr<clang::TargetInfo> mTarget;
96  void createTarget(uint32_t BitWidth);
97
98
99  // File manager (for prepocessor doing the job such as header file search)
100  std::unique_ptr<clang::FileManager> mFileMgr;
101  std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
102  void createFileManager();
103
104
105  // Source manager (responsible for the source code handling)
106  std::unique_ptr<clang::SourceManager> mSourceMgr;
107  void createSourceManager();
108
109
110  // Preprocessor (source code preprocessor)
111  std::unique_ptr<clang::Preprocessor> mPP;
112  void createPreprocessor();
113
114
115  // AST context (the context to hold long-lived AST nodes)
116  std::unique_ptr<clang::ASTContext> mASTContext;
117  void createASTContext();
118
119
120  // AST consumer, responsible for code generation
121  std::unique_ptr<clang::ASTConsumer> mBackend;
122
123
124  // File names
125  std::string mInputFileName;
126  std::string mOutputFileName;
127  std::string mOutput32FileName;
128
129  std::string mDepOutputFileName;
130  std::string mDepTargetBCFileName;
131  std::vector<std::string> mAdditionalDepTargets;
132  std::vector<std::string> mGeneratedFileNames;
133
134  OutputType mOT;
135
136  // Output stream
137  std::unique_ptr<llvm::tool_output_file> mOS;
138
139  // Dependency output stream
140  std::unique_ptr<llvm::tool_output_file> mDOS;
141
142  std::vector<std::string> mIncludePaths;
143
144 protected:
145  PragmaList mPragmas;
146
147  clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
148  clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
149  clang::FileManager &getFileManager() { return *mFileMgr; }
150  clang::SourceManager &getSourceManager() { return *mSourceMgr; }
151  clang::Preprocessor &getPreprocessor() { return *mPP; }
152  clang::ASTContext &getASTContext() { return *mASTContext; }
153
154  inline clang::TargetOptions const &getTargetOptions() const
155    { return *mTargetOpts.get(); }
156
157  virtual void initDiagnostic() {}
158  virtual void initPreprocessor() {}
159  virtual void initASTContext() {}
160
161  virtual clang::ASTConsumer *
162    createBackend(const clang::CodeGenOptions& CodeGenOpts,
163                  llvm::raw_ostream *OS,
164                  OutputType OT);
165
166 public:
167  static const llvm::StringRef PragmaMetadataName;
168
169  static void GlobalInitialization();
170
171  Slang();
172
173  void init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
174            DiagnosticBuffer *DiagClient);
175
176  virtual clang::ModuleLoadResult loadModule(
177      clang::SourceLocation ImportLoc,
178      clang::ModuleIdPath Path,
179      clang::Module::NameVisibilityKind VK,
180      bool IsInclusionDirective);
181
182  bool setInputSource(llvm::StringRef InputFile, const char *Text,
183                      size_t TextLength);
184
185  bool setInputSource(llvm::StringRef InputFile);
186
187  std::string const &getInputFileName() const { return mInputFileName; }
188
189  void setIncludePaths(const std::vector<std::string> &IncludePaths) {
190    mIncludePaths = IncludePaths;
191  }
192
193  void setOutputType(OutputType OT) { mOT = OT; }
194
195  bool setOutput(const char *OutputFile);
196
197  // For use with 64-bit compilation/reflection. This only sets the filename of
198  // the 32-bit bitcode file, and doesn't actually verify it already exists.
199  void setOutput32(const char *OutputFile) {
200    mOutput32FileName = OutputFile;
201  }
202
203  std::string const &getOutputFileName() const {
204    return mOutputFileName;
205  }
206
207  std::string const &getOutput32FileName() const {
208    return mOutput32FileName;
209  }
210
211  bool setDepOutput(const char *OutputFile);
212
213  void setDepTargetBC(const char *TargetBCFile) {
214    mDepTargetBCFileName = TargetBCFile;
215  }
216
217  void setAdditionalDepTargets(
218      std::vector<std::string> const &AdditionalDepTargets) {
219    mAdditionalDepTargets = AdditionalDepTargets;
220  }
221
222  void appendGeneratedFileName(std::string const &GeneratedFileName) {
223    mGeneratedFileNames.push_back(GeneratedFileName);
224  }
225
226  int generateDepFile();
227
228  int compile();
229
230  char const *getErrorMessage() { return mDiagClient->str().c_str(); }
231
232  void setDebugMetadataEmission(bool EmitDebug);
233
234  void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
235
236  // Reset the slang compiler state such that it can be reused to compile
237  // another file
238  virtual void reset(bool SuppressWarnings = false);
239
240  virtual ~Slang();
241};
242
243}  // namespace slang
244
245#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
246