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