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 RSReflectionCpp::RSReflectionCpp(const RSContext *con) :
     45     RSReflectionBase(con) {
     46 
     47 }
     48 
     49 RSReflectionCpp::~RSReflectionCpp() {
     50 
     51 }
     52 
     53 bool RSReflectionCpp::reflect(const string &OutputPathBase,
     54                               const string &InputFileName,
     55                               const string &OutputBCFileName) {
     56     mInputFileName = InputFileName;
     57     mOutputPath = OutputPathBase;
     58     mOutputBCFileName = OutputBCFileName;
     59     mClassName = string("ScriptC_") + stripRS(InputFileName);
     60 
     61     makeHeader("android::renderscriptCpp::ScriptC");
     62     std::vector< std::string > header(mText);
     63     mText.clear();
     64 
     65     makeImpl("android::renderscriptCpp::ScriptC");
     66     std::vector< std::string > cpp(mText);
     67     mText.clear();
     68 
     69 
     70     RSReflectionBase::writeFile(mClassName + ".h", header);
     71     RSReflectionBase::writeFile(mClassName + ".cpp", cpp);
     72 
     73 
     74     return false;
     75 }
     76 
     77 typedef std::vector<std::pair<std::string, std::string> > ArgTy;
     78 
     79 
     80 #define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
     81 
     82 
     83 
     84 bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
     85     startFile(mClassName + ".h");
     86 
     87     write("");
     88     write("#include \"ScriptC.h\"");
     89     write("");
     90 
     91     // Imports
     92     //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
     93         //out() << "import " << Import[i] << ";" << std::endl;
     94     //out() << std::endl;
     95 
     96     if(!baseClass.empty()) {
     97         write("class " + mClassName + " : public " + baseClass + " {");
     98     } else {
     99         write("class " + mClassName + " {");
    100     }
    101 
    102     write("private:");
    103     uint32_t slot = 0;
    104     incIndent();
    105     for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    106            E = mRSContext->export_vars_end(); I != E; I++, slot++) {
    107 
    108         const RSExportVar *ev = *I;
    109         RSReflectionTypeData rtd;
    110         ev->getType()->convertToRTD(&rtd);
    111         if(!ev->isConst()) {
    112             write(string(rtd.type->c_name) + " __" + ev->getName() + ";");
    113         }
    114     }
    115     decIndent();
    116 
    117     write("public:");
    118     incIndent();
    119     write(mClassName + "(android::renderscriptCpp::RenderScript *rs," +
    120             " const char *cacheDir, size_t cacheDirLength);");
    121     write("virtual ~" + mClassName + "();");
    122     write("");
    123 
    124 
    125     // Reflect export variable
    126     slot = 0;
    127     for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
    128            E = mRSContext->export_vars_end(); I != E; I++, slot++) {
    129 
    130         const RSExportVar *ev = *I;
    131         RSReflectionTypeData rtd;
    132         ev->getType()->convertToRTD(&rtd);
    133 
    134         if(!ev->isConst()) {
    135             write(string("void set_") + ev->getName() + "(" + rtd.type->c_name + " v) {");
    136             stringstream tmp;
    137             tmp << slot;
    138             write(string("    setVar(") + tmp.str() + ", v);");
    139             write(string("    __") + ev->getName() + " = v;");
    140             write("}");
    141         }
    142         write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {");
    143         if(ev->isConst()) {
    144             const clang::APValue &val = ev->getInit();
    145             bool isBool = !strcmp(rtd.type->c_name, "bool");
    146             write(string("    return ") + genInitValue(val, isBool) + ";");
    147         } else {
    148             write(string("    return __") + ev->getName() + ";");
    149         }
    150         write("}");
    151         write("");
    152     }
    153 
    154     // Reflect export for each functions
    155     for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
    156              E = mRSContext->export_foreach_end(); I != E; I++) {
    157 
    158         const RSExportForEach *ef = *I;
    159         if (ef->isDummyRoot()) {
    160             write("// No forEach_root(...)");
    161             continue;
    162         }
    163 
    164         stringstream tmp;
    165         tmp << "void forEach_" << ef->getName() << "(";
    166         if(ef->hasIn() && ef->hasOut()) {
    167             tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
    168             tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
    169         } else if(ef->hasIn()) {
    170             tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
    171         } else {
    172             tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
    173         }
    174 
    175         if(ef->getParamPacketType()) {
    176             for(RSExportForEach::const_param_iterator i = ef->params_begin(),
    177                      e = ef->params_end(); i != e; i++) {
    178 
    179                 RSReflectionTypeData rtd;
    180                 (*i)->getType()->convertToRTD(&rtd);
    181                 tmp << rtd.type->c_name << " " << (*i)->getName();
    182             }
    183         }
    184         tmp << ") const;";
    185         write(tmp);
    186     }
    187 
    188 
    189     // Reflect export function
    190     for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
    191            E = mRSContext->export_funcs_end(); I != E; I++) {
    192 
    193         //genExportFunction(C, *I);
    194     }
    195 
    196     decIndent();
    197     write("};");
    198     return true;
    199 }
    200 
    201 bool RSReflectionCpp::writeBC() {
    202     FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
    203     if (pfin == NULL) {
    204         fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str());
    205         return false;
    206     }
    207 
    208     unsigned char buf[16];
    209     int read_length;
    210     write("static const unsigned char __txt[] = {");
    211     incIndent();
    212     while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
    213         string s;
    214         for(int i = 0; i < read_length; i++) {
    215             char buf2[16];
    216             sprintf(buf2, "0x%02x,", buf[i]);
    217             s += buf2;
    218         }
    219         write(s);
    220     }
    221     decIndent();
    222     write("};");
    223     write("");
    224     return true;
    225 }
    226 
    227 bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
    228     startFile(mClassName + ".h");
    229 
    230     write("");
    231     write("#include \"" + mClassName + ".h\"");
    232     write("");
    233 
    234     writeBC();
    235 
    236     // Imports
    237     //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
    238         //out() << "import " << Import[i] << ";" << std::endl;
    239     //out() << std::endl;
    240 
    241     write(mClassName + "::" + mClassName +
    242           "(android::renderscriptCpp::RenderScript *rs, const char *cacheDir, size_t cacheDirLength) :");
    243     write("        ScriptC(rs, __txt, sizeof(__txt), \"" + mInputFileName +
    244           "\", 4, cacheDir, cacheDirLength) {");
    245     incIndent();
    246     //...
    247     decIndent();
    248     write("}");
    249     write("");
    250 
    251     write(mClassName + "::~" + mClassName + "() {");
    252     write("}");
    253     write("");
    254 
    255     // Reflect export for each functions
    256     uint32_t slot = 0;
    257     for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
    258              E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
    259 
    260         const RSExportForEach *ef = *I;
    261         if (ef->isDummyRoot()) {
    262             write("// No forEach_root(...)");
    263             continue;
    264         }
    265 
    266         stringstream tmp;
    267         tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
    268         if(ef->hasIn() && ef->hasOut()) {
    269             tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
    270             tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
    271         } else if(ef->hasIn()) {
    272             tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
    273         } else {
    274             tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
    275         }
    276         tmp << ") const {";
    277         write(tmp);
    278         tmp.str("");
    279 
    280         tmp << "    forEach(" << slot << ", ";
    281         if(ef->hasIn() && ef->hasOut()) {
    282             tmp << "ain, aout, NULL, 0);";
    283         } else if(ef->hasIn()) {
    284             tmp << "ain, NULL, 0);";
    285         } else {
    286             tmp << "aout, NULL, 0);";
    287         }
    288         write(tmp);
    289 
    290         write("}");
    291         write("");
    292     }
    293 
    294 
    295     // Reflect export function
    296     slot = 0;
    297     for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
    298            E = mRSContext->export_funcs_end(); I != E; I++) {
    299 
    300         //genExportFunction(C, *I);
    301     }
    302 
    303     decIndent();
    304     return true;
    305 }
    306 
    307 
    308 
    309 }
    310