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