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
32namespace slang {
33
34  class RSContext;
35  class RSExportVar;
36  class RSExportFunc;
37  class RSExportForEach;
38
39class RSReflection {
40 private:
41  const RSContext *mRSContext;
42
43  std::string mLastError;
44  std::vector<std::string> *mGeneratedFileNames;
45
46  inline void setError(const std::string &Error) { mLastError = Error; }
47
48  class Context {
49   private:
50    static const char *const ApacheLicenseNote;
51
52    bool mVerbose;
53
54    std::string mOutputPathBase;
55
56    std::string mInputRSFile;
57
58    std::string mPackageName;
59    std::string mRSPackageName;
60    std::string mResourceId;
61    std::string mPaddingPrefix;
62
63    std::string mClassName;
64
65    std::string mLicenseNote;
66
67    std::string mIndent;
68
69    int mPaddingFieldIndex;
70
71    int mNextExportVarSlot;
72    int mNextExportFuncSlot;
73    int mNextExportForEachSlot;
74
75    // A mapping from a field in a record type to its index in the rsType
76    // instance. Only used when generates TypeClass (ScriptField_*).
77    typedef std::map<const RSExportRecordType::Field*, unsigned>
78        FieldIndexMapTy;
79    FieldIndexMapTy mFieldIndexMap;
80    // Field index of current processing TypeClass.
81    unsigned mFieldIndex;
82
83    inline void clear() {
84      mClassName = "";
85      mIndent = "";
86      mPaddingFieldIndex = 1;
87      mNextExportVarSlot = 0;
88      mNextExportFuncSlot = 0;
89      mNextExportForEachSlot = 0;
90      return;
91    }
92
93    bool openClassFile(const std::string &ClassName,
94                       std::string &ErrorMsg);
95
96   public:
97    typedef enum {
98      AM_Public,
99      AM_Protected,
100      AM_Private,
101      AM_PublicSynchronized
102    } AccessModifier;
103
104    bool mUseStdout;
105    mutable std::ofstream mOF;
106
107    // Generated RS Elements for type-checking code.
108    std::set<std::string> mTypesToCheck;
109
110    // Generated FieldPackers for unsigned setters/validation.
111    std::set<std::string> mFieldPackerTypes;
112
113    bool addTypeNameForElement(const std::string &TypeName);
114    bool addTypeNameForFieldPacker(const std::string &TypeName);
115
116    static const char *AccessModifierStr(AccessModifier AM);
117
118    Context(const std::string &OutputPathBase,
119            const std::string &InputRSFile,
120            const std::string &PackageName,
121            const std::string &RSPackageName,
122            const std::string &ResourceId,
123            const std::string &PaddingPrefix,
124            bool UseStdout)
125        : mVerbose(true),
126          mOutputPathBase(OutputPathBase),
127          mInputRSFile(InputRSFile),
128          mPackageName(PackageName),
129          mRSPackageName(RSPackageName),
130          mResourceId(ResourceId),
131          mPaddingPrefix(PaddingPrefix),
132          mLicenseNote(ApacheLicenseNote),
133          mUseStdout(UseStdout) {
134      clear();
135      resetFieldIndex();
136      clearFieldIndexMap();
137      return;
138    }
139
140    inline std::ostream &out() const {
141      return ((mUseStdout) ? std::cout : mOF);
142    }
143    inline std::ostream &indent() const {
144      out() << mIndent;
145      return out();
146    }
147
148    inline void incIndentLevel() {
149      mIndent.append(4, ' ');
150      return;
151    }
152
153    inline void decIndentLevel() {
154      slangAssert(getIndentLevel() > 0 && "No indent");
155      mIndent.erase(0, 4);
156      return;
157    }
158
159    inline int getIndentLevel() { return (mIndent.length() >> 2); }
160
161    inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
162
163    inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
164    inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
165
166    // Will remove later due to field name information is not necessary for
167    // C-reflect-to-Java
168    inline std::string createPaddingField() {
169      return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++);
170    }
171
172    inline void setLicenseNote(const std::string &LicenseNote) {
173      mLicenseNote = LicenseNote;
174    }
175
176    bool startClass(AccessModifier AM,
177                    bool IsStatic,
178                    const std::string &ClassName,
179                    const char *SuperClassName,
180                    std::string &ErrorMsg);
181    void endClass();
182
183    void startFunction(AccessModifier AM,
184                       bool IsStatic,
185                       const char *ReturnType,
186                       const std::string &FunctionName,
187                       int Argc, ...);
188
189    typedef std::vector<std::pair<std::string, std::string> > ArgTy;
190    void startFunction(AccessModifier AM,
191                       bool IsStatic,
192                       const char *ReturnType,
193                       const std::string &FunctionName,
194                       const ArgTy &Args);
195    void endFunction();
196
197    void startBlock(bool ShouldIndent = false);
198    void endBlock();
199
200    inline const std::string &getPackageName() const { return mPackageName; }
201    inline const std::string &getRSPackageName() const {
202      return mRSPackageName;
203    }
204    inline const std::string &getClassName() const { return mClassName; }
205    inline const std::string &getResourceId() const { return mResourceId; }
206
207    void startTypeClass(const std::string &ClassName);
208    void endTypeClass();
209
210    inline void incFieldIndex() { mFieldIndex++; }
211
212    inline void resetFieldIndex() { mFieldIndex = 0; }
213
214    inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
215      slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
216                  "Nested structure never occurs in C language.");
217      mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
218    }
219
220    inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
221      FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
222      slangAssert((I != mFieldIndexMap.end()) &&
223                  "Requesting field is out of scope.");
224      return I->second;
225    }
226
227    inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
228  };
229
230  bool genScriptClass(Context &C,
231                      const std::string &ClassName,
232                      std::string &ErrorMsg);
233  void genScriptClassConstructor(Context &C);
234
235  static void genInitBoolExportVariable(Context &C,
236                                        const std::string &VarName,
237                                        const clang::APValue &Val);
238  static void genInitPrimitiveExportVariable(Context &C,
239                                             const std::string &VarName,
240                                             const clang::APValue &Val);
241  static void genInitExportVariable(Context &C,
242                                    const RSExportType *ET,
243                                    const std::string &VarName,
244                                    const clang::APValue &Val);
245  static void genInitValue(Context &C, const clang::APValue &Val);
246  void genExportVariable(Context &C, const RSExportVar *EV);
247  void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV);
248  void genPointerTypeExportVariable(Context &C, const RSExportVar *EV);
249  void genVectorTypeExportVariable(Context &C, const RSExportVar *EV);
250  void genMatrixTypeExportVariable(Context &C, const RSExportVar *EV);
251  void genConstantArrayTypeExportVariable(Context &C, const RSExportVar *EV);
252  void genRecordTypeExportVariable(Context &C, const RSExportVar *EV);
253  void genPrivateExportVariable(Context &C,
254                                const std::string &TypeName,
255                                const std::string &VarName);
256  void genSetExportVariable(Context &C,
257                            const std::string &TypeName,
258                            const RSExportVar *EV);
259  void genGetExportVariable(Context &C,
260                            const std::string &TypeName,
261                            const std::string &VarName);
262  void genGetFieldID(Context &C,
263                     const std::string &VarName);
264
265  void genExportFunction(Context &C,
266                         const RSExportFunc *EF);
267
268  void genExportForEach(Context &C,
269                        const RSExportForEach *EF);
270
271  static void genTypeCheck(Context &C,
272                           const RSExportType *ET,
273                           const char *VarName);
274
275  static void genTypeInstanceFromPointer(Context &C,
276                                         const RSExportType *ET);
277
278  static void genTypeInstance(Context &C,
279                              const RSExportType *ET);
280
281  static void genFieldPackerInstance(Context &C,
282                                     const RSExportType *ET);
283
284  bool genTypeClass(Context &C,
285                    const RSExportRecordType *ERT,
286                    std::string &ErrorMsg);
287  void genTypeItemClass(Context &C, const RSExportRecordType *ERT);
288  void genTypeClassConstructor(Context &C, const RSExportRecordType *ERT);
289  void genTypeClassCopyToArray(Context &C, const RSExportRecordType *ERT);
290  void genTypeClassCopyToArrayLocal(Context &C, const RSExportRecordType *ERT);
291  void genTypeClassItemSetter(Context &C, const RSExportRecordType *ERT);
292  void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT);
293  void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT);
294  void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT);
295  void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT);
296  void genTypeClassResize(Context &C);
297
298  void genBuildElement(Context &C,
299                       const char *ElementBuilderName,
300                       const RSExportRecordType *ERT,
301                       const char *RenderScriptVar,
302                       bool IsInline);
303  void genAddElementToElementBuilder(Context &C,
304                                     const RSExportType *ERT,
305                                     const std::string &VarName,
306                                     const char *ElementBuilderName,
307                                     const char *RenderScriptVar,
308                                     unsigned ArraySize);
309  void genAddPaddingToElementBuiler(Context &C,
310                                    int PaddingSize,
311                                    const char *ElementBuilderName,
312                                    const char *RenderScriptVar);
313
314  bool genCreateFieldPacker(Context &C,
315                            const RSExportType *T,
316                            const char *FieldPackerName);
317  void genPackVarOfType(Context &C,
318                        const RSExportType *T,
319                        const char *VarName,
320                        const char *FieldPackerName);
321  void genAllocateVarOfType(Context &C,
322                            const RSExportType *T,
323                            const std::string &VarName);
324  void genNewItemBufferIfNull(Context &C, const char *Index);
325  void genNewItemBufferPackerIfNull(Context &C);
326
327 public:
328  explicit RSReflection(const RSContext *Context,
329      std::vector<std::string> *GeneratedFileNames)
330      : mRSContext(Context),
331        mLastError(""),
332        mGeneratedFileNames(GeneratedFileNames) {
333    slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
334    return;
335  }
336
337  bool reflect(const std::string &OutputPathBase,
338               const std::string &OutputPackageName,
339               const std::string &RSPackageName,
340               const std::string &InputFileName,
341               const std::string &OutputBCFileName);
342
343  inline const char *getLastError() const {
344    if (mLastError.empty())
345      return NULL;
346    else
347      return mLastError.c_str();
348  }
349};  // class RSReflection
350
351}   // namespace slang
352
353#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_  NOLINT
354