• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, 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 
GetMatrixTypeName(const RSExportMatrixType * EMT)46 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
47   static const char *MatrixTypeCNameMap[] = {
48     "rs_matrix2x2",
49     "rs_matrix3x3",
50     "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 NULL;
59 }
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       return RSExportPrimitiveType::getRSReflectionType(
66           static_cast<const RSExportPrimitiveType*>(ET))->c_name;
67     }
68     case RSExportType::ExportClassPointer: {
69       const RSExportType *PointeeType =
70           static_cast<const RSExportPointerType*>(ET)->getPointeeType();
71 
72       if (PointeeType->getClass() != RSExportType::ExportClassRecord)
73         return "android::sp<android::RSC::Allocation>";
74       else
75         return PointeeType->getElementName();
76     }
77     case RSExportType::ExportClassVector: {
78       const RSExportVectorType *EVT =
79           static_cast<const RSExportVectorType*>(ET);
80       std::stringstream VecName;
81       VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
82               << EVT->getNumElement();
83       return VecName.str();
84     }
85     case RSExportType::ExportClassMatrix: {
86       return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET));
87     }
88     case RSExportType::ExportClassConstantArray: {
89       // TODO: Fix this for C arrays!
90       const RSExportConstantArrayType* CAT =
91           static_cast<const RSExportConstantArrayType*>(ET);
92       std::string ElementTypeName = GetTypeName(CAT->getElementType());
93       if (Brackets) {
94         ElementTypeName.append("[]");
95       }
96       return ElementTypeName;
97     }
98     case RSExportType::ExportClassRecord: {
99       // TODO: Fix for C structs!
100       return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
101     }
102     default: {
103       slangAssert(false && "Unknown class of type");
104     }
105   }
106 
107   return "";
108 }
109 
110 
RSReflectionCpp(const RSContext * con)111 RSReflectionCpp::RSReflectionCpp(const RSContext *con)
112     : RSReflectionBase(con) {
113   clear();
114 }
115 
~RSReflectionCpp()116 RSReflectionCpp::~RSReflectionCpp() {
117 }
118 
reflect(const string & OutputPathBase,const string & InputFileName,const string & OutputBCFileName)119 bool RSReflectionCpp::reflect(const string &OutputPathBase,
120                               const string &InputFileName,
121                               const string &OutputBCFileName) {
122   mInputFileName = InputFileName;
123   mOutputPath = OutputPathBase;
124   mOutputBCFileName = OutputBCFileName;
125   mClassName = string("ScriptC_") + stripRS(InputFileName);
126 
127   makeHeader("android::RSC::ScriptC");
128   std::vector< std::string > header(mText);
129   mText.clear();
130 
131   makeImpl("android::RSC::ScriptC");
132   std::vector< std::string > cpp(mText);
133   mText.clear();
134 
135 
136   writeFile(mClassName + ".h", header);
137   writeFile(mClassName + ".cpp", cpp);
138 
139 
140   return true;
141 }
142 
143 
144 #define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
145 
146 
147 
makeHeader(const std::string & baseClass)148 bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
149   startFile(mClassName + ".h");
150 
151   write("");
152   write("#include \"RenderScript.h\"");
153   write("using namespace android::RSC;");
154   write("");
155 
156   // Imports
157   //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
158       //out() << "import " << Import[i] << ";" << std::endl;
159   //out() << std::endl;
160 
161   if (!baseClass.empty()) {
162     write("class " + mClassName + " : public " + baseClass + " {");
163   } else {
164     write("class " + mClassName + " {");
165   }
166 
167   write("private:");
168   uint32_t slot = 0;
169   incIndent();
170   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
171          E = mRSContext->export_vars_end(); I != E; I++, slot++) {
172     const RSExportVar *ev = *I;
173     RSReflectionTypeData rtd;
174     ev->getType()->convertToRTD(&rtd);
175     if (!ev->isConst()) {
176       write(GetTypeName(ev->getType()) + " __" + ev->getName() + ";");
177     }
178   }
179   decIndent();
180 
181   write("public:");
182   incIndent();
183   write(mClassName + "(android::sp<android::RSC::RS> rs," +
184           " const char *cacheDir, size_t cacheDirLength);");
185   write("virtual ~" + mClassName + "();");
186   write("");
187 
188 
189   // Reflect export variable
190   slot = 0;
191   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
192          E = mRSContext->export_vars_end(); I != E; I++, slot++) {
193     genExportVariable(*I);
194   }
195 
196   // Reflect export for each functions
197   for (RSContext::const_export_foreach_iterator
198            I = mRSContext->export_foreach_begin(),
199            E = mRSContext->export_foreach_end(); I != E; I++) {
200     const RSExportForEach *ef = *I;
201     if (ef->isDummyRoot()) {
202       write("// No forEach_root(...)");
203       continue;
204     }
205 
206     ArgTy Args;
207     stringstream ss;
208     ss << "void forEach_" << ef->getName() << "(";
209 
210     if (ef->hasIn()) {
211       Args.push_back(std::make_pair(
212           "android::sp<const android::RSC::Allocation>", "ain"));
213     }
214 
215     if (ef->hasOut() || ef->hasReturn()) {
216       Args.push_back(std::make_pair(
217           "android::sp<const android::RSC::Allocation>", "aout"));
218     }
219 
220     const RSExportRecordType *ERT = ef->getParamPacketType();
221     if (ERT) {
222       for (RSExportForEach::const_param_iterator i = ef->params_begin(),
223            e = ef->params_end(); i != e; i++) {
224         RSReflectionTypeData rtd;
225         (*i)->getType()->convertToRTD(&rtd);
226         Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
227       }
228     }
229     makeArgs(ss, Args);
230     ss << ");";
231     write(ss);
232   }
233 
234 
235   // Reflect export function
236   for (RSContext::const_export_func_iterator
237         I = mRSContext->export_funcs_begin(),
238         E = mRSContext->export_funcs_end(); I != E; I++) {
239     const RSExportFunc *ef = *I;
240 
241     stringstream ss;
242     makeFunctionSignature(ss, false, ef);
243     write(ss);
244   }
245 
246   decIndent();
247   write("};");
248   return true;
249 }
250 
writeBC()251 bool RSReflectionCpp::writeBC() {
252   FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
253   if (pfin == NULL) {
254     fprintf(stderr, "Error: could not read file %s\n",
255             mOutputBCFileName.c_str());
256     return false;
257   }
258 
259   unsigned char buf[16];
260   int read_length;
261   write("static const unsigned char __txt[] = {");
262   incIndent();
263   while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
264     string s;
265     for (int i = 0; i < read_length; i++) {
266       char buf2[16];
267       snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
268       s += buf2;
269     }
270     write(s);
271   }
272   decIndent();
273   write("};");
274   write("");
275   return true;
276 }
277 
makeImpl(const std::string & baseClass)278 bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
279   startFile(mClassName + ".cpp");
280 
281   write("");
282   write("#include \"" + mClassName + ".h\"");
283   write("");
284 
285   writeBC();
286 
287   // Imports
288   //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
289       //out() << "import " << Import[i] << ";" << std::endl;
290   //out() << std::endl;
291 
292   write("\n");
293   stringstream ss;
294   ss << mClassName << "::" << mClassName
295      << "(android::sp<android::RSC::RS> rs, const char *cacheDir, "
296         "size_t cacheDirLength) :\n"
297         "        ScriptC(rs, __txt, sizeof(__txt), \""
298      << mClassName << "\", " << mClassName.length()
299      << ", cacheDir, cacheDirLength) {";
300   write(ss);
301   incIndent();
302   //...
303   decIndent();
304   write("}");
305   write("");
306 
307   write(mClassName + "::~" + mClassName + "() {");
308   write("}");
309   write("");
310 
311   // Reflect export for each functions
312   uint32_t slot = 0;
313   for (RSContext::const_export_foreach_iterator
314        I = mRSContext->export_foreach_begin(),
315        E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
316     const RSExportForEach *ef = *I;
317     if (ef->isDummyRoot()) {
318       write("// No forEach_root(...)");
319       continue;
320     }
321 
322     stringstream tmp;
323     ArgTy Args;
324     tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
325 
326     if (ef->hasIn()) {
327       Args.push_back(std::make_pair(
328           "android::sp<const android::RSC::Allocation>", "ain"));
329     }
330 
331     if (ef->hasOut() || ef->hasReturn()) {
332       Args.push_back(std::make_pair(
333           "android::sp<const android::RSC::Allocation>", "aout"));
334     }
335 
336     const RSExportRecordType *ERT = ef->getParamPacketType();
337     if (ERT) {
338       for (RSExportForEach::const_param_iterator i = ef->params_begin(),
339            e = ef->params_end(); i != e; i++) {
340         RSReflectionTypeData rtd;
341         (*i)->getType()->convertToRTD(&rtd);
342         Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
343       }
344     }
345     makeArgs(tmp, Args);
346 
347     tmp << ") {";
348     write(tmp);
349     tmp.str("");
350 
351     std::string FieldPackerName = ef->getName() + "_fp";
352     if (ERT) {
353       if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
354         genPackVarOfType(ERT, NULL, FieldPackerName.c_str());
355       }
356     }
357     tmp << "    forEach(" << slot << ", ";
358 
359     if (ef->hasIn()) {
360       tmp << "ain, ";
361     } else {
362       tmp << "NULL, ";
363     }
364 
365     if (ef->hasOut() || ef->hasReturn()) {
366       tmp << "aout, ";
367     } else {
368       tmp << "NULL, ";
369     }
370 
371     tmp << "NULL, 0);";
372     write(tmp);
373 
374     write("}");
375     write("");
376   }
377 
378   slot = 0;
379   // Reflect export function
380   for (RSContext::const_export_func_iterator
381        I = mRSContext->export_funcs_begin(),
382        E = mRSContext->export_funcs_end(); I != E; I++) {
383     const RSExportFunc *ef = *I;
384 
385     stringstream ss;
386     makeFunctionSignature(ss, true, ef);
387     write(ss);
388     ss.str("");
389     const RSExportRecordType *params = ef->getParamPacketType();
390     size_t param_len = 0;
391     if (params) {
392       param_len = RSExportType::GetTypeAllocSize(params);
393       if (genCreateFieldPacker(params, "__fp")) {
394         genPackVarOfType(params, NULL, "__fp");
395       }
396     }
397 
398     ss.str("");
399     ss << "    invoke(" << slot;
400     if (params) {
401       ss << ", __fp.getData(), " << param_len << ");";
402     } else {
403       ss << ", NULL, 0);";
404     }
405     write(ss);
406 
407     write("}");
408     write("");
409 
410     slot++;
411   }
412 
413   decIndent();
414   return true;
415 }
416 
genExportVariable(const RSExportVar * EV)417 void RSReflectionCpp::genExportVariable(const RSExportVar *EV) {
418   const RSExportType *ET = EV->getType();
419 
420   switch (ET->getClass()) {
421     case RSExportType::ExportClassPrimitive: {
422       genPrimitiveTypeExportVariable(EV);
423       break;
424     }
425     case RSExportType::ExportClassPointer: {
426       genPointerTypeExportVariable(EV);
427       break;
428     }
429     case RSExportType::ExportClassVector: {
430       genVectorTypeExportVariable(EV);
431       break;
432     }
433     case RSExportType::ExportClassMatrix: {
434       genMatrixTypeExportVariable(EV);
435       break;
436     }
437     case RSExportType::ExportClassConstantArray: {
438       genConstantArrayTypeExportVariable(EV);
439       break;
440     }
441     case RSExportType::ExportClassRecord: {
442       genRecordTypeExportVariable(EV);
443       break;
444     }
445     default: {
446       slangAssert(false && "Unknown class of type");
447     }
448   }
449 }
450 
451 
genPrimitiveTypeExportVariable(const RSExportVar * EV)452 void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) {
453   RSReflectionTypeData rtd;
454   EV->getType()->convertToRTD(&rtd);
455 
456   if (!EV->isConst()) {
457     write(string("void set_") + EV->getName() + "(" + rtd.type->c_name +
458           " v) {");
459     stringstream tmp;
460     tmp << getNextExportVarSlot();
461     write(string("    setVar(") + tmp.str() + ", &v, sizeof(v));");
462     write(string("    __") + EV->getName() + " = v;");
463     write("}");
464   }
465   write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {");
466   if (EV->isConst()) {
467     const clang::APValue &val = EV->getInit();
468     bool isBool = !strcmp(rtd.type->c_name, "bool");
469     write(string("    return ") + genInitValue(val, isBool) + ";");
470   } else {
471     write(string("    return __") + EV->getName() + ";");
472   }
473   write("}");
474   write("");
475 }
476 
genPointerTypeExportVariable(const RSExportVar * EV)477 void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
478   const RSExportType *ET = EV->getType();
479 
480   slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
481               "Variable should be type of pointer here");
482 
483   std::string TypeName = GetTypeName(ET);
484   std::string VarName = EV->getName();
485 
486   RSReflectionTypeData rtd;
487   EV->getType()->convertToRTD(&rtd);
488   uint32_t slot = getNextExportVarSlot();
489 
490   if (!EV->isConst()) {
491     write(string("void bind_") + VarName + "(" + TypeName +
492           " v) {");
493     stringstream tmp;
494     tmp << slot;
495     write(string("    bindAllocation(v, ") + tmp.str() + ");");
496     write(string("    __") + VarName + " = v;");
497     write("}");
498   }
499   write(TypeName + " get_" + VarName + "() const {");
500   if (EV->isConst()) {
501     const clang::APValue &val = EV->getInit();
502     bool isBool = !strcmp(TypeName.c_str(), "bool");
503     write(string("    return ") + genInitValue(val, isBool) + ";");
504   } else {
505     write(string("    return __") + VarName + ";");
506   }
507   write("}");
508   write("");
509 
510 }
511 
genVectorTypeExportVariable(const RSExportVar * EV)512 void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) {
513   slangAssert(false);
514 }
515 
genMatrixTypeExportVariable(const RSExportVar * EV)516 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
517   slangAssert(false);
518 }
519 
genConstantArrayTypeExportVariable(const RSExportVar * EV)520 void RSReflectionCpp::genConstantArrayTypeExportVariable(
521     const RSExportVar *EV) {
522   slangAssert(false);
523 }
524 
genRecordTypeExportVariable(const RSExportVar * EV)525 void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) {
526   slangAssert(false);
527 }
528 
529 
makeFunctionSignature(std::stringstream & ss,bool isDefinition,const RSExportFunc * ef)530 void RSReflectionCpp::makeFunctionSignature(
531     std::stringstream &ss,
532     bool isDefinition,
533     const RSExportFunc *ef) {
534   ss << "void ";
535   if (isDefinition) {
536     ss << mClassName << "::";
537   }
538   ss << "invoke_" << ef->getName() << "(";
539 
540   if (ef->getParamPacketType()) {
541     bool FirstArg = true;
542     for (RSExportFunc::const_param_iterator i = ef->params_begin(),
543          e = ef->params_end(); i != e; i++) {
544       RSReflectionTypeData rtd;
545       (*i)->getType()->convertToRTD(&rtd);
546       if (!FirstArg) {
547         ss << ", ";
548       } else {
549         FirstArg = false;
550       }
551       ss << rtd.type->c_name << " " << (*i)->getName();
552     }
553   }
554 
555   if (isDefinition) {
556     ss << ") {";
557   } else {
558     ss << ");";
559   }
560 }
561 
makeArgs(std::stringstream & ss,const ArgTy & Args)562 void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) {
563   bool FirstArg = true;
564 
565   for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) {
566     if (!FirstArg) {
567       ss << ", ";
568     } else {
569       FirstArg = false;
570     }
571 
572     ss << I->first << " " << I->second;
573   }
574 }
575 
genCreateFieldPacker(const RSExportType * ET,const char * FieldPackerName)576 bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
577                                            const char *FieldPackerName) {
578   size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
579 
580   if (AllocSize > 0) {
581     std::stringstream ss;
582     ss << "    FieldPacker " << FieldPackerName << "("
583        << AllocSize << ");";
584     write(ss);
585     return true;
586   }
587 
588   return false;
589 }
590 
genPackVarOfType(const RSExportType * ET,const char * VarName,const char * FieldPackerName)591 void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
592                                        const char *VarName,
593                                        const char *FieldPackerName) {
594   std::stringstream ss;
595   switch (ET->getClass()) {
596     case RSExportType::ExportClassPrimitive:
597     case RSExportType::ExportClassVector:
598     case RSExportType::ExportClassPointer:
599     case RSExportType::ExportClassMatrix: {
600       RSReflectionTypeData rtd;
601       ET->convertToRTD(&rtd);
602       ss << "    " << FieldPackerName << ".add(" << VarName << ");";
603       write(ss);
604       break;
605     }
606     case RSExportType::ExportClassConstantArray: {
607       /*const RSExportConstantArrayType *ECAT =
608           static_cast<const RSExportConstantArrayType *>(ET);
609 
610       // TODO(zonr): more elegant way. Currently, we obtain the unique index
611       //             variable (this method involves recursive call which means
612       //             we may have more than one level loop, therefore we can't
613       //             always use the same index variable name here) name given
614       //             in the for-loop from counting the '.' in @VarName.
615       unsigned Level = 0;
616       size_t LastDotPos = 0;
617       std::string ElementVarName(VarName);
618 
619       while (LastDotPos != std::string::npos) {
620         LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
621         Level++;
622       }
623       std::string IndexVarName("ct");
624       IndexVarName.append(llvm::utostr_32(Level));
625 
626       C.indent() << "for (int " << IndexVarName << " = 0; " <<
627                           IndexVarName << " < " << ECAT->getSize() << "; " <<
628                           IndexVarName << "++)";
629       C.startBlock();
630 
631       ElementVarName.append("[" + IndexVarName + "]");
632       genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
633                        FieldPackerName);
634 
635       C.endBlock();*/
636       break;
637     }
638     case RSExportType::ExportClassRecord: {
639       const RSExportRecordType *ERT =
640           static_cast<const RSExportRecordType*>(ET);
641       // Relative pos from now on in field packer
642       unsigned Pos = 0;
643 
644       for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
645                E = ERT->fields_end();
646            I != E;
647            I++) {
648         const RSExportRecordType::Field *F = *I;
649         std::string FieldName;
650         size_t FieldOffset = F->getOffsetInParent();
651         size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
652         size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
653 
654         if (VarName != NULL)
655           FieldName = VarName + ("." + F->getName());
656         else
657           FieldName = F->getName();
658 
659         if (FieldOffset > Pos) {
660           ss.str("");
661           ss << "    " << FieldPackerName << ".skip("
662              << (FieldOffset - Pos) << ");";
663           write(ss);
664         }
665 
666         genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
667 
668         // There is padding in the field type
669         if (FieldAllocSize > FieldStoreSize) {
670           ss.str("");
671           ss << "    " << FieldPackerName << ".skip("
672              << (FieldAllocSize - FieldStoreSize) << ");";
673           write(ss);
674         }
675 
676         Pos = FieldOffset + FieldAllocSize;
677       }
678 
679       // There maybe some padding after the struct
680       if (RSExportType::GetTypeAllocSize(ERT) > Pos) {
681         ss.str("");
682         ss << "    " << FieldPackerName << ".skip("
683            << RSExportType::GetTypeAllocSize(ERT) - Pos << ");";
684         write(ss);
685       }
686       break;
687     }
688     default: {
689       slangAssert(false && "Unknown class of type");
690     }
691   }
692 }
693 
694 }  // namespace slang
695