slang_rs_reflection_cpp.cpp revision 003ac666e57669d4312b5792068c3db302ee7b84
1d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam/*
2d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Copyright 2013, The Android Open Source Project
3d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam *
4d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Licensed under the Apache License, Version 2.0 (the "License");
5d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * you may not use this file except in compliance with the License.
6d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * You may obtain a copy of the License at
7d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam *
8d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam *     http://www.apache.org/licenses/LICENSE-2.0
9d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam *
10d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * Unless required by applicable law or agreed to in writing, software
11d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * distributed under the License is distributed on an "AS IS" BASIS,
12d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * See the License for the specific language governing permissions and
14d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam * limitations under the License.
15d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam */
16d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
17d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <sys/stat.h>
18d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <stdio.h>
19d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <stdlib.h>
20d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
217c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam#include <cstdarg>
22d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <cctype>
23d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
24d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <algorithm>
25d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <sstream>
26d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include <string>
27059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam#include <utility>
28059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam
297c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam#include "os_sep.h"
30d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_context.h"
31d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_export_var.h"
32d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_export_foreach.h"
33d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_export_func.h"
34d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_reflect_utils.h"
35d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_version.h"
36d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_utils.h"
37d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
38d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#include "slang_rs_reflection_cpp.h"
39d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
40d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamusing namespace std;
41d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
427c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lamnamespace slang {
437c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
44d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#define RS_TYPE_ITEM_CLASS_NAME          "Item"
45d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
46d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam#define RS_ELEM_PREFIX "__rs_elem_"
47059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam
48059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lamstatic const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
49d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  static const char *MatrixTypeCNameMap[] = {
50d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    "rs_matrix2x2",
517c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    "rs_matrix3x3",
52059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam    "rs_matrix4x4",
53d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  };
54d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  unsigned Dim = EMT->getDim();
55d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
56d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char*)))
57d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    return MatrixTypeCNameMap[ EMT->getDim() - 2 ];
587c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
59059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam  slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
60d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  return NULL;
61d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam}
62d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
63d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
64d832154e333a3a45b5faecd518b664ddd297183cMaurice Lamstatic std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
65d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  switch (ET->getClass()) {
667c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    case RSExportType::ExportClassPrimitive: {
67d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      return RSExportPrimitiveType::getRSReflectionType(
68d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam          static_cast<const RSExportPrimitiveType*>(ET))->c_name;
69d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
70d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    case RSExportType::ExportClassPointer: {
71d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      const RSExportType *PointeeType =
72d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
73d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
74d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
75d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam        return "android::RSC::sp<android::RSC::Allocation>";
767c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      else
77d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam        return PointeeType->getElementName();
78d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
79d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    case RSExportType::ExportClassVector: {
80d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      const RSExportVectorType *EVT =
81d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam          static_cast<const RSExportVectorType*>(ET);
82d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      std::stringstream VecName;
83d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
84d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam              << EVT->getNumElement();
85d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      return VecName.str();
86d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
87d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    case RSExportType::ExportClassMatrix: {
88d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET));
897c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
90d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    case RSExportType::ExportClassConstantArray: {
91d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      // TODO: Fix this for C arrays!
92d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      const RSExportConstantArrayType* CAT =
93d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam          static_cast<const RSExportConstantArrayType*>(ET);
94d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      std::string ElementTypeName = GetTypeName(CAT->getElementType());
95d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      if (Brackets) {
96d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam        ElementTypeName.append("[]");
97d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      }
98d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      return ElementTypeName;
99d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
100d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    case RSExportType::ExportClassRecord: {
1017c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      // TODO: Fix for C structs!
102d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
103d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
104d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    default: {
105d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam      slangAssert(false && "Unknown class of type");
106d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    }
107d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  }
108d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
109d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  return "";
110d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam}
111059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam
112059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam
113d832154e333a3a45b5faecd518b664ddd297183cMaurice LamRSReflectionCpp::RSReflectionCpp(const RSContext *con)
114d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    : RSReflectionBase(con) {
115d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  clear();
116d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam}
117cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam
118cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice LamRSReflectionCpp::~RSReflectionCpp() {
1197c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam}
120cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam
121cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lambool RSReflectionCpp::reflect(const string &OutputPathBase,
122cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam                              const string &InputFileName,
123cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam                              const string &OutputBCFileName) {
124cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  mInputFileName = InputFileName;
125cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  mOutputPath = OutputPathBase;
126cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  mOutputBCFileName = OutputBCFileName;
127cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  mClassName = string("ScriptC_") + stripRS(InputFileName);
128cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam
129cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  makeHeader("android::RSC::ScriptC");
130cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  std::vector< std::string > header(mText);
131cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  mText.clear();
132cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam
133cf90658b5c16018c9f3db7fd1d872025cff5d1dcMaurice Lam  makeImpl("android::RSC::ScriptC");
13404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam  std::vector< std::string > cpp(mText);
13504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam  mText.clear();
13604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam
1377c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1387c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  writeFile(mClassName + ".h", header);
13904eecdd42f0bc9751825f9f21131a59852256278Maurice Lam  writeFile(mClassName + ".cpp", cpp);
14004eecdd42f0bc9751825f9f21131a59852256278Maurice Lam
14104eecdd42f0bc9751825f9f21131a59852256278Maurice Lam
14204eecdd42f0bc9751825f9f21131a59852256278Maurice Lam  return true;
14304eecdd42f0bc9751825f9f21131a59852256278Maurice Lam}
14404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam
14504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam
14604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
1477c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1487c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1497c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1507c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lambool RSReflectionCpp::makeHeader(const std::string &baseClass) {
1517c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  startFile(mClassName + ".h");
1527c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1537c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("");
1547c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("#include \"RenderScript.h\"");
1557c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("using namespace android::RSC;");
1567c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("");
1577c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1587c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  // Imports
1597c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
1607c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      //out() << "import " << Import[i] << ";" << std::endl;
1617c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  //out() << std::endl;
1627c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1637c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  if (!baseClass.empty()) {
1647c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    write("class " + mClassName + " : public " + baseClass + " {");
1657c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  } else {
1667c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    write("class " + mClassName + " {");
1677c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  }
1687c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
1697c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("private:");
1707c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  uint32_t slot = 0;
1717c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  incIndent();
1727c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
1737c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam         E = mRSContext->export_vars_end(); I != E; I++, slot++) {
1747c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportVar *ev = *I;
1757c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (!ev->isConst()) {
1767c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      write(GetTypeName(ev->getType()) + " __" + ev->getName() + ";");
1777c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
1787c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  }
1797c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  for (RSContext::const_export_foreach_iterator
1807c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam           I = mRSContext->export_foreach_begin(),
1817c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam           E = mRSContext->export_foreach_end(); I != E; I++) {
1827c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportForEach *EF = *I;
1837c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportType *IET = EF->getInType();
1847c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportType *OET = EF->getOutType();
1857c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (IET) {
1867c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      genTypeInstanceFromPointer(IET);
1877c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
1887c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (OET) {
1897c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      genTypeInstanceFromPointer(OET);
1907c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
1917c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  }
1927c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
19304eecdd42f0bc9751825f9f21131a59852256278Maurice Lam  for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
19404eecdd42f0bc9751825f9f21131a59852256278Maurice Lam                                       E = mTypesToCheck.end();
19504eecdd42f0bc9751825f9f21131a59852256278Maurice Lam       I != E;
19604eecdd42f0bc9751825f9f21131a59852256278Maurice Lam       I++) {
1977c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    write("android::RSC::sp<const android::RSC::Element> " RS_ELEM_PREFIX
1987c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam          + *I + ";");
1997c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  }
2007c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2017c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  decIndent();
2027c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2037c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("public:");
2047c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  incIndent();
2057c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write(mClassName + "(android::RSC::sp<android::RSC::RS> rs);");
2067c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("virtual ~" + mClassName + "();");
2077c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  write("");
2087c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2097c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2107c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  // Reflect export variable
2117c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  slot = 0;
2127c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
2137c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam         E = mRSContext->export_vars_end(); I != E; I++, slot++) {
2147c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    genExportVariable(*I);
2157c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  }
2167c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2177c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  // Reflect export for each functions
2187c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam  for (RSContext::const_export_foreach_iterator
2197c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam           I = mRSContext->export_foreach_begin(),
2207c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam           E = mRSContext->export_foreach_end(); I != E; I++) {
2217c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportForEach *ef = *I;
2227c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (ef->isDummyRoot()) {
2237c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      write("// No forEach_root(...)");
2247c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      continue;
2257c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
2267c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2277c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    ArgTy Args;
2287c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    stringstream ss;
2297c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    ss << "void forEach_" << ef->getName() << "(";
2307c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2317c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (ef->hasIn()) {
2327c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      Args.push_back(std::make_pair(
2337c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam          "android::RSC::sp<const android::RSC::Allocation>", "ain"));
2347c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
2357c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2367c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (ef->hasOut() || ef->hasReturn()) {
2377c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      Args.push_back(std::make_pair(
2387c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam          "android::RSC::sp<const android::RSC::Allocation>", "aout"));
2397c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    }
2407c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam
2417c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    const RSExportRecordType *ERT = ef->getParamPacketType();
2427c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam    if (ERT) {
2437c7aa7d0d3cd465b1f4c0aa812fc4006cd7a14adMaurice Lam      for (RSExportForEach::const_param_iterator i = ef->params_begin(),
244059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam           e = ef->params_end(); i != e; i++) {
245059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam        RSReflectionTypeData rtd;
246059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam        (*i)->getType()->convertToRTD(&rtd);
247059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam        Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
248059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam      }
249059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam    }
250059321ff28f79a2cbe630b4d814a96ff9254643aMaurice Lam    makeArgs(ss, Args);
251d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    ss << ");";
252d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    write(ss);
253d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  }
254d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
255d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
256d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  // Reflect export function
257d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  for (RSContext::const_export_func_iterator
258d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam        I = mRSContext->export_funcs_begin(),
259d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam        E = mRSContext->export_funcs_end(); I != E; I++) {
260d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    const RSExportFunc *ef = *I;
261d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
262d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    stringstream ss;
263d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    makeFunctionSignature(ss, false, ef);
264d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    write(ss);
265d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  }
266d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
267d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  decIndent();
268d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  write("};");
269d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  return true;
270d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam}
271d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
272d832154e333a3a45b5faecd518b664ddd297183cMaurice Lambool RSReflectionCpp::writeBC() {
273d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
274d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  if (pfin == NULL) {
275d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    fprintf(stderr, "Error: could not read file %s\n",
276d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam            mOutputBCFileName.c_str());
277d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam    return false;
278d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  }
279d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam
280d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  unsigned char buf[16];
281d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  int read_length;
282d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  write("static const unsigned char __txt[] = {");
283d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  incIndent();
284d832154e333a3a45b5faecd518b664ddd297183cMaurice Lam  while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
285    string s;
286    for (int i = 0; i < read_length; i++) {
287      char buf2[16];
288      snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
289      s += buf2;
290    }
291    write(s);
292  }
293  decIndent();
294  write("};");
295  write("");
296  return true;
297}
298
299bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
300  startFile(mClassName + ".cpp");
301
302  write("");
303  write("#include \"" + mClassName + ".h\"");
304  write("");
305
306  writeBC();
307
308  // Imports
309  //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
310      //out() << "import " << Import[i] << ";" << std::endl;
311  //out() << std::endl;
312
313  write("\n");
314  stringstream ss;
315  const std::string &packageName = mRSContext->getReflectJavaPackageName();
316  ss << mClassName << "::" << mClassName
317     << "(android::RSC::sp<android::RSC::RS> rs):\n"
318        "        ScriptC(rs, __txt, sizeof(__txt), \""
319     << stripRS(mInputFileName) << "\", " << stripRS(mInputFileName).length()
320     << ", \"/data/data/" << packageName << "/app\", sizeof(\"" << packageName << "\")) {";
321  write(ss);
322  incIndent();
323  for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
324                                       E = mTypesToCheck.end();
325       I != E;
326       I++) {
327    write(RS_ELEM_PREFIX + *I + " = android::RSC::Element::" + *I + "(mRS);");
328  }
329  decIndent();
330  write("}");
331  write("");
332
333  write(mClassName + "::~" + mClassName + "() {");
334  write("}");
335  write("");
336
337  // Reflect export for each functions
338  uint32_t slot = 0;
339  for (RSContext::const_export_foreach_iterator
340       I = mRSContext->export_foreach_begin(),
341       E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
342    const RSExportForEach *ef = *I;
343    if (ef->isDummyRoot()) {
344      write("// No forEach_root(...)");
345      continue;
346    }
347
348    stringstream tmp;
349    ArgTy Args;
350    tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
351
352    if (ef->hasIn()) {
353      Args.push_back(std::make_pair(
354          "android::RSC::sp<const android::RSC::Allocation>", "ain"));
355    }
356
357    if (ef->hasOut() || ef->hasReturn()) {
358      Args.push_back(std::make_pair(
359          "android::RSC::sp<const android::RSC::Allocation>", "aout"));
360    }
361
362    const RSExportRecordType *ERT = ef->getParamPacketType();
363    if (ERT) {
364      for (RSExportForEach::const_param_iterator i = ef->params_begin(),
365           e = ef->params_end(); i != e; i++) {
366        RSReflectionTypeData rtd;
367        (*i)->getType()->convertToRTD(&rtd);
368        Args.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
369      }
370    }
371    makeArgs(tmp, Args);
372
373    tmp << ") {";
374    write(tmp);
375    tmp.str("");
376
377    const RSExportType *IET = ef->getInType();
378    const RSExportType *OET = ef->getOutType();
379
380    incIndent();
381    if (IET) {
382      genTypeCheck(IET, "ain");
383    }
384
385    if (OET) {
386      genTypeCheck(OET, "aout");
387    }
388    decIndent();
389
390    std::string FieldPackerName = ef->getName() + "_fp";
391    if (ERT) {
392      if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
393        genPackVarOfType(ERT, NULL, FieldPackerName.c_str());
394      }
395    }
396    tmp << "    forEach(" << slot << ", ";
397
398    if (ef->hasIn()) {
399      tmp << "ain, ";
400    } else {
401      tmp << "NULL, ";
402    }
403
404    if (ef->hasOut() || ef->hasReturn()) {
405      tmp << "aout, ";
406    } else {
407      tmp << "NULL, ";
408    }
409
410    // FIXME (no support for usrData with C++ kernels)
411    tmp << "NULL, 0);";
412    write(tmp);
413
414    write("}");
415    write("");
416  }
417
418  slot = 0;
419  // Reflect export function
420  for (RSContext::const_export_func_iterator
421       I = mRSContext->export_funcs_begin(),
422       E = mRSContext->export_funcs_end(); I != E; I++) {
423    const RSExportFunc *ef = *I;
424
425    stringstream ss;
426    makeFunctionSignature(ss, true, ef);
427    write(ss);
428    ss.str("");
429    const RSExportRecordType *params = ef->getParamPacketType();
430    size_t param_len = 0;
431    if (params) {
432      param_len = RSExportType::GetTypeAllocSize(params);
433      if (genCreateFieldPacker(params, "__fp")) {
434        genPackVarOfType(params, NULL, "__fp");
435      }
436    }
437
438    ss.str("");
439    ss << "    invoke(" << slot;
440    if (params) {
441      ss << ", __fp.getData(), " << param_len << ");";
442    } else {
443      ss << ", NULL, 0);";
444    }
445    write(ss);
446
447    write("}");
448    write("");
449
450    slot++;
451  }
452
453  decIndent();
454  return true;
455}
456
457void RSReflectionCpp::genExportVariable(const RSExportVar *EV) {
458  const RSExportType *ET = EV->getType();
459
460  switch (ET->getClass()) {
461    case RSExportType::ExportClassPrimitive: {
462      genPrimitiveTypeExportVariable(EV);
463      break;
464    }
465    case RSExportType::ExportClassPointer: {
466      genPointerTypeExportVariable(EV);
467      break;
468    }
469    case RSExportType::ExportClassVector: {
470      genVectorTypeExportVariable(EV);
471      break;
472    }
473    case RSExportType::ExportClassMatrix: {
474      genMatrixTypeExportVariable(EV);
475      break;
476    }
477    case RSExportType::ExportClassConstantArray: {
478      genConstantArrayTypeExportVariable(EV);
479      break;
480    }
481    case RSExportType::ExportClassRecord: {
482      genRecordTypeExportVariable(EV);
483      break;
484    }
485    default: {
486      slangAssert(false && "Unknown class of type");
487    }
488  }
489}
490
491
492void RSReflectionCpp::genPrimitiveTypeExportVariable(const RSExportVar *EV) {
493  RSReflectionTypeData rtd;
494  EV->getType()->convertToRTD(&rtd);
495
496  if (!EV->isConst()) {
497    write(string("void set_") + EV->getName() + "(" + rtd.type->c_name +
498          " v) {");
499    stringstream tmp;
500    tmp << getNextExportVarSlot();
501    write(string("    setVar(") + tmp.str() + ", &v, sizeof(v));");
502    write(string("    __") + EV->getName() + " = v;");
503    write("}");
504  }
505  write(string(rtd.type->c_name) + " get_" + EV->getName() + "() const {");
506  if (EV->isConst()) {
507    const clang::APValue &val = EV->getInit();
508    bool isBool = !strcmp(rtd.type->c_name, "bool");
509    write(string("    return ") + genInitValue(val, isBool) + ";");
510  } else {
511    write(string("    return __") + EV->getName() + ";");
512  }
513  write("}");
514  write("");
515}
516
517void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
518  const RSExportType *ET = EV->getType();
519
520  slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
521              "Variable should be type of pointer here");
522
523  std::string TypeName = GetTypeName(ET);
524  std::string VarName = EV->getName();
525
526  RSReflectionTypeData rtd;
527  EV->getType()->convertToRTD(&rtd);
528  uint32_t slot = getNextExportVarSlot();
529
530  if (!EV->isConst()) {
531    write(string("void bind_") + VarName + "(" + TypeName +
532          " v) {");
533    stringstream tmp;
534    tmp << slot;
535    write(string("    bindAllocation(v, ") + tmp.str() + ");");
536    write(string("    __") + VarName + " = v;");
537    write("}");
538  }
539  write(TypeName + " get_" + VarName + "() const {");
540  if (EV->isConst()) {
541    const clang::APValue &val = EV->getInit();
542    bool isBool = !strcmp(TypeName.c_str(), "bool");
543    write(string("    return ") + genInitValue(val, isBool) + ";");
544  } else {
545    write(string("    return __") + VarName + ";");
546  }
547  write("}");
548  write("");
549
550}
551
552void RSReflectionCpp::genVectorTypeExportVariable(const RSExportVar *EV) {
553  slangAssert(false);
554}
555
556void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
557  slangAssert(false);
558}
559
560void RSReflectionCpp::genConstantArrayTypeExportVariable(
561    const RSExportVar *EV) {
562  slangAssert(false);
563}
564
565void RSReflectionCpp::genRecordTypeExportVariable(const RSExportVar *EV) {
566  slangAssert(false);
567}
568
569
570void RSReflectionCpp::makeFunctionSignature(
571    std::stringstream &ss,
572    bool isDefinition,
573    const RSExportFunc *ef) {
574  ss << "void ";
575  if (isDefinition) {
576    ss << mClassName << "::";
577  }
578  ss << "invoke_" << ef->getName() << "(";
579
580  if (ef->getParamPacketType()) {
581    bool FirstArg = true;
582    for (RSExportFunc::const_param_iterator i = ef->params_begin(),
583         e = ef->params_end(); i != e; i++) {
584      RSReflectionTypeData rtd;
585      (*i)->getType()->convertToRTD(&rtd);
586      if (!FirstArg) {
587        ss << ", ";
588      } else {
589        FirstArg = false;
590      }
591      ss << rtd.type->c_name << " " << (*i)->getName();
592    }
593  }
594
595  if (isDefinition) {
596    ss << ") {";
597  } else {
598    ss << ");";
599  }
600}
601
602void RSReflectionCpp::makeArgs(std::stringstream &ss, const ArgTy& Args) {
603  bool FirstArg = true;
604
605  for (ArgTy::const_iterator I = Args.begin(), E = Args.end(); I != E; I++) {
606    if (!FirstArg) {
607      ss << ", ";
608    } else {
609      FirstArg = false;
610    }
611
612    ss << I->first << " " << I->second;
613  }
614}
615
616bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
617                                           const char *FieldPackerName) {
618  size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
619
620  if (AllocSize > 0) {
621    std::stringstream ss;
622    ss << "    FieldPacker " << FieldPackerName << "("
623       << AllocSize << ");";
624    write(ss);
625    return true;
626  }
627
628  return false;
629}
630
631void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
632                                       const char *VarName,
633                                       const char *FieldPackerName) {
634  std::stringstream ss;
635  switch (ET->getClass()) {
636    case RSExportType::ExportClassPrimitive:
637    case RSExportType::ExportClassVector:
638    case RSExportType::ExportClassPointer:
639    case RSExportType::ExportClassMatrix: {
640      ss << "    " << FieldPackerName << ".add(" << VarName << ");";
641      write(ss);
642      break;
643    }
644    case RSExportType::ExportClassConstantArray: {
645      /*const RSExportConstantArrayType *ECAT =
646          static_cast<const RSExportConstantArrayType *>(ET);
647
648      // TODO(zonr): more elegant way. Currently, we obtain the unique index
649      //             variable (this method involves recursive call which means
650      //             we may have more than one level loop, therefore we can't
651      //             always use the same index variable name here) name given
652      //             in the for-loop from counting the '.' in @VarName.
653      unsigned Level = 0;
654      size_t LastDotPos = 0;
655      std::string ElementVarName(VarName);
656
657      while (LastDotPos != std::string::npos) {
658        LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
659        Level++;
660      }
661      std::string IndexVarName("ct");
662      IndexVarName.append(llvm::utostr_32(Level));
663
664      C.indent() << "for (int " << IndexVarName << " = 0; " <<
665                          IndexVarName << " < " << ECAT->getSize() << "; " <<
666                          IndexVarName << "++)";
667      C.startBlock();
668
669      ElementVarName.append("[" + IndexVarName + "]");
670      genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
671                       FieldPackerName);
672
673      C.endBlock();*/
674      break;
675    }
676    case RSExportType::ExportClassRecord: {
677      const RSExportRecordType *ERT =
678          static_cast<const RSExportRecordType*>(ET);
679      // Relative pos from now on in field packer
680      unsigned Pos = 0;
681
682      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
683               E = ERT->fields_end();
684           I != E;
685           I++) {
686        const RSExportRecordType::Field *F = *I;
687        std::string FieldName;
688        size_t FieldOffset = F->getOffsetInParent();
689        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
690        size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
691
692        if (VarName != NULL)
693          FieldName = VarName + ("." + F->getName());
694        else
695          FieldName = F->getName();
696
697        if (FieldOffset > Pos) {
698          ss.str("");
699          ss << "    " << FieldPackerName << ".skip("
700             << (FieldOffset - Pos) << ");";
701          write(ss);
702        }
703
704        genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
705
706        // There is padding in the field type
707        if (FieldAllocSize > FieldStoreSize) {
708          ss.str("");
709          ss << "    " << FieldPackerName << ".skip("
710             << (FieldAllocSize - FieldStoreSize) << ");";
711          write(ss);
712        }
713
714        Pos = FieldOffset + FieldAllocSize;
715      }
716
717      // There maybe some padding after the struct
718      if (RSExportType::GetTypeAllocSize(ERT) > Pos) {
719        ss.str("");
720        ss << "    " << FieldPackerName << ".skip("
721           << RSExportType::GetTypeAllocSize(ERT) - Pos << ");";
722        write(ss);
723      }
724      break;
725    }
726    default: {
727      slangAssert(false && "Unknown class of type");
728    }
729  }
730}
731
732
733void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
734                                   const char *VarName) {
735  stringstream tmp;
736  tmp << "// Type check for " << VarName;
737  write(tmp);
738  tmp.str("");
739
740  if (ET->getClass() == RSExportType::ExportClassPointer) {
741    const RSExportPointerType *EPT =
742        static_cast<const RSExportPointerType*>(ET);
743    ET = EPT->getPointeeType();
744  }
745
746  std::string TypeName;
747  switch (ET->getClass()) {
748    case RSExportType::ExportClassPrimitive:
749    case RSExportType::ExportClassVector:
750    case RSExportType::ExportClassRecord: {
751      TypeName = ET->getElementName();
752      break;
753    }
754
755    default:
756      break;
757  }
758
759  if (!TypeName.empty()) {
760    //tmp << "// TypeName: " << TypeName;
761    tmp << "if (!" << VarName
762        << "->getType()->getElement()->isCompatible("
763        << RS_ELEM_PREFIX
764        << TypeName << ")) {";
765    write(tmp);
766
767    incIndent();
768    write("mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
769          "\"Incompatible type\");");
770    write("return;");
771    decIndent();
772
773    write("}");
774  }
775}
776
777void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
778  if (ET->getClass() == RSExportType::ExportClassPointer) {
779    // For pointer parameters to original forEach kernels.
780    const RSExportPointerType *EPT =
781        static_cast<const RSExportPointerType*>(ET);
782    genTypeInstance(EPT->getPointeeType());
783  } else {
784    // For handling pass-by-value kernel parameters.
785    genTypeInstance(ET);
786  }
787}
788
789void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
790  switch (ET->getClass()) {
791    case RSExportType::ExportClassPrimitive:
792    case RSExportType::ExportClassVector:
793    case RSExportType::ExportClassConstantArray:
794    case RSExportType::ExportClassRecord: {
795      std::string TypeName = ET->getElementName();
796      addTypeNameForElement(TypeName);
797      break;
798    }
799
800    default:
801      break;
802  }
803}
804
805
806
807}  // namespace slang
808