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