1 /*
2 * Copyright 2013, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sys/stat.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <iostream>
21
22 #include <cstdarg>
23 #include <cctype>
24
25 #include <algorithm>
26 #include <sstream>
27 #include <string>
28
29 #include "os_sep.h"
30 #include "slang_rs_context.h"
31 #include "slang_rs_export_var.h"
32 #include "slang_rs_export_foreach.h"
33 #include "slang_rs_export_func.h"
34 #include "slang_rs_reflect_utils.h"
35 #include "slang_version.h"
36
37 #include "slang_rs_reflection_cpp.h"
38
39 using namespace std;
40
41 namespace slang {
42
43 const char kRsTypeItemClassName[] = "Item";
44 const char kRsElemPrefix[] = "__rs_elem_";
45 // The name of the Allocation type that is reflected in C++
46 const char kAllocationSp[] = "android::RSC::sp<android::RSC::Allocation>";
47
GetMatrixTypeName(const RSExportMatrixType * EMT)48 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
49 static const char *MatrixTypeCNameMap[] = {
50 "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
51 };
52 unsigned Dim = EMT->getDim();
53
54 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
55 return MatrixTypeCNameMap[EMT->getDim() - 2];
56
57 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
58 return nullptr;
59 }
60
GetTypeName(const RSExportType * ET,bool PreIdentifier=true)61 static std::string GetTypeName(const RSExportType *ET, bool PreIdentifier = true) {
62 if((!PreIdentifier) && (ET->getClass() != RSExportType::ExportClassConstantArray)) {
63 slangAssert(false && "Non-array type post identifier?");
64 return "";
65 }
66 switch (ET->getClass()) {
67 case RSExportType::ExportClassPrimitive: {
68 const RSExportPrimitiveType *EPT =
69 static_cast<const RSExportPrimitiveType *>(ET);
70 if (EPT->isRSObjectType()) {
71 return std::string("android::RSC::sp<const android::RSC::") +
72 RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
73 } else {
74 return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
75 }
76 }
77 case RSExportType::ExportClassPointer: {
78 const RSExportType *PointeeType =
79 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
80
81 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
82 return kAllocationSp;
83 else
84 return PointeeType->getElementName();
85 }
86 case RSExportType::ExportClassVector: {
87 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
88 std::stringstream VecName;
89 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
90 << EVT->getNumElement();
91 return VecName.str();
92 }
93 case RSExportType::ExportClassMatrix: {
94 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
95 }
96 case RSExportType::ExportClassConstantArray: {
97 const RSExportConstantArrayType *CAT =
98 static_cast<const RSExportConstantArrayType *>(ET);
99 if (PreIdentifier) {
100 std::string ElementTypeName = GetTypeName(CAT->getElementType());
101 return ElementTypeName;
102 }
103 else {
104 std::stringstream ArraySpec;
105 ArraySpec << "[" << CAT->getNumElement() << "]";
106 return ArraySpec.str();
107 }
108 }
109 case RSExportType::ExportClassRecord: {
110 // TODO: Fix for C structs!
111 return ET->getElementName() + "." + kRsTypeItemClassName;
112 }
113 default: { slangAssert(false && "Unknown class of type"); }
114 }
115
116 return "";
117 }
118
RSReflectionCpp(const RSContext * Context,const string & OutputDirectory,const string & RSSourceFileName,const string & BitCodeFileName)119 RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
120 const string &OutputDirectory,
121 const string &RSSourceFileName,
122 const string &BitCodeFileName)
123 : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
124 mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
125 mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0) {
126 mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
127 mClassName = "ScriptC_" + mCleanedRSFileName;
128 }
129
~RSReflectionCpp()130 RSReflectionCpp::~RSReflectionCpp() {}
131
reflect()132 bool RSReflectionCpp::reflect() {
133 writeHeaderFile();
134 writeImplementationFile();
135
136 return true;
137 }
138
139 #define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
140
writeHeaderFile()141 bool RSReflectionCpp::writeHeaderFile() {
142 // Create the file and write the license note.
143 if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
144 mRSContext->getLicenseNote(), false,
145 mRSContext->getVerbose())) {
146 return false;
147 }
148
149 mOut.indent() << "#include \"RenderScript.h\"\n\n";
150 // Add NOLINT to suppress clang-tidy warnings of "using namespace".
151 // Keep "using namespace" to compile existing code.
152 mOut.indent() << "using namespace android::RSC; // NOLINT\n\n";
153
154 mOut.comment("This class encapsulates access to the exported elements of the script. "
155 "Typically, you would instantiate this class once, call the set_* methods "
156 "for each of the exported global variables you want to change, then call "
157 "one of the forEach_ methods to invoke a kernel.");
158 mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
159 mOut.startBlock();
160
161 mOut.decreaseIndent();
162 mOut.indent() << "private:\n";
163 mOut.increaseIndent();
164
165 genFieldsToStoreExportVariableValues();
166 genTypeInstancesUsedInForEach();
167 genFieldsForAllocationTypeVerification();
168
169 mOut.decreaseIndent();
170 mOut.indent() << "public:\n";
171 mOut.increaseIndent();
172
173 // Generate the constructor and destructor declarations.
174 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
175 mOut.indent() << "virtual ~" << mClassName << "();\n\n";
176
177 genExportVariablesGetterAndSetter();
178 genForEachDeclarations();
179 genExportFunctionDeclarations();
180
181 mOut.endBlock(true);
182 mOut.closeFile();
183 return true;
184 }
185
genTypeInstancesUsedInForEach()186 void RSReflectionCpp::genTypeInstancesUsedInForEach() {
187 for (auto I = mRSContext->export_foreach_begin(),
188 E = mRSContext->export_foreach_end();
189 I != E; I++) {
190 const RSExportForEach *EF = *I;
191 const RSExportType *OET = EF->getOutType();
192
193 if (OET) {
194 genTypeInstanceFromPointer(OET);
195 }
196
197 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
198
199 for (RSExportForEach::InTypeIter BI = InTypes.begin(),
200 EI = InTypes.end(); BI != EI; BI++) {
201
202 genTypeInstanceFromPointer(*BI);
203 }
204 }
205 }
206
genFieldsForAllocationTypeVerification()207 void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
208 bool CommentAdded = false;
209 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
210 E = mTypesToCheck.end();
211 I != E; I++) {
212 if (!CommentAdded) {
213 mOut.comment("The following elements are used to verify the types of "
214 "allocations passed to kernels.");
215 CommentAdded = true;
216 }
217 mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
218 << kRsElemPrefix << *I << ";\n";
219 }
220 }
221
genFieldsToStoreExportVariableValues()222 void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
223 bool CommentAdded = false;
224 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
225 E = mRSContext->export_vars_end();
226 I != E; I++) {
227 const RSExportVar *ev = *I;
228 if (ev->isConst()) {
229 continue;
230 }
231 if (!CommentAdded) {
232 mOut.comment("For each non-const variable exported by the script, we "
233 "have an equivalent field. This field contains the last "
234 "value this variable was set to using the set_ method. "
235 "This may not be current value of the variable in the "
236 "script, as the script is free to modify its internal "
237 "variable without changing this field. If the script "
238 "initializes the exported variable, the constructor will "
239 "initialize this field to the same value.");
240 CommentAdded = true;
241 }
242 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
243 << ev->getName() << ";\n";
244 }
245 }
246
genForEachDeclarations()247 void RSReflectionCpp::genForEachDeclarations() {
248 bool CommentAdded = false;
249 for (RSContext::const_export_foreach_iterator
250 I = mRSContext->export_foreach_begin(),
251 E = mRSContext->export_foreach_end();
252 I != E; I++) {
253 const RSExportForEach *ForEach = *I;
254
255 if (ForEach->isDummyRoot()) {
256 mOut.indent() << "// No forEach_root(...)\n";
257 continue;
258 }
259
260 if (!CommentAdded) {
261 mOut.comment("For each kernel of the script corresponds one method. "
262 "That method queues the kernel for execution. The kernel "
263 "may not have completed nor even started by the time this "
264 "function returns. Calls that extract the data out of the "
265 "output allocation will wait for the kernels to complete.");
266 CommentAdded = true;
267 }
268
269 std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
270 mOut.indent() << FunctionStart;
271
272 ArgumentList Arguments;
273 const RSExportForEach::InVec &Ins = ForEach->getIns();
274 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
275 BI != EI; BI++) {
276
277 Arguments.push_back(Argument(kAllocationSp, (*BI)->getName()));
278 }
279
280 if (ForEach->hasOut() || ForEach->hasReturn()) {
281 Arguments.push_back(Argument(kAllocationSp, "aout"));
282 }
283
284 const RSExportRecordType *ERT = ForEach->getParamPacketType();
285 if (ERT) {
286 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
287 e = ForEach->params_end();
288 i != e; i++) {
289 RSReflectionTypeData rtd;
290 (*i)->getType()->convertToRTD(&rtd);
291 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
292 }
293 }
294 genArguments(Arguments, FunctionStart.length());
295 mOut << ");\n";
296 }
297 }
298
genExportFunctionDeclarations()299 void RSReflectionCpp::genExportFunctionDeclarations() {
300 for (RSContext::const_export_func_iterator
301 I = mRSContext->export_funcs_begin(),
302 E = mRSContext->export_funcs_end();
303 I != E; I++) {
304 const RSExportFunc *ef = *I;
305
306 makeFunctionSignature(false, ef);
307 }
308 }
309
310 // forEach_* implementation
genExportForEachBodies()311 void RSReflectionCpp::genExportForEachBodies() {
312 uint32_t slot = 0;
313 for (auto I = mRSContext->export_foreach_begin(),
314 E = mRSContext->export_foreach_end();
315 I != E; I++, slot++) {
316 const RSExportForEach *ef = *I;
317 if (ef->isDummyRoot()) {
318 mOut.indent() << "// No forEach_root(...)\n";
319 continue;
320 }
321
322 ArgumentList Arguments;
323 std::string FunctionStart =
324 "void " + mClassName + "::forEach_" + ef->getName() + "(";
325 mOut.indent() << FunctionStart;
326
327 if (ef->hasIns()) {
328 // FIXME: Add support for kernels with multiple inputs.
329 slangAssert(ef->getIns().size() == 1);
330 Arguments.push_back(Argument(kAllocationSp, "ain"));
331 }
332
333 if (ef->hasOut() || ef->hasReturn()) {
334 Arguments.push_back(Argument(kAllocationSp, "aout"));
335 }
336
337 const RSExportRecordType *ERT = ef->getParamPacketType();
338 if (ERT) {
339 for (RSExportForEach::const_param_iterator i = ef->params_begin(),
340 e = ef->params_end();
341 i != e; i++) {
342 RSReflectionTypeData rtd;
343 (*i)->getType()->convertToRTD(&rtd);
344 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
345 }
346 }
347 genArguments(Arguments, FunctionStart.length());
348 mOut << ")";
349 mOut.startBlock();
350
351 const RSExportType *OET = ef->getOutType();
352 const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
353 if (ef->hasIns()) {
354 // FIXME: Add support for kernels with multiple inputs.
355 slangAssert(ef->getIns().size() == 1);
356 genTypeCheck(InTypes[0], "ain");
357 }
358 if (OET) {
359 genTypeCheck(OET, "aout");
360 }
361
362 // TODO Add the appropriate dimension checking code, as seen in
363 // slang_rs_reflection.cpp.
364
365 std::string FieldPackerName = ef->getName() + "_fp";
366 if (ERT) {
367 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
368 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
369 }
370 }
371 mOut.indent() << "forEach(" << slot << ", ";
372
373 if (ef->hasIns()) {
374 // FIXME: Add support for kernels with multiple inputs.
375 slangAssert(ef->getIns().size() == 1);
376 mOut << "ain, ";
377 } else {
378 mOut << "NULL, ";
379 }
380
381 if (ef->hasOut() || ef->hasReturn()) {
382 mOut << "aout, ";
383 } else {
384 mOut << "NULL, ";
385 }
386
387 // FIXME (no support for usrData with C++ kernels)
388 mOut << "NULL, 0);\n";
389 mOut.endBlock();
390 }
391 }
392
393 // invoke_* implementation
genExportFunctionBodies()394 void RSReflectionCpp::genExportFunctionBodies() {
395 uint32_t slot = 0;
396 // Reflect export function
397 for (auto I = mRSContext->export_funcs_begin(),
398 E = mRSContext->export_funcs_end();
399 I != E; I++) {
400 const RSExportFunc *ef = *I;
401
402 makeFunctionSignature(true, ef);
403 mOut.startBlock();
404 const RSExportRecordType *params = ef->getParamPacketType();
405 size_t param_len = 0;
406 if (params) {
407 param_len = params->getAllocSize();
408 if (genCreateFieldPacker(params, "__fp")) {
409 genPackVarOfType(params, nullptr, "__fp");
410 }
411 }
412
413 mOut.indent() << "invoke(" << slot;
414 if (params) {
415 mOut << ", __fp.getData(), " << param_len << ");\n";
416 } else {
417 mOut << ", NULL, 0);\n";
418 }
419 mOut.endBlock();
420
421 slot++;
422 }
423 }
424
genEncodedBitCode()425 bool RSReflectionCpp::genEncodedBitCode() {
426 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
427 if (pfin == nullptr) {
428 fprintf(stderr, "Error: could not read file %s\n",
429 mBitCodeFilePath.c_str());
430 return false;
431 }
432
433 unsigned char buf[16];
434 int read_length;
435 mOut.indent() << "static const unsigned char __txt[] =";
436 mOut.startBlock();
437 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
438 mOut.indent();
439 for (int i = 0; i < read_length; i++) {
440 char buf2[16];
441 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
442 mOut << buf2;
443 }
444 mOut << "\n";
445 }
446 mOut.endBlock(true);
447 mOut << "\n";
448 return true;
449 }
450
writeImplementationFile()451 bool RSReflectionCpp::writeImplementationFile() {
452 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
453 mRSContext->getLicenseNote(), false,
454 mRSContext->getVerbose())) {
455 return false;
456 }
457
458 // Front matter
459 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
460
461 genEncodedBitCode();
462 mOut.indent() << "\n\n";
463
464 // Constructor
465 const std::string &packageName = mRSContext->getReflectJavaPackageName();
466 mOut.indent() << mClassName << "::" << mClassName
467 << "(android::RSC::sp<android::RSC::RS> rs):\n"
468 " ScriptC(rs, __txt, sizeof(__txt), \""
469 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
470 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
471 << packageName << "\"))";
472 mOut.startBlock();
473 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
474 E = mTypesToCheck.end();
475 I != E; I++) {
476 mOut.indent() << kRsElemPrefix << *I << " = android::RSC::Element::" << *I
477 << "(mRS);\n";
478 }
479
480 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
481 E = mRSContext->export_vars_end();
482 I != E; I++) {
483 const RSExportVar *EV = *I;
484 if (!EV->getInit().isUninit()) {
485 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
486 } else {
487 genZeroInitExportVariable(EV->getName());
488 }
489 }
490 mOut.endBlock();
491
492 // Destructor
493 mOut.indent() << mClassName << "::~" << mClassName << "()";
494 mOut.startBlock();
495 mOut.endBlock();
496
497 // Function bodies
498 genExportForEachBodies();
499 genExportFunctionBodies();
500
501 mOut.closeFile();
502 return true;
503 }
504
genExportVariablesGetterAndSetter()505 void RSReflectionCpp::genExportVariablesGetterAndSetter() {
506 mOut.comment("Methods to set and get the variables exported by the script. "
507 "Const variables will not have a setter.\n\n"
508 "Note that the value returned by the getter may not be the "
509 "current value of the variable in the script. The getter will "
510 "return the initial value of the variable (as defined in the "
511 "script) or the the last value set by using the setter method. "
512 "The script is free to modify its value independently.");
513 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
514 E = mRSContext->export_vars_end();
515 I != E; I++) {
516 const RSExportVar *EV = *I;
517 const RSExportType *ET = EV->getType();
518
519 switch (ET->getClass()) {
520 case RSExportType::ExportClassPrimitive: {
521 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
522 break;
523 }
524 case RSExportType::ExportClassPointer: {
525 // TODO Deprecate this.
526 genPointerTypeExportVariable(EV);
527 break;
528 }
529 case RSExportType::ExportClassVector: {
530 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
531 break;
532 }
533 case RSExportType::ExportClassMatrix: {
534 genMatrixTypeExportVariable(EV);
535 break;
536 }
537 case RSExportType::ExportClassConstantArray: {
538 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
539 EV);
540 break;
541 }
542 case RSExportType::ExportClassRecord: {
543 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
544 break;
545 }
546 default: { slangAssert(false && "Unknown class of type"); }
547 }
548 }
549 }
550
genGetterAndSetter(const RSExportPrimitiveType * EPT,const RSExportVar * EV)551 void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
552 const RSExportVar *EV) {
553 RSReflectionTypeData rtd;
554 EPT->convertToRTD(&rtd);
555 std::string TypeName = GetTypeName(EPT);
556
557 if (!EV->isConst()) {
558 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
559 mOut.startBlock();
560 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
561 if (EPT->isRSObjectType()) {
562 mOut << "v";
563 } else {
564 mOut << "&v, sizeof(v)";
565 }
566 mOut << ");\n";
567 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
568 mOut.endBlock();
569 }
570 mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
571 mOut.startBlock();
572 if (EV->isConst()) {
573 const clang::APValue &val = EV->getInit();
574 bool isBool = !strcmp(TypeName.c_str(), "bool");
575 mOut.indent() << "return ";
576 genInitValue(val, isBool);
577 mOut << ";\n";
578 } else {
579 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
580 << ";\n";
581 }
582 mOut.endBlock();
583 }
584
genPointerTypeExportVariable(const RSExportVar * EV)585 void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
586 const RSExportType *ET = EV->getType();
587
588 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
589 "Variable should be type of pointer here");
590
591 std::string TypeName = GetTypeName(ET);
592 const std::string &VarName = EV->getName();
593
594 RSReflectionTypeData rtd;
595 EV->getType()->convertToRTD(&rtd);
596 uint32_t slot = getNextExportVarSlot();
597
598 if (!EV->isConst()) {
599 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
600 mOut.startBlock();
601 mOut.indent() << "bindAllocation(v, " << slot << ");\n";
602 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
603 mOut.endBlock();
604 }
605 mOut.indent() << TypeName << " get_" << VarName << "() const";
606 mOut.startBlock();
607 if (EV->isConst()) {
608 const clang::APValue &val = EV->getInit();
609 bool isBool = !strcmp(TypeName.c_str(), "bool");
610 mOut.indent() << "return ";
611 genInitValue(val, isBool);
612 mOut << ";\n";
613 } else {
614 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
615 }
616 mOut.endBlock();
617 }
618
genGetterAndSetter(const RSExportVectorType * EVT,const RSExportVar * EV)619 void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
620 const RSExportVar *EV) {
621 slangAssert(EVT != nullptr);
622
623 RSReflectionTypeData rtd;
624 EVT->convertToRTD(&rtd);
625
626 if (!EV->isConst()) {
627 mOut.indent() << "void set_" << EV->getName() << "("
628 << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
629 << " v)";
630 mOut.startBlock();
631 mOut.indent() << "setVar(" << getNextExportVarSlot()
632 << ", &v, sizeof(v));\n";
633 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
634 mOut.endBlock();
635 }
636 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
637 << " get_" << EV->getName() << "() const";
638 mOut.startBlock();
639 if (EV->isConst()) {
640 const clang::APValue &val = EV->getInit();
641 mOut.indent() << "return ";
642 genInitValue(val, false);
643 mOut << ";\n";
644 } else {
645 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
646 << ";\n";
647 }
648 mOut.endBlock();
649 }
650
genMatrixTypeExportVariable(const RSExportVar * EV)651 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
652 uint32_t slot = getNextExportVarSlot();
653 stringstream tmp;
654 tmp << slot;
655
656 const RSExportType *ET = EV->getType();
657 if (ET->getName() == "rs_matrix4x4") {
658 mOut.indent() << "void set_" << EV->getName() << "(float v[16])";
659 mOut.startBlock();
660 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*16);\n";
661 mOut.endBlock();
662 } else if (ET->getName() == "rs_matrix3x3") {
663 mOut.indent() << "void set_" << EV->getName() << "(float v[9])";
664 mOut.startBlock();
665 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*9);";
666 mOut.endBlock();
667 } else if (ET->getName() == "rs_matrix2x2") {
668 mOut.indent() << "void set_" << EV->getName() << "(float v[4])";
669 mOut.startBlock();
670 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*4);";
671 mOut.endBlock();
672 } else {
673 mOut.indent() << "#error: TODO: " << ET->getName();
674 slangAssert(false);
675 }
676 }
677
genGetterAndSetter(const RSExportConstantArrayType * AT,const RSExportVar * EV)678 void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
679 const RSExportVar *EV) {
680 std::stringstream ArraySpec;
681 const RSExportType *ET = EV->getType();
682
683 const RSExportConstantArrayType *CAT =
684 static_cast<const RSExportConstantArrayType *>(ET);
685
686 uint32_t slot = getNextExportVarSlot();
687 stringstream tmp;
688 tmp << slot;
689
690 ArraySpec << CAT->getNumElement();
691 mOut.indent() << "void set_" << EV->getName() << "(" << GetTypeName(EV->getType()) << " v "
692 << GetTypeName(EV->getType(), false) << ")";
693 mOut.startBlock();
694 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(" << GetTypeName(EV->getType()) + ") *"
695 << ArraySpec.str() << ");";
696 mOut.endBlock();
697 }
698
genGetterAndSetter(const RSExportRecordType * ERT,const RSExportVar * EV)699 void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
700 const RSExportVar *EV) {
701 slangAssert(false);
702 }
703
makeFunctionSignature(bool isDefinition,const RSExportFunc * ef)704 void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
705 const RSExportFunc *ef) {
706 mOut.indent() << "void ";
707 if (isDefinition) {
708 mOut << mClassName << "::";
709 }
710 mOut << "invoke_" << ef->getName() << "(";
711
712 if (ef->getParamPacketType()) {
713 bool FirstArg = true;
714 for (RSExportFunc::const_param_iterator i = ef->params_begin(),
715 e = ef->params_end();
716 i != e; i++) {
717 if (!FirstArg) {
718 mOut << ", ";
719 } else {
720 FirstArg = false;
721 }
722 mOut << GetTypeName((*i)->getType()) << " " << (*i)->getName();
723 }
724 }
725
726 if (isDefinition) {
727 mOut << ")";
728 } else {
729 mOut << ");\n";
730 }
731 }
732
genArguments(const ArgumentList & Arguments,int Offset)733 void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
734 bool FirstArg = true;
735
736 for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
737 I != E; I++) {
738 if (!FirstArg) {
739 mOut << ",\n";
740 mOut.indent() << string(Offset, ' ');
741 } else {
742 FirstArg = false;
743 }
744
745 mOut << I->Type << " " << I->Name;
746 if (!I->DefaultValue.empty()) {
747 mOut << " = " << I->DefaultValue;
748 }
749 }
750 }
751
genCreateFieldPacker(const RSExportType * ET,const char * FieldPackerName)752 bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
753 const char *FieldPackerName) {
754 size_t AllocSize = ET->getAllocSize();
755
756 if (AllocSize > 0) {
757 mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
758 << AllocSize << ");\n";
759 return true;
760 }
761
762 return false;
763 }
764
genPackVarOfType(const RSExportType * ET,const char * VarName,const char * FieldPackerName)765 void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
766 const char *VarName,
767 const char *FieldPackerName) {
768 switch (ET->getClass()) {
769 case RSExportType::ExportClassPrimitive:
770 case RSExportType::ExportClassVector:
771 case RSExportType::ExportClassPointer:
772 case RSExportType::ExportClassMatrix: {
773 mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
774 break;
775 }
776 case RSExportType::ExportClassConstantArray: {
777 /*const RSExportConstantArrayType *ECAT =
778 static_cast<const RSExportConstantArrayType *>(ET);
779
780 // TODO(zonr): more elegant way. Currently, we obtain the unique index
781 // variable (this method involves recursive call which means
782 // we may have more than one level loop, therefore we can't
783 // always use the same index variable name here) name given
784 // in the for-loop from counting the '.' in @VarName.
785 unsigned Level = 0;
786 size_t LastDotPos = 0;
787 std::string ElementVarName(VarName);
788
789 while (LastDotPos != std::string::npos) {
790 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
791 Level++;
792 }
793 std::string IndexVarName("ct");
794 IndexVarName.append(llvm::utostr(Level));
795
796 C.indent() << "for (int " << IndexVarName << " = 0; " <<
797 IndexVarName << " < " << ECAT->getSize() << "; " <<
798 IndexVarName << "++)";
799 C.startBlock();
800
801 ElementVarName.append("[" + IndexVarName + "]");
802 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
803 FieldPackerName);
804
805 C.endBlock();*/
806 break;
807 }
808 case RSExportType::ExportClassRecord: {
809 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
810 // Relative pos from now on in field packer
811 unsigned Pos = 0;
812
813 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
814 E = ERT->fields_end();
815 I != E; I++) {
816 const RSExportRecordType::Field *F = *I;
817 std::string FieldName;
818 size_t FieldOffset = F->getOffsetInParent();
819 const RSExportType *T = F->getType();
820 size_t FieldStoreSize = T->getStoreSize();
821 size_t FieldAllocSize = T->getAllocSize();
822
823 if (VarName != nullptr)
824 FieldName = VarName + ("." + F->getName());
825 else
826 FieldName = F->getName();
827
828 if (FieldOffset > Pos) {
829 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
830 << ");\n";
831 }
832
833 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
834
835 // There is padding in the field type
836 if (FieldAllocSize > FieldStoreSize) {
837 mOut.indent() << FieldPackerName << ".skip("
838 << (FieldAllocSize - FieldStoreSize) << ");\n";
839 }
840
841 Pos = FieldOffset + FieldAllocSize;
842 }
843
844 // There maybe some padding after the struct
845 if (ERT->getAllocSize() > Pos) {
846 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
847 << ");\n";
848 }
849 break;
850 }
851 default: { slangAssert(false && "Unknown class of type"); }
852 }
853 }
854
genTypeCheck(const RSExportType * ET,const char * VarName)855 void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
856 const char *VarName) {
857 mOut.indent() << "// Type check for " << VarName << "\n";
858
859 if (ET->getClass() == RSExportType::ExportClassPointer) {
860 const RSExportPointerType *EPT =
861 static_cast<const RSExportPointerType *>(ET);
862 ET = EPT->getPointeeType();
863 }
864
865 std::string TypeName;
866 switch (ET->getClass()) {
867 case RSExportType::ExportClassPrimitive:
868 case RSExportType::ExportClassVector:
869 case RSExportType::ExportClassRecord: {
870 TypeName = ET->getElementName();
871 break;
872 }
873
874 default:
875 break;
876 }
877
878 if (!TypeName.empty()) {
879 mOut.indent() << "if (!" << VarName
880 << "->getType()->getElement()->isCompatible("
881 << kRsElemPrefix << TypeName << "))";
882 mOut.startBlock();
883 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
884 "\"Incompatible type\");\n";
885 mOut.indent() << "return;\n";
886 mOut.endBlock();
887 }
888 }
889
genTypeInstanceFromPointer(const RSExportType * ET)890 void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
891 if (ET->getClass() == RSExportType::ExportClassPointer) {
892 // For pointer parameters to original forEach kernels.
893 const RSExportPointerType *EPT =
894 static_cast<const RSExportPointerType *>(ET);
895 genTypeInstance(EPT->getPointeeType());
896 } else {
897 // For handling pass-by-value kernel parameters.
898 genTypeInstance(ET);
899 }
900 }
901
genTypeInstance(const RSExportType * ET)902 void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
903 switch (ET->getClass()) {
904 case RSExportType::ExportClassPrimitive:
905 case RSExportType::ExportClassVector:
906 case RSExportType::ExportClassConstantArray:
907 case RSExportType::ExportClassRecord: {
908 std::string TypeName = ET->getElementName();
909 mTypesToCheck.insert(TypeName);
910 break;
911 }
912
913 default:
914 break;
915 }
916 }
917
genInitExportVariable(const RSExportType * ET,const std::string & VarName,const clang::APValue & Val)918 void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
919 const std::string &VarName,
920 const clang::APValue &Val) {
921 slangAssert(!Val.isUninit() && "Not a valid initializer");
922
923 switch (ET->getClass()) {
924 case RSExportType::ExportClassPrimitive: {
925 const RSExportPrimitiveType *EPT =
926 static_cast<const RSExportPrimitiveType *>(ET);
927 if (EPT->getType() == DataTypeBoolean) {
928 genInitBoolExportVariable(VarName, Val);
929 } else {
930 genInitPrimitiveExportVariable(VarName, Val);
931 }
932 break;
933 }
934 case RSExportType::ExportClassPointer: {
935 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
936 std::cerr << "Initializer which is non-NULL to pointer type variable "
937 "will be ignored" << std::endl;
938 break;
939 }
940 case RSExportType::ExportClassVector: {
941 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
942 switch (Val.getKind()) {
943 case clang::APValue::Int:
944 case clang::APValue::Float: {
945 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
946 std::string Name = VarName + "." + getVectorAccessor(i);
947 genInitPrimitiveExportVariable(Name, Val);
948 }
949 break;
950 }
951 case clang::APValue::Vector: {
952 unsigned NumElements = std::min(
953 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
954 for (unsigned i = 0; i < NumElements; i++) {
955 const clang::APValue &ElementVal = Val.getVectorElt(i);
956 std::string Name = VarName + "." + getVectorAccessor(i);
957 genInitPrimitiveExportVariable(Name, ElementVal);
958 }
959 break;
960 }
961 case clang::APValue::MemberPointer:
962 case clang::APValue::Uninitialized:
963 case clang::APValue::ComplexInt:
964 case clang::APValue::ComplexFloat:
965 case clang::APValue::LValue:
966 case clang::APValue::Array:
967 case clang::APValue::Struct:
968 case clang::APValue::Union:
969 case clang::APValue::AddrLabelDiff: {
970 slangAssert(false && "Unexpected type of value of initializer.");
971 }
972 }
973 break;
974 }
975 case RSExportType::ExportClassMatrix:
976 case RSExportType::ExportClassConstantArray:
977 case RSExportType::ExportClassRecord: {
978 slangAssert(false && "Unsupported initializer for record/matrix/constant "
979 "array type variable currently");
980 break;
981 }
982 default: { slangAssert(false && "Unknown class of type"); }
983 }
984 }
985
getVectorAccessor(unsigned Index)986 const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
987 static const char *VectorAccessorMap[] = {/* 0 */ "x",
988 /* 1 */ "y",
989 /* 2 */ "z",
990 /* 3 */ "w",
991 };
992
993 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
994 "Out-of-bound index to access vector member");
995
996 return VectorAccessorMap[Index];
997 }
998
genZeroInitExportVariable(const std::string & VarName)999 void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
1000 mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
1001 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
1002 }
1003
1004 void
genInitPrimitiveExportVariable(const std::string & VarName,const clang::APValue & Val)1005 RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
1006 const clang::APValue &Val) {
1007 slangAssert(!Val.isUninit() && "Not a valid initializer");
1008
1009 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
1010 genInitValue(Val);
1011 mOut << ";\n";
1012 }
1013
genInitValue(const clang::APValue & Val,bool asBool)1014 void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
1015 switch (Val.getKind()) {
1016 case clang::APValue::Int: {
1017 const llvm::APInt &api = Val.getInt();
1018 if (asBool) {
1019 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
1020 } else {
1021 // TODO: Handle unsigned correctly for C++
1022 mOut << api.getSExtValue();
1023 if (api.getBitWidth() > 32) {
1024 mOut << "L";
1025 }
1026 }
1027 break;
1028 }
1029
1030 case clang::APValue::Float: {
1031 const llvm::APFloat &apf = Val.getFloat();
1032 llvm::SmallString<30> s;
1033 apf.toString(s);
1034 mOut << s.c_str();
1035 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
1036 if (s.count('.') == 0) {
1037 mOut << ".f";
1038 } else {
1039 mOut << "f";
1040 }
1041 }
1042 break;
1043 }
1044
1045 case clang::APValue::ComplexInt:
1046 case clang::APValue::ComplexFloat:
1047 case clang::APValue::LValue:
1048 case clang::APValue::Vector: {
1049 slangAssert(false && "Primitive type cannot have such kind of initializer");
1050 break;
1051 }
1052
1053 default: { slangAssert(false && "Unknown kind of initializer"); }
1054 }
1055 }
1056
genInitBoolExportVariable(const std::string & VarName,const clang::APValue & Val)1057 void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
1058 const clang::APValue &Val) {
1059 slangAssert(!Val.isUninit() && "Not a valid initializer");
1060 slangAssert((Val.getKind() == clang::APValue::Int) &&
1061 "Bool type has wrong initial APValue");
1062
1063 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
1064 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
1065 << ";";
1066 }
1067
1068 } // namespace slang
1069