slang_rs_reflection_cpp.cpp revision 02a9826b586f765a95e3c75bd6080c4ee8e2e911
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
40using namespace std;
41
42namespace slang {
43
44RSReflectionCpp::RSReflectionCpp(const RSContext *con)
45    : RSReflectionBase(con) {
46}
47
48RSReflectionCpp::~RSReflectionCpp() {
49}
50
51bool RSReflectionCpp::reflect(const string &OutputPathBase,
52                              const string &InputFileName,
53                              const string &OutputBCFileName) {
54  mInputFileName = InputFileName;
55  mOutputPath = OutputPathBase;
56  mOutputBCFileName = OutputBCFileName;
57  mClassName = string("ScriptC_") + stripRS(InputFileName);
58
59  makeHeader("android::renderscriptCpp::ScriptC");
60  std::vector< std::string > header(mText);
61  mText.clear();
62
63  makeImpl("android::renderscriptCpp::ScriptC");
64  std::vector< std::string > cpp(mText);
65  mText.clear();
66
67
68  writeFile(mClassName + ".h", header);
69  writeFile(mClassName + ".cpp", cpp);
70
71
72  return true;
73}
74
75typedef std::vector<std::pair<std::string, std::string> > ArgTy;
76
77
78#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
79
80
81
82bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
83  startFile(mClassName + ".h");
84
85  write("");
86  write("#include \"RenderScript.h\"");
87  write("using namespace android::renderscriptCpp;");
88  write("");
89
90  // Imports
91  //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
92      //out() << "import " << Import[i] << ";" << std::endl;
93  //out() << std::endl;
94
95  if (!baseClass.empty()) {
96    write("class " + mClassName + " : public " + baseClass + " {");
97  } else {
98    write("class " + mClassName + " {");
99  }
100
101  write("private:");
102  uint32_t slot = 0;
103  incIndent();
104  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
105         E = mRSContext->export_vars_end(); I != E; I++, slot++) {
106    const RSExportVar *ev = *I;
107    RSReflectionTypeData rtd;
108    ev->getType()->convertToRTD(&rtd);
109    if (!ev->isConst()) {
110      write(string(rtd.type->c_name) + " __" + ev->getName() + ";");
111    }
112  }
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 << ") const;";
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 << ") const {";
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
313    ss << "    invoke(" << slot << ", NULL, 0);";
314    write(ss);
315
316    write("}");
317    write("");
318
319    slot++;
320  }
321
322  decIndent();
323  return true;
324}
325
326
327void RSReflectionCpp::makeFunctionSignature(
328    std::stringstream &ss,
329    bool isDefinition,
330    const RSExportFunc *ef) {
331  ss << "void ";
332  if (isDefinition) {
333    ss << mClassName << "::";
334  }
335  ss << "invoke_" << ef->getName() << "(";
336
337  if (ef->getParamPacketType()) {
338    bool FirstArg = true;
339    for (RSExportFunc::const_param_iterator i = ef->params_begin(),
340         e = ef->params_end(); i != e; i++) {
341      RSReflectionTypeData rtd;
342      (*i)->getType()->convertToRTD(&rtd);
343      if (!FirstArg) {
344        ss << ", ";
345      } else {
346        FirstArg = false;
347      }
348      ss << rtd.type->c_name << " " << (*i)->getName();
349    }
350  }
351
352  if (isDefinition) {
353    ss << ") {";
354  } else {
355    ss << ");";
356  }
357}
358
359}  // namespace slang
360