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" 26 using 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 38 namespace llvm { 39 class tool_output_file; 40 } 41 42 namespace 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 57 namespace slang { 58 59 class 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