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