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