Home | History | Annotate | Download | only in slang
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sys/stat.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 
     21 #include <cstdarg>
     22 #include <cctype>
     23 
     24 #include <algorithm>
     25 #include <sstream>
     26 #include <string>
     27 #include <utility>
     28 
     29 #include "os_sep.h"
     30 #include "slang_rs_context.h"
     31 #include "slang_rs_export_var.h"
     32 #include "slang_rs_export_foreach.h"
     33 #include "slang_rs_export_func.h"
     34 #include "slang_rs_reflect_utils.h"
     35 #include "slang_version.h"
     36 #include "slang_utils.h"
     37 
     38 #include "slang_rs_reflection_cpp.h"
     39 
     40 using namespace std;
     41 
     42 namespace slang {
     43 
     44 #define RS_TYPE_ITEM_CLASS_NAME          "Item"
     45 
     46 static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
     47   static const char *MatrixTypeCNameMap[] = {
     48     "rs_matrix2x2",
     49     "rs_matrix3x3",
     50     "rs_matrix4x4",
     51   };
     52   unsigned Dim = EMT->getDim();
     53 
     54   if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char*)))
     55     return MatrixTypeCNameMap[ EMT->getDim() - 2 ];
     56 
     57   slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
     58   return NULL;
     59 }
     60 
     61 
     62 static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
     63   switch (ET->getClass()) {
     64     case RSExportType::ExportClassPrimitive: {
     65       return RSExportPrimitiveType::getRSReflectionType(
     66           static_cast<const RSExportPrimitiveType*>(ET))->c_name;
     67     }
     68     case RSExportType::ExportClassPointer: {
     69       const RSExportType *PointeeType =
     70           static_cast<const RSExportPointerType*>(ET)->getPointeeType();
     71 
     72       if (PointeeType->getClass() != RSExportType::ExportClassRecord)
     73         return "android::sp<android::RSC::Allocation>";
     74       else
     75         return PointeeType->getElementName();
     76     }
     77     case RSExportType::ExportClassVector: {
     78       const RSExportVectorType *EVT =
     79           static_cast<const RSExportVectorType*>(ET);
     80       std::stringstream VecName;
     81       VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
     82               << EVT->getNumElement();
     83       return VecName.str();
     84     }
     85     case RSExportType::ExportClassMatrix: {
     86       return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET));
     87     }
     88     case RSExportType::ExportClassConstantArray: {
     89       // TODO: Fix this for C arrays!
     90       const RSExportConstantArrayType* CAT =
     91           static_cast<const RSExportConstantArrayType*>(ET);
     92       std::string ElementTypeName = GetTypeName(CAT->getElementType());
     93       if (Brackets) {
     94         ElementTypeName.append("[]");
     95       }
     96       return ElementTypeName;
     97     }
     98     case RSExportType::ExportClassRecord: {
     99       // TODO: Fix for C structs!
    100       return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
    101     }
    102     default: {
    103       slangAssert(false && "Unknown class of type");
    104     }
    105   }
    106 
    107   return "";
    108 }
    109 
    110 
    111 RSReflectionCpp::RSReflectionCpp(const RSContext *con)
    112     : RSReflectionBase(con) {
    113   clear();
    114 }
    115 
    116 RSReflectionCpp::~RSReflectionCpp() {
    117 }
    118 
    119 bool RSReflectionCpp::reflect(const string &OutputPathBase,
    120                               const string &InputFileName,
    121                               const string &OutputBCFileName) {
    122   mInputFileName = InputFileName;
    123   mOutputPath = OutputPathBase;
    124   mOutputBCFileName = OutputBCFileName;
    125   mClassName = string("ScriptC_") + stripRS(InputFileName);
    126 
    127   makeHeader("android::RSC::ScriptC");
    128   std::vector< std::string > header(mText);
    129   mText.clear();
    130 
    131   makeImpl("android::RSC::ScriptC");
    132   std::vector< std::string > cpp(mText);
    133   mText.clear();
    134 
    135 
    136   writeFile(mClassName + ".h", header);
    137   writeFile(mClassName + ".cpp", cpp);
    138 
    139 
    140   return true;
    141 }
    142 
    143 
    144 #define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
    145 
    146 
    147 
    148 bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
    149   startFile(mClassName + ".h");
    150 
    151   write("");
    152   write("#include \"RenderScript.h\"");
    153   write("using namespace android::RSC;");
    154   write("");
    155 
    156   // Imports
    157   //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
    158       //out() << "import " << Import[i] << ";" << std::endl;
    159   //out() << std::endl;
    160 
    161   if (!baseClass.empty()) {
    162     write("class " + mClassName + " : public " + baseClass + " {");
    163   } else {
    164     write("class " + mClassName + " {");
    165   }
    166 
    167   write("private:");
    168   uint32_t slot = 0;
    169   incIndent();
    170   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    171          E = mRSContext->export_vars_end(); I != E; I++, slot++) {
    172     const RSExportVar *ev = *I;
    173     RSReflectionTypeData rtd;
    174     ev->getType()->convertToRTD(&rtd);
    175     if (!ev->isConst()) {
    176       write(GetTypeName(ev->getType()) + " __" + ev->getName() + ";");
    177     }
    178   }
    179   decIndent();
    180 
    181   write("public:");
    182   incIndent();
    183   write(mClassName + "(android::sp<android::RSC::RS> rs," +
    184           " const char *cacheDir, size_t cacheDirLength);");
    185   write("virtual ~" + mClassName + "();");
    186   write("");
    187 
    188 
    189   // Reflect export variable
    190   slot = 0;
    191   for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    192          E = mRSContext->export_vars_end(); I != E; I++, slot++) {
    193     genExportVariable(*I);
    194   }
    195 
    196   // Reflect export for each functions
    197   for (RSContext::const_export_foreach_iterator
    198            I = mRSContext->export_foreach_begin(),
    199            E = mRSContext->export_foreach_end(); I != E; I++) {
    200     const RSExportForEach *ef = *I;
    201     if (ef->isDummyRoot()) {
    202       write("// No forEach_root(...)");
    203       continue;
    204     }
    205 
    206     ArgTy Args;
    207     stringstream ss;
    208     ss << "void forEach_" << ef->getName() << "(";
    209 
    210     if (ef->hasIn()) {
    211       Args.push_back(std::make_pair(
    212           "android::sp<const android::RSC::Allocation>", "ain"));
    213     }
    214 
    215     if (ef->hasOut() || ef->hasReturn()) {
    216       Args.push_back(std::make_pair(
    217           "android::sp<const android::RSC::Allocation>", "aout"));
    218     }
    219 
    220     const RSExportRecordType *ERT = ef->getParamPacketType();
    221     if (ERT) {
    222       for (RSExportForEach::const_param_iterator i = ef->params_begin(),
    223            e = ef->params_end(); i != e; i++) {
    224         RSReflectionTypeData rtd;
    225         (*i)->getType()->convertToRTD(&rtd);
    226         Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
    227       }
    228     }
    229     makeArgs(ss, Args);
    230     ss << ");";
    231     write(ss);
    232   }
    233 
    234 
    235   // Reflect export function
    236   for (RSContext::const_export_func_iterator
    237         I = mRSContext->export_funcs_begin(),
    238         E = mRSContext->export_funcs_end(); I != E; I++) {
    239     const RSExportFunc *ef = *I;
    240 
    241     stringstream ss;
    242     makeFunctionSignature(ss, false, ef);
    243     write(ss);
    244   }
    245 
    246   decIndent();
    247   write("};");
    248   return true;
    249 }
    250 
    251 bool RSReflectionCpp::writeBC() {
    252   FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
    253   if (pfin == NULL) {
    254     fprintf(stderr, "Error: could not read file %s\n",
    255             mOutputBCFileName.c_str());
    256     return false;
    257   }
    258 
    259   unsigned char buf[16];
    260   int read_length;
    261   write("static const unsigned char __txt[] = {");
    262   incIndent();
    263   while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
    264     string s;
    265     for (int i = 0; i < read_length; i++) {
    266       char buf2[16];
    267       snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
    268       s += buf2;
    269     }
    270     write(s);
    271   }
    272   decIndent();
    273   write("};");
    274   write("");
    275   return true;
    276 }
    277 
    278 bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
    279   startFile(mClassName + ".cpp");
    280 
    281   write("");
    282   write("#include \"" + mClassName + ".h\"");
    283   write("");
    284 
    285   writeBC();
    286 
    287   // Imports
    288   //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
    289       //out() << "import " << Import[i] << ";" << std::endl;
    290   //out() << std::endl;
    291 
    292   write("\n");
    293   stringstream ss;
    294   ss << mClassName << "::" << mClassName
    295      << "(android::sp<android::RSC::RS> rs, const char *cacheDir, "
    296         "size_t cacheDirLength) :\n"
    297         "        ScriptC(rs, __txt, sizeof(__txt), \""
    298      << mClassName << "\", " << mClassName.length()
    299      << ", cacheDir, cacheDirLength) {";
    300   write(ss);
    301   incIndent();
    302   //...
    303   decIndent();
    304   write("}");
    305   write("");
    306 
    307   write(mClassName + "::~" + mClassName + "() {");
    308   write("}");
    309   write("");
    310 
    311   // Reflect export for each functions
    312   uint32_t slot = 0;
    313   for (RSContext::const_export_foreach_iterator
    314        I = mRSContext->export_foreach_begin(),
    315        E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
    316     const RSExportForEach *ef = *I;
    317     if (ef->isDummyRoot()) {
    318       write("// No forEach_root(...)");
    319       continue;
    320     }
    321 
    322     stringstream tmp;
    323     ArgTy Args;
    324     tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
    325 
    326     if (ef->hasIn()) {
    327       Args.push_back(std::make_pair(
    328           "android::sp<const android::RSC::Allocation>", "ain"));
    329     }
    330 
    331     if (ef->hasOut() || ef->hasReturn()) {
    332       Args.push_back(std::make_pair(
    333           "android::sp<const android::RSC::Allocation>", "aout"));
    334     }
    335 
    336     const RSExportRecordType *ERT = ef->getParamPacketType();
    337     if (ERT) {
    338       for (RSExportForEach::const_param_iterator i = ef->params_begin(),
    339            e = ef->params_end(); i != e; i++) {
    340         RSReflectionTypeData rtd;
    341         (*i)->getType()->convertToRTD(&rtd);
    342         Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
    343       }
    344     }
    345     makeArgs(tmp, Args);
    346 
    347     tmp << ") {";
    348     write(tmp);
    349     tmp.str("");
    350 
    351     std::string FieldPackerName = ef->getName() + "_fp";
    352     if (ERT) {
    353       if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
    354         genPackVarOfType(ERT, NULL, FieldPackerName.c_str());
    355       }
    356     }
    357     tmp << "    forEach(" << slot << ", ";
    358 
    359     if (ef->hasIn()) {
    360       tmp << "ain, ";
    361     } else {
    362       tmp << "NULL, ";
    363     }
    364 
    365     if (ef->hasOut() || ef->hasReturn()) {
    366       tmp << "aout, ";
    367     } else {
    368       tmp << "NULL, ";
    369     }
    370 
    371     tmp << "NULL, 0);";
    372     write(tmp);
    373 
    374     write("}");
    375     write("");
    376   }
    377 
    378   slot = 0;
    379   // Reflect export function
    380   for (RSContext::const_export_func_iterator
    381        I = mRSContext->export_funcs_begin(),
    382        E = mRSContext->export_funcs_end(); I != E; I++) {
    383     const RSExportFunc *ef = *I;
    384 
    385     stringstream ss;
    386     makeFunctionSignature(ss, true, ef);
    387     write(ss);
    388     ss.str("");
    389     const RSExportRecordType *params = ef->getParamPacketType();
    390     size_t param_len = 0;
    391     if (params) {
    392       param_len = RSExportType::GetTypeAllocSize(params);
    393       if (genCreateFieldPacker(params, "__fp")) {
    394         genPackVarOfType(params, NULL, "__fp");
    395       }
    396     }
    397 
    398     ss.str("");
    399     ss << "    invoke(" << slot;
    400     if (params) {
    401       ss << ", __fp.getData(), " << param_len << ");";
    402     } else {
    403       ss << ", NULL, 0);";
    404     }
    405     write(ss);
    406 
    407     write("}");
    408     write("");
    409 
    410     slot++;
    411   }
    412 
    413   decIndent();
    414   return true;
    415 }
    416 
    417 void RSReflectionCpp::genExportVariable(const RSExportVar *EV) {
    418   const RSExportType *ET = EV->getType();
    419 
    420   switch (ET->getClass()) {
    421     case RSExportType::ExportClassPrimitive: {
    422       genPrimitiveTypeExportVariable(EV);
    423       break;
    424     }
    425     case RSExportType::ExportClassPointer: {
    426       genPointerTypeExportVariable(EV);
    427       break;
    428     }
    429     case RSExportType::ExportClassVector: {
    430       genVectorTypeExportVariable(EV);
    431       break;
    432     }
    433     case RSExportType::ExportClassMatrix: {
    434       genMatrixTypeExportVariable(EV);
    435       break;
    436     }
    437     case RSExportType::ExportClassConstantArray: {
    438       genConstantArrayTypeExportVariable(EV);
    439       break;
    440     }
    441     case RSExportType::ExportClassRecord: {
    442       genRecordTypeExportVariable(EV);
    443       break;
    444     }
    445     default: {
    446       slangAssert(false && "Unknown class of type");
    447     }
    448   }
    449 }
    450 
    451 
    452 void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) {
    453   RSReflectionTypeData rtd;
    454   EV->getType()->convertToRTD(&rtd);
    455 
    456   if (!EV->isConst()) {
    457     write(string("void set_") + EV->getName() + "(" + rtd.type->c_name +
    458           " v) {");
    459     stringstream tmp;
    460     tmp << getNextExportVarSlot();
    461     write(string("    setVar(") + tmp.str() + ", &v, sizeof(v));");
    462     write(string("    __") + EV->getName() + " = v;");
    463     write("}");
    464   }
    465   write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {");
    466   if (EV->isConst()) {
    467     const clang::APValue &val = EV->getInit();
    468     bool isBool = !strcmp(rtd.type->c_name, "bool");
    469     write(string("    return ") + genInitValue(val, isBool) + ";");
    470   } else {
    471     write(string("    return __") + EV->getName() + ";");
    472   }
    473   write("}");
    474   write("");
    475 }
    476 
    477 void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
    478   const RSExportType *ET = EV->getType();
    479 
    480   slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
    481               "Variable should be type of pointer here");
    482 
    483   std::string TypeName = GetTypeName(ET);
    484   std::string VarName = EV->getName();
    485 
    486   RSReflectionTypeData rtd;
    487   EV->getType()->convertToRTD(&rtd);
    488   uint32_t slot = getNextExportVarSlot();
    489 
    490   if (!EV->isConst()) {
    491     write(string("void bind_") + VarName + "(" + TypeName +
    492           " v) {");
    493     stringstream tmp;
    494     tmp << slot;
    495     write(string("    bindAllocation(v, ") + tmp.str() + ");");
    496     write(string("    __") + VarName + " = v;");
    497     write("}");
    498   }
    499   write(TypeName + " get_" + VarName + "() const {");
    500   if (EV->isConst()) {
    501     const clang::APValue &val = EV->getInit();
    502     bool isBool = !strcmp(TypeName.c_str(), "bool");
    503     write(string("    return ") + genInitValue(val, isBool) + ";");
    504   } else {
    505     write(string("    return __") + VarName + ";");
    506   }
    507   write("}");
    508   write("");
    509 
    510 }
    511 
    512 void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) {
    513   slangAssert(false);
    514 }
    515 
    516 void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
    517   slangAssert(false);
    518 }
    519 
    520 void RSReflectionCpp::genConstantArrayTypeExportVariable(
    521     const RSExportVar *EV) {
    522   slangAssert(false);
    523 }
    524 
    525 void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) {
    526   slangAssert(false);
    527 }
    528 
    529 
    530 void RSReflectionCpp::makeFunctionSignature(
    531     std::stringstream &ss,
    532     bool isDefinition,
    533     const RSExportFunc *ef) {
    534   ss << "void ";
    535   if (isDefinition) {
    536     ss << mClassName << "::";
    537   }
    538   ss << "invoke_" << ef->getName() << "(";
    539 
    540   if (ef->getParamPacketType()) {
    541     bool FirstArg = true;
    542     for (RSExportFunc::const_param_iterator i = ef->params_begin(),
    543          e = ef->params_end(); i != e; i++) {
    544       RSReflectionTypeData rtd;
    545       (*i)->getType()->convertToRTD(&rtd);
    546       if (!FirstArg) {
    547         ss << ", ";
    548       } else {
    549         FirstArg = false;
    550       }
    551       ss << rtd.type->c_name << " " << (*i)->getName();
    552     }
    553   }
    554 
    555   if (isDefinition) {
    556     ss << ") {";
    557   } else {
    558     ss << ");";
    559   }
    560 }
    561 
    562 void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) {
    563   bool FirstArg = true;
    564 
    565   for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) {
    566     if (!FirstArg) {
    567       ss << ", ";
    568     } else {
    569       FirstArg = false;
    570     }
    571 
    572     ss << I->first << " " << I->second;
    573   }
    574 }
    575 
    576 bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
    577                                            const char *FieldPackerName) {
    578   size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
    579 
    580   if (AllocSize > 0) {
    581     std::stringstream ss;
    582     ss << "    FieldPacker " << FieldPackerName << "("
    583        << AllocSize << ");";
    584     write(ss);
    585     return true;
    586   }
    587 
    588   return false;
    589 }
    590 
    591 void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
    592                                        const char *VarName,
    593                                        const char *FieldPackerName) {
    594   std::stringstream ss;
    595   switch (ET->getClass()) {
    596     case RSExportType::ExportClassPrimitive:
    597     case RSExportType::ExportClassVector:
    598     case RSExportType::ExportClassPointer:
    599     case RSExportType::ExportClassMatrix: {
    600       RSReflectionTypeData rtd;
    601       ET->convertToRTD(&rtd);
    602       ss << "    " << FieldPackerName << ".add(" << VarName << ");";
    603       write(ss);
    604       break;
    605     }
    606     case RSExportType::ExportClassConstantArray: {
    607       /*const RSExportConstantArrayType *ECAT =
    608           static_cast<const RSExportConstantArrayType *>(ET);
    609 
    610       // TODO(zonr): more elegant way. Currently, we obtain the unique index
    611       //             variable (this method involves recursive call which means
    612       //             we may have more than one level loop, therefore we can't
    613       //             always use the same index variable name here) name given
    614       //             in the for-loop from counting the '.' in @VarName.
    615       unsigned Level = 0;
    616       size_t LastDotPos = 0;
    617       std::string ElementVarName(VarName);
    618 
    619       while (LastDotPos != std::string::npos) {
    620         LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
    621         Level++;
    622       }
    623       std::string IndexVarName("ct");
    624       IndexVarName.append(llvm::utostr_32(Level));
    625 
    626       C.indent() << "for (int " << IndexVarName << " = 0; " <<
    627                           IndexVarName << " < " << ECAT->getSize() << "; " <<
    628                           IndexVarName << "++)";
    629       C.startBlock();
    630 
    631       ElementVarName.append("[" + IndexVarName + "]");
    632       genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
    633                        FieldPackerName);
    634 
    635       C.endBlock();*/
    636       break;
    637     }
    638     case RSExportType::ExportClassRecord: {
    639       const RSExportRecordType *ERT =
    640           static_cast<const RSExportRecordType*>(ET);
    641       // Relative pos from now on in field packer
    642       unsigned Pos = 0;
    643 
    644       for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
    645                E = ERT->fields_end();
    646            I != E;
    647            I++) {
    648         const RSExportRecordType::Field *F = *I;
    649         std::string FieldName;
    650         size_t FieldOffset = F->getOffsetInParent();
    651         size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
    652         size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
    653 
    654         if (VarName != NULL)
    655           FieldName = VarName + ("." + F->getName());
    656         else
    657           FieldName = F->getName();
    658 
    659         if (FieldOffset > Pos) {
    660           ss.str("");
    661           ss << "    " << FieldPackerName << ".skip("
    662              << (FieldOffset - Pos) << ");";
    663           write(ss);
    664         }
    665 
    666         genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
    667 
    668         // There is padding in the field type
    669         if (FieldAllocSize > FieldStoreSize) {
    670           ss.str("");
    671           ss << "    " << FieldPackerName << ".skip("
    672              << (FieldAllocSize - FieldStoreSize) << ");";
    673           write(ss);
    674         }
    675 
    676         Pos = FieldOffset + FieldAllocSize;
    677       }
    678 
    679       // There maybe some padding after the struct
    680       if (RSExportType::GetTypeAllocSize(ERT) > Pos) {
    681         ss.str("");
    682         ss << "    " << FieldPackerName << ".skip("
    683            << RSExportType::GetTypeAllocSize(ERT) - Pos << ");";
    684         write(ss);
    685       }
    686       break;
    687     }
    688     default: {
    689       slangAssert(false && "Unknown class of type");
    690     }
    691   }
    692 }
    693 
    694 }  // namespace slang
    695