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 isSyntheticName(const llvm::StringRef Name)142 static bool isSyntheticName(const llvm::StringRef Name) { return Name.startswith(".rs."); } 143 getPreprocessor()144 inline clang::Preprocessor &getPreprocessor() const { return mPP; } getASTContext()145 inline clang::ASTContext &getASTContext() const { return mCtx; } getMangleContext()146 inline clang::MangleContext &getMangleContext() const { 147 return *mMangleCtx; 148 } getDataLayout()149 inline const llvm::DataLayout *getDataLayout() const { return mDataLayout; } getLLVMContext()150 inline llvm::LLVMContext &getLLVMContext() const { return mLLVMContext; } getSourceManager()151 inline const clang::SourceManager *getSourceManager() const { 152 return &mPP.getSourceManager(); 153 } getDiagnostics()154 inline clang::DiagnosticsEngine *getDiagnostics() const { 155 return &mPP.getDiagnostics(); 156 } getTargetAPI()157 inline unsigned int getTargetAPI() const { 158 return mTargetAPI; 159 } 160 getVerbose()161 inline bool getVerbose() const { 162 return mVerbose; 163 } is64Bit()164 inline bool is64Bit() const { 165 return mIs64Bit; 166 } 167 setLicenseNote(const std::string & S)168 inline void setLicenseNote(const std::string &S) { 169 mLicenseNote = new std::string(S); 170 } getLicenseNote()171 inline const std::string *getLicenseNote() const { return mLicenseNote; } 172 addExportType(const std::string & S)173 inline void addExportType(const std::string &S) { 174 mNeedExportTypes.insert(S); 175 } 176 setReflectJavaPackageName(const std::string & S)177 inline void setReflectJavaPackageName(const std::string &S) { 178 mReflectJavaPackageName = S; 179 } getReflectJavaPackageName()180 inline const std::string &getReflectJavaPackageName() const { 181 return mReflectJavaPackageName; 182 } 183 setRSPackageName(const std::string & S)184 inline void setRSPackageName(const std::string &S) { 185 mRSPackageName = S; 186 } 187 getRSPackageName()188 inline const std::string &getRSPackageName() const { return mRSPackageName; } 189 190 void setAllocationType(const clang::TypeDecl* TD); getAllocationType()191 inline const clang::QualType& getAllocationType() const { 192 return mAllocationType; 193 } 194 195 void setScriptCallType(const clang::TypeDecl* TD); getScriptCallType()196 inline const clang::QualType& getScriptCallType() const { 197 return mScriptCallType; 198 } 199 200 bool addForEach(const clang::FunctionDecl* FD); 201 bool processExports(); newExportable(RSExportable * E)202 inline void newExportable(RSExportable *E) { 203 if (E != nullptr) 204 mExportables.push_back(E); 205 } 206 typedef ExportableList::iterator exportable_iterator; exportable_begin()207 exportable_iterator exportable_begin() { 208 return mExportables.begin(); 209 } exportable_end()210 exportable_iterator exportable_end() { 211 return mExportables.end(); 212 } 213 214 typedef ExportVarList::const_iterator const_export_var_iterator; export_vars_begin()215 const_export_var_iterator export_vars_begin() const { 216 return mExportVars.begin(); 217 } export_vars_end()218 const_export_var_iterator export_vars_end() const { 219 return mExportVars.end(); 220 } hasExportVar()221 inline bool hasExportVar() const { 222 return !mExportVars.empty(); 223 } 224 225 typedef ExportFuncList::const_iterator const_export_func_iterator; export_funcs_begin()226 const_export_func_iterator export_funcs_begin() const { 227 return mExportFuncs.begin(); 228 } export_funcs_end()229 const_export_func_iterator export_funcs_end() const { 230 return mExportFuncs.end(); 231 } hasExportFunc()232 inline bool hasExportFunc() const { return !mExportFuncs.empty(); } 233 234 typedef ExportForEachVector::const_iterator const_export_foreach_iterator; export_foreach_begin()235 const_export_foreach_iterator export_foreach_begin() const { 236 return mExportForEach.begin(); 237 } export_foreach_end()238 const_export_foreach_iterator export_foreach_end() const { 239 return mExportForEach.end(); 240 } hasExportForEach()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; export_reduce_begin()245 const_export_reduce_iterator export_reduce_begin() const { 246 return mExportReduce.begin(); 247 } export_reduce_end()248 const_export_reduce_iterator export_reduce_end() const { 249 return mExportReduce.end(); 250 } hasExportReduce()251 inline bool hasExportReduce() const { return !mExportReduce.empty(); } addExportReduce(RSExportReduce * Reduce)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. insertExportReduceResultType(RSExportType * Type)259 void insertExportReduceResultType(RSExportType *Type) { mExportReduceResultType.insert(Type); } 260 261 template <class FilterIn, class Compare> getReduceResultTypes(FilterIn Filt,Compare Comp)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; export_types_begin()276 export_type_iterator export_types_begin() { return mExportTypes.begin(); } export_types_end()277 export_type_iterator export_types_end() { return mExportTypes.end(); } export_types_begin()278 const_export_type_iterator export_types_begin() const { 279 return mExportTypes.begin(); 280 } export_types_end()281 const_export_type_iterator export_types_end() const { 282 return mExportTypes.end(); 283 } hasExportType()284 inline bool hasExportType() const { return !mExportTypes.empty(); } findExportType(const llvm::StringRef & TypeName)285 export_type_iterator findExportType(const llvm::StringRef &TypeName) { 286 return mExportTypes.find(TypeName); 287 } findExportType(const llvm::StringRef & TypeName)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 getVersion()298 int getVersion() const { return version; } setVersion(int v)299 void setVersion(int v) { 300 version = v; 301 } 302 isCompatLib()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 addPragma(const std::string & T,const std::string & V)309 void addPragma(const std::string &T, const std::string &V) { 310 mPragmas->push_back(make_pair(T, V)); 311 } setPrecision(const std::string & P)312 void setPrecision(const std::string &P) { mPrecision = P; } getPrecision()313 std::string getPrecision() { return mPrecision; } 314 315 // Report an error or a warning to the user. 316 template <unsigned N> Report(clang::DiagnosticsEngine::Level Level,const char (& Message)[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> Report(clang::DiagnosticsEngine::Level Level,const clang::SourceLocation Loc,const char (& Message)[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> ReportError(const char (& Message)[N])336 clang::DiagnosticBuilder ReportError(const char (&Message)[N]) { 337 return Report<N>(clang::DiagnosticsEngine::Error, Message); 338 } 339 340 template <unsigned N> ReportError(const clang::SourceLocation Loc,const char (& Message)[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> ReportWarning(const char (& Message)[N])347 clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) { 348 return Report<N>(clang::DiagnosticsEngine::Warning, Message); 349 } 350 351 template <unsigned N> ReportWarning(const clang::SourceLocation Loc,const char (& Message)[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