blob: 03f2ee580d93e7d0f2750c767ccc44479b3dadc7 [file] [log] [blame]
Jason Sams1b6a0882012-03-12 15:07:58 -07001/*
Tim Murrayee9d7b02013-07-30 11:13:27 -07002 * Copyright 2013, The Android Open Source Project
Jason Sams1b6a0882012-03-12 15:07:58 -07003 *
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>
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -070020#include <iostream>
Jason Sams1b6a0882012-03-12 15:07:58 -070021
22#include <cstdarg>
23#include <cctype>
24
25#include <algorithm>
26#include <sstream>
27#include <string>
28#include <utility>
29
30#include "os_sep.h"
31#include "slang_rs_context.h"
32#include "slang_rs_export_var.h"
33#include "slang_rs_export_foreach.h"
34#include "slang_rs_export_func.h"
35#include "slang_rs_reflect_utils.h"
36#include "slang_version.h"
Jason Sams1b6a0882012-03-12 15:07:58 -070037
38#include "slang_rs_reflection_cpp.h"
39
40using namespace std;
41
42namespace slang {
43
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070044#define RS_TYPE_ITEM_CLASS_NAME "Item"
Stephen Hines7dd6da22012-11-15 19:56:03 -080045
Stephen Hines003ac662013-08-21 00:37:51 -070046#define RS_ELEM_PREFIX "__rs_elem_"
47
Stephen Hines7dd6da22012-11-15 19:56:03 -080048static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
49 static const char *MatrixTypeCNameMap[] = {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070050 "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
Stephen Hines7dd6da22012-11-15 19:56:03 -080051 };
52 unsigned Dim = EMT->getDim();
53
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070054 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
55 return MatrixTypeCNameMap[EMT->getDim() - 2];
Stephen Hines7dd6da22012-11-15 19:56:03 -080056
57 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
Chris Wailes5abbe0e2014-08-12 15:58:29 -070058 return nullptr;
Stephen Hines7dd6da22012-11-15 19:56:03 -080059}
60
Stephen Hines7dd6da22012-11-15 19:56:03 -080061static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
62 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070063 case RSExportType::ExportClassPrimitive: {
64 const RSExportPrimitiveType *EPT =
65 static_cast<const RSExportPrimitiveType *>(ET);
66 if (EPT->isRSObjectType()) {
67 return std::string("android::RSC::sp<const android::RSC::") +
68 RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
69 } else {
70 return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
Stephen Hines7dd6da22012-11-15 19:56:03 -080071 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070072 }
73 case RSExportType::ExportClassPointer: {
74 const RSExportType *PointeeType =
75 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
Stephen Hines7dd6da22012-11-15 19:56:03 -080076
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070077 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
78 return "android::RSC::sp<android::RSC::Allocation>";
79 else
80 return PointeeType->getElementName();
81 }
82 case RSExportType::ExportClassVector: {
83 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
84 std::stringstream VecName;
85 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
86 << EVT->getNumElement();
87 return VecName.str();
88 }
89 case RSExportType::ExportClassMatrix: {
90 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
91 }
92 case RSExportType::ExportClassConstantArray: {
93 // TODO: Fix this for C arrays!
94 const RSExportConstantArrayType *CAT =
95 static_cast<const RSExportConstantArrayType *>(ET);
96 std::string ElementTypeName = GetTypeName(CAT->getElementType());
97 if (Brackets) {
98 ElementTypeName.append("[]");
Stephen Hines7dd6da22012-11-15 19:56:03 -080099 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700100 return ElementTypeName;
101 }
102 case RSExportType::ExportClassRecord: {
103 // TODO: Fix for C structs!
104 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
105 }
106 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800107 }
108
109 return "";
110}
111
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700112RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
113 const string &OutputDirectory,
114 const string &RSSourceFileName,
115 const string &BitCodeFileName)
116 : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
117 mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
118 mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0) {
119 mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
120 mClassName = "ScriptC_" + mCleanedRSFileName;
Jason Sams1b6a0882012-03-12 15:07:58 -0700121}
122
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700123RSReflectionCpp::~RSReflectionCpp() {}
Jason Sams1b6a0882012-03-12 15:07:58 -0700124
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700125bool RSReflectionCpp::reflect() {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700126 writeHeaderFile();
127 writeImplementationFile();
Jason Sams1b6a0882012-03-12 15:07:58 -0700128
Stephen Hines02a98262012-11-14 12:40:26 -0800129 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700130}
131
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700132#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
Jason Sams1b6a0882012-03-12 15:07:58 -0700133
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700134bool RSReflectionCpp::writeHeaderFile() {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700135 // Create the file and write the license note.
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700136 if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700137 mRSContext->getLicenseNote(), false,
138 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700139 return false;
140 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700141
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700142 mOut.indent() << "#include \"RenderScript.h\"\n\n";
143 mOut.indent() << "using namespace android::RSC;\n\n";
Jason Sams1b6a0882012-03-12 15:07:58 -0700144
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700145 mOut.comment("This class encapsulates access to the exported elements of the script. "
146 "Typically, you would instantiate this class once, call the set_* methods "
147 "for each of the exported global variables you want to change, then call "
148 "one of the forEach_ methods to invoke a kernel.");
149 mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700150 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800151
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700152 mOut.decreaseIndent();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700153 mOut.indent() << "private:\n";
154 mOut.increaseIndent();
155
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700156 genFieldsToStoreExportVariableValues();
157 genTypeInstancesUsedInForEach();
158 genFieldsForAllocationTypeVerification();
Stephen Hines80706832013-08-28 18:08:57 -0700159
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700160 mOut.decreaseIndent();
161 mOut.indent() << "public:\n";
162 mOut.increaseIndent();
163
164 // Generate the constructor and destructor declarations.
165 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
166 mOut.indent() << "virtual ~" << mClassName << "();\n\n";
167
168 genExportVariablesGetterAndSetter();
169 genForEachDeclarations();
170 genExportFunctionDeclarations();
171
172 mOut.endBlock(true);
173 mOut.closeFile();
174 return true;
175}
176
177void RSReflectionCpp::genTypeInstancesUsedInForEach() {
Stephen Hines003ac662013-08-21 00:37:51 -0700178 for (RSContext::const_export_foreach_iterator
179 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700180 E = mRSContext->export_foreach_end();
181 I != E; I++) {
Stephen Hines003ac662013-08-21 00:37:51 -0700182 const RSExportForEach *EF = *I;
Stephen Hines003ac662013-08-21 00:37:51 -0700183 const RSExportType *OET = EF->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700184
Stephen Hines003ac662013-08-21 00:37:51 -0700185 if (OET) {
186 genTypeInstanceFromPointer(OET);
187 }
Chris Wailesc9454af2014-06-13 17:25:40 -0700188
189 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
190
191 for (RSExportForEach::InTypeIter BI = InTypes.begin(),
192 EI = InTypes.end(); BI != EI; BI++) {
193
194 genTypeInstanceFromPointer(*BI);
195 }
Stephen Hines003ac662013-08-21 00:37:51 -0700196 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700197}
Stephen Hines003ac662013-08-21 00:37:51 -0700198
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700199void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700200 bool CommentAdded = false;
Stephen Hines003ac662013-08-21 00:37:51 -0700201 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
202 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700203 I != E; I++) {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700204 if (!CommentAdded) {
205 mOut.comment("The following elements are used to verify the types of "
206 "allocations passed to kernels.");
207 CommentAdded = true;
208 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700209 mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
210 << RS_ELEM_PREFIX << *I << ";\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700211 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700212}
Stephen Hines003ac662013-08-21 00:37:51 -0700213
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700214void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700215 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800216 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700217 E = mRSContext->export_vars_end();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700218 I != E; I++) {
219 const RSExportVar *ev = *I;
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700220 if (ev->isConst()) {
221 continue;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700222 }
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700223 if (!CommentAdded) {
224 mOut.comment("For each non-const variable exported by the script, we "
225 "have an equivalent field. This field contains the last "
226 "value this variable was set to using the set_ method. "
227 "This may not be current value of the variable in the "
228 "script, as the script is free to modify its internal "
229 "variable without changing this field. If the script "
230 "initializes the exported variable, the constructor will "
231 "initialize this field to the same value.");
232 CommentAdded = true;
233 }
234 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
235 << ev->getName() << ";\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800236 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700237}
Jason Sams1b6a0882012-03-12 15:07:58 -0700238
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700239void RSReflectionCpp::genForEachDeclarations() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700240 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800241 for (RSContext::const_export_foreach_iterator
242 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700243 E = mRSContext->export_foreach_end();
244 I != E; I++) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700245 const RSExportForEach *ForEach = *I;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700246
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700247 if (ForEach->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700248 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800249 continue;
250 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700251
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700252 if (!CommentAdded) {
253 mOut.comment("For each kernel of the script corresponds one method. "
254 "That method queues the kernel for execution. The kernel "
255 "may not have completed nor even started by the time this "
256 "function returns. Calls that extract the data out of the "
257 "output allocation will wait for the kernels to complete.");
258 CommentAdded = true;
259 }
260
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700261 std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700262 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800263
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700264 ArgumentList Arguments;
Chris Wailesc9454af2014-06-13 17:25:40 -0700265 const RSExportForEach::InVec &Ins = ForEach->getIns();
266 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
267 BI != EI; BI++) {
268
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700269 Arguments.push_back(std::make_pair(
Chris Wailesc9454af2014-06-13 17:25:40 -0700270 "android::RSC::sp<const android::RSC::Allocation>", (*BI)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800271 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700272
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700273 if (ForEach->hasOut() || ForEach->hasReturn()) {
274 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700275 "android::RSC::sp<const android::RSC::Allocation>", "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800276 }
277
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700278 const RSExportRecordType *ERT = ForEach->getParamPacketType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800279 if (ERT) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700280 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
281 e = ForEach->params_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700282 i != e; i++) {
Jason Sams192392f2012-03-13 16:22:12 -0700283 RSReflectionTypeData rtd;
Stephen Hines02a98262012-11-14 12:40:26 -0800284 (*i)->getType()->convertToRTD(&rtd);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700285 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800286 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700287 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700288 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700289 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800290 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700291}
Jason Sams1b6a0882012-03-12 15:07:58 -0700292
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700293void RSReflectionCpp::genExportFunctionDeclarations() {
Stephen Hines02a98262012-11-14 12:40:26 -0800294 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700295 I = mRSContext->export_funcs_begin(),
296 E = mRSContext->export_funcs_end();
297 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800298 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700299
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700300 makeFunctionSignature(false, ef);
Stephen Hines02a98262012-11-14 12:40:26 -0800301 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700302}
303
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700304bool RSReflectionCpp::genEncodedBitCode() {
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700305 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700306 if (pfin == nullptr) {
Stephen Hines02a98262012-11-14 12:40:26 -0800307 fprintf(stderr, "Error: could not read file %s\n",
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700308 mBitCodeFilePath.c_str());
Stephen Hines02a98262012-11-14 12:40:26 -0800309 return false;
310 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700311
Stephen Hines02a98262012-11-14 12:40:26 -0800312 unsigned char buf[16];
313 int read_length;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700314 mOut.indent() << "static const unsigned char __txt[] =";
315 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800316 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700317 mOut.indent();
Stephen Hines02a98262012-11-14 12:40:26 -0800318 for (int i = 0; i < read_length; i++) {
319 char buf2[16];
320 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700321 mOut << buf2;
Jason Sams1b6a0882012-03-12 15:07:58 -0700322 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700323 mOut << "\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800324 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700325 mOut.endBlock(true);
326 mOut << "\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800327 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700328}
329
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700330bool RSReflectionCpp::writeImplementationFile() {
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700331 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700332 mRSContext->getLicenseNote(), false,
333 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700334 return false;
335 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700336
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700337 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800338
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700339 genEncodedBitCode();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700340 mOut.indent() << "\n\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800341
Tim Murraydde98532013-07-23 15:55:19 -0700342 const std::string &packageName = mRSContext->getReflectJavaPackageName();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700343 mOut.indent() << mClassName << "::" << mClassName
344 << "(android::RSC::sp<android::RSC::RS> rs):\n"
345 " ScriptC(rs, __txt, sizeof(__txt), \""
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700346 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
347 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
348 << packageName << "\"))";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700349 mOut.startBlock();
Stephen Hines003ac662013-08-21 00:37:51 -0700350 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
351 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700352 I != E; I++) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700353 mOut.indent() << RS_ELEM_PREFIX << *I << " = android::RSC::Element::" << *I
354 << "(mRS);\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700355 }
Stephen Hines80706832013-08-28 18:08:57 -0700356
357 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
358 E = mRSContext->export_vars_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700359 I != E; I++) {
Stephen Hines80706832013-08-28 18:08:57 -0700360 const RSExportVar *EV = *I;
361 if (!EV->getInit().isUninit()) {
362 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
363 } else {
364 genZeroInitExportVariable(EV->getName());
365 }
366 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700367 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800368
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700369 mOut.indent() << mClassName << "::~" << mClassName << "()";
370 mOut.startBlock();
371 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800372
373 // Reflect export for each functions
374 uint32_t slot = 0;
375 for (RSContext::const_export_foreach_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700376 I = mRSContext->export_foreach_begin(),
377 E = mRSContext->export_foreach_end();
378 I != E; I++, slot++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800379 const RSExportForEach *ef = *I;
380 if (ef->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700381 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800382 continue;
383 }
384
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700385 ArgumentList Arguments;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700386 std::string FunctionStart =
387 "void " + mClassName + "::forEach_" + ef->getName() + "(";
388 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800389
Chris Wailesc9454af2014-06-13 17:25:40 -0700390 if (ef->hasIns()) {
391 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700392 slangAssert(ef->getIns().size() == 1);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700393 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700394 "android::RSC::sp<const android::RSC::Allocation>", "ain"));
Stephen Hines02a98262012-11-14 12:40:26 -0800395 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800396
397 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700398 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700399 "android::RSC::sp<const android::RSC::Allocation>", "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800400 }
401
402 const RSExportRecordType *ERT = ef->getParamPacketType();
403 if (ERT) {
404 for (RSExportForEach::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700405 e = ef->params_end();
406 i != e; i++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800407 RSReflectionTypeData rtd;
408 (*i)->getType()->convertToRTD(&rtd);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700409 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800410 }
411 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700412 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700413 mOut << ")";
414 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800415
Stephen Hines003ac662013-08-21 00:37:51 -0700416 const RSExportType *OET = ef->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700417 const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
418 if (ef->hasIns()) {
419 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700420 slangAssert(ef->getIns().size() == 1);
Chris Wailesc9454af2014-06-13 17:25:40 -0700421 genTypeCheck(InTypes[0], "ain");
Stephen Hines003ac662013-08-21 00:37:51 -0700422 }
Stephen Hines003ac662013-08-21 00:37:51 -0700423 if (OET) {
424 genTypeCheck(OET, "aout");
425 }
Stephen Hines003ac662013-08-21 00:37:51 -0700426
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700427 // TODO Add the appropriate dimension checking code, as seen in
428 // slang_rs_reflection.cpp.
429
Stephen Hines7dd6da22012-11-15 19:56:03 -0800430 std::string FieldPackerName = ef->getName() + "_fp";
431 if (ERT) {
432 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700433 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
Stephen Hines7dd6da22012-11-15 19:56:03 -0800434 }
Stephen Hines02a98262012-11-14 12:40:26 -0800435 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700436 mOut.indent() << "forEach(" << slot << ", ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800437
Chris Wailesc9454af2014-06-13 17:25:40 -0700438 if (ef->hasIns()) {
439 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700440 slangAssert(ef->getIns().size() == 1);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700441 mOut << "ain, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800442 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700443 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800444 }
445
446 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700447 mOut << "aout, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800448 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700449 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800450 }
451
Stephen Hines003ac662013-08-21 00:37:51 -0700452 // FIXME (no support for usrData with C++ kernels)
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700453 mOut << "NULL, 0);\n";
454 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800455 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700456
Stephen Hines02a98262012-11-14 12:40:26 -0800457 slot = 0;
458 // Reflect export function
459 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700460 I = mRSContext->export_funcs_begin(),
461 E = mRSContext->export_funcs_end();
462 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800463 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700464
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700465 makeFunctionSignature(true, ef);
466 mOut.startBlock();
Stephen Hines713377e2012-11-14 19:32:43 -0800467 const RSExportRecordType *params = ef->getParamPacketType();
468 size_t param_len = 0;
469 if (params) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700470 param_len = params->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800471 if (genCreateFieldPacker(params, "__fp")) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700472 genPackVarOfType(params, nullptr, "__fp");
Stephen Hines713377e2012-11-14 19:32:43 -0800473 }
Stephen Hines713377e2012-11-14 19:32:43 -0800474 }
475
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700476 mOut.indent() << "invoke(" << slot;
Stephen Hines713377e2012-11-14 19:32:43 -0800477 if (params) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700478 mOut << ", __fp.getData(), " << param_len << ");\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800479 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700480 mOut << ", NULL, 0);\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800481 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700482 mOut.endBlock();
Jason Sams1b6a0882012-03-12 15:07:58 -0700483
Stephen Hines02a98262012-11-14 12:40:26 -0800484 slot++;
485 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700486
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700487 mOut.closeFile();
Stephen Hines02a98262012-11-14 12:40:26 -0800488 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700489}
490
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700491void RSReflectionCpp::genExportVariablesGetterAndSetter() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700492 mOut.comment("Methods to set and get the variables exported by the script. "
493 "Const variables will not have a setter.\n\n"
494 "Note that the value returned by the getter may not be the "
495 "current value of the variable in the script. The getter will "
496 "return the initial value of the variable (as defined in the "
497 "script) or the the last value set by using the setter method. "
498 "The script is free to modify its value independently.");
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700499 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
500 E = mRSContext->export_vars_end();
501 I != E; I++) {
502 const RSExportVar *EV = *I;
503 const RSExportType *ET = EV->getType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800504
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700505 switch (ET->getClass()) {
506 case RSExportType::ExportClassPrimitive: {
507 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
508 break;
509 }
510 case RSExportType::ExportClassPointer: {
511 // TODO Deprecate this.
512 genPointerTypeExportVariable(EV);
513 break;
514 }
515 case RSExportType::ExportClassVector: {
516 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
517 break;
518 }
519 case RSExportType::ExportClassMatrix: {
520 genMatrixTypeExportVariable(EV);
521 break;
522 }
523 case RSExportType::ExportClassConstantArray: {
524 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
525 EV);
526 break;
527 }
528 case RSExportType::ExportClassRecord: {
529 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
530 break;
531 }
532 default: { slangAssert(false && "Unknown class of type"); }
533 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800534 }
535}
536
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700537void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
538 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800539 RSReflectionTypeData rtd;
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800540 EPT->convertToRTD(&rtd);
541 std::string TypeName = GetTypeName(EPT, false);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800542
543 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700544 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
545 mOut.startBlock();
546 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800547 if (EPT->isRSObjectType()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700548 mOut << "v";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800549 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700550 mOut << "&v, sizeof(v)";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800551 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700552 mOut << ");\n";
553 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
554 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800555 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700556 mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
557 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800558 if (EV->isConst()) {
559 const clang::APValue &val = EV->getInit();
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800560 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700561 mOut.indent() << "return ";
562 genInitValue(val, isBool);
563 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800564 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700565 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
566 << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800567 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700568 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800569}
570
571void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
572 const RSExportType *ET = EV->getType();
573
574 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
575 "Variable should be type of pointer here");
576
577 std::string TypeName = GetTypeName(ET);
578 std::string VarName = EV->getName();
579
580 RSReflectionTypeData rtd;
581 EV->getType()->convertToRTD(&rtd);
582 uint32_t slot = getNextExportVarSlot();
583
584 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700585 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
586 mOut.startBlock();
587 mOut.indent() << "bindAllocation(v, " << slot << ");\n";
588 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
589 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800590 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700591 mOut.indent() << TypeName << " get_" << VarName << "() const";
592 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800593 if (EV->isConst()) {
594 const clang::APValue &val = EV->getInit();
595 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700596 mOut.indent() << "return ";
597 genInitValue(val, isBool);
598 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800599 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700600 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800601 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700602 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800603}
604
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700605void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
606 const RSExportVar *EV) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700607 slangAssert(EVT != nullptr);
Stephen Hines80706832013-08-28 18:08:57 -0700608
609 RSReflectionTypeData rtd;
610 EVT->convertToRTD(&rtd);
611
Stephen Hines80706832013-08-28 18:08:57 -0700612 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700613 mOut.indent() << "void set_" << EV->getName() << "("
614 << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
615 << " v)";
616 mOut.startBlock();
617 mOut.indent() << "setVar(" << getNextExportVarSlot()
618 << ", &v, sizeof(v));\n";
619 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
620 mOut.endBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700621 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700622 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
623 << " get_" << EV->getName() << "() const";
624 mOut.startBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700625 if (EV->isConst()) {
626 const clang::APValue &val = EV->getInit();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700627 mOut.indent() << "return ";
628 genInitValue(val, false);
629 mOut << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700630 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700631 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
632 << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700633 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700634 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800635}
636
637void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
638 slangAssert(false);
639}
640
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700641void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
642 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800643 slangAssert(false);
644}
645
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700646void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
647 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800648 slangAssert(false);
649}
650
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700651void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700652 const RSExportFunc *ef) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700653 mOut.indent() << "void ";
Stephen Hines02a98262012-11-14 12:40:26 -0800654 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700655 mOut << mClassName << "::";
Stephen Hines02a98262012-11-14 12:40:26 -0800656 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700657 mOut << "invoke_" << ef->getName() << "(";
Stephen Hines38dceea2012-11-13 17:33:55 -0800658
Stephen Hines02a98262012-11-14 12:40:26 -0800659 if (ef->getParamPacketType()) {
660 bool FirstArg = true;
661 for (RSExportFunc::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700662 e = ef->params_end();
663 i != e; i++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800664 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700665 mOut << ", ";
Stephen Hines02a98262012-11-14 12:40:26 -0800666 } else {
667 FirstArg = false;
668 }
Stephen Hines19879e82015-06-30 16:11:34 -0700669 mOut << GetTypeName((*i)->getType(), false) << " " << (*i)->getName();
Stephen Hines38dceea2012-11-13 17:33:55 -0800670 }
Stephen Hines02a98262012-11-14 12:40:26 -0800671 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800672
Stephen Hines02a98262012-11-14 12:40:26 -0800673 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700674 mOut << ")";
Stephen Hines02a98262012-11-14 12:40:26 -0800675 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700676 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800677 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800678}
679
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700680void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800681 bool FirstArg = true;
682
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700683 for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
684 I != E; I++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800685 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700686 mOut << ",\n";
687 mOut.indent() << string(Offset, ' ');
Stephen Hines7dd6da22012-11-15 19:56:03 -0800688 } else {
689 FirstArg = false;
690 }
691
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700692 mOut << I->first << " " << I->second;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800693 }
694}
695
696bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
697 const char *FieldPackerName) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700698 size_t AllocSize = ET->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800699
700 if (AllocSize > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700701 mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
702 << AllocSize << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800703 return true;
704 }
705
706 return false;
707}
708
709void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
710 const char *VarName,
711 const char *FieldPackerName) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800712 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700713 case RSExportType::ExportClassPrimitive:
714 case RSExportType::ExportClassVector:
715 case RSExportType::ExportClassPointer:
716 case RSExportType::ExportClassMatrix: {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700717 mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700718 break;
719 }
720 case RSExportType::ExportClassConstantArray: {
721 /*const RSExportConstantArrayType *ECAT =
722 static_cast<const RSExportConstantArrayType *>(ET);
723
724 // TODO(zonr): more elegant way. Currently, we obtain the unique index
725 // variable (this method involves recursive call which means
726 // we may have more than one level loop, therefore we can't
727 // always use the same index variable name here) name given
728 // in the for-loop from counting the '.' in @VarName.
729 unsigned Level = 0;
730 size_t LastDotPos = 0;
731 std::string ElementVarName(VarName);
732
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700733 while (LastDotPos != std::string::npos) {
734 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
735 Level++;
736 }
737 std::string IndexVarName("ct");
738 IndexVarName.append(llvm::utostr_32(Level));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800739
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700740 C.indent() << "for (int " << IndexVarName << " = 0; " <<
741 IndexVarName << " < " << ECAT->getSize() << "; " <<
742 IndexVarName << "++)";
743 C.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800744
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700745 ElementVarName.append("[" + IndexVarName + "]");
746 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
747 FieldPackerName);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800748
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700749 C.endBlock();*/
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700750 break;
751 }
752 case RSExportType::ExportClassRecord: {
753 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
754 // Relative pos from now on in field packer
755 unsigned Pos = 0;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800756
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700757 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
758 E = ERT->fields_end();
759 I != E; I++) {
760 const RSExportRecordType::Field *F = *I;
761 std::string FieldName;
762 size_t FieldOffset = F->getOffsetInParent();
763 const RSExportType *T = F->getType();
764 size_t FieldStoreSize = T->getStoreSize();
765 size_t FieldAllocSize = T->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800766
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700767 if (VarName != nullptr)
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700768 FieldName = VarName + ("." + F->getName());
769 else
770 FieldName = F->getName();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800771
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700772 if (FieldOffset > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700773 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
774 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800775 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700776
777 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
778
779 // There is padding in the field type
780 if (FieldAllocSize > FieldStoreSize) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700781 mOut.indent() << FieldPackerName << ".skip("
782 << (FieldAllocSize - FieldStoreSize) << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700783 }
784
785 Pos = FieldOffset + FieldAllocSize;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800786 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700787
788 // There maybe some padding after the struct
789 if (ERT->getAllocSize() > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700790 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
791 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800792 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700793 break;
794 }
795 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800796 }
797}
798
Stephen Hines003ac662013-08-21 00:37:51 -0700799void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
800 const char *VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700801 mOut.indent() << "// Type check for " << VarName << "\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700802
803 if (ET->getClass() == RSExportType::ExportClassPointer) {
804 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700805 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -0700806 ET = EPT->getPointeeType();
807 }
808
809 std::string TypeName;
810 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700811 case RSExportType::ExportClassPrimitive:
812 case RSExportType::ExportClassVector:
813 case RSExportType::ExportClassRecord: {
814 TypeName = ET->getElementName();
815 break;
816 }
Stephen Hines003ac662013-08-21 00:37:51 -0700817
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700818 default:
819 break;
Stephen Hines003ac662013-08-21 00:37:51 -0700820 }
821
822 if (!TypeName.empty()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700823 mOut.indent() << "if (!" << VarName
824 << "->getType()->getElement()->isCompatible("
825 << RS_ELEM_PREFIX << TypeName << "))";
826 mOut.startBlock();
827 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
828 "\"Incompatible type\");\n";
829 mOut.indent() << "return;\n";
830 mOut.endBlock();
Stephen Hines003ac662013-08-21 00:37:51 -0700831 }
832}
833
834void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
835 if (ET->getClass() == RSExportType::ExportClassPointer) {
836 // For pointer parameters to original forEach kernels.
837 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700838 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -0700839 genTypeInstance(EPT->getPointeeType());
840 } else {
841 // For handling pass-by-value kernel parameters.
842 genTypeInstance(ET);
843 }
844}
845
846void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
847 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700848 case RSExportType::ExportClassPrimitive:
849 case RSExportType::ExportClassVector:
850 case RSExportType::ExportClassConstantArray:
851 case RSExportType::ExportClassRecord: {
852 std::string TypeName = ET->getElementName();
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700853 mTypesToCheck.insert(TypeName);
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700854 break;
855 }
Stephen Hines003ac662013-08-21 00:37:51 -0700856
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700857 default:
858 break;
Stephen Hines003ac662013-08-21 00:37:51 -0700859 }
860}
861
Stephen Hines80706832013-08-28 18:08:57 -0700862void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
863 const std::string &VarName,
864 const clang::APValue &Val) {
865 slangAssert(!Val.isUninit() && "Not a valid initializer");
Stephen Hines003ac662013-08-21 00:37:51 -0700866
Stephen Hines80706832013-08-28 18:08:57 -0700867 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700868 case RSExportType::ExportClassPrimitive: {
869 const RSExportPrimitiveType *EPT =
870 static_cast<const RSExportPrimitiveType *>(ET);
871 if (EPT->getType() == DataTypeBoolean) {
872 genInitBoolExportVariable(VarName, Val);
873 } else {
874 genInitPrimitiveExportVariable(VarName, Val);
875 }
876 break;
877 }
878 case RSExportType::ExportClassPointer: {
879 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
880 std::cerr << "Initializer which is non-NULL to pointer type variable "
881 "will be ignored" << std::endl;
882 break;
883 }
884 case RSExportType::ExportClassVector: {
885 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
886 switch (Val.getKind()) {
887 case clang::APValue::Int:
888 case clang::APValue::Float: {
889 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
890 std::string Name = VarName + "." + getVectorAccessor(i);
891 genInitPrimitiveExportVariable(Name, Val);
Stephen Hines80706832013-08-28 18:08:57 -0700892 }
893 break;
894 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700895 case clang::APValue::Vector: {
896 unsigned NumElements = std::min(
897 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
898 for (unsigned i = 0; i < NumElements; i++) {
899 const clang::APValue &ElementVal = Val.getVectorElt(i);
900 std::string Name = VarName + "." + getVectorAccessor(i);
901 genInitPrimitiveExportVariable(Name, ElementVal);
Stephen Hines80706832013-08-28 18:08:57 -0700902 }
903 break;
904 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700905 case clang::APValue::MemberPointer:
906 case clang::APValue::Uninitialized:
907 case clang::APValue::ComplexInt:
908 case clang::APValue::ComplexFloat:
909 case clang::APValue::LValue:
910 case clang::APValue::Array:
911 case clang::APValue::Struct:
912 case clang::APValue::Union:
913 case clang::APValue::AddrLabelDiff: {
914 slangAssert(false && "Unexpected type of value of initializer.");
Stephen Hines80706832013-08-28 18:08:57 -0700915 }
Stephen Hines80706832013-08-28 18:08:57 -0700916 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700917 break;
918 }
919 case RSExportType::ExportClassMatrix:
920 case RSExportType::ExportClassConstantArray:
921 case RSExportType::ExportClassRecord: {
922 slangAssert(false && "Unsupported initializer for record/matrix/constant "
923 "array type variable currently");
924 break;
925 }
926 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines80706832013-08-28 18:08:57 -0700927 }
Stephen Hines80706832013-08-28 18:08:57 -0700928}
929
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700930const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
931 static const char *VectorAccessorMap[] = {/* 0 */ "x",
932 /* 1 */ "y",
933 /* 2 */ "z",
934 /* 3 */ "w",
935 };
936
937 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
938 "Out-of-bound index to access vector member");
939
940 return VectorAccessorMap[Index];
941}
942
Stephen Hines80706832013-08-28 18:08:57 -0700943void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700944 mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
945 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
Stephen Hines80706832013-08-28 18:08:57 -0700946}
947
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700948void
949RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
950 const clang::APValue &Val) {
Stephen Hines80706832013-08-28 18:08:57 -0700951 slangAssert(!Val.isUninit() && "Not a valid initializer");
952
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700953 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
954 genInitValue(Val);
955 mOut << ";\n";
956}
957
958void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
959 switch (Val.getKind()) {
960 case clang::APValue::Int: {
961 llvm::APInt api = Val.getInt();
962 if (asBool) {
963 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
964 } else {
965 // TODO: Handle unsigned correctly for C++
966 mOut << api.getSExtValue();
967 if (api.getBitWidth() > 32) {
968 mOut << "L";
969 }
970 }
971 break;
972 }
973
974 case clang::APValue::Float: {
975 llvm::APFloat apf = Val.getFloat();
976 llvm::SmallString<30> s;
977 apf.toString(s);
978 mOut << s.c_str();
979 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
980 if (s.count('.') == 0) {
981 mOut << ".f";
982 } else {
983 mOut << "f";
984 }
985 }
986 break;
987 }
988
989 case clang::APValue::ComplexInt:
990 case clang::APValue::ComplexFloat:
991 case clang::APValue::LValue:
992 case clang::APValue::Vector: {
993 slangAssert(false && "Primitive type cannot have such kind of initializer");
994 break;
995 }
996
997 default: { slangAssert(false && "Unknown kind of initializer"); }
998 }
Stephen Hines80706832013-08-28 18:08:57 -0700999}
1000
1001void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
1002 const clang::APValue &Val) {
1003 slangAssert(!Val.isUninit() && "Not a valid initializer");
1004 slangAssert((Val.getKind() == clang::APValue::Int) &&
1005 "Bool type has wrong initial APValue");
1006
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001007 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
1008 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
1009 << ";";
Stephen Hines80706832013-08-28 18:08:57 -07001010}
Stephen Hines003ac662013-08-21 00:37:51 -07001011
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001012} // namespace slang