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