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 <string>
     22 #include <vector>
     23 
     24 // Terrible workaround for TargetOptions.h not using llvm::RefCountedBase!
     25 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     26 using llvm::RefCountedBase;
     27 
     28 #include "clang/Basic/TargetOptions.h"
     29 #include "clang/Lex/ModuleLoader.h"
     30 
     31 #include "llvm/ADT/StringRef.h"
     32 
     33 #include "llvm/Target/TargetMachine.h"
     34 
     35 #include "slang_diagnostic_buffer.h"
     36 #include "slang_pragma_recorder.h"
     37 
     38 namespace llvm {
     39   class tool_output_file;
     40 }
     41 
     42 namespace clang {
     43   class ASTConsumer;
     44   class ASTContext;
     45   class Backend;
     46   class CodeGenOptions;
     47   class Diagnostic;
     48   class DiagnosticsEngine;
     49   class FileManager;
     50   class FileSystemOptions;
     51   class LangOptions;
     52   class Preprocessor;
     53   class SourceManager;
     54   class TargetInfo;
     55 }  // namespace clang
     56 
     57 namespace slang {
     58 
     59 class Slang : public clang::ModuleLoader {
     60   static clang::LangOptions LangOpts;
     61   static clang::CodeGenOptions CodeGenOpts;
     62 
     63   static bool GlobalInitialized;
     64 
     65   static void LLVMErrorHandler(void *UserData, const std::string &Message,
     66                                bool GenCrashDialog);
     67 
     68  public:
     69   enum OutputType {
     70     OT_Dependency,
     71     OT_Assembly,
     72     OT_LLVMAssembly,
     73     OT_Bitcode,
     74     OT_Nothing,
     75     OT_Object,
     76 
     77     OT_Default = OT_Bitcode
     78   };
     79 
     80  private:
     81   bool mInitialized;
     82 
     83   // Diagnostics Mediator (An interface for both Producer and Consumer)
     84   std::unique_ptr<clang::Diagnostic> mDiag;
     85 
     86   // Diagnostics Engine (Producer and Diagnostics Reporter)
     87   clang::DiagnosticsEngine *mDiagEngine;
     88 
     89   // Diagnostics Consumer
     90   // NOTE: The ownership is taken by mDiagEngine after creation.
     91   DiagnosticBuffer *mDiagClient;
     92 
     93   // The target being compiled for
     94   std::shared_ptr<clang::TargetOptions> mTargetOpts;
     95   std::unique_ptr<clang::TargetInfo> mTarget;
     96   void createTarget(uint32_t BitWidth);
     97 
     98 
     99   // File manager (for prepocessor doing the job such as header file search)
    100   std::unique_ptr<clang::FileManager> mFileMgr;
    101   std::unique_ptr<clang::FileSystemOptions> mFileSysOpt;
    102   void createFileManager();
    103 
    104 
    105   // Source manager (responsible for the source code handling)
    106   std::unique_ptr<clang::SourceManager> mSourceMgr;
    107   void createSourceManager();
    108 
    109 
    110   // Preprocessor (source code preprocessor)
    111   std::unique_ptr<clang::Preprocessor> mPP;
    112   void createPreprocessor();
    113 
    114 
    115   // AST context (the context to hold long-lived AST nodes)
    116   std::unique_ptr<clang::ASTContext> mASTContext;
    117   void createASTContext();
    118 
    119 
    120   // AST consumer, responsible for code generation
    121   std::unique_ptr<clang::ASTConsumer> mBackend;
    122 
    123 
    124   // File names
    125   std::string mInputFileName;
    126   std::string mOutputFileName;
    127   std::string mOutput32FileName;
    128 
    129   std::string mDepOutputFileName;
    130   std::string mDepTargetBCFileName;
    131   std::vector<std::string> mAdditionalDepTargets;
    132   std::vector<std::string> mGeneratedFileNames;
    133 
    134   OutputType mOT;
    135 
    136   // Output stream
    137   std::unique_ptr<llvm::tool_output_file> mOS;
    138 
    139   // Dependency output stream
    140   std::unique_ptr<llvm::tool_output_file> mDOS;
    141 
    142   std::vector<std::string> mIncludePaths;
    143 
    144  protected:
    145   PragmaList mPragmas;
    146 
    147   clang::DiagnosticsEngine &getDiagnostics() { return *mDiagEngine; }
    148   clang::TargetInfo const &getTargetInfo() const { return *mTarget; }
    149   clang::FileManager &getFileManager() { return *mFileMgr; }
    150   clang::SourceManager &getSourceManager() { return *mSourceMgr; }
    151   clang::Preprocessor &getPreprocessor() { return *mPP; }
    152   clang::ASTContext &getASTContext() { return *mASTContext; }
    153 
    154   inline clang::TargetOptions const &getTargetOptions() const
    155     { return *mTargetOpts.get(); }
    156 
    157   virtual void initDiagnostic() {}
    158   virtual void initPreprocessor() {}
    159   virtual void initASTContext() {}
    160 
    161   virtual clang::ASTConsumer *
    162     createBackend(const clang::CodeGenOptions& CodeGenOpts,
    163                   llvm::raw_ostream *OS,
    164                   OutputType OT);
    165 
    166  public:
    167   static const llvm::StringRef PragmaMetadataName;
    168 
    169   static void GlobalInitialization();
    170 
    171   Slang();
    172 
    173   void init(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
    174             DiagnosticBuffer *DiagClient);
    175 
    176   virtual clang::ModuleLoadResult loadModule(
    177       clang::SourceLocation ImportLoc,
    178       clang::ModuleIdPath Path,
    179       clang::Module::NameVisibilityKind VK,
    180       bool IsInclusionDirective);
    181 
    182   bool setInputSource(llvm::StringRef InputFile, const char *Text,
    183                       size_t TextLength);
    184 
    185   bool setInputSource(llvm::StringRef InputFile);
    186 
    187   std::string const &getInputFileName() const { return mInputFileName; }
    188 
    189   void setIncludePaths(const std::vector<std::string> &IncludePaths) {
    190     mIncludePaths = IncludePaths;
    191   }
    192 
    193   void setOutputType(OutputType OT) { mOT = OT; }
    194 
    195   bool setOutput(const char *OutputFile);
    196 
    197   // For use with 64-bit compilation/reflection. This only sets the filename of
    198   // the 32-bit bitcode file, and doesn't actually verify it already exists.
    199   void setOutput32(const char *OutputFile) {
    200     mOutput32FileName = OutputFile;
    201   }
    202 
    203   std::string const &getOutputFileName() const {
    204     return mOutputFileName;
    205   }
    206 
    207   std::string const &getOutput32FileName() const {
    208     return mOutput32FileName;
    209   }
    210 
    211   bool setDepOutput(const char *OutputFile);
    212 
    213   void setDepTargetBC(const char *TargetBCFile) {
    214     mDepTargetBCFileName = TargetBCFile;
    215   }
    216 
    217   void setAdditionalDepTargets(
    218       std::vector<std::string> const &AdditionalDepTargets) {
    219     mAdditionalDepTargets = AdditionalDepTargets;
    220   }
    221 
    222   void appendGeneratedFileName(std::string const &GeneratedFileName) {
    223     mGeneratedFileNames.push_back(GeneratedFileName);
    224   }
    225 
    226   int generateDepFile();
    227 
    228   int compile();
    229 
    230   char const *getErrorMessage() { return mDiagClient->str().c_str(); }
    231 
    232   void setDebugMetadataEmission(bool EmitDebug);
    233 
    234   void setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel);
    235 
    236   // Reset the slang compiler state such that it can be reused to compile
    237   // another file
    238   virtual void reset(bool SuppressWarnings = false);
    239 
    240   virtual ~Slang();
    241 };
    242 
    243 }  // namespace slang
    244 
    245 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_H_  NOLINT
    246