Home | History | Annotate | Download | only in slang
      1 /*
      2  * Copyright 2010-2012, 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_RS_CONTEXT_H_  // NOLINT
     18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_CONTEXT_H_
     19 
     20 #include <cstdio>
     21 #include <list>
     22 #include <map>
     23 #include <set>
     24 #include <string>
     25 #include <unordered_set>
     26 #include <vector>
     27 
     28 #include "clang/Lex/Preprocessor.h"
     29 #include "clang/AST/Mangle.h"
     30 
     31 #include "llvm/ADT/StringSet.h"
     32 #include "llvm/ADT/StringMap.h"
     33 
     34 #include "slang_pragma_list.h"
     35 
     36 namespace llvm {
     37   class LLVMContext;
     38   class DataLayout;
     39 }   // namespace llvm
     40 
     41 namespace clang {
     42   class VarDecl;
     43   class ASTContext;
     44   class TargetInfo;
     45   class FunctionDecl;
     46   class QualType;
     47   class SourceManager;
     48   class TypeDecl;
     49   class FunctionDecl;
     50 }   // namespace clang
     51 
     52 namespace slang {
     53   class Backend;
     54   class RSExportable;
     55   class RSExportVar;
     56   class RSExportFunc;
     57   class RSExportForEach;
     58   class RSExportReduce;
     59   class RSExportType;
     60 
     61 class RSContext {
     62   typedef llvm::StringSet<> NeedExportVarSet;
     63   typedef llvm::StringSet<> NeedExportFuncSet;
     64   typedef llvm::StringSet<> NeedExportTypeSet;
     65 
     66  public:
     67   typedef std::list<RSExportable*> ExportableList;
     68   typedef std::list<RSExportVar*> ExportVarList;
     69   typedef std::list<RSExportFunc*> ExportFuncList;
     70   typedef std::vector<RSExportForEach*> ExportForEachVector;
     71   typedef std::list<RSExportReduce*> ExportReduceList;
     72 
     73   // WARNING: Sorted by pointer value, resulting in unpredictable order
     74   typedef std::unordered_set<RSExportType*> ExportReduceResultTypeSet;
     75 
     76   typedef llvm::StringMap<RSExportType*> ExportTypeMap;
     77 
     78  private:
     79   clang::Preprocessor &mPP;
     80   clang::ASTContext &mCtx;
     81   PragmaList *mPragmas;
     82   // Precision specified via pragma, either rs_fp_full or rs_fp_relaxed. If
     83   // empty, rs_fp_full is assumed.
     84   std::string mPrecision;
     85   unsigned int mTargetAPI;
     86   bool mVerbose;
     87 
     88   llvm::DataLayout *mDataLayout;
     89   llvm::LLVMContext &mLLVMContext;
     90 
     91   ExportableList mExportables;
     92 
     93   NeedExportTypeSet mNeedExportTypes;
     94 
     95   std::string *mLicenseNote;
     96   std::string mReflectJavaPackageName;
     97   std::string mReflectJavaPathName;
     98 
     99   std::string mRSPackageName;
    100 
    101   int version;
    102 
    103   std::unique_ptr<clang::MangleContext> mMangleCtx;
    104 
    105   bool mIs64Bit;
    106 
    107   bool processExportVar(const clang::VarDecl *VD);
    108   bool processExportFunc(const clang::FunctionDecl *FD);
    109   bool processExportType(const llvm::StringRef &Name);
    110 
    111   int getForEachSlotNumber(const clang::StringRef& funcName);
    112   unsigned mNextSlot;
    113 
    114   ExportVarList mExportVars;
    115   ExportFuncList mExportFuncs;
    116   std::map<llvm::StringRef, unsigned> mExportForEachMap;
    117   ExportForEachVector mExportForEach;
    118   ExportForEachVector::iterator mFirstOldStyleKernel;
    119   ExportReduceList mExportReduce;
    120   ExportReduceResultTypeSet mExportReduceResultType;
    121   ExportTypeMap mExportTypes;
    122 
    123   clang::QualType mAllocationType;
    124   clang::QualType mScriptCallType;
    125 
    126   std::set<const clang::FunctionDecl *> mUsedByReducePragmaFns;
    127 
    128   // Populated by markUsedByReducePragma().
    129   // Consumed by processReducePragmas().
    130   std::vector<clang::VarDecl *> mUsedByReducePragmaDummyVars;
    131 
    132  public:
    133   RSContext(clang::Preprocessor &PP,
    134             clang::ASTContext &Ctx,
    135             const clang::TargetInfo &Target,
    136             PragmaList *Pragmas,
    137             unsigned int TargetAPI,
    138             bool Verbose);
    139 
    140   enum CheckName { CheckNameNo, CheckNameYes };
    141 
    142   static bool isSyntheticName(const llvm::StringRef Name) { return Name.startswith(".rs."); }
    143 
    144   inline clang::Preprocessor &getPreprocessor() const { return mPP; }
    145   inline clang::ASTContext &getASTContext() const { return mCtx; }
    146   inline clang::MangleContext &getMangleContext() const {
    147     return *mMangleCtx;
    148   }
    149   inline const llvm::DataLayout *getDataLayout() const { return mDataLayout; }
    150   inline llvm::LLVMContext &getLLVMContext() const { return mLLVMContext; }
    151   inline const clang::SourceManager *getSourceManager() const {
    152     return &mPP.getSourceManager();
    153   }
    154   inline clang::DiagnosticsEngine *getDiagnostics() const {
    155     return &mPP.getDiagnostics();
    156   }
    157   inline unsigned int getTargetAPI() const {
    158     return mTargetAPI;
    159   }
    160 
    161   inline bool getVerbose() const {
    162     return mVerbose;
    163   }
    164   inline bool is64Bit() const {
    165     return mIs64Bit;
    166   }
    167 
    168   inline void setLicenseNote(const std::string &S) {
    169     mLicenseNote = new std::string(S);
    170   }
    171   inline const std::string *getLicenseNote() const { return mLicenseNote; }
    172 
    173   inline void addExportType(const std::string &S) {
    174     mNeedExportTypes.insert(S);
    175   }
    176 
    177   inline void setReflectJavaPackageName(const std::string &S) {
    178     mReflectJavaPackageName = S;
    179   }
    180   inline const std::string &getReflectJavaPackageName() const {
    181     return mReflectJavaPackageName;
    182   }
    183 
    184   inline void setRSPackageName(const std::string &S) {
    185     mRSPackageName = S;
    186   }
    187 
    188   inline const std::string &getRSPackageName() const { return mRSPackageName; }
    189 
    190   void setAllocationType(const clang::TypeDecl* TD);
    191   inline const clang::QualType& getAllocationType() const {
    192     return mAllocationType;
    193   }
    194 
    195   void setScriptCallType(const clang::TypeDecl* TD);
    196   inline const clang::QualType& getScriptCallType() const {
    197     return mScriptCallType;
    198   }
    199 
    200   bool addForEach(const clang::FunctionDecl* FD);
    201   bool processExports();
    202   inline void newExportable(RSExportable *E) {
    203     if (E != nullptr)
    204       mExportables.push_back(E);
    205   }
    206   typedef ExportableList::iterator exportable_iterator;
    207   exportable_iterator exportable_begin() {
    208     return mExportables.begin();
    209   }
    210   exportable_iterator exportable_end() {
    211     return mExportables.end();
    212   }
    213 
    214   typedef ExportVarList::const_iterator const_export_var_iterator;
    215   const_export_var_iterator export_vars_begin() const {
    216     return mExportVars.begin();
    217   }
    218   const_export_var_iterator export_vars_end() const {
    219     return mExportVars.end();
    220   }
    221   inline bool hasExportVar() const {
    222     return !mExportVars.empty();
    223   }
    224 
    225   typedef ExportFuncList::const_iterator const_export_func_iterator;
    226   const_export_func_iterator export_funcs_begin() const {
    227     return mExportFuncs.begin();
    228   }
    229   const_export_func_iterator export_funcs_end() const {
    230     return mExportFuncs.end();
    231   }
    232   inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
    233 
    234   typedef ExportForEachVector::const_iterator const_export_foreach_iterator;
    235   const_export_foreach_iterator export_foreach_begin() const {
    236     return mExportForEach.begin();
    237   }
    238   const_export_foreach_iterator export_foreach_end() const {
    239     return mExportForEach.end();
    240   }
    241   inline bool hasExportForEach() const { return !mExportForEach.empty(); }
    242   int getForEachSlotNumber(const clang::FunctionDecl* FD);
    243 
    244   typedef ExportReduceList::const_iterator const_export_reduce_iterator;
    245   const_export_reduce_iterator export_reduce_begin() const {
    246     return mExportReduce.begin();
    247   }
    248   const_export_reduce_iterator export_reduce_end() const {
    249     return mExportReduce.end();
    250   }
    251   inline bool hasExportReduce() const { return !mExportReduce.empty(); }
    252   void addExportReduce(RSExportReduce *Reduce) {
    253     mExportReduce.push_back(Reduce);
    254   }
    255   bool processReducePragmas(Backend *BE);
    256   void markUsedByReducePragma(clang::FunctionDecl *FD, CheckName Check);
    257 
    258   // If the type has already been inserted, has no effect.
    259   void insertExportReduceResultType(RSExportType *Type) { mExportReduceResultType.insert(Type); }
    260 
    261   template <class FilterIn, class Compare>
    262   std::vector<RSExportType *> getReduceResultTypes(FilterIn Filt, Compare Comp) const {
    263     std::vector<RSExportType *> Return;
    264     std::copy_if(mExportReduceResultType.begin(), mExportReduceResultType.end(), std::back_inserter(Return), Filt);
    265     std::sort(Return.begin(), Return.end(), Comp);
    266     auto ReturnNewEndIter = std::unique(Return.begin(), Return.end(),
    267                                         [Comp](const RSExportType *a, const RSExportType *b) {
    268                                           return !Comp(a, b) && !Comp(b, a);
    269                                         });
    270     Return.erase(ReturnNewEndIter, Return.end());
    271     return Return;
    272   }
    273 
    274   typedef ExportTypeMap::iterator export_type_iterator;
    275   typedef ExportTypeMap::const_iterator const_export_type_iterator;
    276   export_type_iterator export_types_begin() { return mExportTypes.begin(); }
    277   export_type_iterator export_types_end() { return mExportTypes.end(); }
    278   const_export_type_iterator export_types_begin() const {
    279     return mExportTypes.begin();
    280   }
    281   const_export_type_iterator export_types_end() const {
    282     return mExportTypes.end();
    283   }
    284   inline bool hasExportType() const { return !mExportTypes.empty(); }
    285   export_type_iterator findExportType(const llvm::StringRef &TypeName) {
    286     return mExportTypes.find(TypeName);
    287   }
    288   const_export_type_iterator findExportType(const llvm::StringRef &TypeName)
    289       const {
    290     return mExportTypes.find(TypeName);
    291   }
    292 
    293   // Insert the specified Typename/Type pair into the map. If the key already
    294   // exists in the map, return false and ignore the request, otherwise insert it
    295   // and return true.
    296   bool insertExportType(const llvm::StringRef &TypeName, RSExportType *Type);
    297 
    298   int getVersion() const { return version; }
    299   void setVersion(int v) {
    300     version = v;
    301   }
    302 
    303   bool isCompatLib() const {
    304     // If we are not targeting the actual Android Renderscript classes,
    305     // we should reflect code that works with the compatibility library.
    306     return (mRSPackageName.compare("android.renderscript") != 0);
    307   }
    308 
    309   void addPragma(const std::string &T, const std::string &V) {
    310     mPragmas->push_back(make_pair(T, V));
    311   }
    312   void setPrecision(const std::string &P) { mPrecision = P; }
    313   std::string getPrecision() { return mPrecision; }
    314 
    315   // Report an error or a warning to the user.
    316   template <unsigned N>
    317   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
    318                                              const char (&Message)[N]) {
    319   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
    320   return DiagEngine->Report(DiagEngine->getCustomDiagID(Level, Message));
    321   }
    322 
    323   template <unsigned N>
    324   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
    325                                              const clang::SourceLocation Loc,
    326                                              const char (&Message)[N]) {
    327   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
    328   const clang::SourceManager *SM = getSourceManager();
    329   return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM),
    330                             DiagEngine->getCustomDiagID(Level, Message));
    331   }
    332 
    333   // Utility functions to report errors and warnings to make the calling code
    334   // easier to read.
    335   template <unsigned N>
    336   clang::DiagnosticBuilder ReportError(const char (&Message)[N]) {
    337     return Report<N>(clang::DiagnosticsEngine::Error, Message);
    338   }
    339 
    340   template <unsigned N>
    341   clang::DiagnosticBuilder ReportError(const clang::SourceLocation Loc,
    342                                        const char (&Message)[N]) {
    343     return Report<N>(clang::DiagnosticsEngine::Error, Loc, Message);
    344   }
    345 
    346   template <unsigned N>
    347   clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) {
    348     return Report<N>(clang::DiagnosticsEngine::Warning, Message);
    349   }
    350 
    351   template <unsigned N>
    352   clang::DiagnosticBuilder ReportWarning(const clang::SourceLocation Loc,
    353                                          const char (&Message)[N]) {
    354     return Report<N>(clang::DiagnosticsEngine::Warning, Loc, Message);
    355   }
    356 
    357   ~RSContext();
    358 };
    359 
    360 }   // namespace slang
    361 
    362 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_CONTEXT_H_  NOLINT
    363