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   const 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   // For diagnostic purposes, we record the order in which we parse
    115   // foreach kernels -- which is not necessarily the same order in
    116   // which they appear in mExportForEach.
    117   unsigned mNextForEachOrdinal;
    118 
    119   ExportVarList mExportVars;
    120   ExportFuncList mExportFuncs;
    121   std::map<llvm::StringRef, unsigned> mExportForEachMap;
    122   ExportForEachVector mExportForEach;
    123   ExportForEachVector::iterator mFirstOldStyleKernel;
    124   ExportReduceList mExportReduce;
    125   ExportReduceResultTypeSet mExportReduceResultType;
    126   ExportTypeMap mExportTypes;
    127 
    128   clang::QualType mAllocationType;
    129   clang::QualType mScriptCallType;
    130 
    131   std::set<const clang::FunctionDecl *> mUsedByReducePragmaFns;
    132 
    133   // Populated by markUsedByReducePragma().
    134   // Consumed by processReducePragmas().
    135   std::vector<clang::VarDecl *> mUsedByReducePragmaDummyVars;
    136 
    137  public:
    138   RSContext(clang::Preprocessor &PP,
    139             clang::ASTContext &Ctx,
    140             const clang::TargetInfo &Target,
    141             PragmaList *Pragmas,
    142             unsigned int TargetAPI,
    143             bool Verbose);
    144 
    145   enum CheckName { CheckNameNo, CheckNameYes };
    146 
    147   static bool isSyntheticName(const llvm::StringRef Name) { return Name.startswith(".rs."); }
    148 
    149   inline clang::Preprocessor &getPreprocessor() const { return mPP; }
    150   inline clang::ASTContext &getASTContext() const { return mCtx; }
    151   inline clang::MangleContext &getMangleContext() const {
    152     return *mMangleCtx;
    153   }
    154   inline const llvm::DataLayout &getDataLayout() const { return mDataLayout; }
    155   inline llvm::LLVMContext &getLLVMContext() const { return mLLVMContext; }
    156   inline const clang::SourceManager *getSourceManager() const {
    157     return &mPP.getSourceManager();
    158   }
    159   inline clang::DiagnosticsEngine *getDiagnostics() const {
    160     return &mPP.getDiagnostics();
    161   }
    162   inline unsigned int getTargetAPI() const {
    163     return mTargetAPI;
    164   }
    165 
    166   inline bool getVerbose() const {
    167     return mVerbose;
    168   }
    169   inline bool is64Bit() const {
    170     return mIs64Bit;
    171   }
    172 
    173   inline void setLicenseNote(const std::string &S) {
    174     mLicenseNote = new std::string(S);
    175   }
    176   inline const std::string *getLicenseNote() const { return mLicenseNote; }
    177 
    178   inline void addExportType(const std::string &S) {
    179     mNeedExportTypes.insert(S);
    180   }
    181 
    182   inline void setReflectJavaPackageName(const std::string &S) {
    183     mReflectJavaPackageName = S;
    184   }
    185   inline const std::string &getReflectJavaPackageName() const {
    186     return mReflectJavaPackageName;
    187   }
    188 
    189   inline void setRSPackageName(const std::string &S) {
    190     mRSPackageName = S;
    191   }
    192 
    193   inline const std::string &getRSPackageName() const { return mRSPackageName; }
    194 
    195   void setAllocationType(const clang::TypeDecl* TD);
    196   inline const clang::QualType& getAllocationType() const {
    197     return mAllocationType;
    198   }
    199 
    200   void setScriptCallType(const clang::TypeDecl* TD);
    201   inline const clang::QualType& getScriptCallType() const {
    202     return mScriptCallType;
    203   }
    204 
    205   bool addForEach(const clang::FunctionDecl* FD);
    206 
    207   bool processExports();
    208   inline void newExportable(RSExportable *E) {
    209     if (E != nullptr)
    210       mExportables.push_back(E);
    211   }
    212   typedef ExportableList::iterator exportable_iterator;
    213   exportable_iterator exportable_begin() {
    214     return mExportables.begin();
    215   }
    216   exportable_iterator exportable_end() {
    217     return mExportables.end();
    218   }
    219 
    220   typedef ExportVarList::const_iterator const_export_var_iterator;
    221   const_export_var_iterator export_vars_begin() const {
    222     return mExportVars.begin();
    223   }
    224   const_export_var_iterator export_vars_end() const {
    225     return mExportVars.end();
    226   }
    227   inline bool hasExportVar() const {
    228     return !mExportVars.empty();
    229   }
    230   size_t export_vars_size() const {
    231     return mExportVars.size();
    232   }
    233 
    234   typedef ExportFuncList::const_iterator const_export_func_iterator;
    235   const_export_func_iterator export_funcs_begin() const {
    236     return mExportFuncs.begin();
    237   }
    238   const_export_func_iterator export_funcs_end() const {
    239     return mExportFuncs.end();
    240   }
    241   inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
    242   size_t export_funcs_size() const {
    243     return mExportFuncs.size();
    244   }
    245 
    246   typedef ExportForEachVector::const_iterator const_export_foreach_iterator;
    247   const_export_foreach_iterator export_foreach_begin() const {
    248     return mExportForEach.begin();
    249   }
    250   const_export_foreach_iterator export_foreach_end() const {
    251     return mExportForEach.end();
    252   }
    253   inline bool hasExportForEach() const { return !mExportForEach.empty(); }
    254   int getForEachSlotNumber(const clang::FunctionDecl* FD);
    255 
    256   // count up from zero
    257   unsigned getNextForEachOrdinal() { return mNextForEachOrdinal++; }
    258   unsigned getNumAssignedForEachOrdinals() const { return mNextForEachOrdinal; }
    259 
    260   typedef ExportReduceList::const_iterator const_export_reduce_iterator;
    261   const_export_reduce_iterator export_reduce_begin() const {
    262     return mExportReduce.begin();
    263   }
    264   const_export_reduce_iterator export_reduce_end() const {
    265     return mExportReduce.end();
    266   }
    267   size_t export_reduce_size() const {
    268     return mExportReduce.size();
    269   }
    270   inline bool hasExportReduce() const { return !mExportReduce.empty(); }
    271   void addExportReduce(RSExportReduce *Reduce) {
    272     mExportReduce.push_back(Reduce);
    273   }
    274   bool processReducePragmas(Backend *BE);
    275   void markUsedByReducePragma(clang::FunctionDecl *FD, CheckName Check);
    276 
    277   // If the type has already been inserted, has no effect.
    278   void insertExportReduceResultType(RSExportType *Type) { mExportReduceResultType.insert(Type); }
    279 
    280   template <class FilterIn, class Compare>
    281   std::vector<RSExportType *> getReduceResultTypes(FilterIn Filt, Compare Comp) const {
    282     std::vector<RSExportType *> Return;
    283     std::copy_if(mExportReduceResultType.begin(), mExportReduceResultType.end(), std::back_inserter(Return), Filt);
    284     std::sort(Return.begin(), Return.end(), Comp);
    285     auto ReturnNewEndIter = std::unique(Return.begin(), Return.end(),
    286                                         [Comp](const RSExportType *a, const RSExportType *b) {
    287                                           return !Comp(a, b) && !Comp(b, a);
    288                                         });
    289     Return.erase(ReturnNewEndIter, Return.end());
    290     return Return;
    291   }
    292 
    293   typedef ExportTypeMap::iterator export_type_iterator;
    294   typedef ExportTypeMap::const_iterator const_export_type_iterator;
    295   export_type_iterator export_types_begin() { return mExportTypes.begin(); }
    296   export_type_iterator export_types_end() { return mExportTypes.end(); }
    297   const_export_type_iterator export_types_begin() const {
    298     return mExportTypes.begin();
    299   }
    300   const_export_type_iterator export_types_end() const {
    301     return mExportTypes.end();
    302   }
    303   inline bool hasExportType() const { return !mExportTypes.empty(); }
    304   export_type_iterator findExportType(const llvm::StringRef &TypeName) {
    305     return mExportTypes.find(TypeName);
    306   }
    307   const_export_type_iterator findExportType(const llvm::StringRef &TypeName)
    308       const {
    309     return mExportTypes.find(TypeName);
    310   }
    311 
    312   // Insert the specified Typename/Type pair into the map. If the key already
    313   // exists in the map, return false and ignore the request, otherwise insert it
    314   // and return true.
    315   bool insertExportType(const llvm::StringRef &TypeName, RSExportType *Type);
    316 
    317   int getVersion() const { return version; }
    318   void setVersion(int v) {
    319     version = v;
    320   }
    321 
    322   bool isCompatLib() const {
    323     // If we are not targeting the actual Android Renderscript classes,
    324     // we should reflect code that works with the compatibility library.
    325     return (mRSPackageName.compare("android.renderscript") != 0);
    326   }
    327 
    328   void addPragma(const std::string &T, const std::string &V) {
    329     mPragmas->push_back(make_pair(T, V));
    330   }
    331   void setPrecision(const std::string &P) { mPrecision = P; }
    332   std::string getPrecision() { return mPrecision; }
    333 
    334   // Report an error or a warning to the user.
    335   template <unsigned N>
    336   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
    337                                              const char (&Message)[N]) const {
    338   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
    339   return DiagEngine->Report(DiagEngine->getCustomDiagID(Level, Message));
    340   }
    341 
    342   template <unsigned N>
    343   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
    344                                              const clang::SourceLocation Loc,
    345                                              const char (&Message)[N]) const {
    346   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
    347   const clang::SourceManager *SM = getSourceManager();
    348   return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM),
    349                             DiagEngine->getCustomDiagID(Level, Message));
    350   }
    351 
    352   // Utility functions to report errors and warnings to make the calling code
    353   // easier to read.
    354   template <unsigned N>
    355   clang::DiagnosticBuilder ReportError(const char (&Message)[N]) const {
    356     return Report<N>(clang::DiagnosticsEngine::Error, Message);
    357   }
    358 
    359   template <unsigned N>
    360   clang::DiagnosticBuilder ReportError(const clang::SourceLocation Loc,
    361                                        const char (&Message)[N]) const {
    362     return Report<N>(clang::DiagnosticsEngine::Error, Loc, Message);
    363   }
    364 
    365   template <unsigned N>
    366   clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) const {
    367     return Report<N>(clang::DiagnosticsEngine::Warning, Message);
    368   }
    369 
    370   template <unsigned N>
    371   clang::DiagnosticBuilder ReportWarning(const clang::SourceLocation Loc,
    372                                          const char (&Message)[N]) const {
    373     return Report<N>(clang::DiagnosticsEngine::Warning, Loc, Message);
    374   }
    375 
    376   ~RSContext();
    377 };
    378 
    379 }   // namespace slang
    380 
    381 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_CONTEXT_H_  NOLINT
    382