slang_rs_reflection.h revision c383a500aa59423264811be3874461bf8adbfea0
1/*
2 * Copyright 2010, 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 _SLANG_COMPILER_RS_REFLECTION_H
18#define _SLANG_COMPILER_RS_REFLECTION_H
19
20#include <map>
21#include <vector>
22#include <string>
23#include <cassert>
24#include <fstream>
25#include <iostream>
26
27#include "llvm/ADT/StringExtras.h"
28
29#include "slang_rs_export_type.h"
30
31namespace slang {
32
33  class RSContext;
34  class RSExportVar;
35  class RSExportFunc;
36
37class RSReflection {
38 private:
39  const RSContext *mRSContext;
40
41  std::string mLastError;
42  inline void setError(const std::string &Error) { mLastError = Error; }
43
44  class Context {
45   private:
46    static const char *const ApacheLicenseNote;
47
48    static const char *const Import[];
49
50    bool mVerbose;
51
52    std::string mOutputPathBase;
53
54    std::string mInputRSFile;
55
56    std::string mPackageName;
57    std::string mResourceId;
58
59    std::string mClassName;
60
61    std::string mLicenseNote;
62
63    std::string mIndent;
64
65    int mPaddingFieldIndex;
66
67    int mNextExportVarSlot;
68    int mNextExportFuncSlot;
69
70    // A mapping from a field in a record type to its index in the rsType
71    // instance. Only used when generates TypeClass (ScriptField_*).
72    typedef std::map<const RSExportRecordType::Field*, unsigned> FieldIndexMapTy;
73    FieldIndexMapTy mFieldIndexMap;
74    // Field index of current processing TypeClass.
75    unsigned mFieldIndex;
76
77    inline void clear() {
78      mClassName = "";
79      mIndent = "";
80      mPaddingFieldIndex = 1;
81      mNextExportVarSlot = 0;
82      mNextExportFuncSlot = 0;
83      return;
84    }
85
86    bool openClassFile(const std::string &ClassName,
87                       std::string &ErrorMsg);
88
89   public:
90    typedef enum {
91      AM_Public,
92      AM_Protected,
93      AM_Private
94    } AccessModifier;
95
96    bool mUseStdout;
97    mutable std::ofstream mOF;
98
99    static const char *AccessModifierStr(AccessModifier AM);
100
101    Context(const std::string &OutputPathBase,
102            const std::string &InputRSFile,
103            const std::string &PackageName,
104            const std::string &ResourceId,
105            bool UseStdout)
106        : mVerbose(true),
107          mOutputPathBase(OutputPathBase),
108          mInputRSFile(InputRSFile),
109          mPackageName(PackageName),
110          mResourceId(ResourceId),
111          mLicenseNote(ApacheLicenseNote),
112          mUseStdout(UseStdout) {
113      clear();
114      resetFieldIndex();
115      clearFieldIndexMap();
116      return;
117    }
118
119    inline std::ostream &out() const {
120      return ((mUseStdout) ? std::cout : mOF);
121    }
122    inline std::ostream &indent() const {
123      out() << mIndent;
124      return out();
125    }
126
127    inline void incIndentLevel() {
128      mIndent.append(4, ' ');
129      return;
130    }
131
132    inline void decIndentLevel() {
133      assert(getIndentLevel() > 0 && "No indent");
134      mIndent.erase(0, 4);
135      return;
136    }
137
138    inline int getIndentLevel() { return (mIndent.length() >> 2); }
139
140    inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
141
142    inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
143
144    // Will remove later due to field name information is not necessary for
145    // C-reflect-to-Java
146    inline std::string createPaddingField() {
147      return "#padding_" + llvm::itostr(mPaddingFieldIndex++);
148    }
149
150    inline void setLicenseNote(const std::string &LicenseNote) {
151      mLicenseNote = LicenseNote;
152    }
153
154    bool startClass(AccessModifier AM,
155                    bool IsStatic,
156                    const std::string &ClassName,
157                    const char *SuperClassName,
158                    std::string &ErrorMsg);
159    void endClass();
160
161    void startFunction(AccessModifier AM,
162                       bool IsStatic,
163                       const char *ReturnType,
164                       const std::string &FunctionName,
165                       int Argc, ...);
166
167    typedef std::vector<std::pair<std::string, std::string> > ArgTy;
168    void startFunction(AccessModifier AM,
169                       bool IsStatic,
170                       const char *ReturnType,
171                       const std::string &FunctionName,
172                       const ArgTy &Args);
173    void endFunction();
174
175    void startBlock(bool ShouldIndent = false);
176    void endBlock();
177
178    inline const std::string &getPackageName() const { return mPackageName; }
179    inline const std::string &getClassName() const { return mClassName; }
180    inline const std::string &getResourceId() const { return mResourceId; }
181
182    void startTypeClass(const std::string &ClassName);
183    void endTypeClass();
184
185    inline void incFieldIndex() { mFieldIndex++; }
186
187    inline void resetFieldIndex() { mFieldIndex = 0; }
188
189    inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
190      assert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
191             "Nested structure never occurs in C language.");
192      mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
193    }
194
195    inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
196      FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
197      assert((I != mFieldIndexMap.end()) &&
198             "Requesting field is out of scope.");
199      return I->second;
200    }
201
202    inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
203  };
204
205  bool genScriptClass(Context &C,
206                      const std::string &ClassName,
207                      std::string &ErrorMsg);
208  void genScriptClassConstructor(Context &C);
209
210  void genInitBoolExportVariable(Context &C,
211                                 const std::string &VarName,
212                                 const clang::APValue &Val);
213  void genInitPrimitiveExportVariable(Context &C,
214                                      const std::string &VarName,
215                                      const clang::APValue &Val);
216  void genInitExportVariable(Context &C,
217                             const RSExportType *ET,
218                             const std::string &VarName,
219                             const clang::APValue &Val);
220  void genExportVariable(Context &C, const RSExportVar *EV);
221  void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV);
222  void genPointerTypeExportVariable(Context &C, const RSExportVar *EV);
223  void genVectorTypeExportVariable(Context &C, const RSExportVar *EV);
224  void genMatrixTypeExportVariable(Context &C, const RSExportVar *EV);
225  void genConstantArrayTypeExportVariable(Context &C, const RSExportVar *EV);
226  void genRecordTypeExportVariable(Context &C, const RSExportVar *EV);
227  void genGetExportVariable(Context &C,
228                            const std::string &TypeName,
229                            const std::string &VarName);
230
231  void genExportFunction(Context &C,
232                         const RSExportFunc *EF);
233
234  bool genTypeClass(Context &C,
235                    const RSExportRecordType *ERT,
236                    std::string &ErrorMsg);
237  void genTypeItemClass(Context &C, const RSExportRecordType *ERT);
238  void genTypeClassConstructor(Context &C, const RSExportRecordType *ERT);
239  void genTypeClassCopyToArray(Context &C, const RSExportRecordType *ERT);
240  void genTypeClassItemSetter(Context &C, const RSExportRecordType *ERT);
241  void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT);
242  void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT);
243  void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT);
244  void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT);
245
246  void genBuildElement(Context &C,
247                       const RSExportRecordType *ERT,
248                       const char *RenderScriptVar);
249  void genAddElementToElementBuilder(Context &C,
250                                     const RSExportType *ERT,
251                                     const std::string &VarName,
252                                     const char *ElementBuilderName,
253                                     const char *RenderScriptVar);
254  void genAddPaddingToElementBuiler(Context &C,
255                                    int PaddingSize,
256                                    const char *ElementBuilderName,
257                                    const char *RenderScriptVar);
258
259  bool genCreateFieldPacker(Context &C,
260                            const RSExportType *T,
261                            const char *FieldPackerName);
262  void genPackVarOfType(Context &C,
263                        const RSExportType *T,
264                        const char *VarName,
265                        const char *FieldPackerName);
266  void genAllocateVarOfType(Context &C,
267                            const RSExportType *T,
268                            const std::string &VarName);
269  void genNewItemBufferIfNull(Context &C, const char *Index);
270  void genNewItemBufferPackerIfNull(Context &C);
271
272 public:
273  explicit RSReflection(const RSContext *Context)
274      : mRSContext(Context),
275        mLastError("") {
276    return;
277  }
278
279  bool reflect(const std::string &OutputPathBase,
280               const std::string &OutputPackageName,
281               const std::string &InputFileName,
282               const std::string &OutputBCFileName);
283
284  inline const char *getLastError() const {
285    if (mLastError.empty())
286      return NULL;
287    else
288      return mLastError.c_str();
289  }
290};  // class RSReflection
291
292}   // namespace slang
293
294#endif  // _SLANG_COMPILER_RS_REFLECTION_H
295