Home | History | Annotate | Download | only in slang
      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 
     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 
     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 
    113 RSReflectionCpp::RSReflectionCpp(const RSContext *con)
    114     : RSReflectionBase(con) {
    115   clear();
    116 }
    117 
    118 RSReflectionCpp::~RSReflectionCpp() {
    119 }
    120 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    615 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
    616   slangAssert(false);
    617 }
    618 
    619 void RSReflectionCpp::genConstantArrayTypeExportVariable(
    620     const RSExportVar *EV) {
    621   slangAssert(false);
    622 }
    623 
    624 void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) {
    625   slangAssert(false);
    626 }
    627 
    628 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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