blob: 4d2f795d20de8bfb28dae3660788bb02467286ea [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hines0a813a32012-08-03 16:52:40 -07002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070017#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ // NOLINT
Stephen Hinese639eb52010-11-08 19:27:20 -080018#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019
Shih-wei Liao462aefd2010-06-04 15:32:04 -070020#include <fstream>
21#include <iostream>
Stephen Hinese639eb52010-11-08 19:27:20 -080022#include <map>
Stephen Hines48b72bf2011-06-10 15:37:27 -070023#include <set>
Stephen Hinese639eb52010-11-08 19:27:20 -080024#include <string>
25#include <vector>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070026
zonr6315f762010-10-05 15:35:14 +080027#include "llvm/ADT/StringExtras.h"
28
Stephen Hines6e6578a2011-02-07 18:05:48 -080029#include "slang_assert.h"
zonr6315f762010-10-05 15:35:14 +080030#include "slang_rs_export_type.h"
Jean-Luc Brouilletf33e1562014-06-03 17:55:57 -070031#include "slang_rs_reflect_utils.h"
David Grossd80e58b2017-07-24 11:41:12 -070032#include "slang_rs_reflection_state.h"
zonr6315f762010-10-05 15:35:14 +080033
Shih-wei Liao462aefd2010-06-04 15:32:04 -070034namespace slang {
35
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070036class RSContext;
37class RSExportVar;
38class RSExportFunc;
39class RSExportForEach;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040
Jean-Luc Brouillet602def72014-05-27 16:11:37 -070041class RSReflectionJava {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070042private:
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070043 const RSContext *mRSContext;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
David Grossd80e58b2017-07-24 11:41:12 -070045 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
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -070052 // The name of the Java package name we're creating this file for,
53 // e.g. com.example.android.rs.flashlight
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070054 std::string mPackageName;
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -070055 // The name of the Java Renderscript package we'll be using,
56 // e.g. android.renderscript
57 // e.g. android.support.v8.renderscript
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070058 std::string mRSPackageName;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070059
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -070060 // 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
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -070080 // This is set by startClass() and will change for the multiple classes generated.
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070081 std::string mClassName;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070082
Tim Murray3a38b742014-07-02 10:41:08 -070083 // This is the token used for determining the size of a given ScriptField.Item.
84 std::string mItemSizeof;
85
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070086 bool mEmbedBitcodeInJava;
Stephen Hines44d495d2014-05-22 19:42:55 -070087
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070088 int mNextExportVarSlot;
89 int mNextExportFuncSlot;
90 int mNextExportForEachSlot;
Matt Wala7682b662015-07-30 15:53:47 -070091 int mNextExportReduceSlot;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Jean-Luc Brouilletf33e1562014-06-03 17:55:57 -070093 GeneratedFile mOut;
94
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -070095 std::string mLastError;
96 std::vector<std::string> *mGeneratedFileNames;
97
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -070098 // A mapping from a field in a record type to its index in the rsType
99 // instance. Only used when generates TypeClass (ScriptField_*).
David Grossd80e58b2017-07-24 11:41:12 -0700100 //
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;
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700106 FieldIndexMapTy mFieldIndexMap;
107 // Field index of current processing TypeClass.
David Grossd80e58b2017-07-24 11:41:12 -0700108 unsigned mFieldIndex; // corresponds to FieldIndexMapTy::mapped_type.first
109 unsigned mField32Index; // corresponds to FieldIndexMapTy::mapped_type.second
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700110
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700111 inline void setError(const std::string &Error) { mLastError = Error; }
112
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700113 inline void clear() {
114 mClassName = "";
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700115 mNextExportVarSlot = 0;
116 mNextExportFuncSlot = 0;
117 mNextExportForEachSlot = 0;
Matt Wala7682b662015-07-30 15:53:47 -0700118 mNextExportReduceSlot = 0;
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700119 }
Shih-wei Liao9c631ff2010-09-17 11:57:29 -0700120
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700121public:
122 typedef enum {
123 AM_Public,
124 AM_Protected,
125 AM_Private,
126 AM_PublicSynchronized
127 } AccessModifier;
Zonr Chang8c6d9b22010-10-07 18:01:19 +0800128
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700129 // Generated RS Elements for type-checking code.
130 std::set<std::string> mTypesToCheck;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700132 // Generated FieldPackers for unsigned setters/validation.
133 std::set<std::string> mFieldPackerTypes;
Stephen Hines48b72bf2011-06-10 15:37:27 -0700134
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700135 bool addTypeNameForElement(const std::string &TypeName);
136 bool addTypeNameForFieldPacker(const std::string &TypeName);
Stephen Hines1f6c3312012-07-03 17:23:33 -0700137
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700138 static const char *AccessModifierStr(AccessModifier AM);
Stephen Hines1f6c3312012-07-03 17:23:33 -0700139
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700140 inline bool getEmbedBitcodeInJava() const { return mEmbedBitcodeInJava; }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700141
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700142 inline int getNextExportVarSlot() { return mNextExportVarSlot++; }
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700143 inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; }
144 inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; }
Matt Wala7682b662015-07-30 15:53:47 -0700145 inline int getNextExportReduceSlot() { return mNextExportReduceSlot++; }
Stephen Hines44d495d2014-05-22 19:42:55 -0700146
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700147 bool startClass(AccessModifier AM, bool IsStatic,
148 const std::string &ClassName, const char *SuperClassName,
149 std::string &ErrorMsg);
150 void endClass();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700151
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700152 void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType,
153 const std::string &FunctionName, int Argc, ...);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700154
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700155 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();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700159
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700160 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; }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700164
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700165 void startTypeClass(const std::string &ClassName);
166 void endTypeClass();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700167
David Grossd80e58b2017-07-24 11:41:12 -0700168 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 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700174
David Grossd80e58b2017-07-24 11:41:12 -0700175 inline void resetFieldIndex() { mFieldIndex = mField32Index = 0; }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700176
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700177 inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
178 slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
179 "Nested structure never occurs in C language.");
David Grossd80e58b2017-07-24 11:41:12 -0700180 mFieldIndexMap.insert(std::make_pair(F, std::make_pair(mFieldIndex, mField32Index)));
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700181 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182
David Grossd80e58b2017-07-24 11:41:12 -0700183 inline std::pair<unsigned, unsigned> getFieldIndex(const RSExportRecordType::Field *F) const {
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700184 FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
185 slangAssert((I != mFieldIndexMap.end()) &&
186 "Requesting field is out of scope.");
187 return I->second;
188 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700189
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700190 inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700191
David Gross47cf31e2017-05-31 15:17:00 -0700192 enum {
193 TypeNameWithConstantArrayBrackets = 0x01,
194 TypeNameWithRecordElementName = 0x02,
David Grossd80e58b2017-07-24 11:41:12 -0700195
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
David Gross47cf31e2017-05-31 15:17:00 -0700204 TypeNameDefault = TypeNameWithConstantArrayBrackets|TypeNameWithRecordElementName
205 };
206 static std::string GetTypeName(const RSExportType *ET, unsigned Style = TypeNameDefault);
207
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700208private:
David Gross1c6bf882016-06-02 14:46:55 -0700209 static bool exportableReduce(const RSExportType *ResultType);
David Gross277fd5e2016-01-14 12:19:56 -0800210
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700211 bool genScriptClass(const std::string &ClassName, std::string &ErrorMsg);
212 void genScriptClassConstructor();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700213
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700214 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);
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700220 void genInitValue(const clang::APValue &Val, bool asBool);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700221 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);
David Grossd80e58b2017-07-24 11:41:12 -0700226 void genConstantArrayTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
227 void genRecordTypeExportVariable(const RSExportVar *EV, ReflectionState::Val32 AllocSize32);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700228 void genPrivateExportVariable(const std::string &TypeName,
Stephen Hines0d26cef2012-05-01 19:23:01 -0700229 const std::string &VarName);
David Grossd80e58b2017-07-24 11:41:12 -0700230 void genSetExportVariable(const std::string &TypeName, const RSExportVar *EV, unsigned Dimension,
231 ReflectionState::Val32 AllocSize32 = ReflectionState::NoVal32());
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700232 void genGetExportVariable(const std::string &TypeName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700233 const std::string &VarName);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700234 void genGetFieldID(const std::string &VarName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700236 void genExportFunction(const RSExportFunc *EF);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700238 void genExportForEach(const RSExportForEach *EF);
Stephen Hines593a8942011-05-10 15:29:50 -0700239
Matt Wala7682b662015-07-30 15:53:47 -0700240 void genExportReduce(const RSExportReduce *ER);
David Gross1c6bf882016-06-02 14:46:55 -0700241 void genExportReduceAllocationVariant(const RSExportReduce *ER);
242 void genExportReduceArrayVariant(const RSExportReduce *ER);
243 void genExportReduceResultType(const RSExportType *ResultType);
David Gross277fd5e2016-01-14 12:19:56 -0800244
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700245 void genTypeCheck(const RSExportType *ET, const char *VarName);
Stephen Hines48b72bf2011-06-10 15:37:27 -0700246
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700247 void genTypeInstanceFromPointer(const RSExportType *ET);
Stephen Hinesa6b54142012-04-09 18:25:08 -0700248
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700249 void genTypeInstance(const RSExportType *ET);
Stephen Hinesb5a89fb2011-05-17 14:48:02 -0700250
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700251 void genFieldPackerInstance(const RSExportType *ET);
Stephen Hines1f6c3312012-07-03 17:23:33 -0700252
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700253 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();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264
David Grossd80e58b2017-07-24 11:41:12 -0700265 // 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
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700273 void genBuildElement(const char *ElementBuilderName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 const RSExportRecordType *ERT,
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700275 const char *RenderScriptVar, bool IsInline);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700276 void genAddElementToElementBuilder(const RSExportType *ERT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 const std::string &VarName,
278 const char *ElementBuilderName,
Zonr Chang89273bd2010-10-14 20:57:38 +0800279 const char *RenderScriptVar,
280 unsigned ArraySize);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281
David Grossd80e58b2017-07-24 11:41:12 -0700282 bool genCreateFieldPacker(const RSExportType *T, const char *FieldPackerName,
283 ReflectionState::Val32 AllocSize32);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700284 void genPackVarOfType(const RSExportType *T, const char *VarName,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700285 const char *FieldPackerName);
Jean-Luc Brouillet2e205d02014-06-02 21:06:52 -0700286 void genAllocateVarOfType(const RSExportType *T, const std::string &VarName);
287 void genNewItemBufferIfNull(const char *Index);
288 void genNewItemBufferPackerIfNull();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700289
Chih-Hung Hsiehe2ead842016-08-12 15:57:25 -0700290 void genPairwiseDimCheck(const std::string &name0, const std::string &name1);
Matt Wala7682b662015-07-30 15:53:47 -0700291 void genVectorLengthCompatibilityCheck(const std::string &ArrayName, unsigned VecSize);
David Gross277fd5e2016-01-14 12:19:56 -0800292 void genNullArrayCheck(const std::string &ArrayName);
Chris Wailesc9454af2014-06-13 17:25:40 -0700293
David Grossd80e58b2017-07-24 11:41:12 -0700294 // 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
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700306public:
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700307 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,
David Grossd80e58b2017-07-24 11:41:12 -0700312 bool EmbedBitcodeInJava,
313 ReflectionState *RState);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700314
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700315 bool reflect();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700316
317 inline const char *getLastError() const {
318 if (mLastError.empty())
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700319 return nullptr;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 else
321 return mLastError.c_str();
322 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700323}; // class RSReflectionJava
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700324
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700325} // namespace slang
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700326
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700327#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ NOLINT