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