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_REFLECTION_H_ // NOLINT
18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_
19 
20 #include <fstream>
21 #include <iostream>
22 #include <map>
23 #include <set>
24 #include <string>
25 #include <vector>
26 
27 #include "llvm/ADT/StringExtras.h"
28 
29 #include "slang_assert.h"
30 #include "slang_rs_export_type.h"
31 #include "slang_rs_reflect_utils.h"
32 
33 namespace slang {
34 
35 class RSContext;
36 class RSExportVar;
37 class RSExportFunc;
38 class RSExportForEach;
39 
40 class RSReflectionJava {
41 private:
42   const RSContext *mRSContext;
43 
44   // The name of the Java package name we're creating this file for,
45   // e.g. com.example.android.rs.flashlight
46   std::string mPackageName;
47   // The name of the Java Renderscript package we'll be using,
48   // e.g. android.renderscript
49   // e.g. android.support.v8.renderscript
50   std::string mRSPackageName;
51 
52   // The directory under which we'll create the Java files, in appropriate subdirectories,
53   // e.g. /tmp/myout
54   std::string mOutputBaseDirectory;
55   // The output directory for the specfied package (mPackageName),
56   // e.g. /tmp/myout/com/example/android/rs/flashlight/
57   // TODO This includes the terminating separator.  Needed?
58   std::string mOutputDirectory;
59 
60   // The full path of the .rs file that we are reflecting.
61   std::string mRSSourceFileName;
62   // The full path where the generated bit code can be read.
63   std::string mBitCodeFileName;
64 
65   // The name of the resource we pass to the RenderScript constructor
66   // e.g. flashlight
67   std::string mResourceId;
68   // The name of the Java class we are generating for this script.
69   // e.g. ScriptC_flashlight
70   std::string mScriptClassName;
71 
72 
73   // This is set by startClass() and will change for the multiple classes generated.
74   std::string mClassName;
75 
76   // This is the token used for determining the size of a given ScriptField.Item.
77   std::string mItemSizeof;
78 
79   bool mEmbedBitcodeInJava;
80 
81   int mNextExportVarSlot;
82   int mNextExportFuncSlot;
83   int mNextExportForEachSlot;
84   int mNextExportReduceSlot;
85 
86   GeneratedFile mOut;
87 
88   std::string mLastError;
89   std::vector<std::string> *mGeneratedFileNames;
90 
91   // A mapping from a field in a record type to its index in the rsType
92   // instance. Only used when generates TypeClass (ScriptField_*).
93   typedef std::map<const RSExportRecordType::Field *, unsigned> FieldIndexMapTy;
94   FieldIndexMapTy mFieldIndexMap;
95   // Field index of current processing TypeClass.
96   unsigned mFieldIndex;
97 
setError(const std::string & Error)98   inline void setError(const std::string &Error) { mLastError = Error; }
99 
clear()100   inline void clear() {
101     mClassName = "";
102     mNextExportVarSlot = 0;
103     mNextExportFuncSlot = 0;
104     mNextExportForEachSlot = 0;
105     mNextExportReduceSlot = 0;
106   }
107 
108 public:
109   typedef enum {
110     AM_Public,
111     AM_Protected,
112     AM_Private,
113     AM_PublicSynchronized
114   } AccessModifier;
115 
116   // Generated RS Elements for type-checking code.
117   std::set<std::string> mTypesToCheck;
118 
119   // Generated FieldPackers for unsigned setters/validation.
120   std::set<std::string> mFieldPackerTypes;
121 
122   bool addTypeNameForElement(const std::string &TypeName);
123   bool addTypeNameForFieldPacker(const std::string &TypeName);
124 
125   static const char *AccessModifierStr(AccessModifier AM);
126 
getEmbedBitcodeInJava()127   inline bool getEmbedBitcodeInJava() const { return mEmbedBitcodeInJava; }
128 
getNextExportVarSlot()129   inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
getNextExportFuncSlot()130   inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
getNextExportForEachSlot()131   inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
getNextExportReduceSlot()132   inline int getNextExportReduceSlot() { return mNextExportReduceSlot++; }
133 
134   bool startClass(AccessModifier AM, bool IsStatic,
135                   const std::string &ClassName, const char *SuperClassName,
136                   std::string &ErrorMsg);
137   void endClass();
138 
139   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
140                      const std::string &FunctionName, int Argc, ...);
141 
142   typedef std::vector<std::pair<std::string, std::string>> ArgTy;
143   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
144                      const std::string &FunctionName, const ArgTy &Args);
145   void endFunction();
146 
getPackageName()147   inline const std::string &getPackageName() const { return mPackageName; }
getRSPackageName()148   inline const std::string &getRSPackageName() const { return mRSPackageName; }
getClassName()149   inline const std::string &getClassName() const { return mClassName; }
getResourceId()150   inline const std::string &getResourceId() const { return mResourceId; }
151 
152   void startTypeClass(const std::string &ClassName);
153   void endTypeClass();
154 
incFieldIndex()155   inline void incFieldIndex() { mFieldIndex++; }
156 
resetFieldIndex()157   inline void resetFieldIndex() { mFieldIndex = 0; }
158 
addFieldIndexMapping(const RSExportRecordType::Field * F)159   inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
160     slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
161                 "Nested structure never occurs in C language.");
162     mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
163   }
164 
getFieldIndex(const RSExportRecordType::Field * F)165   inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
166     FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
167     slangAssert((I != mFieldIndexMap.end()) &&
168                 "Requesting field is out of scope.");
169     return I->second;
170   }
171 
clearFieldIndexMap()172   inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
173 
174 private:
175   static bool exportableReduce(const RSExportType *ResultType);
176 
177   bool genScriptClass(const std::string &ClassName, std::string &ErrorMsg);
178   void genScriptClassConstructor();
179 
180   void genInitBoolExportVariable(const std::string &VarName,
181                                  const clang::APValue &Val);
182   void genInitPrimitiveExportVariable(const std::string &VarName,
183                                       const clang::APValue &Val);
184   void genInitExportVariable(const RSExportType *ET, const std::string &VarName,
185                              const clang::APValue &Val);
186   void genInitValue(const clang::APValue &Val, bool asBool);
187   void genExportVariable(const RSExportVar *EV);
188   void genPrimitiveTypeExportVariable(const RSExportVar *EV);
189   void genPointerTypeExportVariable(const RSExportVar *EV);
190   void genVectorTypeExportVariable(const RSExportVar *EV);
191   void genMatrixTypeExportVariable(const RSExportVar *EV);
192   void genConstantArrayTypeExportVariable(const RSExportVar *EV);
193   void genRecordTypeExportVariable(const RSExportVar *EV);
194   void genPrivateExportVariable(const std::string &TypeName,
195                                 const std::string &VarName);
196   void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension);
197   void genGetExportVariable(const std::string &TypeName,
198                             const std::string &VarName);
199   void genGetFieldID(const std::string &VarName);
200 
201   void genExportFunction(const RSExportFunc *EF);
202 
203   void genExportForEach(const RSExportForEach *EF);
204 
205   void genExportReduce(const RSExportReduce *ER);
206   void genExportReduceAllocationVariant(const RSExportReduce *ER);
207   void genExportReduceArrayVariant(const RSExportReduce *ER);
208   void genExportReduceResultType(const RSExportType *ResultType);
209 
210   void genTypeCheck(const RSExportType *ET, const char *VarName);
211 
212   void genTypeInstanceFromPointer(const RSExportType *ET);
213 
214   void genTypeInstance(const RSExportType *ET);
215 
216   void genFieldPackerInstance(const RSExportType *ET);
217 
218   bool genTypeClass(const RSExportRecordType *ERT, std::string &ErrorMsg);
219   void genTypeItemClass(const RSExportRecordType *ERT);
220   void genTypeClassConstructor(const RSExportRecordType *ERT);
221   void genTypeClassCopyToArray(const RSExportRecordType *ERT);
222   void genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT);
223   void genTypeClassItemSetter(const RSExportRecordType *ERT);
224   void genTypeClassItemGetter(const RSExportRecordType *ERT);
225   void genTypeClassComponentSetter(const RSExportRecordType *ERT);
226   void genTypeClassComponentGetter(const RSExportRecordType *ERT);
227   void genTypeClassCopyAll(const RSExportRecordType *ERT);
228   void genTypeClassResize();
229 
230   void genBuildElement(const char *ElementBuilderName,
231                        const RSExportRecordType *ERT,
232                        const char *RenderScriptVar, bool IsInline);
233   void genAddElementToElementBuilder(const RSExportType *ERT,
234                                      const std::string &VarName,
235                                      const char *ElementBuilderName,
236                                      const char *RenderScriptVar,
237                                      unsigned ArraySize);
238 
239   bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName);
240   void genPackVarOfType(const RSExportType *T, const char *VarName,
241                         const char *FieldPackerName);
242   void genAllocateVarOfType(const RSExportType *T, const std::string &VarName);
243   void genNewItemBufferIfNull(const char *Index);
244   void genNewItemBufferPackerIfNull();
245 
246   void genPairwiseDimCheck(std::string name0, std::string name1);
247   void genVectorLengthCompatibilityCheck(const std::string &ArrayName, unsigned VecSize);
248   void genNullArrayCheck(const std::string &ArrayName);
249 
250 public:
251   RSReflectionJava(const RSContext *Context,
252                    std::vector<std::string> *GeneratedFileNames,
253                    const std::string &OutputBaseDirectory,
254                    const std::string &RSSourceFilename,
255                    const std::string &BitCodeFileName,
256                    bool EmbedBitcodeInJava);
257 
258   bool reflect();
259 
getLastError()260   inline const char *getLastError() const {
261     if (mLastError.empty())
262       return nullptr;
263     else
264       return mLastError.c_str();
265   }
266 }; // class RSReflectionJava
267 
268 } // namespace slang
269 
270 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  NOLINT
271