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
34namespace slang {
35
36class RSContext;
37class RSExportVar;
38class RSExportFunc;
39class RSExportForEach;
40
41class RSReflectionJava {
42private:
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
111  inline void setError(const std::string &Error) { mLastError = Error; }
112
113  inline void clear() {
114    mClassName = "";
115    mNextExportVarSlot = 0;
116    mNextExportFuncSlot = 0;
117    mNextExportForEachSlot = 0;
118    mNextExportReduceSlot = 0;
119  }
120
121public:
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
140  inline bool getEmbedBitcodeInJava() const { return mEmbedBitcodeInJava; }
141
142  inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
143  inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
144  inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
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
160  inline const std::string &getPackageName() const { return mPackageName; }
161  inline const std::string &getRSPackageName() const { return mRSPackageName; }
162  inline const std::string &getClassName() const { return mClassName; }
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
169  inline void incFieldIndex(unsigned Which) {
170    slangAssert(!(Which & ~(FieldIndex | Field32Index)));
171    if (Which & FieldIndex  ) mFieldIndex++;
172    if (Which & Field32Index) mField32Index++;
173  }
174
175  inline void resetFieldIndex() { mFieldIndex = mField32Index = 0; }
176
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
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
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
208private:
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
306public:
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
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