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