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 #include "slang_rs_reflection_state.h"
33 
34 namespace slang {
35 
36 class RSContext;
37 class RSExportVar;
38 class RSExportFunc;
39 class RSExportForEach;
40 
41 class RSReflectionJava {
42 private:
43   const RSContext *mRSContext;
44 
45   ReflectionState *mState;
46 
47   // If we're in the "collecting" state (according to mState), we
48   // don't actually generate code, but we do want to keep track of
49   // some information about what we WOULD generate.
50   const bool mCollecting;
51 
52   // The name of the Java package name we're creating this file for,
53   // e.g. com.example.android.rs.flashlight
54   std::string mPackageName;
55   // The name of the Java Renderscript package we'll be using,
56   // e.g. android.renderscript
57   // e.g. android.support.v8.renderscript
58   std::string mRSPackageName;
59 
60   // The directory under which we'll create the Java files, in appropriate subdirectories,
61   // e.g. /tmp/myout
62   std::string mOutputBaseDirectory;
63   // The output directory for the specfied package (mPackageName),
64   // e.g. /tmp/myout/com/example/android/rs/flashlight/
65   // TODO This includes the terminating separator.  Needed?
66   std::string mOutputDirectory;
67 
68   // The full path of the .rs file that we are reflecting.
69   std::string mRSSourceFileName;
70   // The full path where the generated bit code can be read.
71   std::string mBitCodeFileName;
72 
73   // The name of the resource we pass to the RenderScript constructor
74   // e.g. flashlight
75   std::string mResourceId;
76   // The name of the Java class we are generating for this script.
77   // e.g. ScriptC_flashlight
78   std::string mScriptClassName;
79 
80   // This is set by startClass() and will change for the multiple classes generated.
81   std::string mClassName;
82 
83   // This is the token used for determining the size of a given ScriptField.Item.
84   std::string mItemSizeof;
85 
86   bool mEmbedBitcodeInJava;
87 
88   int mNextExportVarSlot;
89   int mNextExportFuncSlot;
90   int mNextExportForEachSlot;
91   int mNextExportReduceSlot;
92 
93   GeneratedFile mOut;
94 
95   std::string mLastError;
96   std::vector<std::string> *mGeneratedFileNames;
97 
98   // A mapping from a field in a record type to its index in the rsType
99   // instance. Only used when generates TypeClass (ScriptField_*).
100   //
101   // .first = field index
102   // .second = when compiling for both 32-bit and 64-bit (RSCCOptions::mEmit3264),
103   //           and we are reflecting 64-bit code, this is field index for 32-bit;
104   //           otherwise, it is undefined
105   typedef std::map<const RSExportRecordType::Field *, std::pair<unsigned,unsigned> > FieldIndexMapTy;
106   FieldIndexMapTy mFieldIndexMap;
107   // Field index of current processing TypeClass.
108   unsigned mFieldIndex;    // corresponds to FieldIndexMapTy::mapped_type.first
109   unsigned mField32Index;  // corresponds to FieldIndexMapTy::mapped_type.second
110 
setError(const std::string & Error)111   inline void setError(const std::string &Error) { mLastError = Error; }
112 
clear()113   inline void clear() {
114     mClassName = "";
115     mNextExportVarSlot = 0;
116     mNextExportFuncSlot = 0;
117     mNextExportForEachSlot = 0;
118     mNextExportReduceSlot = 0;
119   }
120 
121 public:
122   typedef enum {
123     AM_Public,
124     AM_Protected,
125     AM_Private,
126     AM_PublicSynchronized
127   } AccessModifier;
128 
129   // Generated RS Elements for type-checking code.
130   std::set<std::string> mTypesToCheck;
131 
132   // Generated FieldPackers for unsigned setters/validation.
133   std::set<std::string> mFieldPackerTypes;
134 
135   bool addTypeNameForElement(const std::string &TypeName);
136   bool addTypeNameForFieldPacker(const std::string &TypeName);
137 
138   static const char *AccessModifierStr(AccessModifier AM);
139 
getEmbedBitcodeInJava()140   inline bool getEmbedBitcodeInJava() const { return mEmbedBitcodeInJava; }
141 
getNextExportVarSlot()142   inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
getNextExportFuncSlot()143   inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
getNextExportForEachSlot()144   inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
getNextExportReduceSlot()145   inline int getNextExportReduceSlot() { return mNextExportReduceSlot++; }
146 
147   bool startClass(AccessModifier AM, bool IsStatic,
148                   const std::string &ClassName, const char *SuperClassName,
149                   std::string &ErrorMsg);
150   void endClass();
151 
152   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
153                      const std::string &FunctionName, int Argc, ...);
154 
155   typedef std::vector<std::pair<std::string, std::string>> ArgTy;
156   void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
157                      const std::string &FunctionName, const ArgTy &Args);
158   void endFunction();
159 
getPackageName()160   inline const std::string &getPackageName() const { return mPackageName; }
getRSPackageName()161   inline const std::string &getRSPackageName() const { return mRSPackageName; }
getClassName()162   inline const std::string &getClassName() const { return mClassName; }
getResourceId()163   inline const std::string &getResourceId() const { return mResourceId; }
164 
165   void startTypeClass(const std::string &ClassName);
166   void endTypeClass();
167 
168   enum { FieldIndex = 0x1, Field32Index = 0x2 };  // bitmask
incFieldIndex(unsigned Which)169   inline void incFieldIndex(unsigned Which) {
170     slangAssert(!(Which & ~(FieldIndex | Field32Index)));
171     if (Which & FieldIndex  ) mFieldIndex++;
172     if (Which & Field32Index) mField32Index++;
173   }
174 
resetFieldIndex()175   inline void resetFieldIndex() { mFieldIndex = mField32Index = 0; }
176 
addFieldIndexMapping(const RSExportRecordType::Field * F)177   inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
178     slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
179                 "Nested structure never occurs in C language.");
180     mFieldIndexMap.insert(std::make_pair(F, std::make_pair(mFieldIndex, mField32Index)));
181   }
182 
getFieldIndex(const RSExportRecordType::Field * F)183   inline std::pair<unsigned, unsigned> getFieldIndex(const RSExportRecordType::Field *F) const {
184     FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
185     slangAssert((I != mFieldIndexMap.end()) &&
186                 "Requesting field is out of scope.");
187     return I->second;
188   }
189 
clearFieldIndexMap()190   inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
191 
192   enum {
193     TypeNameWithConstantArrayBrackets = 0x01,
194     TypeNameWithRecordElementName     = 0x02,
195 
196     // Three major flavors of types:
197     // - Java
198     // - C
199     // - PseudoC -- Identical to C for all types supported by C;
200     //              for other types, uses a simplified C-like syntax
201     TypeNameC                         = 0x04,
202     TypeNamePseudoC                   = 0x08,
203 
204     TypeNameDefault                   = TypeNameWithConstantArrayBrackets|TypeNameWithRecordElementName
205   };
206   static std::string GetTypeName(const RSExportType *ET, unsigned Style = TypeNameDefault);
207 
208 private:
209   static bool exportableReduce(const RSExportType *ResultType);
210 
211   bool genScriptClass(const std::string &ClassName, std::string &ErrorMsg);
212   void genScriptClassConstructor();
213 
214   void genInitBoolExportVariable(const std::string &VarName,
215                                  const clang::APValue &Val);
216   void genInitPrimitiveExportVariable(const std::string &VarName,
217                                       const clang::APValue &Val);
218   void genInitExportVariable(const RSExportType *ET, const std::string &VarName,
219                              const clang::APValue &Val);
220   void genInitValue(const clang::APValue &Val, bool asBool);
221   void genExportVariable(const RSExportVar *EV);
222   void genPrimitiveTypeExportVariable(const RSExportVar *EV);
223   void genPointerTypeExportVariable(const RSExportVar *EV);
224   void genVectorTypeExportVariable(const RSExportVar *EV);
225   void genMatrixTypeExportVariable(const RSExportVar *EV);
226   void genConstantArrayTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
227   void genRecordTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
228   void genPrivateExportVariable(const std::string &TypeName,
229                                 const std::string &VarName);
230   void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension,
231                             ReflectionState::Val32 AllocSize32 = ReflectionState::NoVal32());
232   void genGetExportVariable(const std::string &TypeName,
233                             const std::string &VarName);
234   void genGetFieldID(const std::string &VarName);
235 
236   void genExportFunction(const RSExportFunc *EF);
237 
238   void genExportForEach(const RSExportForEach *EF);
239 
240   void genExportReduce(const RSExportReduce *ER);
241   void genExportReduceAllocationVariant(const RSExportReduce *ER);
242   void genExportReduceArrayVariant(const RSExportReduce *ER);
243   void genExportReduceResultType(const RSExportType *ResultType);
244 
245   void genTypeCheck(const RSExportType *ET, const char *VarName);
246 
247   void genTypeInstanceFromPointer(const RSExportType *ET);
248 
249   void genTypeInstance(const RSExportType *ET);
250 
251   void genFieldPackerInstance(const RSExportType *ET);
252 
253   bool genTypeClass(const RSExportRecordType *ERT, std::string &ErrorMsg);
254   void genTypeItemClass(const RSExportRecordType *ERT);
255   void genTypeClassConstructor(const RSExportRecordType *ERT);
256   void genTypeClassCopyToArray(const RSExportRecordType *ERT);
257   void genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT);
258   void genTypeClassItemSetter(const RSExportRecordType *ERT);
259   void genTypeClassItemGetter(const RSExportRecordType *ERT);
260   void genTypeClassComponentSetter(const RSExportRecordType *ERT);
261   void genTypeClassComponentGetter(const RSExportRecordType *ERT);
262   void genTypeClassCopyAll(const RSExportRecordType *ERT);
263   void genTypeClassResize();
264 
265   // emits an expression that evaluates to true on a 64-bit target and
266   // false on a 32-bit target
267   void genCheck64Bit(bool Parens);
268 
269   // emits a fragment of the class definition needed to set up for
270   // genCheck64Bit()
271   void genCompute64Bit();
272 
273   void genBuildElement(const char *ElementBuilderName,
274                        const RSExportRecordType *ERT,
275                        const char *RenderScriptVar, bool IsInline);
276   void genAddElementToElementBuilder(const RSExportType *ERT,
277                                      const std::string &VarName,
278                                      const char *ElementBuilderName,
279                                      const char *RenderScriptVar,
280                                      unsigned ArraySize);
281 
282   bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName,
283                             ReflectionState::Val32 AllocSize32);
284   void genPackVarOfType(const RSExportType *T, const char *VarName,
285                         const char *FieldPackerName);
286   void genAllocateVarOfType(const RSExportType *T, const std::string &VarName);
287   void genNewItemBufferIfNull(const char *Index);
288   void genNewItemBufferPackerIfNull();
289 
290   void genPairwiseDimCheck(const std::string &name0, const std::string &name1);
291   void genVectorLengthCompatibilityCheck(const std::string &ArrayName, unsigned VecSize);
292   void genNullArrayCheck(const std::string &ArrayName);
293 
294   // NOTE
295   //
296   // If there's a nonempty Prefix, then:
297   // - If there's a nonzero value to emit, then emit the prefix followed by the value.
298   // - Otherwise, emit nothing.
299   //
300   // If there's an empty Prefix, then
301   // - Always emit a value, even if zero.
302   //
303   void genConditionalVal(const std::string &Prefix, bool Parens,
304                          size_t Val, ReflectionState::Val32 Val32);
305 
306 public:
307   RSReflectionJava(const RSContext *Context,
308                    std::vector<std::string> *GeneratedFileNames,
309                    const std::string &OutputBaseDirectory,
310                    const std::string &RSSourceFilename,
311                    const std::string &BitCodeFileName,
312                    bool EmbedBitcodeInJava,
313                    ReflectionState *RState);
314 
315   bool reflect();
316 
getLastError()317   inline const char *getLastError() const {
318     if (mLastError.empty())
319       return nullptr;
320     else
321       return mLastError.c_str();
322   }
323 }; // class RSReflectionJava
324 
325 } // namespace slang
326 
327 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  NOLINT
328