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