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 isSyntheticName(const llvm::StringRef Name)147 static bool isSyntheticName(const llvm::StringRef Name) { return Name.startswith(".rs."); } 148 getPreprocessor()149 inline clang::Preprocessor &getPreprocessor() const { return mPP; } getASTContext()150 inline clang::ASTContext &getASTContext() const { return mCtx; } getMangleContext()151 inline clang::MangleContext &getMangleContext() const { 152 return *mMangleCtx; 153 } getDataLayout()154 inline const llvm::DataLayout &getDataLayout() const { return mDataLayout; } getLLVMContext()155 inline llvm::LLVMContext &getLLVMContext() const { return mLLVMContext; } getSourceManager()156 inline const clang::SourceManager *getSourceManager() const { 157 return &mPP.getSourceManager(); 158 } getDiagnostics()159 inline clang::DiagnosticsEngine *getDiagnostics() const { 160 return &mPP.getDiagnostics(); 161 } getTargetAPI()162 inline unsigned int getTargetAPI() const { 163 return mTargetAPI; 164 } 165 getVerbose()166 inline bool getVerbose() const { 167 return mVerbose; 168 } is64Bit()169 inline bool is64Bit() const { 170 return mIs64Bit; 171 } 172 setLicenseNote(const std::string & S)173 inline void setLicenseNote(const std::string &S) { 174 mLicenseNote = new std::string(S); 175 } getLicenseNote()176 inline const std::string *getLicenseNote() const { return mLicenseNote; } 177 addExportType(const std::string & S)178 inline void addExportType(const std::string &S) { 179 mNeedExportTypes.insert(S); 180 } 181 setReflectJavaPackageName(const std::string & S)182 inline void setReflectJavaPackageName(const std::string &S) { 183 mReflectJavaPackageName = S; 184 } getReflectJavaPackageName()185 inline const std::string &getReflectJavaPackageName() const { 186 return mReflectJavaPackageName; 187 } 188 setRSPackageName(const std::string & S)189 inline void setRSPackageName(const std::string &S) { 190 mRSPackageName = S; 191 } 192 getRSPackageName()193 inline const std::string &getRSPackageName() const { return mRSPackageName; } 194 195 void setAllocationType(const clang::TypeDecl* TD); getAllocationType()196 inline const clang::QualType& getAllocationType() const { 197 return mAllocationType; 198 } 199 200 void setScriptCallType(const clang::TypeDecl* TD); getScriptCallType()201 inline const clang::QualType& getScriptCallType() const { 202 return mScriptCallType; 203 } 204 205 bool addForEach(const clang::FunctionDecl* FD); 206 207 bool processExports(); newExportable(RSExportable * E)208 inline void newExportable(RSExportable *E) { 209 if (E != nullptr) 210 mExportables.push_back(E); 211 } 212 typedef ExportableList::iterator exportable_iterator; exportable_begin()213 exportable_iterator exportable_begin() { 214 return mExportables.begin(); 215 } exportable_end()216 exportable_iterator exportable_end() { 217 return mExportables.end(); 218 } 219 220 typedef ExportVarList::const_iterator const_export_var_iterator; export_vars_begin()221 const_export_var_iterator export_vars_begin() const { 222 return mExportVars.begin(); 223 } export_vars_end()224 const_export_var_iterator export_vars_end() const { 225 return mExportVars.end(); 226 } hasExportVar()227 inline bool hasExportVar() const { 228 return !mExportVars.empty(); 229 } export_vars_size()230 size_t export_vars_size() const { 231 return mExportVars.size(); 232 } 233 234 typedef ExportFuncList::const_iterator const_export_func_iterator; export_funcs_begin()235 const_export_func_iterator export_funcs_begin() const { 236 return mExportFuncs.begin(); 237 } export_funcs_end()238 const_export_func_iterator export_funcs_end() const { 239 return mExportFuncs.end(); 240 } hasExportFunc()241 inline bool hasExportFunc() const { return !mExportFuncs.empty(); } export_funcs_size()242 size_t export_funcs_size() const { 243 return mExportFuncs.size(); 244 } 245 246 typedef ExportForEachVector::const_iterator const_export_foreach_iterator; export_foreach_begin()247 const_export_foreach_iterator export_foreach_begin() const { 248 return mExportForEach.begin(); 249 } export_foreach_end()250 const_export_foreach_iterator export_foreach_end() const { 251 return mExportForEach.end(); 252 } hasExportForEach()253 inline bool hasExportForEach() const { return !mExportForEach.empty(); } 254 int getForEachSlotNumber(const clang::FunctionDecl* FD); 255 256 // count up from zero getNextForEachOrdinal()257 unsigned getNextForEachOrdinal() { return mNextForEachOrdinal++; } getNumAssignedForEachOrdinals()258 unsigned getNumAssignedForEachOrdinals() const { return mNextForEachOrdinal; } 259 260 typedef ExportReduceList::const_iterator const_export_reduce_iterator; export_reduce_begin()261 const_export_reduce_iterator export_reduce_begin() const { 262 return mExportReduce.begin(); 263 } export_reduce_end()264 const_export_reduce_iterator export_reduce_end() const { 265 return mExportReduce.end(); 266 } export_reduce_size()267 size_t export_reduce_size() const { 268 return mExportReduce.size(); 269 } hasExportReduce()270 inline bool hasExportReduce() const { return !mExportReduce.empty(); } addExportReduce(RSExportReduce * Reduce)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. insertExportReduceResultType(RSExportType * Type)278 void insertExportReduceResultType(RSExportType *Type) { mExportReduceResultType.insert(Type); } 279 280 template <class FilterIn, class Compare> getReduceResultTypes(FilterIn Filt,Compare Comp)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; export_types_begin()295 export_type_iterator export_types_begin() { return mExportTypes.begin(); } export_types_end()296 export_type_iterator export_types_end() { return mExportTypes.end(); } export_types_begin()297 const_export_type_iterator export_types_begin() const { 298 return mExportTypes.begin(); 299 } export_types_end()300 const_export_type_iterator export_types_end() const { 301 return mExportTypes.end(); 302 } hasExportType()303 inline bool hasExportType() const { return !mExportTypes.empty(); } findExportType(const llvm::StringRef & TypeName)304 export_type_iterator findExportType(const llvm::StringRef &TypeName) { 305 return mExportTypes.find(TypeName); 306 } findExportType(const llvm::StringRef & TypeName)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 getVersion()317 int getVersion() const { return version; } setVersion(int v)318 void setVersion(int v) { 319 version = v; 320 } 321 isCompatLib()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 addPragma(const std::string & T,const std::string & V)328 void addPragma(const std::string &T, const std::string &V) { 329 mPragmas->push_back(make_pair(T, V)); 330 } setPrecision(const std::string & P)331 void setPrecision(const std::string &P) { mPrecision = P; } getPrecision()332 std::string getPrecision() { return mPrecision; } 333 334 // Report an error or a warning to the user. 335 template <unsigned N> Report(clang::DiagnosticsEngine::Level Level,const char (& Message)[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> Report(clang::DiagnosticsEngine::Level Level,const clang::SourceLocation Loc,const char (& Message)[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> ReportError(const char (& Message)[N])355 clang::DiagnosticBuilder ReportError(const char (&Message)[N]) const { 356 return Report<N>(clang::DiagnosticsEngine::Error, Message); 357 } 358 359 template <unsigned N> ReportError(const clang::SourceLocation Loc,const char (& Message)[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> ReportWarning(const char (& Message)[N])366 clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) const { 367 return Report<N>(clang::DiagnosticsEngine::Warning, Message); 368 } 369 370 template <unsigned N> ReportWarning(const clang::SourceLocation Loc,const char (& Message)[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