• 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 
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