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 #include <iostream>
     21 
     22 #include <cstdarg>
     23 #include <cctype>
     24 
     25 #include <algorithm>
     26 #include <sstream>
     27 #include <string>
     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 
     37 #include "slang_rs_reflection_cpp.h"
     38 
     39 using namespace std;
     40 
     41 namespace slang {
     42 
     43 const char kRsTypeItemClassName[] = "Item";
     44 const char kRsElemPrefix[] = "__rs_elem_";
     45 // The name of the Allocation type that is reflected in C++
     46 const char kAllocationSp[] = "android::RSC::sp<android::RSC::Allocation>";
     47 
     48 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
     49   static const char *MatrixTypeCNameMap[] = {
     50       "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
     51   };
     52   unsigned Dim = EMT->getDim();
     53 
     54   if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
     55     return MatrixTypeCNameMap[EMT->getDim() - 2];
     56 
     57   slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
     58   return nullptr;
     59 }
     60 
     61 static std::string GetTypeName(const RSExportType *ET, bool PreIdentifier = true) {
     62   if((!PreIdentifier) && (ET->getClass() != RSExportType::ExportClassConstantArray)) {
     63     slangAssert(false && "Non-array type post identifier?");
     64     return "";
     65   }
     66   switch (ET->getClass()) {
     67   case RSExportType::ExportClassPrimitive: {
     68     const RSExportPrimitiveType *EPT =
     69         static_cast<const RSExportPrimitiveType *>(ET);
     70     if (EPT->isRSObjectType()) {
     71       return std::string("android::RSC::sp<const android::RSC::") +
     72              RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
     73     } else {
     74       return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
     75     }
     76   }
     77   case RSExportType::ExportClassPointer: {
     78     const RSExportType *PointeeType =
     79         static_cast<const RSExportPointerType *>(ET)->getPointeeType();
     80 
     81     if (PointeeType->getClass() != RSExportType::ExportClassRecord)
     82       return kAllocationSp;
     83     else
     84       return PointeeType->getElementName();
     85   }
     86   case RSExportType::ExportClassVector: {
     87     const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
     88     std::stringstream VecName;
     89     VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
     90             << EVT->getNumElement();
     91     return VecName.str();
     92   }
     93   case RSExportType::ExportClassMatrix: {
     94     return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
     95   }
     96   case RSExportType::ExportClassConstantArray: {
     97     const RSExportConstantArrayType *CAT =
     98         static_cast<const RSExportConstantArrayType *>(ET);
     99     if (PreIdentifier) {
    100       std::string ElementTypeName = GetTypeName(CAT->getElementType());
    101       return ElementTypeName;
    102     }
    103     else {
    104       std::stringstream ArraySpec;
    105       ArraySpec << "[" << CAT->getNumElement() << "]";
    106       return ArraySpec.str();
    107     }
    108   }
    109   case RSExportType::ExportClassRecord: {
    110     // TODO: Fix for C structs!
    111     return ET->getElementName() + "." + kRsTypeItemClassName;
    112   }
    113   default: { slangAssert(false && "Unknown class of type"); }
    114   }
    115 
    116   return "";
    117 }
    118 
    119 RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
    120                                  const string &OutputDirectory,
    121                                  const string &RSSourceFileName,
    122                                  const string &BitCodeFileName)
    123     : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
    124       mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
    125       mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0) {
    126   mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
    127   mClassName = "ScriptC_" + mCleanedRSFileName;
    128 }
    129 
    130 RSReflectionCpp::~RSReflectionCpp() {}
    131 
    132 bool RSReflectionCpp::reflect() {
    133   writeHeaderFile();
    134   writeImplementationFile();
    135 
    136   return true;
    137 }
    138 
    139 #define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
    140 
    141 bool RSReflectionCpp::writeHeaderFile() {
    142   // Create the file and write the license note.
    143   if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
    144                       mRSContext->getLicenseNote(), false,
    145                       mRSContext->getVerbose())) {
    146     return false;
    147   }
    148 
    149   mOut.indent() << "#include \"RenderScript.h\"\n\n";
    150   mOut.indent() << "using namespace android::RSC;\n\n";
    151 
    152   mOut.comment("This class encapsulates access to the exported elements of the script.  "
    153                "Typically, you would instantiate this class once, call the set_* methods "
    154                "for each of the exported global variables you want to change, then call "
    155                "one of the forEach_ methods to invoke a kernel.");
    156   mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
    157   mOut.startBlock();
    158 
    159   mOut.decreaseIndent();
    160   mOut.indent() << "private:\n";
    161   mOut.increaseIndent();
    162 
    163   genFieldsToStoreExportVariableValues();
    164   genTypeInstancesUsedInForEach();
    165   genFieldsForAllocationTypeVerification();
    166 
    167   mOut.decreaseIndent();
    168   mOut.indent() << "public:\n";
    169   mOut.increaseIndent();
    170 
    171   // Generate the constructor and destructor declarations.
    172   mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
    173   mOut.indent() << "virtual ~" << mClassName << "();\n\n";
    174 
    175   genExportVariablesGetterAndSetter();
    176   genForEachDeclarations();
    177   genExportFunctionDeclarations();
    178 
    179   mOut.endBlock(true);
    180   mOut.closeFile();
    181   return true;
    182 }
    183 
    184 void RSReflectionCpp::genTypeInstancesUsedInForEach() {
    185   for (auto I = mRSContext->export_foreach_begin(),
    186             E = mRSContext->export_foreach_end();
    187        I != E; I++) {
    188     const RSExportForEach *EF = *I;
    189     const RSExportType *OET = EF->getOutType();
    190 
    191     if (OET) {
    192       genTypeInstanceFromPointer(OET);
    193     }
    194 
    195     const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
    196 
    197     for (RSExportForEach::InTypeIter BI = InTypes.begin(),
    198          EI = InTypes.end(); BI != EI; BI++) {
    199 
    200       genTypeInstanceFromPointer(*BI);
    201     }
    202   }
    203 }
    204 
    205 void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
    206   bool CommentAdded = false;
    207   for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
    208                                        E = mTypesToCheck.end();
    209        I != E; I++) {
    210     if (!CommentAdded) {
    211       mOut.comment("The following elements are used to verify the types of "
    212                    "allocations passed to kernels.");
    213       CommentAdded = true;
    214     }
    215     mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
    216                   << kRsElemPrefix << *I << ";\n";
    217   }
    218 }
    219 
    220 void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
    221   bool CommentAdded = false;
    222   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    223                                             E = mRSContext->export_vars_end();
    224        I != E; I++) {
    225     const RSExportVar *ev = *I;
    226     if (ev->isConst()) {
    227       continue;
    228     }
    229     if (!CommentAdded) {
    230       mOut.comment("For each non-const variable exported by the script, we "
    231                    "have an equivalent field.  This field contains the last "
    232                    "value this variable was set to using the set_ method.  "
    233                    "This may not be current value of the variable in the "
    234                    "script, as the script is free to modify its internal "
    235                    "variable without changing this field.  If the script "
    236                    "initializes the exported variable, the constructor will "
    237                    "initialize this field to the same value.");
    238       CommentAdded = true;
    239     }
    240     mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
    241                   << ev->getName() << ";\n";
    242   }
    243 }
    244 
    245 void RSReflectionCpp::genForEachDeclarations() {
    246   bool CommentAdded = false;
    247   for (RSContext::const_export_foreach_iterator
    248            I = mRSContext->export_foreach_begin(),
    249            E = mRSContext->export_foreach_end();
    250        I != E; I++) {
    251     const RSExportForEach *ForEach = *I;
    252 
    253     if (ForEach->isDummyRoot()) {
    254       mOut.indent() << "// No forEach_root(...)\n";
    255       continue;
    256     }
    257 
    258     if (!CommentAdded) {
    259       mOut.comment("For each kernel of the script corresponds one method.  "
    260                    "That method queues the kernel for execution.  The kernel "
    261                    "may not have completed nor even started by the time this "
    262                    "function returns.  Calls that extract the data out of the "
    263                    "output allocation will wait for the kernels to complete.");
    264       CommentAdded = true;
    265     }
    266 
    267     std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
    268     mOut.indent() << FunctionStart;
    269 
    270     ArgumentList Arguments;
    271     const RSExportForEach::InVec &Ins = ForEach->getIns();
    272     for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
    273          BI != EI; BI++) {
    274 
    275       Arguments.push_back(Argument(kAllocationSp, (*BI)->getName()));
    276     }
    277 
    278     if (ForEach->hasOut() || ForEach->hasReturn()) {
    279       Arguments.push_back(Argument(kAllocationSp, "aout"));
    280     }
    281 
    282     const RSExportRecordType *ERT = ForEach->getParamPacketType();
    283     if (ERT) {
    284       for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
    285                                                  e = ForEach->params_end();
    286            i != e; i++) {
    287         RSReflectionTypeData rtd;
    288         (*i)->getType()->convertToRTD(&rtd);
    289         Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
    290       }
    291     }
    292     genArguments(Arguments, FunctionStart.length());
    293     mOut << ");\n";
    294   }
    295 }
    296 
    297 void RSReflectionCpp::genExportFunctionDeclarations() {
    298   for (RSContext::const_export_func_iterator
    299            I = mRSContext->export_funcs_begin(),
    300            E = mRSContext->export_funcs_end();
    301        I != E; I++) {
    302     const RSExportFunc *ef = *I;
    303 
    304     makeFunctionSignature(false, ef);
    305   }
    306 }
    307 
    308 // forEach_* implementation
    309 void RSReflectionCpp::genExportForEachBodies() {
    310   uint32_t slot = 0;
    311   for (auto I = mRSContext->export_foreach_begin(),
    312             E = mRSContext->export_foreach_end();
    313        I != E; I++, slot++) {
    314     const RSExportForEach *ef = *I;
    315     if (ef->isDummyRoot()) {
    316       mOut.indent() << "// No forEach_root(...)\n";
    317       continue;
    318     }
    319 
    320     ArgumentList Arguments;
    321     std::string FunctionStart =
    322         "void " + mClassName + "::forEach_" + ef->getName() + "(";
    323     mOut.indent() << FunctionStart;
    324 
    325     if (ef->hasIns()) {
    326       // FIXME: Add support for kernels with multiple inputs.
    327       slangAssert(ef->getIns().size() == 1);
    328       Arguments.push_back(Argument(kAllocationSp, "ain"));
    329     }
    330 
    331     if (ef->hasOut() || ef->hasReturn()) {
    332       Arguments.push_back(Argument(kAllocationSp, "aout"));
    333     }
    334 
    335     const RSExportRecordType *ERT = ef->getParamPacketType();
    336     if (ERT) {
    337       for (RSExportForEach::const_param_iterator i = ef->params_begin(),
    338                                                  e = ef->params_end();
    339            i != e; i++) {
    340         RSReflectionTypeData rtd;
    341         (*i)->getType()->convertToRTD(&rtd);
    342         Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
    343       }
    344     }
    345     genArguments(Arguments, FunctionStart.length());
    346     mOut << ")";
    347     mOut.startBlock();
    348 
    349     const RSExportType *OET = ef->getOutType();
    350     const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
    351     if (ef->hasIns()) {
    352       // FIXME: Add support for kernels with multiple inputs.
    353       slangAssert(ef->getIns().size() == 1);
    354       genTypeCheck(InTypes[0], "ain");
    355     }
    356     if (OET) {
    357       genTypeCheck(OET, "aout");
    358     }
    359 
    360     // TODO Add the appropriate dimension checking code, as seen in
    361     // slang_rs_reflection.cpp.
    362 
    363     std::string FieldPackerName = ef->getName() + "_fp";
    364     if (ERT) {
    365       if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
    366         genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
    367       }
    368     }
    369     mOut.indent() << "forEach(" << slot << ", ";
    370 
    371     if (ef->hasIns()) {
    372       // FIXME: Add support for kernels with multiple inputs.
    373       slangAssert(ef->getIns().size() == 1);
    374       mOut << "ain, ";
    375     } else {
    376       mOut << "NULL, ";
    377     }
    378 
    379     if (ef->hasOut() || ef->hasReturn()) {
    380       mOut << "aout, ";
    381     } else {
    382       mOut << "NULL, ";
    383     }
    384 
    385     // FIXME (no support for usrData with C++ kernels)
    386     mOut << "NULL, 0);\n";
    387     mOut.endBlock();
    388   }
    389 }
    390 
    391 // invoke_* implementation
    392 void RSReflectionCpp::genExportFunctionBodies() {
    393   uint32_t slot = 0;
    394   // Reflect export function
    395   for (auto I = mRSContext->export_funcs_begin(),
    396             E = mRSContext->export_funcs_end();
    397        I != E; I++) {
    398     const RSExportFunc *ef = *I;
    399 
    400     makeFunctionSignature(true, ef);
    401     mOut.startBlock();
    402     const RSExportRecordType *params = ef->getParamPacketType();
    403     size_t param_len = 0;
    404     if (params) {
    405       param_len = params->getAllocSize();
    406       if (genCreateFieldPacker(params, "__fp")) {
    407         genPackVarOfType(params, nullptr, "__fp");
    408       }
    409     }
    410 
    411     mOut.indent() << "invoke(" << slot;
    412     if (params) {
    413       mOut << ", __fp.getData(), " << param_len << ");\n";
    414     } else {
    415       mOut << ", NULL, 0);\n";
    416     }
    417     mOut.endBlock();
    418 
    419     slot++;
    420   }
    421 }
    422 
    423 bool RSReflectionCpp::genEncodedBitCode() {
    424   FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
    425   if (pfin == nullptr) {
    426     fprintf(stderr, "Error: could not read file %s\n",
    427             mBitCodeFilePath.c_str());
    428     return false;
    429   }
    430 
    431   unsigned char buf[16];
    432   int read_length;
    433   mOut.indent() << "static const unsigned char __txt[] =";
    434   mOut.startBlock();
    435   while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
    436     mOut.indent();
    437     for (int i = 0; i < read_length; i++) {
    438       char buf2[16];
    439       snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
    440       mOut << buf2;
    441     }
    442     mOut << "\n";
    443   }
    444   mOut.endBlock(true);
    445   mOut << "\n";
    446   return true;
    447 }
    448 
    449 bool RSReflectionCpp::writeImplementationFile() {
    450   if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
    451                       mRSContext->getLicenseNote(), false,
    452                       mRSContext->getVerbose())) {
    453     return false;
    454   }
    455 
    456   // Front matter
    457   mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
    458 
    459   genEncodedBitCode();
    460   mOut.indent() << "\n\n";
    461 
    462   // Constructor
    463   const std::string &packageName = mRSContext->getReflectJavaPackageName();
    464   mOut.indent() << mClassName << "::" << mClassName
    465                 << "(android::RSC::sp<android::RSC::RS> rs):\n"
    466                    "        ScriptC(rs, __txt, sizeof(__txt), \""
    467                 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
    468                 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
    469                 << packageName << "\"))";
    470   mOut.startBlock();
    471   for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
    472                                        E = mTypesToCheck.end();
    473        I != E; I++) {
    474     mOut.indent() << kRsElemPrefix << *I << " = android::RSC::Element::" << *I
    475                   << "(mRS);\n";
    476   }
    477 
    478   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    479                                             E = mRSContext->export_vars_end();
    480        I != E; I++) {
    481     const RSExportVar *EV = *I;
    482     if (!EV->getInit().isUninit()) {
    483       genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
    484     } else {
    485       genZeroInitExportVariable(EV->getName());
    486     }
    487   }
    488   mOut.endBlock();
    489 
    490   // Destructor
    491   mOut.indent() << mClassName << "::~" << mClassName << "()";
    492   mOut.startBlock();
    493   mOut.endBlock();
    494 
    495   // Function bodies
    496   genExportForEachBodies();
    497   genExportFunctionBodies();
    498 
    499   mOut.closeFile();
    500   return true;
    501 }
    502 
    503 void RSReflectionCpp::genExportVariablesGetterAndSetter() {
    504   mOut.comment("Methods to set and get the variables exported by the script. "
    505                "Const variables will not have a setter.\n\n"
    506                "Note that the value returned by the getter may not be the "
    507                "current value of the variable in the script.  The getter will "
    508                "return the initial value of the variable (as defined in the "
    509                "script) or the the last value set by using the setter method.  "
    510                "The script is free to modify its value independently.");
    511   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    512                                             E = mRSContext->export_vars_end();
    513        I != E; I++) {
    514     const RSExportVar *EV = *I;
    515     const RSExportType *ET = EV->getType();
    516 
    517     switch (ET->getClass()) {
    518     case RSExportType::ExportClassPrimitive: {
    519       genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
    520       break;
    521     }
    522     case RSExportType::ExportClassPointer: {
    523       // TODO Deprecate this.
    524       genPointerTypeExportVariable(EV);
    525       break;
    526     }
    527     case RSExportType::ExportClassVector: {
    528       genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
    529       break;
    530     }
    531     case RSExportType::ExportClassMatrix: {
    532       genMatrixTypeExportVariable(EV);
    533       break;
    534     }
    535     case RSExportType::ExportClassConstantArray: {
    536       genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
    537                          EV);
    538       break;
    539     }
    540     case RSExportType::ExportClassRecord: {
    541       genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
    542       break;
    543     }
    544     default: { slangAssert(false && "Unknown class of type"); }
    545     }
    546   }
    547 }
    548 
    549 void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
    550                                          const RSExportVar *EV) {
    551   RSReflectionTypeData rtd;
    552   EPT->convertToRTD(&rtd);
    553   std::string TypeName = GetTypeName(EPT);
    554 
    555   if (!EV->isConst()) {
    556     mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
    557     mOut.startBlock();
    558     mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
    559     if (EPT->isRSObjectType()) {
    560       mOut << "v";
    561    } else {
    562       mOut << "&v, sizeof(v)";
    563     }
    564     mOut << ");\n";
    565     mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
    566     mOut.endBlock();
    567   }
    568   mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
    569   mOut.startBlock();
    570   if (EV->isConst()) {
    571     const clang::APValue &val = EV->getInit();
    572     bool isBool = !strcmp(TypeName.c_str(), "bool");
    573     mOut.indent() << "return ";
    574     genInitValue(val, isBool);
    575     mOut << ";\n";
    576   } else {
    577     mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
    578                   << ";\n";
    579   }
    580   mOut.endBlock();
    581 }
    582 
    583 void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
    584   const RSExportType *ET = EV->getType();
    585 
    586   slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
    587               "Variable should be type of pointer here");
    588 
    589   std::string TypeName = GetTypeName(ET);
    590   std::string VarName = EV->getName();
    591 
    592   RSReflectionTypeData rtd;
    593   EV->getType()->convertToRTD(&rtd);
    594   uint32_t slot = getNextExportVarSlot();
    595 
    596   if (!EV->isConst()) {
    597     mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
    598     mOut.startBlock();
    599     mOut.indent() << "bindAllocation(v, " << slot << ");\n";
    600     mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
    601     mOut.endBlock();
    602   }
    603   mOut.indent() << TypeName << " get_" << VarName << "() const";
    604   mOut.startBlock();
    605   if (EV->isConst()) {
    606     const clang::APValue &val = EV->getInit();
    607     bool isBool = !strcmp(TypeName.c_str(), "bool");
    608     mOut.indent() << "return ";
    609     genInitValue(val, isBool);
    610     mOut << ";\n";
    611   } else {
    612     mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
    613   }
    614   mOut.endBlock();
    615 }
    616 
    617 void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
    618                                          const RSExportVar *EV) {
    619   slangAssert(EVT != nullptr);
    620 
    621   RSReflectionTypeData rtd;
    622   EVT->convertToRTD(&rtd);
    623 
    624   if (!EV->isConst()) {
    625     mOut.indent() << "void set_" << EV->getName() << "("
    626                   << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
    627                   << " v)";
    628     mOut.startBlock();
    629     mOut.indent() << "setVar(" << getNextExportVarSlot()
    630                   << ", &v, sizeof(v));\n";
    631     mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
    632     mOut.endBlock();
    633   }
    634   mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
    635                 << " get_" << EV->getName() << "() const";
    636   mOut.startBlock();
    637   if (EV->isConst()) {
    638     const clang::APValue &val = EV->getInit();
    639     mOut.indent() << "return ";
    640     genInitValue(val, false);
    641     mOut << ";\n";
    642   } else {
    643     mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
    644                   << ";\n";
    645   }
    646   mOut.endBlock();
    647 }
    648 
    649 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
    650   uint32_t slot = getNextExportVarSlot();
    651   stringstream tmp;
    652   tmp << slot;
    653 
    654   const RSExportType *ET = EV->getType();
    655   if (ET->getName() == "rs_matrix4x4") {
    656     mOut.indent() << "void set_" << EV->getName() << "(float v[16])";
    657     mOut.startBlock();
    658     mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*16);\n";
    659     mOut.endBlock();
    660   } else if (ET->getName() == "rs_matrix3x3") {
    661     mOut.indent() << "void set_" << EV->getName() << "(float v[9])";
    662     mOut.startBlock();
    663     mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*9);";
    664     mOut.endBlock();
    665   } else if (ET->getName() == "rs_matrix2x2") {
    666     mOut.indent() << "void set_" << EV->getName() << "(float v[4])";
    667     mOut.startBlock();
    668     mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*4);";
    669     mOut.endBlock();
    670   } else {
    671     mOut.indent() << "#error: TODO: " << ET->getName();
    672     slangAssert(false);
    673   }
    674 }
    675 
    676 void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
    677                                          const RSExportVar *EV) {
    678   std::stringstream ArraySpec;
    679   const RSExportType *ET = EV->getType();
    680 
    681   const RSExportConstantArrayType *CAT =
    682       static_cast<const RSExportConstantArrayType *>(ET);
    683 
    684   uint32_t slot = getNextExportVarSlot();
    685   stringstream tmp;
    686   tmp << slot;
    687 
    688   ArraySpec << CAT->getNumElement();
    689   mOut.indent() << "void set_" << EV->getName() << "(" << GetTypeName(EV->getType()) << " v "
    690       << GetTypeName(EV->getType(), false) << ")";
    691   mOut.startBlock();
    692   mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(" << GetTypeName(EV->getType()) + ") *"
    693       << ArraySpec.str() << ");";
    694   mOut.endBlock();
    695 }
    696 
    697 void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
    698                                          const RSExportVar *EV) {
    699   slangAssert(false);
    700 }
    701 
    702 void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
    703                                             const RSExportFunc *ef) {
    704   mOut.indent() << "void ";
    705   if (isDefinition) {
    706     mOut << mClassName << "::";
    707   }
    708   mOut << "invoke_" << ef->getName() << "(";
    709 
    710   if (ef->getParamPacketType()) {
    711     bool FirstArg = true;
    712     for (RSExportFunc::const_param_iterator i = ef->params_begin(),
    713                                             e = ef->params_end();
    714          i != e; i++) {
    715       if (!FirstArg) {
    716         mOut << ", ";
    717       } else {
    718         FirstArg = false;
    719       }
    720       mOut << GetTypeName((*i)->getType()) << " " << (*i)->getName();
    721     }
    722   }
    723 
    724   if (isDefinition) {
    725     mOut << ")";
    726   } else {
    727     mOut << ");\n";
    728   }
    729 }
    730 
    731 void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
    732   bool FirstArg = true;
    733 
    734   for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
    735        I != E; I++) {
    736     if (!FirstArg) {
    737       mOut << ",\n";
    738       mOut.indent() << string(Offset, ' ');
    739     } else {
    740       FirstArg = false;
    741     }
    742 
    743     mOut << I->Type << " " << I->Name;
    744     if (!I->DefaultValue.empty()) {
    745       mOut << " = " << I->DefaultValue;
    746     }
    747   }
    748 }
    749 
    750 bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
    751                                            const char *FieldPackerName) {
    752   size_t AllocSize = ET->getAllocSize();
    753 
    754   if (AllocSize > 0) {
    755     mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
    756                   << AllocSize << ");\n";
    757     return true;
    758   }
    759 
    760   return false;
    761 }
    762 
    763 void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
    764                                        const char *VarName,
    765                                        const char *FieldPackerName) {
    766   switch (ET->getClass()) {
    767   case RSExportType::ExportClassPrimitive:
    768   case RSExportType::ExportClassVector:
    769   case RSExportType::ExportClassPointer:
    770   case RSExportType::ExportClassMatrix: {
    771     mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
    772     break;
    773   }
    774   case RSExportType::ExportClassConstantArray: {
    775     /*const RSExportConstantArrayType *ECAT =
    776         static_cast<const RSExportConstantArrayType *>(ET);
    777 
    778     // TODO(zonr): more elegant way. Currently, we obtain the unique index
    779     //             variable (this method involves recursive call which means
    780     //             we may have more than one level loop, therefore we can't
    781     //             always use the same index variable name here) name given
    782     //             in the for-loop from counting the '.' in @VarName.
    783     unsigned Level = 0;
    784     size_t LastDotPos = 0;
    785     std::string ElementVarName(VarName);
    786 
    787   while (LastDotPos != std::string::npos) {
    788     LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
    789     Level++;
    790   }
    791   std::string IndexVarName("ct");
    792   IndexVarName.append(llvm::utostr_32(Level));
    793 
    794   C.indent() << "for (int " << IndexVarName << " = 0; " <<
    795                       IndexVarName << " < " << ECAT->getSize() << "; " <<
    796                       IndexVarName << "++)";
    797   C.startBlock();
    798 
    799   ElementVarName.append("[" + IndexVarName + "]");
    800   genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
    801                    FieldPackerName);
    802 
    803   C.endBlock();*/
    804     break;
    805   }
    806   case RSExportType::ExportClassRecord: {
    807     const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
    808     // Relative pos from now on in field packer
    809     unsigned Pos = 0;
    810 
    811     for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
    812                                                   E = ERT->fields_end();
    813          I != E; I++) {
    814       const RSExportRecordType::Field *F = *I;
    815       std::string FieldName;
    816       size_t FieldOffset = F->getOffsetInParent();
    817       const RSExportType *T = F->getType();
    818       size_t FieldStoreSize = T->getStoreSize();
    819       size_t FieldAllocSize = T->getAllocSize();
    820 
    821       if (VarName != nullptr)
    822         FieldName = VarName + ("." + F->getName());
    823       else
    824         FieldName = F->getName();
    825 
    826       if (FieldOffset > Pos) {
    827         mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
    828                       << ");\n";
    829       }
    830 
    831       genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
    832 
    833       // There is padding in the field type
    834       if (FieldAllocSize > FieldStoreSize) {
    835         mOut.indent() << FieldPackerName << ".skip("
    836                       << (FieldAllocSize - FieldStoreSize) << ");\n";
    837       }
    838 
    839       Pos = FieldOffset + FieldAllocSize;
    840     }
    841 
    842     // There maybe some padding after the struct
    843     if (ERT->getAllocSize() > Pos) {
    844       mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
    845                     << ");\n";
    846     }
    847     break;
    848   }
    849   default: { slangAssert(false && "Unknown class of type"); }
    850   }
    851 }
    852 
    853 void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
    854                                    const char *VarName) {
    855   mOut.indent() << "// Type check for " << VarName << "\n";
    856 
    857   if (ET->getClass() == RSExportType::ExportClassPointer) {
    858     const RSExportPointerType *EPT =
    859         static_cast<const RSExportPointerType *>(ET);
    860     ET = EPT->getPointeeType();
    861   }
    862 
    863   std::string TypeName;
    864   switch (ET->getClass()) {
    865   case RSExportType::ExportClassPrimitive:
    866   case RSExportType::ExportClassVector:
    867   case RSExportType::ExportClassRecord: {
    868     TypeName = ET->getElementName();
    869     break;
    870   }
    871 
    872   default:
    873     break;
    874   }
    875 
    876   if (!TypeName.empty()) {
    877     mOut.indent() << "if (!" << VarName
    878                   << "->getType()->getElement()->isCompatible("
    879                   << kRsElemPrefix << TypeName << "))";
    880     mOut.startBlock();
    881     mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
    882                      "\"Incompatible type\");\n";
    883     mOut.indent() << "return;\n";
    884     mOut.endBlock();
    885   }
    886 }
    887 
    888 void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
    889   if (ET->getClass() == RSExportType::ExportClassPointer) {
    890     // For pointer parameters to original forEach kernels.
    891     const RSExportPointerType *EPT =
    892         static_cast<const RSExportPointerType *>(ET);
    893     genTypeInstance(EPT->getPointeeType());
    894   } else {
    895     // For handling pass-by-value kernel parameters.
    896     genTypeInstance(ET);
    897   }
    898 }
    899 
    900 void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
    901   switch (ET->getClass()) {
    902   case RSExportType::ExportClassPrimitive:
    903   case RSExportType::ExportClassVector:
    904   case RSExportType::ExportClassConstantArray:
    905   case RSExportType::ExportClassRecord: {
    906     std::string TypeName = ET->getElementName();
    907     mTypesToCheck.insert(TypeName);
    908     break;
    909   }
    910 
    911   default:
    912     break;
    913   }
    914 }
    915 
    916 void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
    917                                             const std::string &VarName,
    918                                             const clang::APValue &Val) {
    919   slangAssert(!Val.isUninit() && "Not a valid initializer");
    920 
    921   switch (ET->getClass()) {
    922   case RSExportType::ExportClassPrimitive: {
    923     const RSExportPrimitiveType *EPT =
    924         static_cast<const RSExportPrimitiveType *>(ET);
    925     if (EPT->getType() == DataTypeBoolean) {
    926       genInitBoolExportVariable(VarName, Val);
    927     } else {
    928       genInitPrimitiveExportVariable(VarName, Val);
    929     }
    930     break;
    931   }
    932   case RSExportType::ExportClassPointer: {
    933     if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
    934       std::cerr << "Initializer which is non-NULL to pointer type variable "
    935                    "will be ignored" << std::endl;
    936     break;
    937   }
    938   case RSExportType::ExportClassVector: {
    939     const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
    940     switch (Val.getKind()) {
    941     case clang::APValue::Int:
    942     case clang::APValue::Float: {
    943       for (unsigned i = 0; i < EVT->getNumElement(); i++) {
    944         std::string Name = VarName + "." + getVectorAccessor(i);
    945         genInitPrimitiveExportVariable(Name, Val);
    946       }
    947       break;
    948     }
    949     case clang::APValue::Vector: {
    950       unsigned NumElements = std::min(
    951           static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
    952       for (unsigned i = 0; i < NumElements; i++) {
    953         const clang::APValue &ElementVal = Val.getVectorElt(i);
    954         std::string Name = VarName + "." + getVectorAccessor(i);
    955         genInitPrimitiveExportVariable(Name, ElementVal);
    956       }
    957       break;
    958     }
    959     case clang::APValue::MemberPointer:
    960     case clang::APValue::Uninitialized:
    961     case clang::APValue::ComplexInt:
    962     case clang::APValue::ComplexFloat:
    963     case clang::APValue::LValue:
    964     case clang::APValue::Array:
    965     case clang::APValue::Struct:
    966     case clang::APValue::Union:
    967     case clang::APValue::AddrLabelDiff: {
    968       slangAssert(false && "Unexpected type of value of initializer.");
    969     }
    970     }
    971     break;
    972   }
    973   case RSExportType::ExportClassMatrix:
    974   case RSExportType::ExportClassConstantArray:
    975   case RSExportType::ExportClassRecord: {
    976     slangAssert(false && "Unsupported initializer for record/matrix/constant "
    977                          "array type variable currently");
    978     break;
    979   }
    980   default: { slangAssert(false && "Unknown class of type"); }
    981   }
    982 }
    983 
    984 const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
    985   static const char *VectorAccessorMap[] = {/* 0 */ "x",
    986                                             /* 1 */ "y",
    987                                             /* 2 */ "z",
    988                                             /* 3 */ "w",
    989   };
    990 
    991   slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
    992               "Out-of-bound index to access vector member");
    993 
    994   return VectorAccessorMap[Index];
    995 }
    996 
    997 void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
    998   mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
    999                 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
   1000 }
   1001 
   1002 void
   1003 RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
   1004                                                 const clang::APValue &Val) {
   1005   slangAssert(!Val.isUninit() && "Not a valid initializer");
   1006 
   1007   mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
   1008   genInitValue(Val);
   1009   mOut << ";\n";
   1010 }
   1011 
   1012 void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
   1013   switch (Val.getKind()) {
   1014   case clang::APValue::Int: {
   1015     llvm::APInt api = Val.getInt();
   1016     if (asBool) {
   1017       mOut << ((api.getSExtValue() == 0) ? "false" : "true");
   1018     } else {
   1019       // TODO: Handle unsigned correctly for C++
   1020       mOut << api.getSExtValue();
   1021       if (api.getBitWidth() > 32) {
   1022         mOut << "L";
   1023       }
   1024     }
   1025     break;
   1026   }
   1027 
   1028   case clang::APValue::Float: {
   1029     llvm::APFloat apf = Val.getFloat();
   1030     llvm::SmallString<30> s;
   1031     apf.toString(s);
   1032     mOut << s.c_str();
   1033     if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
   1034       if (s.count('.') == 0) {
   1035         mOut << ".f";
   1036       } else {
   1037         mOut << "f";
   1038       }
   1039     }
   1040     break;
   1041   }
   1042 
   1043   case clang::APValue::ComplexInt:
   1044   case clang::APValue::ComplexFloat:
   1045   case clang::APValue::LValue:
   1046   case clang::APValue::Vector: {
   1047     slangAssert(false && "Primitive type cannot have such kind of initializer");
   1048     break;
   1049   }
   1050 
   1051   default: { slangAssert(false && "Unknown kind of initializer"); }
   1052   }
   1053 }
   1054 
   1055 void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
   1056                                                 const clang::APValue &Val) {
   1057   slangAssert(!Val.isUninit() && "Not a valid initializer");
   1058   slangAssert((Val.getKind() == clang::APValue::Int) &&
   1059               "Bool type has wrong initial APValue");
   1060 
   1061   mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
   1062                 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
   1063                 << ";";
   1064 }
   1065 
   1066 } // namespace slang
   1067