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