slang_rs_reflection_cpp.cpp revision 713377ec412f448273158c954f6816f07f8bcd20
1526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen/*
2526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright 2012, The Android Open Source Project
3526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
4526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Licensed under the Apache License, Version 2.0 (the "License");
5526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * you may not use this file except in compliance with the License.
6526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * You may obtain a copy of the License at
7526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
8526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *     http://www.apache.org/licenses/LICENSE-2.0
9526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
10526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Unless required by applicable law or agreed to in writing, software
11526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * distributed under the License is distributed on an "AS IS" BASIS,
12526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * See the License for the specific language governing permissions and
14526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * limitations under the License.
15526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */
16526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
17526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <sys/stat.h>
18526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <stdio.h>
19526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <stdlib.h>
20526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
21526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <cstdarg>
22526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <cctype>
23526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
24526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <algorithm>
25526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <sstream>
26526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <string>
27526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include <utility>
28526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
29526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "os_sep.h"
30526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_context.h"
31526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_var.h"
32526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_foreach.h"
33526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_export_func.h"
34526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_reflect_utils.h"
35526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_version.h"
36526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_utils.h"
37526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
38526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#include "slang_rs_reflection_cpp.h"
39526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
40526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenusing namespace std;
41526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
42526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wennamespace slang {
43526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
44526ecd1799a2fc467cfce114eae3578b42ccb786Ye WenRSReflectionCpp::RSReflectionCpp(const RSContext *con)
45526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    : RSReflectionBase(con) {
46526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen}
47526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
48526ecd1799a2fc467cfce114eae3578b42ccb786Ye WenRSReflectionCpp::~RSReflectionCpp() {
49526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen}
50526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
51526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenbool RSReflectionCpp::reflect(const string &OutputPathBase,
52526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                              const string &InputFileName,
53526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                              const string &OutputBCFileName) {
54526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mInputFileName = InputFileName;
55526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mOutputPath = OutputPathBase;
56526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mOutputBCFileName = OutputBCFileName;
57526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mClassName = string("ScriptC_") + stripRS(InputFileName);
58526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
59526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  makeHeader("android::renderscriptCpp::ScriptC");
60526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  std::vector< std::string > header(mText);
61526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mText.clear();
62526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
63526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  makeImpl("android::renderscriptCpp::ScriptC");
64526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  std::vector< std::string > cpp(mText);
65526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  mText.clear();
66526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
67526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
68526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  writeFile(mClassName + ".h", header);
69526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  writeFile(mClassName + ".cpp", cpp);
70526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
71526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
72526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  return true;
73526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen}
74526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
75526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wentypedef std::vector<std::pair<std::string, std::string> > ArgTy;
76526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
77526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
78526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
79526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
80526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
81526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
82526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenbool RSReflectionCpp::makeHeader(const std::string &baseClass) {
83526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  startFile(mClassName + ".h");
84526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
85526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  write("");
86526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  write("#include \"RenderScript.h\"");
87526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  write("using namespace android::renderscriptCpp;");
88526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  write("");
89526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
90526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  // Imports
91526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
92526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen      //out() << "import " << Import[i] << ";" << std::endl;
93526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  //out() << std::endl;
94526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
95526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  if (!baseClass.empty()) {
96526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    write("class " + mClassName + " : public " + baseClass + " {");
97526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  } else {
98526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    write("class " + mClassName + " {");
99526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  }
100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
101526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  write("private:");
102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  uint32_t slot = 0;
103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  incIndent();
104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         E = mRSContext->export_vars_end(); I != E; I++, slot++) {
106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    const RSExportVar *ev = *I;
107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    RSReflectionTypeData rtd;
108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    ev->getType()->convertToRTD(&rtd);
109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    if (!ev->isConst()) {
110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen      write(string(rtd.type->c_name) + " __" + ev->getName() + ";");
111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen  }
113  decIndent();
114
115  write("public:");
116  incIndent();
117  write(mClassName + "(android::sp<android::renderscriptCpp::RS> rs," +
118          " const char *cacheDir, size_t cacheDirLength);");
119  write("virtual ~" + mClassName + "();");
120  write("");
121
122
123  // Reflect export variable
124  slot = 0;
125  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
126         E = mRSContext->export_vars_end(); I != E; I++, slot++) {
127    const RSExportVar *ev = *I;
128    RSReflectionTypeData rtd;
129    ev->getType()->convertToRTD(&rtd);
130
131    if (!ev->isConst()) {
132      write(string("void set_") + ev->getName() + "(" + rtd.type->c_name +
133            " v) {");
134      stringstream tmp;
135      tmp << slot;
136      write(string("    setVar(") + tmp.str() + ", &v, sizeof(v));");
137      write(string("    __") + ev->getName() + " = v;");
138      write("}");
139    }
140    write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {");
141    if (ev->isConst()) {
142      const clang::APValue &val = ev->getInit();
143      bool isBool = !strcmp(rtd.type->c_name, "bool");
144      write(string("    return ") + genInitValue(val, isBool) + ";");
145    } else {
146      write(string("    return __") + ev->getName() + ";");
147    }
148    write("}");
149    write("");
150  }
151
152  // Reflect export for each functions
153  for (RSContext::const_export_foreach_iterator
154           I = mRSContext->export_foreach_begin(),
155           E = mRSContext->export_foreach_end(); I != E; I++) {
156    const RSExportForEach *ef = *I;
157    if (ef->isDummyRoot()) {
158      write("// No forEach_root(...)");
159      continue;
160    }
161
162    stringstream tmp;
163    tmp << "void forEach_" << ef->getName() << "(";
164    if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) {
165      tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
166      tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
167    } else if (ef->hasIn()) {
168      tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
169    } else {
170      tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
171    }
172
173    if (ef->getParamPacketType()) {
174      for (RSExportForEach::const_param_iterator i = ef->params_begin(),
175           e = ef->params_end(); i != e; i++) {
176        RSReflectionTypeData rtd;
177        (*i)->getType()->convertToRTD(&rtd);
178        tmp << rtd.type->c_name << " " << (*i)->getName();
179      }
180    }
181    tmp << ");";
182    write(tmp);
183  }
184
185
186  // Reflect export function
187  for (RSContext::const_export_func_iterator
188        I = mRSContext->export_funcs_begin(),
189        E = mRSContext->export_funcs_end(); I != E; I++) {
190    const RSExportFunc *ef = *I;
191
192    stringstream ss;
193    makeFunctionSignature(ss, false, ef);
194    write(ss);
195  }
196
197  decIndent();
198  write("};");
199  return true;
200}
201
202bool RSReflectionCpp::writeBC() {
203  FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
204  if (pfin == NULL) {
205    fprintf(stderr, "Error: could not read file %s\n",
206            mOutputBCFileName.c_str());
207    return false;
208  }
209
210  unsigned char buf[16];
211  int read_length;
212  write("static const unsigned char __txt[] = {");
213  incIndent();
214  while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
215    string s;
216    for (int i = 0; i < read_length; i++) {
217      char buf2[16];
218      snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
219      s += buf2;
220    }
221    write(s);
222  }
223  decIndent();
224  write("};");
225  write("");
226  return true;
227}
228
229bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
230  startFile(mClassName + ".h");
231
232  write("");
233  write("#include \"" + mClassName + ".h\"");
234  write("");
235
236  writeBC();
237
238  // Imports
239  //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
240      //out() << "import " << Import[i] << ";" << std::endl;
241  //out() << std::endl;
242
243  write("\n");
244  stringstream ss;
245  ss << mClassName << "::" << mClassName
246     << "(android::sp<android::renderscriptCpp::RS> rs, "
247        "const char *cacheDir, size_t cacheDirLength) :\n"
248     << "        ScriptC(rs, __txt, sizeof(__txt), \""
249     << mClassName << "\", " << mClassName.length()
250     << ", cacheDir, cacheDirLength) {";
251  write(ss);
252  incIndent();
253  //...
254  decIndent();
255  write("}");
256  write("");
257
258  write(mClassName + "::~" + mClassName + "() {");
259  write("}");
260  write("");
261
262  // Reflect export for each functions
263  uint32_t slot = 0;
264  for (RSContext::const_export_foreach_iterator
265       I = mRSContext->export_foreach_begin(),
266       E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
267    const RSExportForEach *ef = *I;
268    if (ef->isDummyRoot()) {
269      write("// No forEach_root(...)");
270      continue;
271    }
272
273    stringstream tmp;
274    tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
275    if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) {
276      tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
277      tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
278    } else if (ef->hasIn()) {
279      tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
280    } else {
281      tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
282    }
283    tmp << ") {";
284    write(tmp);
285    tmp.str("");
286
287    tmp << "    forEach(" << slot << ", ";
288    if (ef->hasIn() && (ef->hasOut() || ef->hasReturn())) {
289      tmp << "ain, aout, NULL, 0);";
290    } else if (ef->hasIn()) {
291      tmp << "ain, NULL, 0);";
292    } else {
293      tmp << "aout, NULL, 0);";
294    }
295    write(tmp);
296
297    write("}");
298    write("");
299  }
300
301  slot = 0;
302  // Reflect export function
303  for (RSContext::const_export_func_iterator
304       I = mRSContext->export_funcs_begin(),
305       E = mRSContext->export_funcs_end(); I != E; I++) {
306    const RSExportFunc *ef = *I;
307
308    stringstream ss;
309    makeFunctionSignature(ss, true, ef);
310    write(ss);
311    ss.str("");
312    const RSExportRecordType *params = ef->getParamPacketType();
313    size_t param_len = 0;
314    if (params) {
315      param_len = RSExportType::GetTypeAllocSize(params);
316      ss << "    FieldPacker __fp(" << param_len << ");";
317      write(ss);
318      for (RSExportFunc::const_param_iterator i = ef->params_begin(),
319           e = ef->params_end(); i != e; i++) {
320        RSReflectionTypeData rtd;
321        (*i)->getType()->convertToRTD(&rtd);
322        ss.str("");
323        ss << "    __fp.add(" << (*i)->getName() << ");";
324        write(ss);
325      }
326
327    }
328
329    ss.str("");
330    ss << "    invoke(" << slot;
331    if (params) {
332      ss << ", __fp.getData(), " << param_len << ");";
333    } else {
334      ss << ", NULL, 0);";
335    }
336    write(ss);
337
338    write("}");
339    write("");
340
341    slot++;
342  }
343
344  decIndent();
345  return true;
346}
347
348
349void RSReflectionCpp::makeFunctionSignature(
350    std::stringstream &ss,
351    bool isDefinition,
352    const RSExportFunc *ef) {
353  ss << "void ";
354  if (isDefinition) {
355    ss << mClassName << "::";
356  }
357  ss << "invoke_" << ef->getName() << "(";
358
359  if (ef->getParamPacketType()) {
360    bool FirstArg = true;
361    for (RSExportFunc::const_param_iterator i = ef->params_begin(),
362         e = ef->params_end(); i != e; i++) {
363      RSReflectionTypeData rtd;
364      (*i)->getType()->convertToRTD(&rtd);
365      if (!FirstArg) {
366        ss << ", ";
367      } else {
368        FirstArg = false;
369      }
370      ss << rtd.type->c_name << " " << (*i)->getName();
371    }
372  }
373
374  if (isDefinition) {
375    ss << ") {";
376  } else {
377    ss << ");";
378  }
379}
380
381}  // namespace slang
382