1
2 /*
3 * Copyright 2010-2014, The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "slang_rs_reflection.h"
19
20 #include <sys/stat.h>
21
22 #include <cstdarg>
23 #include <cctype>
24
25 #include <algorithm>
26 #include <sstream>
27 #include <string>
28 #include <utility>
29
30 #include "llvm/ADT/APFloat.h"
31 #include "llvm/ADT/StringExtras.h"
32
33 #include "os_sep.h"
34 #include "slang_rs_context.h"
35 #include "slang_rs_export_var.h"
36 #include "slang_rs_export_foreach.h"
37 #include "slang_rs_export_func.h"
38 #include "slang_rs_reflect_utils.h"
39 #include "slang_version.h"
40
41 #define RS_SCRIPT_CLASS_NAME_PREFIX "ScriptC_"
42 #define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC"
43
44 #define RS_TYPE_CLASS_SUPER_CLASS_NAME ".Script.FieldBase"
45
46 #define RS_TYPE_ITEM_CLASS_NAME "Item"
47
48 #define RS_TYPE_ITEM_SIZEOF_LEGACY "Item.sizeof"
49 #define RS_TYPE_ITEM_SIZEOF_CURRENT "mElement.getBytesSize()"
50
51 #define RS_TYPE_ITEM_BUFFER_NAME "mItemArray"
52 #define RS_TYPE_ITEM_BUFFER_PACKER_NAME "mIOBuffer"
53 #define RS_TYPE_ELEMENT_REF_NAME "mElementCache"
54
55 #define RS_EXPORT_VAR_INDEX_PREFIX "mExportVarIdx_"
56 #define RS_EXPORT_VAR_PREFIX "mExportVar_"
57 #define RS_EXPORT_VAR_ELEM_PREFIX "mExportVarElem_"
58 #define RS_EXPORT_VAR_DIM_PREFIX "mExportVarDim_"
59 #define RS_EXPORT_VAR_CONST_PREFIX "const_"
60
61 #define RS_ELEM_PREFIX "__"
62
63 #define RS_FP_PREFIX "__rs_fp_"
64
65 #define RS_RESOURCE_NAME "__rs_resource_name"
66
67 #define RS_EXPORT_FUNC_INDEX_PREFIX "mExportFuncIdx_"
68 #define RS_EXPORT_FOREACH_INDEX_PREFIX "mExportForEachIdx_"
69
70 #define RS_EXPORT_VAR_ALLOCATION_PREFIX "mAlloction_"
71 #define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_"
72
73 namespace slang {
74
75 class RSReflectionJavaElementBuilder {
76 public:
77 RSReflectionJavaElementBuilder(const char *ElementBuilderName,
78 const RSExportRecordType *ERT,
79 const char *RenderScriptVar,
80 GeneratedFile *Out, const RSContext *RSContext,
81 RSReflectionJava *Reflection);
82 void generate();
83
84 private:
85 void genAddElement(const RSExportType *ET, const std::string &VarName,
86 unsigned ArraySize);
87 void genAddStatementStart();
88 void genAddStatementEnd(const std::string &VarName, unsigned ArraySize);
89 void genAddPadding(int PaddingSize);
90 // TODO Will remove later due to field name information is not necessary for
91 // C-reflect-to-Java
createPaddingField()92 std::string createPaddingField() {
93 return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++);
94 }
95
96 const char *mElementBuilderName;
97 const RSExportRecordType *mERT;
98 const char *mRenderScriptVar;
99 GeneratedFile *mOut;
100 std::string mPaddingPrefix;
101 int mPaddingFieldIndex;
102 const RSContext *mRSContext;
103 RSReflectionJava *mReflection;
104 };
105
GetMatrixTypeName(const RSExportMatrixType * EMT)106 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
107 static const char *MatrixTypeJavaNameMap[] = {/* 2x2 */ "Matrix2f",
108 /* 3x3 */ "Matrix3f",
109 /* 4x4 */ "Matrix4f",
110 };
111 unsigned Dim = EMT->getDim();
112
113 if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char *)))
114 return MatrixTypeJavaNameMap[EMT->getDim() - 2];
115
116 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
117 return nullptr;
118 }
119
GetVectorAccessor(unsigned Index)120 static const char *GetVectorAccessor(unsigned Index) {
121 static const char *VectorAccessorMap[] = {/* 0 */ "x",
122 /* 1 */ "y",
123 /* 2 */ "z",
124 /* 3 */ "w",
125 };
126
127 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
128 "Out-of-bound index to access vector member");
129
130 return VectorAccessorMap[Index];
131 }
132
GetPackerAPIName(const RSExportPrimitiveType * EPT)133 static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) {
134 static const char *PrimitiveTypePackerAPINameMap[] = {
135 "addF16", // DataTypeFloat16
136 "addF32", // DataTypeFloat32
137 "addF64", // DataTypeFloat64
138 "addI8", // DataTypeSigned8
139 "addI16", // DataTypeSigned16
140 "addI32", // DataTypeSigned32
141 "addI64", // DataTypeSigned64
142 "addU8", // DataTypeUnsigned8
143 "addU16", // DataTypeUnsigned16
144 "addU32", // DataTypeUnsigned32
145 "addU64", // DataTypeUnsigned64
146 "addBoolean", // DataTypeBoolean
147 "addU16", // DataTypeUnsigned565
148 "addU16", // DataTypeUnsigned5551
149 "addU16", // DataTypeUnsigned4444
150 "addMatrix", // DataTypeRSMatrix2x2
151 "addMatrix", // DataTypeRSMatrix3x3
152 "addMatrix", // DataTypeRSMatrix4x4
153 "addObj", // DataTypeRSElement
154 "addObj", // DataTypeRSType
155 "addObj", // DataTypeRSAllocation
156 "addObj", // DataTypeRSSampler
157 "addObj", // DataTypeRSScript
158 "addObj", // DataTypeRSMesh
159 "addObj", // DataTypeRSPath
160 "addObj", // DataTypeRSProgramFragment
161 "addObj", // DataTypeRSProgramVertex
162 "addObj", // DataTypeRSProgramRaster
163 "addObj", // DataTypeRSProgramStore
164 "addObj", // DataTypeRSFont
165 };
166 unsigned TypeId = EPT->getType();
167
168 if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char *)))
169 return PrimitiveTypePackerAPINameMap[EPT->getType()];
170
171 slangAssert(false && "GetPackerAPIName : Unknown primitive data type");
172 return nullptr;
173 }
174
GetTypeName(const RSExportType * ET,bool Brackets=true)175 static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
176 switch (ET->getClass()) {
177 case RSExportType::ExportClassPrimitive: {
178 return RSExportPrimitiveType::getRSReflectionType(
179 static_cast<const RSExportPrimitiveType *>(ET))->java_name;
180 }
181 case RSExportType::ExportClassPointer: {
182 const RSExportType *PointeeType =
183 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
184
185 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
186 return "Allocation";
187 else
188 return PointeeType->getElementName();
189 }
190 case RSExportType::ExportClassVector: {
191 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
192 std::stringstream VecName;
193 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
194 << EVT->getNumElement();
195 return VecName.str();
196 }
197 case RSExportType::ExportClassMatrix: {
198 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
199 }
200 case RSExportType::ExportClassConstantArray: {
201 const RSExportConstantArrayType *CAT =
202 static_cast<const RSExportConstantArrayType *>(ET);
203 std::string ElementTypeName = GetTypeName(CAT->getElementType());
204 if (Brackets) {
205 ElementTypeName.append("[]");
206 }
207 return ElementTypeName;
208 }
209 case RSExportType::ExportClassRecord: {
210 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
211 }
212 default: { slangAssert(false && "Unknown class of type"); }
213 }
214
215 return "";
216 }
217
GetTypeNullValue(const RSExportType * ET)218 static const char *GetTypeNullValue(const RSExportType *ET) {
219 switch (ET->getClass()) {
220 case RSExportType::ExportClassPrimitive: {
221 const RSExportPrimitiveType *EPT =
222 static_cast<const RSExportPrimitiveType *>(ET);
223 if (EPT->isRSObjectType())
224 return "null";
225 else if (EPT->getType() == DataTypeBoolean)
226 return "false";
227 else
228 return "0";
229 break;
230 }
231 case RSExportType::ExportClassPointer:
232 case RSExportType::ExportClassVector:
233 case RSExportType::ExportClassMatrix:
234 case RSExportType::ExportClassConstantArray:
235 case RSExportType::ExportClassRecord: {
236 return "null";
237 break;
238 }
239 default: { slangAssert(false && "Unknown class of type"); }
240 }
241 return "";
242 }
243
GetBuiltinElementConstruct(const RSExportType * ET)244 static std::string GetBuiltinElementConstruct(const RSExportType *ET) {
245 if (ET->getClass() == RSExportType::ExportClassPrimitive) {
246 return std::string("Element.") + ET->getElementName();
247 } else if (ET->getClass() == RSExportType::ExportClassVector) {
248 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
249 if (EVT->getType() == DataTypeFloat32) {
250 if (EVT->getNumElement() == 2) {
251 return "Element.F32_2";
252 } else if (EVT->getNumElement() == 3) {
253 return "Element.F32_3";
254 } else if (EVT->getNumElement() == 4) {
255 return "Element.F32_4";
256 } else {
257 slangAssert(false && "Vectors should be size 2, 3, 4");
258 }
259 } else if (EVT->getType() == DataTypeUnsigned8) {
260 if (EVT->getNumElement() == 4)
261 return "Element.U8_4";
262 }
263 } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
264 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET);
265 switch (EMT->getDim()) {
266 case 2:
267 return "Element.MATRIX_2X2";
268 case 3:
269 return "Element.MATRIX_3X3";
270 case 4:
271 return "Element.MATRIX_4X4";
272 default:
273 slangAssert(false && "Unsupported dimension of matrix");
274 }
275 }
276 // RSExportType::ExportClassPointer can't be generated in a struct.
277
278 return "";
279 }
280
281 /********************** Methods to generate script class **********************/
RSReflectionJava(const RSContext * Context,std::vector<std::string> * GeneratedFileNames,const std::string & OutputBaseDirectory,const std::string & RSSourceFileName,const std::string & BitCodeFileName,bool EmbedBitcodeInJava)282 RSReflectionJava::RSReflectionJava(const RSContext *Context,
283 std::vector<std::string> *GeneratedFileNames,
284 const std::string &OutputBaseDirectory,
285 const std::string &RSSourceFileName,
286 const std::string &BitCodeFileName,
287 bool EmbedBitcodeInJava)
288 : mRSContext(Context), mPackageName(Context->getReflectJavaPackageName()),
289 mRSPackageName(Context->getRSPackageName()),
290 mOutputBaseDirectory(OutputBaseDirectory),
291 mRSSourceFileName(RSSourceFileName), mBitCodeFileName(BitCodeFileName),
292 mResourceId(RSSlangReflectUtils::JavaClassNameFromRSFileName(
293 mBitCodeFileName.c_str())),
294 mScriptClassName(RS_SCRIPT_CLASS_NAME_PREFIX +
295 RSSlangReflectUtils::JavaClassNameFromRSFileName(
296 mRSSourceFileName.c_str())),
297 mEmbedBitcodeInJava(EmbedBitcodeInJava), mNextExportVarSlot(0),
298 mNextExportFuncSlot(0), mNextExportForEachSlot(0), mLastError(""),
299 mGeneratedFileNames(GeneratedFileNames), mFieldIndex(0) {
300 slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames");
301 slangAssert(!mPackageName.empty() && mPackageName != "-");
302
303 mOutputDirectory = RSSlangReflectUtils::ComputePackagedPath(
304 OutputBaseDirectory.c_str(), mPackageName.c_str()) +
305 OS_PATH_SEPARATOR_STR;
306
307 // mElement.getBytesSize only exists on JB+
308 if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) {
309 mItemSizeof = RS_TYPE_ITEM_SIZEOF_CURRENT;
310 } else {
311 mItemSizeof = RS_TYPE_ITEM_SIZEOF_LEGACY;
312 }
313 }
314
genScriptClass(const std::string & ClassName,std::string & ErrorMsg)315 bool RSReflectionJava::genScriptClass(const std::string &ClassName,
316 std::string &ErrorMsg) {
317 if (!startClass(AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
318 ErrorMsg))
319 return false;
320
321 genScriptClassConstructor();
322
323 // Reflect export variable
324 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
325 E = mRSContext->export_vars_end();
326 I != E; I++)
327 genExportVariable(*I);
328
329 // Reflect export for each functions (only available on ICS+)
330 if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) {
331 for (RSContext::const_export_foreach_iterator
332 I = mRSContext->export_foreach_begin(),
333 E = mRSContext->export_foreach_end();
334 I != E; I++)
335 genExportForEach(*I);
336 }
337
338 // Reflect export function
339 for (RSContext::const_export_func_iterator
340 I = mRSContext->export_funcs_begin(),
341 E = mRSContext->export_funcs_end();
342 I != E; I++)
343 genExportFunction(*I);
344
345 endClass();
346
347 return true;
348 }
349
genScriptClassConstructor()350 void RSReflectionJava::genScriptClassConstructor() {
351 std::string className(RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName(
352 mRSSourceFileName.c_str()));
353 // Provide a simple way to reference this object.
354 mOut.indent() << "private static final String " RS_RESOURCE_NAME " = \""
355 << getResourceId() << "\";\n";
356
357 // Generate a simple constructor with only a single parameter (the rest
358 // can be inferred from information we already have).
359 mOut.indent() << "// Constructor\n";
360 startFunction(AM_Public, false, nullptr, getClassName(), 1, "RenderScript",
361 "rs");
362
363 if (getEmbedBitcodeInJava()) {
364 // Call new single argument Java-only constructor
365 mOut.indent() << "super(rs,\n";
366 mOut.indent() << " " << RS_RESOURCE_NAME ",\n";
367 mOut.indent() << " " << className << ".getBitCode32(),\n";
368 mOut.indent() << " " << className << ".getBitCode64());\n";
369 } else {
370 // Call alternate constructor with required parameters.
371 // Look up the proper raw bitcode resource id via the context.
372 mOut.indent() << "this(rs,\n";
373 mOut.indent() << " rs.getApplicationContext().getResources(),\n";
374 mOut.indent() << " rs.getApplicationContext().getResources()."
375 "getIdentifier(\n";
376 mOut.indent() << " " RS_RESOURCE_NAME ", \"raw\",\n";
377 mOut.indent()
378 << " rs.getApplicationContext().getPackageName()));\n";
379 endFunction();
380
381 // Alternate constructor (legacy) with 3 original parameters.
382 startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript",
383 "rs", "Resources", "resources", "int", "id");
384 // Call constructor of super class
385 mOut.indent() << "super(rs, resources, id);\n";
386 }
387
388 // If an exported variable has initial value, reflect it
389
390 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
391 E = mRSContext->export_vars_end();
392 I != E; I++) {
393 const RSExportVar *EV = *I;
394 if (!EV->getInit().isUninit()) {
395 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
396 } else if (EV->getArraySize()) {
397 // Always create an initial zero-init array object.
398 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new "
399 << GetTypeName(EV->getType(), false) << "["
400 << EV->getArraySize() << "];\n";
401 size_t NumInits = EV->getNumInits();
402 const RSExportConstantArrayType *ECAT =
403 static_cast<const RSExportConstantArrayType *>(EV->getType());
404 const RSExportType *ET = ECAT->getElementType();
405 for (size_t i = 0; i < NumInits; i++) {
406 std::stringstream Name;
407 Name << EV->getName() << "[" << i << "]";
408 genInitExportVariable(ET, Name.str(), EV->getInitArray(i));
409 }
410 }
411 if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) {
412 genTypeInstance(EV->getType());
413 }
414 genFieldPackerInstance(EV->getType());
415 }
416
417 for (RSContext::const_export_foreach_iterator
418 I = mRSContext->export_foreach_begin(),
419 E = mRSContext->export_foreach_end();
420 I != E; I++) {
421 const RSExportForEach *EF = *I;
422
423 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
424 for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
425 BI != EI; BI++) {
426
427 if (*BI != nullptr) {
428 genTypeInstanceFromPointer(*BI);
429 }
430 }
431
432 const RSExportType *OET = EF->getOutType();
433 if (OET) {
434 genTypeInstanceFromPointer(OET);
435 }
436 }
437
438 endFunction();
439
440 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
441 E = mTypesToCheck.end();
442 I != E; I++) {
443 mOut.indent() << "private Element " RS_ELEM_PREFIX << *I << ";\n";
444 }
445
446 for (std::set<std::string>::iterator I = mFieldPackerTypes.begin(),
447 E = mFieldPackerTypes.end();
448 I != E; I++) {
449 mOut.indent() << "private FieldPacker " RS_FP_PREFIX << *I << ";\n";
450 }
451 }
452
genInitBoolExportVariable(const std::string & VarName,const clang::APValue & Val)453 void RSReflectionJava::genInitBoolExportVariable(const std::string &VarName,
454 const clang::APValue &Val) {
455 slangAssert(!Val.isUninit() && "Not a valid initializer");
456 slangAssert((Val.getKind() == clang::APValue::Int) &&
457 "Bool type has wrong initial APValue");
458
459 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
460
461 mOut << ((Val.getInt().getSExtValue() == 0) ? "false" : "true") << ";\n";
462 }
463
464 void
genInitPrimitiveExportVariable(const std::string & VarName,const clang::APValue & Val)465 RSReflectionJava::genInitPrimitiveExportVariable(const std::string &VarName,
466 const clang::APValue &Val) {
467 slangAssert(!Val.isUninit() && "Not a valid initializer");
468
469 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
470 genInitValue(Val, false);
471 mOut << ";\n";
472 }
473
genInitExportVariable(const RSExportType * ET,const std::string & VarName,const clang::APValue & Val)474 void RSReflectionJava::genInitExportVariable(const RSExportType *ET,
475 const std::string &VarName,
476 const clang::APValue &Val) {
477 slangAssert(!Val.isUninit() && "Not a valid initializer");
478
479 switch (ET->getClass()) {
480 case RSExportType::ExportClassPrimitive: {
481 const RSExportPrimitiveType *EPT =
482 static_cast<const RSExportPrimitiveType *>(ET);
483 if (EPT->getType() == DataTypeBoolean) {
484 genInitBoolExportVariable(VarName, Val);
485 } else {
486 genInitPrimitiveExportVariable(VarName, Val);
487 }
488 break;
489 }
490 case RSExportType::ExportClassPointer: {
491 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
492 std::cout << "Initializer which is non-NULL to pointer type variable "
493 "will be ignored\n";
494 break;
495 }
496 case RSExportType::ExportClassVector: {
497 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
498 switch (Val.getKind()) {
499 case clang::APValue::Int:
500 case clang::APValue::Float: {
501 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
502 std::string Name = VarName + "." + GetVectorAccessor(i);
503 genInitPrimitiveExportVariable(Name, Val);
504 }
505 break;
506 }
507 case clang::APValue::Vector: {
508 std::stringstream VecName;
509 VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
510 << EVT->getNumElement();
511 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
512 << VecName.str() << "();\n";
513
514 unsigned NumElements = std::min(
515 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
516 for (unsigned i = 0; i < NumElements; i++) {
517 const clang::APValue &ElementVal = Val.getVectorElt(i);
518 std::string Name = VarName + "." + GetVectorAccessor(i);
519 genInitPrimitiveExportVariable(Name, ElementVal);
520 }
521 break;
522 }
523 case clang::APValue::MemberPointer:
524 case clang::APValue::Uninitialized:
525 case clang::APValue::ComplexInt:
526 case clang::APValue::ComplexFloat:
527 case clang::APValue::LValue:
528 case clang::APValue::Array:
529 case clang::APValue::Struct:
530 case clang::APValue::Union:
531 case clang::APValue::AddrLabelDiff: {
532 slangAssert(false && "Unexpected type of value of initializer.");
533 }
534 }
535 break;
536 }
537 // TODO(zonr): Resolving initializer of a record (and matrix) type variable
538 // is complex. It cannot obtain by just simply evaluating the initializer
539 // expression.
540 case RSExportType::ExportClassMatrix:
541 case RSExportType::ExportClassConstantArray:
542 case RSExportType::ExportClassRecord: {
543 #if 0
544 unsigned InitIndex = 0;
545 const RSExportRecordType *ERT =
546 static_cast<const RSExportRecordType*>(ET);
547
548 slangAssert((Val.getKind() == clang::APValue::Vector) &&
549 "Unexpected type of initializer for record type variable");
550
551 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName
552 << " = new " << ERT->getElementName()
553 << "." RS_TYPE_ITEM_CLASS_NAME"();\n";
554
555 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
556 E = ERT->fields_end();
557 I != E;
558 I++) {
559 const RSExportRecordType::Field *F = *I;
560 std::string FieldName = VarName + "." + F->getName();
561
562 if (InitIndex > Val.getVectorLength())
563 break;
564
565 genInitPrimitiveExportVariable(FieldName,
566 Val.getVectorElt(InitIndex++));
567 }
568 #endif
569 slangAssert(false && "Unsupported initializer for record/matrix/constant "
570 "array type variable currently");
571 break;
572 }
573 default: { slangAssert(false && "Unknown class of type"); }
574 }
575 }
576
genExportVariable(const RSExportVar * EV)577 void RSReflectionJava::genExportVariable(const RSExportVar *EV) {
578 const RSExportType *ET = EV->getType();
579
580 mOut.indent() << "private final static int " << RS_EXPORT_VAR_INDEX_PREFIX
581 << EV->getName() << " = " << getNextExportVarSlot() << ";\n";
582
583 switch (ET->getClass()) {
584 case RSExportType::ExportClassPrimitive: {
585 genPrimitiveTypeExportVariable(EV);
586 break;
587 }
588 case RSExportType::ExportClassPointer: {
589 genPointerTypeExportVariable(EV);
590 break;
591 }
592 case RSExportType::ExportClassVector: {
593 genVectorTypeExportVariable(EV);
594 break;
595 }
596 case RSExportType::ExportClassMatrix: {
597 genMatrixTypeExportVariable(EV);
598 break;
599 }
600 case RSExportType::ExportClassConstantArray: {
601 genConstantArrayTypeExportVariable(EV);
602 break;
603 }
604 case RSExportType::ExportClassRecord: {
605 genRecordTypeExportVariable(EV);
606 break;
607 }
608 default: { slangAssert(false && "Unknown class of type"); }
609 }
610 }
611
genExportFunction(const RSExportFunc * EF)612 void RSReflectionJava::genExportFunction(const RSExportFunc *EF) {
613 mOut.indent() << "private final static int " << RS_EXPORT_FUNC_INDEX_PREFIX
614 << EF->getName() << " = " << getNextExportFuncSlot() << ";\n";
615
616 // invoke_*()
617 ArgTy Args;
618
619 if (EF->hasParam()) {
620 for (RSExportFunc::const_param_iterator I = EF->params_begin(),
621 E = EF->params_end();
622 I != E; I++) {
623 Args.push_back(
624 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
625 }
626 }
627
628 if (mRSContext->getTargetAPI() >= SLANG_M_TARGET_API) {
629 startFunction(AM_Public, false, "Script.InvokeID",
630 "getInvokeID_" + EF->getName(), 0);
631
632 mOut.indent() << "return createInvokeID(" << RS_EXPORT_FUNC_INDEX_PREFIX
633 << EF->getName() << ");\n";
634
635 endFunction();
636 }
637
638 startFunction(AM_Public, false, "void",
639 "invoke_" + EF->getName(/*Mangle=*/false),
640 // We are using un-mangled name since Java
641 // supports method overloading.
642 Args);
643
644 if (!EF->hasParam()) {
645 mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
646 << ");\n";
647 } else {
648 const RSExportRecordType *ERT = EF->getParamPacketType();
649 std::string FieldPackerName = EF->getName() + "_fp";
650
651 if (genCreateFieldPacker(ERT, FieldPackerName.c_str()))
652 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
653
654 mOut.indent() << "invoke(" << RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName()
655 << ", " << FieldPackerName << ");\n";
656 }
657
658 endFunction();
659 }
660
genPairwiseDimCheck(std::string name0,std::string name1)661 void RSReflectionJava::genPairwiseDimCheck(std::string name0,
662 std::string name1) {
663
664 mOut.indent() << "// Verify dimensions\n";
665 mOut.indent() << "t0 = " << name0 << ".getType();\n";
666 mOut.indent() << "t1 = " << name1 << ".getType();\n";
667 mOut.indent() << "if ((t0.getCount() != t1.getCount()) ||\n";
668 mOut.indent() << " (t0.getX() != t1.getX()) ||\n";
669 mOut.indent() << " (t0.getY() != t1.getY()) ||\n";
670 mOut.indent() << " (t0.getZ() != t1.getZ()) ||\n";
671 mOut.indent() << " (t0.hasFaces() != t1.hasFaces()) ||\n";
672 mOut.indent() << " (t0.hasMipmaps() != t1.hasMipmaps())) {\n";
673 mOut.indent() << " throw new RSRuntimeException(\"Dimension mismatch "
674 << "between parameters " << name0 << " and " << name1
675 << "!\");\n";
676 mOut.indent() << "}\n\n";
677 }
678
genExportForEach(const RSExportForEach * EF)679 void RSReflectionJava::genExportForEach(const RSExportForEach *EF) {
680 if (EF->isDummyRoot()) {
681 // Skip reflection for dummy root() kernels. Note that we have to
682 // advance the next slot number for ForEach, however.
683 mOut.indent() << "//private final static int "
684 << RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName() << " = "
685 << getNextExportForEachSlot() << ";\n";
686 return;
687 }
688
689 mOut.indent() << "private final static int " << RS_EXPORT_FOREACH_INDEX_PREFIX
690 << EF->getName() << " = " << getNextExportForEachSlot()
691 << ";\n";
692
693 // forEach_*()
694 ArgTy Args;
695 bool HasAllocation = false; // at least one in/out allocation?
696
697 const RSExportForEach::InVec &Ins = EF->getIns();
698 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
699 const RSExportType *OET = EF->getOutType();
700
701 if (Ins.size() == 1) {
702 HasAllocation = true;
703 Args.push_back(std::make_pair("Allocation", "ain"));
704
705 } else if (Ins.size() > 1) {
706 HasAllocation = true;
707 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
708 BI++) {
709
710 Args.push_back(std::make_pair("Allocation",
711 "ain_" + (*BI)->getName().str()));
712 }
713 }
714
715 if (EF->hasOut() || EF->hasReturn()) {
716 HasAllocation = true;
717 Args.push_back(std::make_pair("Allocation", "aout"));
718 }
719
720 const RSExportRecordType *ERT = EF->getParamPacketType();
721 if (ERT) {
722 for (RSExportForEach::const_param_iterator I = EF->params_begin(),
723 E = EF->params_end();
724 I != E; I++) {
725 Args.push_back(
726 std::make_pair(GetTypeName((*I)->getType()), (*I)->getName()));
727 }
728 }
729
730 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
731 startFunction(AM_Public, false, "Script.KernelID",
732 "getKernelID_" + EF->getName(), 0);
733
734 // TODO: add element checking
735 mOut.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX
736 << EF->getName() << ", " << EF->getSignatureMetadata()
737 << ", null, null);\n";
738
739 endFunction();
740 }
741
742 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
743 if (HasAllocation) {
744 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
745
746 mOut.indent() << "forEach_" << EF->getName();
747 mOut << "(";
748
749 if (Ins.size() == 1) {
750 mOut << "ain, ";
751
752 } else if (Ins.size() > 1) {
753 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end(); BI != EI;
754 BI++) {
755
756 mOut << "ain_" << (*BI)->getName().str() << ", ";
757 }
758 }
759
760 if (EF->hasOut() || EF->hasReturn()) {
761 mOut << "aout, ";
762 }
763
764 if (EF->hasUsrData()) {
765 mOut << Args.back().second << ", ";
766 }
767
768 // No clipped bounds to pass in.
769 mOut << "null);\n";
770
771 endFunction();
772 }
773
774 // Add the clipped kernel parameters to the Args list.
775 Args.push_back(std::make_pair("Script.LaunchOptions", "sc"));
776 }
777
778 startFunction(AM_Public, false, "void", "forEach_" + EF->getName(), Args);
779
780 if (InTypes.size() == 1) {
781 if (InTypes.front() != nullptr) {
782 genTypeCheck(InTypes.front(), "ain");
783 }
784
785 } else if (InTypes.size() > 1) {
786 size_t Index = 0;
787 for (RSExportForEach::InTypeIter BI = InTypes.begin(), EI = InTypes.end();
788 BI != EI; BI++, ++Index) {
789
790 if (*BI != nullptr) {
791 genTypeCheck(*BI, ("ain_" + Ins[Index]->getName()).str().c_str());
792 }
793 }
794 }
795
796 if (OET) {
797 genTypeCheck(OET, "aout");
798 }
799
800 if (Ins.size() == 1 && (EF->hasOut() || EF->hasReturn())) {
801 mOut.indent() << "Type t0, t1;";
802 genPairwiseDimCheck("ain", "aout");
803
804 } else if (Ins.size() > 1) {
805 mOut.indent() << "Type t0, t1;";
806
807 std::string In0Name = "ain_" + Ins[0]->getName().str();
808
809 for (size_t index = 1; index < Ins.size(); ++index) {
810 genPairwiseDimCheck(In0Name, "ain_" + Ins[index]->getName().str());
811 }
812
813 if (EF->hasOut() || EF->hasReturn()) {
814 genPairwiseDimCheck(In0Name, "aout");
815 }
816 }
817
818 std::string FieldPackerName = EF->getName() + "_fp";
819 if (ERT) {
820 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
821 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
822 }
823 }
824 mOut.indent() << "forEach(" << RS_EXPORT_FOREACH_INDEX_PREFIX
825 << EF->getName();
826
827 if (Ins.size() == 1) {
828 mOut << ", ain";
829 } else if (Ins.size() > 1) {
830 mOut << ", new Allocation[]{ain_" << Ins[0]->getName().str();
831
832 for (size_t index = 1; index < Ins.size(); ++index) {
833 mOut << ", ain_" << Ins[index]->getName().str();
834 }
835
836 mOut << "}";
837
838 } else {
839 mOut << ", (Allocation) null";
840 }
841
842 if (EF->hasOut() || EF->hasReturn())
843 mOut << ", aout";
844 else
845 mOut << ", null";
846
847 if (EF->hasUsrData())
848 mOut << ", " << FieldPackerName;
849 else
850 mOut << ", null";
851
852 if (mRSContext->getTargetAPI() >= SLANG_JB_MR2_TARGET_API) {
853 mOut << ", sc);\n";
854 } else {
855 mOut << ");\n";
856 }
857
858 endFunction();
859 }
860
genTypeInstanceFromPointer(const RSExportType * ET)861 void RSReflectionJava::genTypeInstanceFromPointer(const RSExportType *ET) {
862 if (ET->getClass() == RSExportType::ExportClassPointer) {
863 // For pointer parameters to original forEach kernels.
864 const RSExportPointerType *EPT =
865 static_cast<const RSExportPointerType *>(ET);
866 genTypeInstance(EPT->getPointeeType());
867 } else {
868 // For handling pass-by-value kernel parameters.
869 genTypeInstance(ET);
870 }
871 }
872
genTypeInstance(const RSExportType * ET)873 void RSReflectionJava::genTypeInstance(const RSExportType *ET) {
874 switch (ET->getClass()) {
875 case RSExportType::ExportClassPrimitive:
876 case RSExportType::ExportClassVector:
877 case RSExportType::ExportClassConstantArray: {
878 std::string TypeName = ET->getElementName();
879 if (addTypeNameForElement(TypeName)) {
880 mOut.indent() << RS_ELEM_PREFIX << TypeName << " = Element." << TypeName
881 << "(rs);\n";
882 }
883 break;
884 }
885
886 case RSExportType::ExportClassRecord: {
887 std::string ClassName = ET->getElementName();
888 if (addTypeNameForElement(ClassName)) {
889 mOut.indent() << RS_ELEM_PREFIX << ClassName << " = " << ClassName
890 << ".createElement(rs);\n";
891 }
892 break;
893 }
894
895 default:
896 break;
897 }
898 }
899
genFieldPackerInstance(const RSExportType * ET)900 void RSReflectionJava::genFieldPackerInstance(const RSExportType *ET) {
901 switch (ET->getClass()) {
902 case RSExportType::ExportClassPrimitive:
903 case RSExportType::ExportClassVector:
904 case RSExportType::ExportClassConstantArray:
905 case RSExportType::ExportClassRecord: {
906 std::string TypeName = ET->getElementName();
907 addTypeNameForFieldPacker(TypeName);
908 break;
909 }
910
911 default:
912 break;
913 }
914 }
915
genTypeCheck(const RSExportType * ET,const char * VarName)916 void RSReflectionJava::genTypeCheck(const RSExportType *ET,
917 const char *VarName) {
918 mOut.indent() << "// check " << VarName << "\n";
919
920 if (ET->getClass() == RSExportType::ExportClassPointer) {
921 const RSExportPointerType *EPT =
922 static_cast<const RSExportPointerType *>(ET);
923 ET = EPT->getPointeeType();
924 }
925
926 std::string TypeName;
927
928 switch (ET->getClass()) {
929 case RSExportType::ExportClassPrimitive:
930 case RSExportType::ExportClassVector:
931 case RSExportType::ExportClassRecord: {
932 TypeName = ET->getElementName();
933 break;
934 }
935
936 default:
937 break;
938 }
939
940 if (!TypeName.empty()) {
941 mOut.indent() << "if (!" << VarName
942 << ".getType().getElement().isCompatible(" RS_ELEM_PREFIX
943 << TypeName << ")) {\n";
944 mOut.indent() << " throw new RSRuntimeException(\"Type mismatch with "
945 << TypeName << "!\");\n";
946 mOut.indent() << "}\n";
947 }
948 }
949
genPrimitiveTypeExportVariable(const RSExportVar * EV)950 void RSReflectionJava::genPrimitiveTypeExportVariable(const RSExportVar *EV) {
951 slangAssert(
952 (EV->getType()->getClass() == RSExportType::ExportClassPrimitive) &&
953 "Variable should be type of primitive here");
954
955 const RSExportPrimitiveType *EPT =
956 static_cast<const RSExportPrimitiveType *>(EV->getType());
957 std::string TypeName = GetTypeName(EPT);
958 std::string VarName = EV->getName();
959
960 genPrivateExportVariable(TypeName, EV->getName());
961
962 if (EV->isConst()) {
963 mOut.indent() << "public final static " << TypeName
964 << " " RS_EXPORT_VAR_CONST_PREFIX << VarName << " = ";
965 const clang::APValue &Val = EV->getInit();
966 genInitValue(Val, EPT->getType() == DataTypeBoolean);
967 mOut << ";\n";
968 } else {
969 // set_*()
970 // This must remain synchronized, since multiple Dalvik threads may
971 // be calling setters.
972 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
973 TypeName.c_str(), "v");
974 if ((EPT->getSize() < 4) || EV->isUnsigned()) {
975 // We create/cache a per-type FieldPacker. This allows us to reuse the
976 // validation logic (for catching negative inputs from Dalvik, as well
977 // as inputs that are too large to be represented in the unsigned type).
978 // Sub-integer types are also handled specially here, so that we don't
979 // overwrite bytes accidentally.
980 std::string ElemName = EPT->getElementName();
981 std::string FPName;
982 FPName = RS_FP_PREFIX + ElemName;
983 mOut.indent() << "if (" << FPName << "!= null) {\n";
984 mOut.increaseIndent();
985 mOut.indent() << FPName << ".reset();\n";
986 mOut.decreaseIndent();
987 mOut.indent() << "} else {\n";
988 mOut.increaseIndent();
989 mOut.indent() << FPName << " = new FieldPacker(" << EPT->getSize()
990 << ");\n";
991 mOut.decreaseIndent();
992 mOut.indent() << "}\n";
993
994 genPackVarOfType(EPT, "v", FPName.c_str());
995 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
996 << ", " << FPName << ");\n";
997 } else {
998 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
999 << ", v);\n";
1000 }
1001
1002 // Dalvik update comes last, since the input may be invalid (and hence
1003 // throw an exception).
1004 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
1005
1006 endFunction();
1007 }
1008
1009 genGetExportVariable(TypeName, VarName);
1010 genGetFieldID(VarName);
1011 }
1012
genInitValue(const clang::APValue & Val,bool asBool)1013 void RSReflectionJava::genInitValue(const clang::APValue &Val, bool asBool) {
1014 switch (Val.getKind()) {
1015 case clang::APValue::Int: {
1016 llvm::APInt api = Val.getInt();
1017 if (asBool) {
1018 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
1019 } else {
1020 // TODO: Handle unsigned correctly
1021 mOut << api.getSExtValue();
1022 if (api.getBitWidth() > 32) {
1023 mOut << "L";
1024 }
1025 }
1026 break;
1027 }
1028
1029 case clang::APValue::Float: {
1030 llvm::APFloat apf = Val.getFloat();
1031 llvm::SmallString<30> s;
1032 apf.toString(s);
1033 mOut << s.c_str();
1034 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
1035 if (s.count('.') == 0) {
1036 mOut << ".f";
1037 } else {
1038 mOut << "f";
1039 }
1040 }
1041 break;
1042 }
1043
1044 case clang::APValue::ComplexInt:
1045 case clang::APValue::ComplexFloat:
1046 case clang::APValue::LValue:
1047 case clang::APValue::Vector: {
1048 slangAssert(false && "Primitive type cannot have such kind of initializer");
1049 break;
1050 }
1051
1052 default: { slangAssert(false && "Unknown kind of initializer"); }
1053 }
1054 }
1055
genPointerTypeExportVariable(const RSExportVar * EV)1056 void RSReflectionJava::genPointerTypeExportVariable(const RSExportVar *EV) {
1057 const RSExportType *ET = EV->getType();
1058 const RSExportType *PointeeType;
1059
1060 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
1061 "Variable should be type of pointer here");
1062
1063 PointeeType = static_cast<const RSExportPointerType *>(ET)->getPointeeType();
1064 std::string TypeName = GetTypeName(ET);
1065 std::string VarName = EV->getName();
1066
1067 genPrivateExportVariable(TypeName, VarName);
1068
1069 // bind_*()
1070 startFunction(AM_Public, false, "void", "bind_" + VarName, 1,
1071 TypeName.c_str(), "v");
1072
1073 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
1074 mOut.indent() << "if (v == null) bindAllocation(null, "
1075 << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n";
1076
1077 if (PointeeType->getClass() == RSExportType::ExportClassRecord) {
1078 mOut.indent() << "else bindAllocation(v.getAllocation(), "
1079 << RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");\n";
1080 } else {
1081 mOut.indent() << "else bindAllocation(v, " << RS_EXPORT_VAR_INDEX_PREFIX
1082 << VarName << ");\n";
1083 }
1084
1085 endFunction();
1086
1087 genGetExportVariable(TypeName, VarName);
1088 }
1089
genVectorTypeExportVariable(const RSExportVar * EV)1090 void RSReflectionJava::genVectorTypeExportVariable(const RSExportVar *EV) {
1091 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
1092 "Variable should be type of vector here");
1093
1094 std::string TypeName = GetTypeName(EV->getType());
1095 std::string VarName = EV->getName();
1096
1097 genPrivateExportVariable(TypeName, VarName);
1098 genSetExportVariable(TypeName, EV);
1099 genGetExportVariable(TypeName, VarName);
1100 genGetFieldID(VarName);
1101 }
1102
genMatrixTypeExportVariable(const RSExportVar * EV)1103 void RSReflectionJava::genMatrixTypeExportVariable(const RSExportVar *EV) {
1104 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) &&
1105 "Variable should be type of matrix here");
1106
1107 const RSExportType *ET = EV->getType();
1108 std::string TypeName = GetTypeName(ET);
1109 std::string VarName = EV->getName();
1110
1111 genPrivateExportVariable(TypeName, VarName);
1112
1113 // set_*()
1114 if (!EV->isConst()) {
1115 const char *FieldPackerName = "fp";
1116 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
1117 TypeName.c_str(), "v");
1118 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
1119
1120 if (genCreateFieldPacker(ET, FieldPackerName))
1121 genPackVarOfType(ET, "v", FieldPackerName);
1122 mOut.indent() << "setVar(" RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", "
1123 << FieldPackerName << ");\n";
1124
1125 endFunction();
1126 }
1127
1128 genGetExportVariable(TypeName, VarName);
1129 genGetFieldID(VarName);
1130 }
1131
1132 void
genConstantArrayTypeExportVariable(const RSExportVar * EV)1133 RSReflectionJava::genConstantArrayTypeExportVariable(const RSExportVar *EV) {
1134 slangAssert(
1135 (EV->getType()->getClass() == RSExportType::ExportClassConstantArray) &&
1136 "Variable should be type of constant array here");
1137
1138 std::string TypeName = GetTypeName(EV->getType());
1139 std::string VarName = EV->getName();
1140
1141 genPrivateExportVariable(TypeName, VarName);
1142 genSetExportVariable(TypeName, EV);
1143 genGetExportVariable(TypeName, VarName);
1144 genGetFieldID(VarName);
1145 }
1146
genRecordTypeExportVariable(const RSExportVar * EV)1147 void RSReflectionJava::genRecordTypeExportVariable(const RSExportVar *EV) {
1148 slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
1149 "Variable should be type of struct here");
1150
1151 std::string TypeName = GetTypeName(EV->getType());
1152 std::string VarName = EV->getName();
1153
1154 genPrivateExportVariable(TypeName, VarName);
1155 genSetExportVariable(TypeName, EV);
1156 genGetExportVariable(TypeName, VarName);
1157 genGetFieldID(VarName);
1158 }
1159
genPrivateExportVariable(const std::string & TypeName,const std::string & VarName)1160 void RSReflectionJava::genPrivateExportVariable(const std::string &TypeName,
1161 const std::string &VarName) {
1162 mOut.indent() << "private " << TypeName << " " << RS_EXPORT_VAR_PREFIX
1163 << VarName << ";\n";
1164 }
1165
genSetExportVariable(const std::string & TypeName,const RSExportVar * EV)1166 void RSReflectionJava::genSetExportVariable(const std::string &TypeName,
1167 const RSExportVar *EV) {
1168 if (!EV->isConst()) {
1169 const char *FieldPackerName = "fp";
1170 std::string VarName = EV->getName();
1171 const RSExportType *ET = EV->getType();
1172 startFunction(AM_PublicSynchronized, false, "void", "set_" + VarName, 1,
1173 TypeName.c_str(), "v");
1174 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
1175
1176 if (genCreateFieldPacker(ET, FieldPackerName))
1177 genPackVarOfType(ET, "v", FieldPackerName);
1178
1179 if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) {
1180 // Legacy apps must use the old setVar() without Element/dim components.
1181 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
1182 << ", " << FieldPackerName << ");\n";
1183 } else {
1184 // We only have support for one-dimensional array reflection today,
1185 // but the entry point (i.e. setVar()) takes an array of dimensions.
1186 mOut.indent() << "int []__dimArr = new int[1];\n";
1187 mOut.indent() << "__dimArr[0] = " << ET->getSize() << ";\n";
1188 mOut.indent() << "setVar(" << RS_EXPORT_VAR_INDEX_PREFIX << VarName
1189 << ", " << FieldPackerName << ", " << RS_ELEM_PREFIX
1190 << ET->getElementName() << ", __dimArr);\n";
1191 }
1192
1193 endFunction();
1194 }
1195 }
1196
genGetExportVariable(const std::string & TypeName,const std::string & VarName)1197 void RSReflectionJava::genGetExportVariable(const std::string &TypeName,
1198 const std::string &VarName) {
1199 startFunction(AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
1200
1201 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
1202
1203 endFunction();
1204 }
1205
genGetFieldID(const std::string & VarName)1206 void RSReflectionJava::genGetFieldID(const std::string &VarName) {
1207 // We only generate getFieldID_*() for non-Pointer (bind) types.
1208 if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
1209 startFunction(AM_Public, false, "Script.FieldID", "getFieldID_" + VarName,
1210 0);
1211
1212 mOut.indent() << "return createFieldID(" << RS_EXPORT_VAR_INDEX_PREFIX
1213 << VarName << ", null);\n";
1214
1215 endFunction();
1216 }
1217 }
1218
1219 /******************* Methods to generate script class /end *******************/
1220
genCreateFieldPacker(const RSExportType * ET,const char * FieldPackerName)1221 bool RSReflectionJava::genCreateFieldPacker(const RSExportType *ET,
1222 const char *FieldPackerName) {
1223 size_t AllocSize = ET->getAllocSize();
1224 if (AllocSize > 0)
1225 mOut.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
1226 << AllocSize << ");\n";
1227 else
1228 return false;
1229 return true;
1230 }
1231
genPackVarOfType(const RSExportType * ET,const char * VarName,const char * FieldPackerName)1232 void RSReflectionJava::genPackVarOfType(const RSExportType *ET,
1233 const char *VarName,
1234 const char *FieldPackerName) {
1235 switch (ET->getClass()) {
1236 case RSExportType::ExportClassPrimitive:
1237 case RSExportType::ExportClassVector: {
1238 mOut.indent() << FieldPackerName << "."
1239 << GetPackerAPIName(
1240 static_cast<const RSExportPrimitiveType *>(ET)) << "("
1241 << VarName << ");\n";
1242 break;
1243 }
1244 case RSExportType::ExportClassPointer: {
1245 // Must reflect as type Allocation in Java
1246 const RSExportType *PointeeType =
1247 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
1248
1249 if (PointeeType->getClass() != RSExportType::ExportClassRecord) {
1250 mOut.indent() << FieldPackerName << ".addI32(" << VarName
1251 << ".getPtr());\n";
1252 } else {
1253 mOut.indent() << FieldPackerName << ".addI32(" << VarName
1254 << ".getAllocation().getPtr());\n";
1255 }
1256 break;
1257 }
1258 case RSExportType::ExportClassMatrix: {
1259 mOut.indent() << FieldPackerName << ".addMatrix(" << VarName << ");\n";
1260 break;
1261 }
1262 case RSExportType::ExportClassConstantArray: {
1263 const RSExportConstantArrayType *ECAT =
1264 static_cast<const RSExportConstantArrayType *>(ET);
1265
1266 // TODO(zonr): more elegant way. Currently, we obtain the unique index
1267 // variable (this method involves recursive call which means
1268 // we may have more than one level loop, therefore we can't
1269 // always use the same index variable name here) name given
1270 // in the for-loop from counting the '.' in @VarName.
1271 unsigned Level = 0;
1272 size_t LastDotPos = 0;
1273 std::string ElementVarName(VarName);
1274
1275 while (LastDotPos != std::string::npos) {
1276 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
1277 Level++;
1278 }
1279 std::string IndexVarName("ct");
1280 IndexVarName.append(llvm::utostr_32(Level));
1281
1282 mOut.indent() << "for (int " << IndexVarName << " = 0; " << IndexVarName
1283 << " < " << ECAT->getSize() << "; " << IndexVarName << "++)";
1284 mOut.startBlock();
1285
1286 ElementVarName.append("[" + IndexVarName + "]");
1287 genPackVarOfType(ECAT->getElementType(), ElementVarName.c_str(),
1288 FieldPackerName);
1289
1290 mOut.endBlock();
1291 break;
1292 }
1293 case RSExportType::ExportClassRecord: {
1294 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
1295 // Relative pos from now on in field packer
1296 unsigned Pos = 0;
1297
1298 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1299 E = ERT->fields_end();
1300 I != E; I++) {
1301 const RSExportRecordType::Field *F = *I;
1302 std::string FieldName;
1303 size_t FieldOffset = F->getOffsetInParent();
1304 const RSExportType *T = F->getType();
1305 size_t FieldStoreSize = T->getStoreSize();
1306 size_t FieldAllocSize = T->getAllocSize();
1307
1308 if (VarName != nullptr)
1309 FieldName = VarName + ("." + F->getName());
1310 else
1311 FieldName = F->getName();
1312
1313 if (FieldOffset > Pos) {
1314 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
1315 << ");\n";
1316 }
1317
1318 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
1319
1320 // There is padding in the field type
1321 if (FieldAllocSize > FieldStoreSize) {
1322 mOut.indent() << FieldPackerName << ".skip("
1323 << (FieldAllocSize - FieldStoreSize) << ");\n";
1324 }
1325
1326 Pos = FieldOffset + FieldAllocSize;
1327 }
1328
1329 // There maybe some padding after the struct
1330 if (ERT->getAllocSize() > Pos) {
1331 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
1332 << ");\n";
1333 }
1334 break;
1335 }
1336 default: { slangAssert(false && "Unknown class of type"); }
1337 }
1338 }
1339
genAllocateVarOfType(const RSExportType * T,const std::string & VarName)1340 void RSReflectionJava::genAllocateVarOfType(const RSExportType *T,
1341 const std::string &VarName) {
1342 switch (T->getClass()) {
1343 case RSExportType::ExportClassPrimitive: {
1344 // Primitive type like int in Java has its own storage once it's declared.
1345 //
1346 // FIXME: Should we allocate storage for RS object?
1347 // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
1348 // mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n";
1349 break;
1350 }
1351 case RSExportType::ExportClassPointer: {
1352 // Pointer type is an instance of Allocation or a TypeClass whose value is
1353 // expected to be assigned by programmer later in Java program. Therefore
1354 // we don't reflect things like [VarName] = new Allocation();
1355 mOut.indent() << VarName << " = null;\n";
1356 break;
1357 }
1358 case RSExportType::ExportClassConstantArray: {
1359 const RSExportConstantArrayType *ECAT =
1360 static_cast<const RSExportConstantArrayType *>(T);
1361 const RSExportType *ElementType = ECAT->getElementType();
1362
1363 mOut.indent() << VarName << " = new " << GetTypeName(ElementType) << "["
1364 << ECAT->getSize() << "];\n";
1365
1366 // Primitive type element doesn't need allocation code.
1367 if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
1368 mOut.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize()
1369 << "; $ct++)";
1370 mOut.startBlock();
1371
1372 std::string ElementVarName(VarName);
1373 ElementVarName.append("[$ct]");
1374 genAllocateVarOfType(ElementType, ElementVarName);
1375
1376 mOut.endBlock();
1377 }
1378 break;
1379 }
1380 case RSExportType::ExportClassVector:
1381 case RSExportType::ExportClassMatrix:
1382 case RSExportType::ExportClassRecord: {
1383 mOut.indent() << VarName << " = new " << GetTypeName(T) << "();\n";
1384 break;
1385 }
1386 }
1387 }
1388
genNewItemBufferIfNull(const char * Index)1389 void RSReflectionJava::genNewItemBufferIfNull(const char *Index) {
1390 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME " == null) ";
1391 mOut << RS_TYPE_ITEM_BUFFER_NAME << " = new " << RS_TYPE_ITEM_CLASS_NAME
1392 << "[getType().getX() /* count */];\n";
1393 if (Index != nullptr) {
1394 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index
1395 << "] == null) ";
1396 mOut << RS_TYPE_ITEM_BUFFER_NAME << "[" << Index << "] = new "
1397 << RS_TYPE_ITEM_CLASS_NAME << "();\n";
1398 }
1399 }
1400
genNewItemBufferPackerIfNull()1401 void RSReflectionJava::genNewItemBufferPackerIfNull() {
1402 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " == null) ";
1403 mOut << RS_TYPE_ITEM_BUFFER_PACKER_NAME " = new FieldPacker("
1404 << mItemSizeof << " * getType().getX()/* count */);\n";
1405 }
1406
1407 /********************** Methods to generate type class **********************/
genTypeClass(const RSExportRecordType * ERT,std::string & ErrorMsg)1408 bool RSReflectionJava::genTypeClass(const RSExportRecordType *ERT,
1409 std::string &ErrorMsg) {
1410 std::string ClassName = ERT->getElementName();
1411 std::string superClassName = getRSPackageName();
1412 superClassName += RS_TYPE_CLASS_SUPER_CLASS_NAME;
1413
1414 if (!startClass(AM_Public, false, ClassName, superClassName.c_str(),
1415 ErrorMsg))
1416 return false;
1417
1418 mGeneratedFileNames->push_back(ClassName);
1419
1420 genTypeItemClass(ERT);
1421
1422 // Declare item buffer and item buffer packer
1423 mOut.indent() << "private " << RS_TYPE_ITEM_CLASS_NAME << " "
1424 << RS_TYPE_ITEM_BUFFER_NAME << "[];\n";
1425 mOut.indent() << "private FieldPacker " << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1426 << ";\n";
1427 mOut.indent() << "private static java.lang.ref.WeakReference<Element> "
1428 << RS_TYPE_ELEMENT_REF_NAME
1429 << " = new java.lang.ref.WeakReference<Element>(null);\n";
1430
1431 genTypeClassConstructor(ERT);
1432 genTypeClassCopyToArrayLocal(ERT);
1433 genTypeClassCopyToArray(ERT);
1434 genTypeClassItemSetter(ERT);
1435 genTypeClassItemGetter(ERT);
1436 genTypeClassComponentSetter(ERT);
1437 genTypeClassComponentGetter(ERT);
1438 genTypeClassCopyAll(ERT);
1439 if (!mRSContext->isCompatLib()) {
1440 // Skip the resize method if we are targeting a compatibility library.
1441 genTypeClassResize();
1442 }
1443
1444 endClass();
1445
1446 resetFieldIndex();
1447 clearFieldIndexMap();
1448
1449 return true;
1450 }
1451
genTypeItemClass(const RSExportRecordType * ERT)1452 void RSReflectionJava::genTypeItemClass(const RSExportRecordType *ERT) {
1453 mOut.indent() << "static public class " RS_TYPE_ITEM_CLASS_NAME;
1454 mOut.startBlock();
1455
1456 // Sizeof should not be exposed for 64-bit; it is not accurate
1457 if (mRSContext->getTargetAPI() < 21) {
1458 mOut.indent() << "public static final int sizeof = " << ERT->getAllocSize()
1459 << ";\n";
1460 }
1461
1462 // Member elements
1463 mOut << "\n";
1464 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1465 FE = ERT->fields_end();
1466 FI != FE; FI++) {
1467 mOut.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
1468 << ";\n";
1469 }
1470
1471 // Constructor
1472 mOut << "\n";
1473 mOut.indent() << RS_TYPE_ITEM_CLASS_NAME << "()";
1474 mOut.startBlock();
1475
1476 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1477 FE = ERT->fields_end();
1478 FI != FE; FI++) {
1479 const RSExportRecordType::Field *F = *FI;
1480 genAllocateVarOfType(F->getType(), F->getName());
1481 }
1482
1483 // end Constructor
1484 mOut.endBlock();
1485
1486 // end Item class
1487 mOut.endBlock();
1488 }
1489
genTypeClassConstructor(const RSExportRecordType * ERT)1490 void RSReflectionJava::genTypeClassConstructor(const RSExportRecordType *ERT) {
1491 const char *RenderScriptVar = "rs";
1492
1493 startFunction(AM_Public, true, "Element", "createElement", 1, "RenderScript",
1494 RenderScriptVar);
1495
1496 // TODO(all): Fix weak-refs + multi-context issue.
1497 // mOut.indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME
1498 // << ".get();\n";
1499 // mOut.indent() << "if (e != null) return e;\n";
1500 RSReflectionJavaElementBuilder builder("eb", ERT, RenderScriptVar, &mOut,
1501 mRSContext, this);
1502 builder.generate();
1503
1504 mOut.indent() << "return eb.create();\n";
1505 // mOut.indent() << "e = eb.create();\n";
1506 // mOut.indent() << RS_TYPE_ELEMENT_REF_NAME
1507 // << " = new java.lang.ref.WeakReference<Element>(e);\n";
1508 // mOut.indent() << "return e;\n";
1509 endFunction();
1510
1511 // private with element
1512 startFunction(AM_Private, false, nullptr, getClassName(), 1, "RenderScript",
1513 RenderScriptVar);
1514 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
1515 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
1516 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
1517 endFunction();
1518
1519 // 1D without usage
1520 startFunction(AM_Public, false, nullptr, getClassName(), 2, "RenderScript",
1521 RenderScriptVar, "int", "count");
1522
1523 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
1524 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
1525 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
1526 // Call init() in super class
1527 mOut.indent() << "init(" << RenderScriptVar << ", count);\n";
1528 endFunction();
1529
1530 // 1D with usage
1531 startFunction(AM_Public, false, nullptr, getClassName(), 3, "RenderScript",
1532 RenderScriptVar, "int", "count", "int", "usages");
1533
1534 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << " = null;\n";
1535 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << " = null;\n";
1536 mOut.indent() << "mElement = createElement(" << RenderScriptVar << ");\n";
1537 // Call init() in super class
1538 mOut.indent() << "init(" << RenderScriptVar << ", count, usages);\n";
1539 endFunction();
1540
1541 // create1D with usage
1542 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 3,
1543 "RenderScript", RenderScriptVar, "int", "dimX", "int",
1544 "usages");
1545 mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
1546 << RenderScriptVar << ");\n";
1547 mOut.indent() << "obj.mAllocation = Allocation.createSized("
1548 "rs, obj.mElement, dimX, usages);\n";
1549 mOut.indent() << "return obj;\n";
1550 endFunction();
1551
1552 // create1D without usage
1553 startFunction(AM_Public, true, getClassName().c_str(), "create1D", 2,
1554 "RenderScript", RenderScriptVar, "int", "dimX");
1555 mOut.indent() << "return create1D(" << RenderScriptVar
1556 << ", dimX, Allocation.USAGE_SCRIPT);\n";
1557 endFunction();
1558
1559 // create2D without usage
1560 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 3,
1561 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY");
1562 mOut.indent() << "return create2D(" << RenderScriptVar
1563 << ", dimX, dimY, Allocation.USAGE_SCRIPT);\n";
1564 endFunction();
1565
1566 // create2D with usage
1567 startFunction(AM_Public, true, getClassName().c_str(), "create2D", 4,
1568 "RenderScript", RenderScriptVar, "int", "dimX", "int", "dimY",
1569 "int", "usages");
1570
1571 mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
1572 << RenderScriptVar << ");\n";
1573 mOut.indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);\n";
1574 mOut.indent() << "b.setX(dimX);\n";
1575 mOut.indent() << "b.setY(dimY);\n";
1576 mOut.indent() << "Type t = b.create();\n";
1577 mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n";
1578 mOut.indent() << "return obj;\n";
1579 endFunction();
1580
1581 // createTypeBuilder
1582 startFunction(AM_Public, true, "Type.Builder", "createTypeBuilder", 1,
1583 "RenderScript", RenderScriptVar);
1584 mOut.indent() << "Element e = createElement(" << RenderScriptVar << ");\n";
1585 mOut.indent() << "return new Type.Builder(rs, e);\n";
1586 endFunction();
1587
1588 // createCustom with usage
1589 startFunction(AM_Public, true, getClassName().c_str(), "createCustom", 3,
1590 "RenderScript", RenderScriptVar, "Type.Builder", "tb", "int",
1591 "usages");
1592 mOut.indent() << getClassName() << " obj = new " << getClassName() << "("
1593 << RenderScriptVar << ");\n";
1594 mOut.indent() << "Type t = tb.create();\n";
1595 mOut.indent() << "if (t.getElement() != obj.mElement) {\n";
1596 mOut.indent() << " throw new RSIllegalArgumentException("
1597 "\"Type.Builder did not match expected element type.\");\n";
1598 mOut.indent() << "}\n";
1599 mOut.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);\n";
1600 mOut.indent() << "return obj;\n";
1601 endFunction();
1602 }
1603
genTypeClassCopyToArray(const RSExportRecordType * ERT)1604 void RSReflectionJava::genTypeClassCopyToArray(const RSExportRecordType *ERT) {
1605 startFunction(AM_Private, false, "void", "copyToArray", 2,
1606 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index");
1607
1608 genNewItemBufferPackerIfNull();
1609 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
1610 << mItemSizeof << ");\n";
1611
1612 mOut.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME
1613 ");\n";
1614
1615 endFunction();
1616 }
1617
1618 void
genTypeClassCopyToArrayLocal(const RSExportRecordType * ERT)1619 RSReflectionJava::genTypeClassCopyToArrayLocal(const RSExportRecordType *ERT) {
1620 startFunction(AM_Private, false, "void", "copyToArrayLocal", 2,
1621 RS_TYPE_ITEM_CLASS_NAME, "i", "FieldPacker", "fp");
1622
1623 genPackVarOfType(ERT, "i", "fp");
1624
1625 endFunction();
1626 }
1627
genTypeClassItemSetter(const RSExportRecordType * ERT)1628 void RSReflectionJava::genTypeClassItemSetter(const RSExportRecordType *ERT) {
1629 startFunction(AM_PublicSynchronized, false, "void", "set", 3,
1630 RS_TYPE_ITEM_CLASS_NAME, "i", "int", "index", "boolean",
1631 "copyNow");
1632 genNewItemBufferIfNull(nullptr);
1633 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index] = i;\n";
1634
1635 mOut.indent() << "if (copyNow) ";
1636 mOut.startBlock();
1637
1638 mOut.indent() << "copyToArray(i, index);\n";
1639 mOut.indent() << "FieldPacker fp = new FieldPacker(" << mItemSizeof << ");\n";
1640 mOut.indent() << "copyToArrayLocal(i, fp);\n";
1641 mOut.indent() << "mAllocation.setFromFieldPacker(index, fp);\n";
1642
1643 // End of if (copyNow)
1644 mOut.endBlock();
1645
1646 endFunction();
1647 }
1648
genTypeClassItemGetter(const RSExportRecordType * ERT)1649 void RSReflectionJava::genTypeClassItemGetter(const RSExportRecordType *ERT) {
1650 startFunction(AM_PublicSynchronized, false, RS_TYPE_ITEM_CLASS_NAME, "get", 1,
1651 "int", "index");
1652 mOut.indent() << "if (" << RS_TYPE_ITEM_BUFFER_NAME
1653 << " == null) return null;\n";
1654 mOut.indent() << "return " << RS_TYPE_ITEM_BUFFER_NAME << "[index];\n";
1655 endFunction();
1656 }
1657
1658 void
genTypeClassComponentSetter(const RSExportRecordType * ERT)1659 RSReflectionJava::genTypeClassComponentSetter(const RSExportRecordType *ERT) {
1660 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1661 FE = ERT->fields_end();
1662 FI != FE; FI++) {
1663 const RSExportRecordType::Field *F = *FI;
1664 size_t FieldOffset = F->getOffsetInParent();
1665 size_t FieldStoreSize = F->getType()->getStoreSize();
1666 unsigned FieldIndex = getFieldIndex(F);
1667
1668 startFunction(AM_PublicSynchronized, false, "void", "set_" + F->getName(),
1669 3, "int", "index", GetTypeName(F->getType()).c_str(), "v",
1670 "boolean", "copyNow");
1671 genNewItemBufferPackerIfNull();
1672 genNewItemBufferIfNull("index");
1673 mOut.indent() << RS_TYPE_ITEM_BUFFER_NAME << "[index]." << F->getName()
1674 << " = v;\n";
1675
1676 mOut.indent() << "if (copyNow) ";
1677 mOut.startBlock();
1678
1679 if (FieldOffset > 0) {
1680 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
1681 << mItemSizeof << " + " << FieldOffset
1682 << ");\n";
1683 } else {
1684 mOut.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME << ".reset(index * "
1685 << mItemSizeof << ");\n";
1686 }
1687 genPackVarOfType(F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1688
1689 mOut.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize
1690 << ");\n";
1691 genPackVarOfType(F->getType(), "v", "fp");
1692 mOut.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex
1693 << ", fp);\n";
1694
1695 // End of if (copyNow)
1696 mOut.endBlock();
1697
1698 endFunction();
1699 }
1700 }
1701
1702 void
genTypeClassComponentGetter(const RSExportRecordType * ERT)1703 RSReflectionJava::genTypeClassComponentGetter(const RSExportRecordType *ERT) {
1704 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1705 FE = ERT->fields_end();
1706 FI != FE; FI++) {
1707 const RSExportRecordType::Field *F = *FI;
1708 startFunction(AM_PublicSynchronized, false,
1709 GetTypeName(F->getType()).c_str(), "get_" + F->getName(), 1,
1710 "int", "index");
1711 mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME << " == null) return "
1712 << GetTypeNullValue(F->getType()) << ";\n";
1713 mOut.indent() << "return " RS_TYPE_ITEM_BUFFER_NAME << "[index]."
1714 << F->getName() << ";\n";
1715 endFunction();
1716 }
1717 }
1718
genTypeClassCopyAll(const RSExportRecordType * ERT)1719 void RSReflectionJava::genTypeClassCopyAll(const RSExportRecordType *ERT) {
1720 startFunction(AM_PublicSynchronized, false, "void", "copyAll", 0);
1721
1722 mOut.indent() << "for (int ct = 0; ct < " << RS_TYPE_ITEM_BUFFER_NAME
1723 << ".length; ct++)"
1724 << " copyToArray(" << RS_TYPE_ITEM_BUFFER_NAME
1725 << "[ct], ct);\n";
1726 mOut.indent() << "mAllocation.setFromFieldPacker(0, "
1727 << RS_TYPE_ITEM_BUFFER_PACKER_NAME ");\n";
1728
1729 endFunction();
1730 }
1731
genTypeClassResize()1732 void RSReflectionJava::genTypeClassResize() {
1733 startFunction(AM_PublicSynchronized, false, "void", "resize", 1, "int",
1734 "newSize");
1735
1736 mOut.indent() << "if (mItemArray != null) ";
1737 mOut.startBlock();
1738 mOut.indent() << "int oldSize = mItemArray.length;\n";
1739 mOut.indent() << "int copySize = Math.min(oldSize, newSize);\n";
1740 mOut.indent() << "if (newSize == oldSize) return;\n";
1741 mOut.indent() << "Item ni[] = new Item[newSize];\n";
1742 mOut.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);\n";
1743 mOut.indent() << "mItemArray = ni;\n";
1744 mOut.endBlock();
1745 mOut.indent() << "mAllocation.resize(newSize);\n";
1746
1747 mOut.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME
1748 " != null) " RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
1749 "new FieldPacker(" << mItemSizeof << " * getType().getX()/* count */);\n";
1750
1751 endFunction();
1752 }
1753
1754 /******************** Methods to generate type class /end ********************/
1755
1756 /********** Methods to create Element in Java of given record type ***********/
1757
RSReflectionJavaElementBuilder(const char * ElementBuilderName,const RSExportRecordType * ERT,const char * RenderScriptVar,GeneratedFile * Out,const RSContext * RSContext,RSReflectionJava * Reflection)1758 RSReflectionJavaElementBuilder::RSReflectionJavaElementBuilder(
1759 const char *ElementBuilderName, const RSExportRecordType *ERT,
1760 const char *RenderScriptVar, GeneratedFile *Out, const RSContext *RSContext,
1761 RSReflectionJava *Reflection)
1762 : mElementBuilderName(ElementBuilderName), mERT(ERT),
1763 mRenderScriptVar(RenderScriptVar), mOut(Out), mPaddingFieldIndex(1),
1764 mRSContext(RSContext), mReflection(Reflection) {
1765 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
1766 mPaddingPrefix = "#padding_";
1767 } else {
1768 mPaddingPrefix = "#rs_padding_";
1769 }
1770 }
1771
generate()1772 void RSReflectionJavaElementBuilder::generate() {
1773 mOut->indent() << "Element.Builder " << mElementBuilderName
1774 << " = new Element.Builder(" << mRenderScriptVar << ");\n";
1775 genAddElement(mERT, "", /* ArraySize = */ 0);
1776 }
1777
genAddElement(const RSExportType * ET,const std::string & VarName,unsigned ArraySize)1778 void RSReflectionJavaElementBuilder::genAddElement(const RSExportType *ET,
1779 const std::string &VarName,
1780 unsigned ArraySize) {
1781 std::string ElementConstruct = GetBuiltinElementConstruct(ET);
1782
1783 if (ElementConstruct != "") {
1784 genAddStatementStart();
1785 *mOut << ElementConstruct << "(" << mRenderScriptVar << ")";
1786 genAddStatementEnd(VarName, ArraySize);
1787 } else {
1788
1789 switch (ET->getClass()) {
1790 case RSExportType::ExportClassPrimitive: {
1791 const RSExportPrimitiveType *EPT =
1792 static_cast<const RSExportPrimitiveType *>(ET);
1793 const char *DataTypeName =
1794 RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type;
1795 genAddStatementStart();
1796 *mOut << "Element.createUser(" << mRenderScriptVar
1797 << ", Element.DataType." << DataTypeName << ")";
1798 genAddStatementEnd(VarName, ArraySize);
1799 break;
1800 }
1801 case RSExportType::ExportClassVector: {
1802 const RSExportVectorType *EVT =
1803 static_cast<const RSExportVectorType *>(ET);
1804 const char *DataTypeName =
1805 RSExportPrimitiveType::getRSReflectionType(EVT)->rs_type;
1806 genAddStatementStart();
1807 *mOut << "Element.createVector(" << mRenderScriptVar
1808 << ", Element.DataType." << DataTypeName << ", "
1809 << EVT->getNumElement() << ")";
1810 genAddStatementEnd(VarName, ArraySize);
1811 break;
1812 }
1813 case RSExportType::ExportClassPointer:
1814 // Pointer type variable should be resolved in
1815 // GetBuiltinElementConstruct()
1816 slangAssert(false && "??");
1817 break;
1818 case RSExportType::ExportClassMatrix:
1819 // Matrix type variable should be resolved
1820 // in GetBuiltinElementConstruct()
1821 slangAssert(false && "??");
1822 break;
1823 case RSExportType::ExportClassConstantArray: {
1824 const RSExportConstantArrayType *ECAT =
1825 static_cast<const RSExportConstantArrayType *>(ET);
1826
1827 const RSExportType *ElementType = ECAT->getElementType();
1828 if (ElementType->getClass() != RSExportType::ExportClassRecord) {
1829 genAddElement(ECAT->getElementType(), VarName, ECAT->getSize());
1830 } else {
1831 std::string NewElementBuilderName(mElementBuilderName);
1832 NewElementBuilderName.append(1, '_');
1833
1834 RSReflectionJavaElementBuilder builder(
1835 NewElementBuilderName.c_str(),
1836 static_cast<const RSExportRecordType *>(ElementType),
1837 mRenderScriptVar, mOut, mRSContext, mReflection);
1838 builder.generate();
1839
1840 ArraySize = ECAT->getSize();
1841 genAddStatementStart();
1842 *mOut << NewElementBuilderName << ".create()";
1843 genAddStatementEnd(VarName, ArraySize);
1844 }
1845 break;
1846 }
1847 case RSExportType::ExportClassRecord: {
1848 // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1849 //
1850 // TODO(zonr): Generalize these two function such that there's no
1851 // duplicated codes.
1852 const RSExportRecordType *ERT =
1853 static_cast<const RSExportRecordType *>(ET);
1854 int Pos = 0; // relative pos from now on
1855
1856 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1857 E = ERT->fields_end();
1858 I != E; I++) {
1859 const RSExportRecordType::Field *F = *I;
1860 int FieldOffset = F->getOffsetInParent();
1861 const RSExportType *T = F->getType();
1862 int FieldStoreSize = T->getStoreSize();
1863 int FieldAllocSize = T->getAllocSize();
1864
1865 std::string FieldName;
1866 if (!VarName.empty())
1867 FieldName = VarName + "." + F->getName();
1868 else
1869 FieldName = F->getName();
1870
1871 // Alignment
1872 genAddPadding(FieldOffset - Pos);
1873
1874 // eb.add(...)
1875 mReflection->addFieldIndexMapping(F);
1876 if (F->getType()->getClass() != RSExportType::ExportClassRecord) {
1877 genAddElement(F->getType(), FieldName, 0);
1878 } else {
1879 std::string NewElementBuilderName(mElementBuilderName);
1880 NewElementBuilderName.append(1, '_');
1881
1882 RSReflectionJavaElementBuilder builder(
1883 NewElementBuilderName.c_str(),
1884 static_cast<const RSExportRecordType *>(F->getType()),
1885 mRenderScriptVar, mOut, mRSContext, mReflection);
1886 builder.generate();
1887
1888 genAddStatementStart();
1889 *mOut << NewElementBuilderName << ".create()";
1890 genAddStatementEnd(FieldName, ArraySize);
1891 }
1892
1893 if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
1894 // There is padding within the field type. This is only necessary
1895 // for HC-targeted APIs.
1896 genAddPadding(FieldAllocSize - FieldStoreSize);
1897 }
1898
1899 Pos = FieldOffset + FieldAllocSize;
1900 }
1901
1902 // There maybe some padding after the struct
1903 size_t RecordAllocSize = ERT->getAllocSize();
1904
1905 genAddPadding(RecordAllocSize - Pos);
1906 break;
1907 }
1908 default:
1909 slangAssert(false && "Unknown class of type");
1910 break;
1911 }
1912 }
1913 }
1914
genAddPadding(int PaddingSize)1915 void RSReflectionJavaElementBuilder::genAddPadding(int PaddingSize) {
1916 while (PaddingSize > 0) {
1917 const std::string &VarName = createPaddingField();
1918 genAddStatementStart();
1919 if (PaddingSize >= 4) {
1920 *mOut << "Element.U32(" << mRenderScriptVar << ")";
1921 PaddingSize -= 4;
1922 } else if (PaddingSize >= 2) {
1923 *mOut << "Element.U16(" << mRenderScriptVar << ")";
1924 PaddingSize -= 2;
1925 } else if (PaddingSize >= 1) {
1926 *mOut << "Element.U8(" << mRenderScriptVar << ")";
1927 PaddingSize -= 1;
1928 }
1929 genAddStatementEnd(VarName, 0);
1930 }
1931 }
1932
genAddStatementStart()1933 void RSReflectionJavaElementBuilder::genAddStatementStart() {
1934 mOut->indent() << mElementBuilderName << ".add(";
1935 }
1936
1937 void
genAddStatementEnd(const std::string & VarName,unsigned ArraySize)1938 RSReflectionJavaElementBuilder::genAddStatementEnd(const std::string &VarName,
1939 unsigned ArraySize) {
1940 *mOut << ", \"" << VarName << "\"";
1941 if (ArraySize > 0) {
1942 *mOut << ", " << ArraySize;
1943 }
1944 *mOut << ");\n";
1945 // TODO Review incFieldIndex. It's probably better to assign the numbers at
1946 // the start rather
1947 // than as we're generating the code.
1948 mReflection->incFieldIndex();
1949 }
1950
1951 /******** Methods to create Element in Java of given record type /end ********/
1952
reflect()1953 bool RSReflectionJava::reflect() {
1954 std::string ErrorMsg;
1955 if (!genScriptClass(mScriptClassName, ErrorMsg)) {
1956 std::cerr << "Failed to generate class " << mScriptClassName << " ("
1957 << ErrorMsg << ")\n";
1958 return false;
1959 }
1960
1961 mGeneratedFileNames->push_back(mScriptClassName);
1962
1963 // class ScriptField_<TypeName>
1964 for (RSContext::const_export_type_iterator
1965 TI = mRSContext->export_types_begin(),
1966 TE = mRSContext->export_types_end();
1967 TI != TE; TI++) {
1968 const RSExportType *ET = TI->getValue();
1969
1970 if (ET->getClass() == RSExportType::ExportClassRecord) {
1971 const RSExportRecordType *ERT =
1972 static_cast<const RSExportRecordType *>(ET);
1973
1974 if (!ERT->isArtificial() && !genTypeClass(ERT, ErrorMsg)) {
1975 std::cerr << "Failed to generate type class for struct '"
1976 << ERT->getName() << "' (" << ErrorMsg << ")\n";
1977 return false;
1978 }
1979 }
1980 }
1981
1982 return true;
1983 }
1984
AccessModifierStr(AccessModifier AM)1985 const char *RSReflectionJava::AccessModifierStr(AccessModifier AM) {
1986 switch (AM) {
1987 case AM_Public:
1988 return "public";
1989 break;
1990 case AM_Protected:
1991 return "protected";
1992 break;
1993 case AM_Private:
1994 return "private";
1995 break;
1996 case AM_PublicSynchronized:
1997 return "public synchronized";
1998 break;
1999 default:
2000 return "";
2001 break;
2002 }
2003 }
2004
startClass(AccessModifier AM,bool IsStatic,const std::string & ClassName,const char * SuperClassName,std::string & ErrorMsg)2005 bool RSReflectionJava::startClass(AccessModifier AM, bool IsStatic,
2006 const std::string &ClassName,
2007 const char *SuperClassName,
2008 std::string &ErrorMsg) {
2009 // Open file for class
2010 std::string FileName = ClassName + ".java";
2011 if (!mOut.startFile(mOutputDirectory, FileName, mRSSourceFileName,
2012 mRSContext->getLicenseNote(), true,
2013 mRSContext->getVerbose())) {
2014 return false;
2015 }
2016
2017 // Package
2018 if (!mPackageName.empty()) {
2019 mOut << "package " << mPackageName << ";\n";
2020 }
2021 mOut << "\n";
2022
2023 // Imports
2024 mOut << "import " << mRSPackageName << ".*;\n";
2025 if (getEmbedBitcodeInJava()) {
2026 mOut << "import " << mPackageName << "."
2027 << RSSlangReflectUtils::JavaBitcodeClassNameFromRSFileName(
2028 mRSSourceFileName.c_str()) << ";\n";
2029 } else {
2030 mOut << "import android.content.res.Resources;\n";
2031 }
2032 mOut << "\n";
2033
2034 // All reflected classes should be annotated as hidden, so that they won't
2035 // be exposed in SDK.
2036 mOut << "/**\n";
2037 mOut << " * @hide\n";
2038 mOut << " */\n";
2039
2040 mOut << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
2041 << ClassName;
2042 if (SuperClassName != nullptr)
2043 mOut << " extends " << SuperClassName;
2044
2045 mOut.startBlock();
2046
2047 mClassName = ClassName;
2048
2049 return true;
2050 }
2051
endClass()2052 void RSReflectionJava::endClass() {
2053 mOut.endBlock();
2054 mOut.closeFile();
2055 clear();
2056 }
2057
startTypeClass(const std::string & ClassName)2058 void RSReflectionJava::startTypeClass(const std::string &ClassName) {
2059 mOut.indent() << "public static class " << ClassName;
2060 mOut.startBlock();
2061 }
2062
endTypeClass()2063 void RSReflectionJava::endTypeClass() { mOut.endBlock(); }
2064
startFunction(AccessModifier AM,bool IsStatic,const char * ReturnType,const std::string & FunctionName,int Argc,...)2065 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic,
2066 const char *ReturnType,
2067 const std::string &FunctionName, int Argc,
2068 ...) {
2069 ArgTy Args;
2070 va_list vl;
2071 va_start(vl, Argc);
2072
2073 for (int i = 0; i < Argc; i++) {
2074 const char *ArgType = va_arg(vl, const char *);
2075 const char *ArgName = va_arg(vl, const char *);
2076
2077 Args.push_back(std::make_pair(ArgType, ArgName));
2078 }
2079 va_end(vl);
2080
2081 startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
2082 }
2083
startFunction(AccessModifier AM,bool IsStatic,const char * ReturnType,const std::string & FunctionName,const ArgTy & Args)2084 void RSReflectionJava::startFunction(AccessModifier AM, bool IsStatic,
2085 const char *ReturnType,
2086 const std::string &FunctionName,
2087 const ArgTy &Args) {
2088 mOut.indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
2089 << ((ReturnType) ? ReturnType : "") << " " << FunctionName
2090 << "(";
2091
2092 bool FirstArg = true;
2093 for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) {
2094 if (!FirstArg)
2095 mOut << ", ";
2096 else
2097 FirstArg = false;
2098
2099 mOut << I->first << " " << I->second;
2100 }
2101
2102 mOut << ")";
2103 mOut.startBlock();
2104 }
2105
endFunction()2106 void RSReflectionJava::endFunction() { mOut.endBlock(); }
2107
addTypeNameForElement(const std::string & TypeName)2108 bool RSReflectionJava::addTypeNameForElement(const std::string &TypeName) {
2109 if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
2110 mTypesToCheck.insert(TypeName);
2111 return true;
2112 } else {
2113 return false;
2114 }
2115 }
2116
addTypeNameForFieldPacker(const std::string & TypeName)2117 bool RSReflectionJava::addTypeNameForFieldPacker(const std::string &TypeName) {
2118 if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) {
2119 mFieldPackerTypes.insert(TypeName);
2120 return true;
2121 } else {
2122 return false;
2123 }
2124 }
2125
2126 } // namespace slang
2127