Home | History | Annotate | Download | only in slang
      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 
    195   clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
    196   clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
    197   clang::FileManager &getFileManager() { return *mFileMgr; }
    198   clang::SourceManager &getSourceManager() { return *mSourceMgr; }
    199   clang::Preprocessor &getPreprocessor() { return *mPP; }
    200   clang::ASTContext &getASTContext() { return *mASTContext; }
    201   clang::HeaderSearchOptions &getHeaderSearchOpts() { return *mHSOpts; }
    202   clang::PreprocessorOptions &getPreprocessorOpts() { return *mPPOpts; }
    203 
    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 
    234   std::string const &getInputFileName() const { return mInputFileName; }
    235 
    236   void setIncludePaths(const std::vector<std::string> &IncludePaths) {
    237     mIncludePaths = IncludePaths;
    238   }
    239 
    240   void setOutputType(OutputType OT) { mOT = OT; }
    241 
    242   bool setOutput(const char *OutputFile);
    243 
    244   bool setDepOutput(const char *OutputFile);
    245 
    246   void setDepTargetBC(const char *TargetBCFile) {
    247     mDepTargetBCFileName = TargetBCFile;
    248   }
    249 
    250   void setAdditionalDepTargets(
    251       std::vector<std::string> const &AdditionalDepTargets) {
    252     mAdditionalDepTargets = AdditionalDepTargets;
    253   }
    254 
    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 
    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 
    294   void makeModuleVisible(clang::Module *Mod,
    295                          clang::Module::NameVisibilityKind Visibility,
    296                          clang::SourceLocation ImportLoc) override {}
    297 
    298   clang::GlobalModuleIndex *
    299   loadGlobalModuleIndex(clang::SourceLocation TriggerLoc) override {
    300     // We don't support C++ modules for RenderScript.
    301     return nullptr;
    302   }
    303 
    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