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