/* * Copyright 2010, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_H_ // NOLINT #define _FRAMEWORKS_COMPILE_SLANG_SLANG_H_ #include <cstdio> #include <list> #include <string> #include <utility> #include <vector> #include "llvm/ADT/StringMap.h" #include "slang_rs_reflect_utils.h" #include "slang_version.h" // Terrible workaround for TargetOptions.h not using llvm::RefCountedBase! #include "llvm/ADT/IntrusiveRefCntPtr.h" using llvm::RefCountedBase; #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/StringRef.h" #include "llvm/Target/TargetMachine.h" #include "slang_diagnostic_buffer.h" #include "slang_pragma_recorder.h" namespace llvm { class tool_output_file; } namespace clang { class ASTConsumer; class ASTContext; class Backend; class CodeGenOptions; class Diagnostic; class DiagnosticsEngine; class FileManager; class FileSystemOptions; class LangOptions; class Preprocessor; class SourceManager; class TargetInfo; } // namespace clang namespace slang { class RSCCOptions; class RSContext; class RSExportRecordType; class Slang : public clang::ModuleLoader { public: enum OutputType { OT_Dependency, OT_Assembly, OT_LLVMAssembly, OT_Bitcode, OT_Nothing, OT_Object, OT_Default = OT_Bitcode }; private: // Language options (define the language feature for compiler such as C99) clang::LangOptions LangOpts; // Code generation options for the compiler clang::CodeGenOptions CodeGenOpts; // Returns true if this is a Filterscript file. static bool isFilterscript(const char *Filename); // Diagnostics Engine (Producer and Diagnostics Reporter) clang::DiagnosticsEngine *mDiagEngine; // Diagnostics Consumer // NOTE: The ownership is taken by mDiagEngine after creation. DiagnosticBuffer *mDiagClient; // The target being compiled for std::shared_ptr<clang::TargetOptions> mTargetOpts; std::unique_ptr<clang::TargetInfo> mTarget; void createTarget(uint32_t BitWidth); // File manager (for prepocessor doing the job such as header file search) std::unique_ptr<clang::FileManager> mFileMgr; std::unique_ptr<clang::FileSystemOptions> mFileSysOpt; void createFileManager(); // Source manager (responsible for the source code handling) std::unique_ptr<clang::SourceManager> mSourceMgr; void createSourceManager(); // Preprocessor (source code preprocessor) std::unique_ptr<clang::Preprocessor> mPP; void createPreprocessor(); // AST context (the context to hold long-lived AST nodes) std::unique_ptr<clang::ASTContext> mASTContext; void createASTContext(); // AST consumer, responsible for code generation std::unique_ptr<clang::ASTConsumer> mBackend; // File names std::string mInputFileName; std::string mOutputFileName; std::string mOutput32FileName; std::string mDepOutputFileName; std::string mDepTargetBCFileName; std::vector<std::string> mAdditionalDepTargets; OutputType mOT; // Output stream std::unique_ptr<llvm::tool_output_file> mOS; // Dependency output stream std::unique_ptr<llvm::tool_output_file> mDOS; std::vector<std::string> mIncludePaths; // Context for Renderscript RSContext *mRSContext; bool mAllowRSPrefix; unsigned int mTargetAPI; bool mVerbose; bool mIsFilterscript; // Collect generated filenames (without the .java) for dependency generation std::vector<std::string> mGeneratedFileNames; PragmaList mPragmas; // FIXME: Should be std::list<RSExportable *> here. But currently we only // check ODR on record type. // // ReflectedDefinitions maps record type name to a pair: // <its RSExportRecordType instance, // the first file contains this record type definition> typedef std::pair<RSExportRecordType*, const char*> ReflectedDefinitionTy; typedef llvm::StringMap<ReflectedDefinitionTy> ReflectedDefinitionListTy; ReflectedDefinitionListTy ReflectedDefinitions; bool generateJavaBitcodeAccessor(const std::string &OutputPathBase, const std::string &PackageName, const std::string *LicenseNote); // CurInputFile is the pointer to a char array holding the input filename // and is valid before compile() ends. bool checkODR(const char *CurInputFile); clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; } clang::TargetInfo const &getTargetInfo() const { return *mTarget; } clang::FileManager &getFileManager() { return *mFileMgr; } clang::SourceManager &getSourceManager() { return *mSourceMgr; } clang::Preprocessor &getPreprocessor() { return *mPP; } clang::ASTContext &getASTContext() { return *mASTContext; } inline clang::TargetOptions const &getTargetOptions() const { return *mTargetOpts.get(); } void initPreprocessor(); void initASTContext(); clang::ASTConsumer *createBackend(const clang::CodeGenOptions &CodeGenOpts, llvm::raw_ostream *OS, OutputType OT); public: static const llvm::StringRef PragmaMetadataName; static void GlobalInitialization(); static bool IsRSHeaderFile(const char *File); // FIXME: Determine whether a location is in RS header (i.e., one of the RS // built-in APIs) should only need its names (we need a "list" of RS // built-in APIs). static bool IsLocInRSHeaderFile(const clang::SourceLocation &Loc, const clang::SourceManager &SourceMgr); Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine, DiagnosticBuffer *DiagClient); virtual ~Slang(); bool setInputSource(llvm::StringRef InputFile); std::string const &getInputFileName() const { return mInputFileName; } void setIncludePaths(const std::vector<std::string> &IncludePaths) { mIncludePaths = IncludePaths; } void setOutputType(OutputType OT) { mOT = OT; } bool setOutput(const char *OutputFile); bool setDepOutput(const char *OutputFile); void setDepTargetBC(const char *TargetBCFile) { mDepTargetBCFileName = TargetBCFile; } void setAdditionalDepTargets( std::vector<std::string> const &AdditionalDepTargets) { mAdditionalDepTargets = AdditionalDepTargets; } void appendGeneratedFileName(std::string const &GeneratedFileName) { mGeneratedFileNames.push_back(GeneratedFileName); } int generateDepFile(); int compile(); char const *getErrorMessage() { return mDiagClient->str().c_str(); } void setDebugMetadataEmission(bool EmitDebug); void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel); // Compile bunch of RS files given in the llvm-rs-cc arguments. Return true if // all given input files are successfully compiled without errors. // // @IOFiles - List of pairs of <input file path, output file path>. // // @DepFiles - List of pairs of <output dep. file path, dependent bitcode // target>. If @OutputDep is true, this parameter must be given // with the same number of pairs given in @IOFiles. // // @Opts - Selection of options defined from invoking llvm-rs-cc bool compile(const std::list<std::pair<const char *, const char *>> &IOFiles64, const std::list<std::pair<const char *, const char *>> &IOFiles32, const std::list<std::pair<const char *, const char *>> &DepFiles, const RSCCOptions &Opts, clang::DiagnosticOptions &DiagOpts); clang::ModuleLoadResult loadModule(clang::SourceLocation ImportLoc, clang::ModuleIdPath Path, clang::Module::NameVisibilityKind VK, bool IsInclusionDirective) override; void makeModuleVisible(clang::Module *Mod, clang::Module::NameVisibilityKind Visibility, clang::SourceLocation ImportLoc, bool Complain = false) override {} clang::GlobalModuleIndex * loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override { // We don't support C++ modules for RenderScript. return nullptr; } bool lookupMissingImports(llvm::StringRef Name, clang::SourceLocation TriggerLoc) override { // We don't support C++ modules for RenderScript. return false; } }; } // namespace slang #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_ NOLINT