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 <string>
24 
25 #include "clang/Lex/Preprocessor.h"
26 #include "clang/AST/Mangle.h"
27 
28 #include "llvm/ADT/StringSet.h"
29 #include "llvm/ADT/StringMap.h"
30 
31 #include "slang_pragma_recorder.h"
32 
33 namespace llvm {
34   class LLVMContext;
35   class DataLayout;
36 }   // namespace llvm
37 
38 namespace clang {
39   class VarDecl;
40   class ASTContext;
41   class TargetInfo;
42   class FunctionDecl;
43   class SourceManager;
44 }   // namespace clang
45 
46 namespace slang {
47   class RSExportable;
48   class RSExportVar;
49   class RSExportFunc;
50   class RSExportForEach;
51   class RSExportType;
52 
53 class RSContext {
54   typedef llvm::StringSet<> NeedExportVarSet;
55   typedef llvm::StringSet<> NeedExportFuncSet;
56   typedef llvm::StringSet<> NeedExportTypeSet;
57 
58  public:
59   typedef std::list<RSExportable*> ExportableList;
60   typedef std::list<RSExportVar*> ExportVarList;
61   typedef std::list<RSExportFunc*> ExportFuncList;
62   typedef std::list<RSExportForEach*> ExportForEachList;
63   typedef llvm::StringMap<RSExportType*> ExportTypeMap;
64 
65  private:
66   clang::Preprocessor &mPP;
67   clang::ASTContext &mCtx;
68   PragmaList *mPragmas;
69   // Precision specified via pragma, either rs_fp_full or rs_fp_relaxed. If
70   // empty, rs_fp_full is assumed.
71   std::string mPrecision;
72   unsigned int mTargetAPI;
73   bool mVerbose;
74 
75   llvm::DataLayout *mDataLayout;
76   llvm::LLVMContext &mLLVMContext;
77 
78   ExportableList mExportables;
79 
80   NeedExportTypeSet mNeedExportTypes;
81 
82   std::string *mLicenseNote;
83   std::string mReflectJavaPackageName;
84   std::string mReflectJavaPathName;
85 
86   std::string mRSPackageName;
87 
88   int version;
89 
90   std::unique_ptr<clang::MangleContext> mMangleCtx;
91 
92   bool mIs64Bit;
93 
94   bool processExportVar(const clang::VarDecl *VD);
95   bool processExportFunc(const clang::FunctionDecl *FD);
96   bool processExportType(const llvm::StringRef &Name);
97 
98   void cleanupForEach();
99 
100   ExportVarList mExportVars;
101   ExportFuncList mExportFuncs;
102   ExportForEachList mExportForEach;
103   ExportTypeMap mExportTypes;
104 
105  public:
106   RSContext(clang::Preprocessor &PP,
107             clang::ASTContext &Ctx,
108             const clang::TargetInfo &Target,
109             PragmaList *Pragmas,
110             unsigned int TargetAPI,
111             bool Verbose);
112 
getPreprocessor()113   inline clang::Preprocessor &getPreprocessor() const { return mPP; }
getASTContext()114   inline clang::ASTContext &getASTContext() const { return mCtx; }
getMangleContext()115   inline clang::MangleContext &getMangleContext() const {
116     return *mMangleCtx;
117   }
getDataLayout()118   inline const llvm::DataLayout *getDataLayout() const { return mDataLayout; }
getLLVMContext()119   inline llvm::LLVMContext &getLLVMContext() const { return mLLVMContext; }
getSourceManager()120   inline const clang::SourceManager *getSourceManager() const {
121     return &mPP.getSourceManager();
122   }
getDiagnostics()123   inline clang::DiagnosticsEngine *getDiagnostics() const {
124     return &mPP.getDiagnostics();
125   }
getTargetAPI()126   inline unsigned int getTargetAPI() const {
127     return mTargetAPI;
128   }
129 
getVerbose()130   inline bool getVerbose() const {
131     return mVerbose;
132   }
is64Bit()133   inline bool is64Bit() const {
134     return mIs64Bit;
135   }
136 
setLicenseNote(const std::string & S)137   inline void setLicenseNote(const std::string &S) {
138     mLicenseNote = new std::string(S);
139   }
getLicenseNote()140   inline const std::string *getLicenseNote() const { return mLicenseNote; }
141 
addExportType(const std::string & S)142   inline void addExportType(const std::string &S) {
143     mNeedExportTypes.insert(S);
144   }
145 
setReflectJavaPackageName(const std::string & S)146   inline void setReflectJavaPackageName(const std::string &S) {
147     mReflectJavaPackageName = S;
148   }
getReflectJavaPackageName()149   inline const std::string &getReflectJavaPackageName() const {
150     return mReflectJavaPackageName;
151   }
152 
setRSPackageName(const std::string & S)153   inline void setRSPackageName(const std::string &S) {
154     mRSPackageName = S;
155   }
156 
getRSPackageName()157   inline const std::string &getRSPackageName() const { return mRSPackageName; }
158 
159   bool processExport();
newExportable(RSExportable * E)160   inline void newExportable(RSExportable *E) {
161     if (E != nullptr)
162       mExportables.push_back(E);
163   }
164   typedef ExportableList::iterator exportable_iterator;
exportable_begin()165   exportable_iterator exportable_begin() {
166     return mExportables.begin();
167   }
exportable_end()168   exportable_iterator exportable_end() {
169     return mExportables.end();
170   }
171 
172   typedef ExportVarList::const_iterator const_export_var_iterator;
export_vars_begin()173   const_export_var_iterator export_vars_begin() const {
174     return mExportVars.begin();
175   }
export_vars_end()176   const_export_var_iterator export_vars_end() const {
177     return mExportVars.end();
178   }
hasExportVar()179   inline bool hasExportVar() const {
180     return !mExportVars.empty();
181   }
182 
183   typedef ExportFuncList::const_iterator const_export_func_iterator;
export_funcs_begin()184   const_export_func_iterator export_funcs_begin() const {
185     return mExportFuncs.begin();
186   }
export_funcs_end()187   const_export_func_iterator export_funcs_end() const {
188     return mExportFuncs.end();
189   }
hasExportFunc()190   inline bool hasExportFunc() const { return !mExportFuncs.empty(); }
191 
192   typedef ExportForEachList::const_iterator const_export_foreach_iterator;
export_foreach_begin()193   const_export_foreach_iterator export_foreach_begin() const {
194     return mExportForEach.begin();
195   }
export_foreach_end()196   const_export_foreach_iterator export_foreach_end() const {
197     return mExportForEach.end();
198   }
hasExportForEach()199   inline bool hasExportForEach() const { return !mExportForEach.empty(); }
200 
201   typedef ExportTypeMap::iterator export_type_iterator;
202   typedef ExportTypeMap::const_iterator const_export_type_iterator;
export_types_begin()203   export_type_iterator export_types_begin() { return mExportTypes.begin(); }
export_types_end()204   export_type_iterator export_types_end() { return mExportTypes.end(); }
export_types_begin()205   const_export_type_iterator export_types_begin() const {
206     return mExportTypes.begin();
207   }
export_types_end()208   const_export_type_iterator export_types_end() const {
209     return mExportTypes.end();
210   }
hasExportType()211   inline bool hasExportType() const { return !mExportTypes.empty(); }
findExportType(const llvm::StringRef & TypeName)212   export_type_iterator findExportType(const llvm::StringRef &TypeName) {
213     return mExportTypes.find(TypeName);
214   }
findExportType(const llvm::StringRef & TypeName)215   const_export_type_iterator findExportType(const llvm::StringRef &TypeName)
216       const {
217     return mExportTypes.find(TypeName);
218   }
219 
220   // Insert the specified Typename/Type pair into the map. If the key already
221   // exists in the map, return false and ignore the request, otherwise insert it
222   // and return true.
223   bool insertExportType(const llvm::StringRef &TypeName, RSExportType *Type);
224 
getVersion()225   int getVersion() const { return version; }
setVersion(int v)226   void setVersion(int v) {
227     version = v;
228   }
229 
isCompatLib()230   bool isCompatLib() const {
231     // If we are not targeting the actual Android Renderscript classes,
232     // we should reflect code that works with the compatibility library.
233     return (mRSPackageName.compare("android.renderscript") != 0);
234   }
235 
addPragma(const std::string & T,const std::string & V)236   void addPragma(const std::string &T, const std::string &V) {
237     mPragmas->push_back(make_pair(T, V));
238   }
setPrecision(const std::string & P)239   void setPrecision(const std::string &P) { mPrecision = P; }
getPrecision()240   std::string getPrecision() { return mPrecision; }
241 
242   // Report an error or a warning to the user.
243   template <unsigned N>
Report(clang::DiagnosticsEngine::Level Level,const char (& Message)[N])244   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
245                                              const char (&Message)[N]) {
246   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
247   return DiagEngine->Report(DiagEngine->getCustomDiagID(Level, Message));
248 }
249 
250   template <unsigned N>
Report(clang::DiagnosticsEngine::Level Level,const clang::SourceLocation Loc,const char (& Message)[N])251   clang::DiagnosticBuilder Report(clang::DiagnosticsEngine::Level Level,
252                                              const clang::SourceLocation Loc,
253                                              const char (&Message)[N]) {
254   clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
255   const clang::SourceManager *SM = getSourceManager();
256   return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM),
257                             DiagEngine->getCustomDiagID(Level, Message));
258 }
259 
260   // Utility functions to report errors and warnings to make the calling code
261   // easier to read.
262   template <unsigned N>
ReportError(const char (& Message)[N])263   clang::DiagnosticBuilder ReportError(const char (&Message)[N]) {
264     return Report<N>(clang::DiagnosticsEngine::Error, Message);
265   }
266 
267   template <unsigned N>
ReportError(const clang::SourceLocation Loc,const char (& Message)[N])268   clang::DiagnosticBuilder ReportError(const clang::SourceLocation Loc,
269                                        const char (&Message)[N]) {
270     return Report<N>(clang::DiagnosticsEngine::Error, Loc, Message);
271   }
272 
273   template <unsigned N>
ReportWarning(const char (& Message)[N])274   clang::DiagnosticBuilder ReportWarning(const char (&Message)[N]) {
275     return Report<N>(clang::DiagnosticsEngine::Warning, Message);
276   }
277 
278   template <unsigned N>
ReportWarning(const clang::SourceLocation Loc,const char (& Message)[N])279   clang::DiagnosticBuilder ReportWarning(const clang::SourceLocation Loc,
280                                          const char (&Message)[N]) {
281     return Report<N>(clang::DiagnosticsEngine::Warning, Loc, Message);
282   }
283 
284   ~RSContext();
285 };
286 
287 }   // namespace slang
288 
289 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_CONTEXT_H_  NOLINT
290