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