blob: 0840d377dcad048c344487e35c813973c3285ff8 [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"
37#include "slang_utils.h"
38
39#include "slang_rs_reflection_cpp.h"
40
41using namespace std;
42
43namespace slang {
44
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070045#define RS_TYPE_ITEM_CLASS_NAME "Item"
Stephen Hines7dd6da22012-11-15 19:56:03 -080046
Stephen Hines003ac662013-08-21 00:37:51 -070047#define RS_ELEM_PREFIX "__rs_elem_"
48
Stephen Hines7dd6da22012-11-15 19:56:03 -080049static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
50 static const char *MatrixTypeCNameMap[] = {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070051 "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
Stephen Hines7dd6da22012-11-15 19:56:03 -080052 };
53 unsigned Dim = EMT->getDim();
54
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070055 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
56 return MatrixTypeCNameMap[EMT->getDim() - 2];
Stephen Hines7dd6da22012-11-15 19:56:03 -080057
58 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
59 return NULL;
60}
61
Stephen Hines7dd6da22012-11-15 19:56:03 -080062static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
63 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070064 case RSExportType::ExportClassPrimitive: {
65 const RSExportPrimitiveType *EPT =
66 static_cast<const RSExportPrimitiveType *>(ET);
67 if (EPT->isRSObjectType()) {
68 return std::string("android::RSC::sp<const android::RSC::") +
69 RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
70 } else {
71 return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
Stephen Hines7dd6da22012-11-15 19:56:03 -080072 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070073 }
74 case RSExportType::ExportClassPointer: {
75 const RSExportType *PointeeType =
76 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
Stephen Hines7dd6da22012-11-15 19:56:03 -080077
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070078 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
79 return "android::RSC::sp<android::RSC::Allocation>";
80 else
81 return PointeeType->getElementName();
82 }
83 case RSExportType::ExportClassVector: {
84 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
85 std::stringstream VecName;
86 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
87 << EVT->getNumElement();
88 return VecName.str();
89 }
90 case RSExportType::ExportClassMatrix: {
91 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
92 }
93 case RSExportType::ExportClassConstantArray: {
94 // TODO: Fix this for C arrays!
95 const RSExportConstantArrayType *CAT =
96 static_cast<const RSExportConstantArrayType *>(ET);
97 std::string ElementTypeName = GetTypeName(CAT->getElementType());
98 if (Brackets) {
99 ElementTypeName.append("[]");
Stephen Hines7dd6da22012-11-15 19:56:03 -0800100 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700101 return ElementTypeName;
102 }
103 case RSExportType::ExportClassRecord: {
104 // TODO: Fix for C structs!
105 return ET->getElementName() + "." RS_TYPE_ITEM_CLASS_NAME;
106 }
107 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800108 }
109
110 return "";
111}
112
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700113RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
114 const string &OutputDirectory,
115 const string &RSSourceFileName,
116 const string &BitCodeFileName)
117 : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
118 mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
119 mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0) {
120 mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
121 mClassName = "ScriptC_" + mCleanedRSFileName;
Jason Sams1b6a0882012-03-12 15:07:58 -0700122}
123
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700124RSReflectionCpp::~RSReflectionCpp() {}
Jason Sams1b6a0882012-03-12 15:07:58 -0700125
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700126bool RSReflectionCpp::reflect() {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700127 writeHeaderFile();
128 writeImplementationFile();
Jason Sams1b6a0882012-03-12 15:07:58 -0700129
Stephen Hines02a98262012-11-14 12:40:26 -0800130 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700131}
132
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700133#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
Jason Sams1b6a0882012-03-12 15:07:58 -0700134
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700135bool RSReflectionCpp::writeHeaderFile() {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700136 // Create the file and write the license note.
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700137 if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700138 mRSContext->getLicenseNote(), false,
139 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700140 return false;
141 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700142
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700143 mOut.indent() << "#include \"RenderScript.h\"\n\n";
144 mOut.indent() << "using namespace android::RSC;\n\n";
Jason Sams1b6a0882012-03-12 15:07:58 -0700145
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700146 mOut.comment("This class encapsulates access to the exported elements of the script. "
147 "Typically, you would instantiate this class once, call the set_* methods "
148 "for each of the exported global variables you want to change, then call "
149 "one of the forEach_ methods to invoke a kernel.");
150 mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700151 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800152
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700153 mOut.decreaseIndent();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700154 mOut.indent() << "private:\n";
155 mOut.increaseIndent();
156
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700157 genFieldsToStoreExportVariableValues();
158 genTypeInstancesUsedInForEach();
159 genFieldsForAllocationTypeVerification();
Stephen Hines80706832013-08-28 18:08:57 -0700160
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700161 mOut.decreaseIndent();
162 mOut.indent() << "public:\n";
163 mOut.increaseIndent();
164
165 // Generate the constructor and destructor declarations.
166 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
167 mOut.indent() << "virtual ~" << mClassName << "();\n\n";
168
169 genExportVariablesGetterAndSetter();
170 genForEachDeclarations();
171 genExportFunctionDeclarations();
172
173 mOut.endBlock(true);
174 mOut.closeFile();
175 return true;
176}
177
178void RSReflectionCpp::genTypeInstancesUsedInForEach() {
Stephen Hines003ac662013-08-21 00:37:51 -0700179 for (RSContext::const_export_foreach_iterator
180 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700181 E = mRSContext->export_foreach_end();
182 I != E; I++) {
Stephen Hines003ac662013-08-21 00:37:51 -0700183 const RSExportForEach *EF = *I;
Stephen Hines003ac662013-08-21 00:37:51 -0700184 const RSExportType *OET = EF->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700185
Stephen Hines003ac662013-08-21 00:37:51 -0700186 if (OET) {
187 genTypeInstanceFromPointer(OET);
188 }
Chris Wailesc9454af2014-06-13 17:25:40 -0700189
190 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
191
192 for (RSExportForEach::InTypeIter BI = InTypes.begin(),
193 EI = InTypes.end(); BI != EI; BI++) {
194
195 genTypeInstanceFromPointer(*BI);
196 }
Stephen Hines003ac662013-08-21 00:37:51 -0700197 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700198}
Stephen Hines003ac662013-08-21 00:37:51 -0700199
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700200void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700201 bool CommentAdded = false;
Stephen Hines003ac662013-08-21 00:37:51 -0700202 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
203 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700204 I != E; I++) {
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700205 if (!CommentAdded) {
206 mOut.comment("The following elements are used to verify the types of "
207 "allocations passed to kernels.");
208 CommentAdded = true;
209 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700210 mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
211 << RS_ELEM_PREFIX << *I << ";\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700212 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700213}
Stephen Hines003ac662013-08-21 00:37:51 -0700214
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700215void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700216 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800217 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700218 E = mRSContext->export_vars_end();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700219 I != E; I++) {
220 const RSExportVar *ev = *I;
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700221 if (ev->isConst()) {
222 continue;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700223 }
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700224 if (!CommentAdded) {
225 mOut.comment("For each non-const variable exported by the script, we "
226 "have an equivalent field. This field contains the last "
227 "value this variable was set to using the set_ method. "
228 "This may not be current value of the variable in the "
229 "script, as the script is free to modify its internal "
230 "variable without changing this field. If the script "
231 "initializes the exported variable, the constructor will "
232 "initialize this field to the same value.");
233 CommentAdded = true;
234 }
235 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
236 << ev->getName() << ";\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800237 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700238}
Jason Sams1b6a0882012-03-12 15:07:58 -0700239
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700240void RSReflectionCpp::genForEachDeclarations() {
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700241 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800242 for (RSContext::const_export_foreach_iterator
243 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700244 E = mRSContext->export_foreach_end();
245 I != E; I++) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700246 const RSExportForEach *ForEach = *I;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700247
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700248 if (ForEach->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700249 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800250 continue;
251 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700252
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700253 if (!CommentAdded) {
254 mOut.comment("For each kernel of the script corresponds one method. "
255 "That method queues the kernel for execution. The kernel "
256 "may not have completed nor even started by the time this "
257 "function returns. Calls that extract the data out of the "
258 "output allocation will wait for the kernels to complete.");
259 CommentAdded = true;
260 }
261
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700262 std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700263 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800264
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700265 ArgumentList Arguments;
Chris Wailesc9454af2014-06-13 17:25:40 -0700266 const RSExportForEach::InVec &Ins = ForEach->getIns();
267 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
268 BI != EI; BI++) {
269
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700270 Arguments.push_back(std::make_pair(
Chris Wailesc9454af2014-06-13 17:25:40 -0700271 "android::RSC::sp<const android::RSC::Allocation>", (*BI)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800272 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700273
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700274 if (ForEach->hasOut() || ForEach->hasReturn()) {
275 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700276 "android::RSC::sp<const android::RSC::Allocation>", "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800277 }
278
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700279 const RSExportRecordType *ERT = ForEach->getParamPacketType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800280 if (ERT) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700281 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
282 e = ForEach->params_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700283 i != e; i++) {
Jason Sams192392f2012-03-13 16:22:12 -0700284 RSReflectionTypeData rtd;
Stephen Hines02a98262012-11-14 12:40:26 -0800285 (*i)->getType()->convertToRTD(&rtd);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700286 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800287 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700288 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700289 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700290 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800291 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700292}
Jason Sams1b6a0882012-03-12 15:07:58 -0700293
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700294void RSReflectionCpp::genExportFunctionDeclarations() {
Stephen Hines02a98262012-11-14 12:40:26 -0800295 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700296 I = mRSContext->export_funcs_begin(),
297 E = mRSContext->export_funcs_end();
298 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800299 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700300
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700301 makeFunctionSignature(false, ef);
Stephen Hines02a98262012-11-14 12:40:26 -0800302 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700303}
304
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700305bool RSReflectionCpp::genEncodedBitCode() {
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700306 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
Stephen Hines02a98262012-11-14 12:40:26 -0800307 if (pfin == NULL) {
308 fprintf(stderr, "Error: could not read file %s\n",
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700309 mBitCodeFilePath.c_str());
Stephen Hines02a98262012-11-14 12:40:26 -0800310 return false;
311 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700312
Stephen Hines02a98262012-11-14 12:40:26 -0800313 unsigned char buf[16];
314 int read_length;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700315 mOut.indent() << "static const unsigned char __txt[] =";
316 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800317 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700318 mOut.indent();
Stephen Hines02a98262012-11-14 12:40:26 -0800319 for (int i = 0; i < read_length; i++) {
320 char buf2[16];
321 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700322 mOut << buf2;
Jason Sams1b6a0882012-03-12 15:07:58 -0700323 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700324 mOut << "\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800325 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700326 mOut.endBlock(true);
327 mOut << "\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800328 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700329}
330
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700331bool RSReflectionCpp::writeImplementationFile() {
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700332 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700333 mRSContext->getLicenseNote(), false,
334 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700335 return false;
336 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700337
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700338 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800339
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700340 genEncodedBitCode();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700341 mOut.indent() << "\n\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800342
Tim Murraydde98532013-07-23 15:55:19 -0700343 const std::string &packageName = mRSContext->getReflectJavaPackageName();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700344 mOut.indent() << mClassName << "::" << mClassName
345 << "(android::RSC::sp<android::RSC::RS> rs):\n"
346 " ScriptC(rs, __txt, sizeof(__txt), \""
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700347 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
348 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
349 << packageName << "\"))";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700350 mOut.startBlock();
Stephen Hines003ac662013-08-21 00:37:51 -0700351 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
352 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700353 I != E; I++) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700354 mOut.indent() << RS_ELEM_PREFIX << *I << " = android::RSC::Element::" << *I
355 << "(mRS);\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700356 }
Stephen Hines80706832013-08-28 18:08:57 -0700357
358 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
359 E = mRSContext->export_vars_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700360 I != E; I++) {
Stephen Hines80706832013-08-28 18:08:57 -0700361 const RSExportVar *EV = *I;
362 if (!EV->getInit().isUninit()) {
363 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
364 } else {
365 genZeroInitExportVariable(EV->getName());
366 }
367 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700368 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800369
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700370 mOut.indent() << mClassName << "::~" << mClassName << "()";
371 mOut.startBlock();
372 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800373
374 // Reflect export for each functions
375 uint32_t slot = 0;
376 for (RSContext::const_export_foreach_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700377 I = mRSContext->export_foreach_begin(),
378 E = mRSContext->export_foreach_end();
379 I != E; I++, slot++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800380 const RSExportForEach *ef = *I;
381 if (ef->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700382 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800383 continue;
384 }
385
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700386 ArgumentList Arguments;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700387 std::string FunctionStart =
388 "void " + mClassName + "::forEach_" + ef->getName() + "(";
389 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800390
Chris Wailesc9454af2014-06-13 17:25:40 -0700391 if (ef->hasIns()) {
392 // FIXME: Add support for kernels with multiple inputs.
393 assert(ef->getIns().size() == 1);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700394 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700395 "android::RSC::sp<const android::RSC::Allocation>", "ain"));
Stephen Hines02a98262012-11-14 12:40:26 -0800396 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800397
398 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700399 Arguments.push_back(std::make_pair(
Tim Murrayee9d7b02013-07-30 11:13:27 -0700400 "android::RSC::sp<const android::RSC::Allocation>", "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800401 }
402
403 const RSExportRecordType *ERT = ef->getParamPacketType();
404 if (ERT) {
405 for (RSExportForEach::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700406 e = ef->params_end();
407 i != e; i++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800408 RSReflectionTypeData rtd;
409 (*i)->getType()->convertToRTD(&rtd);
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700410 Arguments.push_back(std::make_pair(rtd.type->c_name, (*i)->getName()));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800411 }
412 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700413 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700414 mOut << ")";
415 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800416
Stephen Hines003ac662013-08-21 00:37:51 -0700417 const RSExportType *OET = ef->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700418 const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
419 if (ef->hasIns()) {
420 // FIXME: Add support for kernels with multiple inputs.
421 assert(ef->getIns().size() == 1);
422 genTypeCheck(InTypes[0], "ain");
Stephen Hines003ac662013-08-21 00:37:51 -0700423 }
Stephen Hines003ac662013-08-21 00:37:51 -0700424 if (OET) {
425 genTypeCheck(OET, "aout");
426 }
Stephen Hines003ac662013-08-21 00:37:51 -0700427
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700428 // TODO Add the appropriate dimension checking code, as seen in
429 // slang_rs_reflection.cpp.
430
Stephen Hines7dd6da22012-11-15 19:56:03 -0800431 std::string FieldPackerName = ef->getName() + "_fp";
432 if (ERT) {
433 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
434 genPackVarOfType(ERT, NULL, FieldPackerName.c_str());
435 }
Stephen Hines02a98262012-11-14 12:40:26 -0800436 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700437 mOut.indent() << "forEach(" << slot << ", ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800438
Chris Wailesc9454af2014-06-13 17:25:40 -0700439 if (ef->hasIns()) {
440 // FIXME: Add support for kernels with multiple inputs.
441 assert(ef->getIns().size() == 1);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700442 mOut << "ain, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800443 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700444 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800445 }
446
447 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700448 mOut << "aout, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800449 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700450 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800451 }
452
Stephen Hines003ac662013-08-21 00:37:51 -0700453 // FIXME (no support for usrData with C++ kernels)
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700454 mOut << "NULL, 0);\n";
455 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800456 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700457
Stephen Hines02a98262012-11-14 12:40:26 -0800458 slot = 0;
459 // Reflect export function
460 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700461 I = mRSContext->export_funcs_begin(),
462 E = mRSContext->export_funcs_end();
463 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800464 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700465
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700466 makeFunctionSignature(true, ef);
467 mOut.startBlock();
Stephen Hines713377e2012-11-14 19:32:43 -0800468 const RSExportRecordType *params = ef->getParamPacketType();
469 size_t param_len = 0;
470 if (params) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700471 param_len = params->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800472 if (genCreateFieldPacker(params, "__fp")) {
473 genPackVarOfType(params, NULL, "__fp");
Stephen Hines713377e2012-11-14 19:32:43 -0800474 }
Stephen Hines713377e2012-11-14 19:32:43 -0800475 }
476
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700477 mOut.indent() << "invoke(" << slot;
Stephen Hines713377e2012-11-14 19:32:43 -0800478 if (params) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700479 mOut << ", __fp.getData(), " << param_len << ");\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800480 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700481 mOut << ", NULL, 0);\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800482 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700483 mOut.endBlock();
Jason Sams1b6a0882012-03-12 15:07:58 -0700484
Stephen Hines02a98262012-11-14 12:40:26 -0800485 slot++;
486 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700487
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700488 mOut.closeFile();
Stephen Hines02a98262012-11-14 12:40:26 -0800489 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700490}
491
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700492void RSReflectionCpp::genExportVariablesGetterAndSetter() {
Jean-Luc Brouilletf5ab7e72014-07-25 15:50:32 -0700493 mOut.comment("Methods to set and get the variables exported by the script. "
494 "Const variables will not have a setter.\n\n"
495 "Note that the value returned by the getter may not be the "
496 "current value of the variable in the script. The getter will "
497 "return the initial value of the variable (as defined in the "
498 "script) or the the last value set by using the setter method. "
499 "The script is free to modify its value independently.");
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700500 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
501 E = mRSContext->export_vars_end();
502 I != E; I++) {
503 const RSExportVar *EV = *I;
504 const RSExportType *ET = EV->getType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800505
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700506 switch (ET->getClass()) {
507 case RSExportType::ExportClassPrimitive: {
508 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
509 break;
510 }
511 case RSExportType::ExportClassPointer: {
512 // TODO Deprecate this.
513 genPointerTypeExportVariable(EV);
514 break;
515 }
516 case RSExportType::ExportClassVector: {
517 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
518 break;
519 }
520 case RSExportType::ExportClassMatrix: {
521 genMatrixTypeExportVariable(EV);
522 break;
523 }
524 case RSExportType::ExportClassConstantArray: {
525 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
526 EV);
527 break;
528 }
529 case RSExportType::ExportClassRecord: {
530 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
531 break;
532 }
533 default: { slangAssert(false && "Unknown class of type"); }
534 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800535 }
536}
537
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700538void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
539 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800540 RSReflectionTypeData rtd;
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800541 EPT->convertToRTD(&rtd);
542 std::string TypeName = GetTypeName(EPT, false);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800543
544 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700545 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
546 mOut.startBlock();
547 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800548 if (EPT->isRSObjectType()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700549 mOut << "v";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800550 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700551 mOut << "&v, sizeof(v)";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800552 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700553 mOut << ");\n";
554 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
555 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800556 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700557 mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
558 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800559 if (EV->isConst()) {
560 const clang::APValue &val = EV->getInit();
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800561 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700562 mOut.indent() << "return ";
563 genInitValue(val, isBool);
564 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800565 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700566 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
567 << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800568 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700569 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800570}
571
572void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
573 const RSExportType *ET = EV->getType();
574
575 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
576 "Variable should be type of pointer here");
577
578 std::string TypeName = GetTypeName(ET);
579 std::string VarName = EV->getName();
580
581 RSReflectionTypeData rtd;
582 EV->getType()->convertToRTD(&rtd);
583 uint32_t slot = getNextExportVarSlot();
584
585 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700586 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
587 mOut.startBlock();
588 mOut.indent() << "bindAllocation(v, " << slot << ");\n";
589 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
590 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800591 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700592 mOut.indent() << TypeName << " get_" << VarName << "() const";
593 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800594 if (EV->isConst()) {
595 const clang::APValue &val = EV->getInit();
596 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700597 mOut.indent() << "return ";
598 genInitValue(val, isBool);
599 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800600 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700601 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800602 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700603 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800604}
605
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700606void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
607 const RSExportVar *EV) {
Stephen Hines80706832013-08-28 18:08:57 -0700608 slangAssert(EVT != NULL);
609
610 RSReflectionTypeData rtd;
611 EVT->convertToRTD(&rtd);
612
Stephen Hines80706832013-08-28 18:08:57 -0700613 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700614 mOut.indent() << "void set_" << EV->getName() << "("
615 << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
616 << " v)";
617 mOut.startBlock();
618 mOut.indent() << "setVar(" << getNextExportVarSlot()
619 << ", &v, sizeof(v));\n";
620 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
621 mOut.endBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700622 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700623 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
624 << " get_" << EV->getName() << "() const";
625 mOut.startBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700626 if (EV->isConst()) {
627 const clang::APValue &val = EV->getInit();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700628 mOut.indent() << "return ";
629 genInitValue(val, false);
630 mOut << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700631 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700632 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
633 << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700634 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700635 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800636}
637
638void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
639 slangAssert(false);
640}
641
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700642void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
643 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800644 slangAssert(false);
645}
646
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700647void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
648 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800649 slangAssert(false);
650}
651
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700652void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700653 const RSExportFunc *ef) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700654 mOut.indent() << "void ";
Stephen Hines02a98262012-11-14 12:40:26 -0800655 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700656 mOut << mClassName << "::";
Stephen Hines02a98262012-11-14 12:40:26 -0800657 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700658 mOut << "invoke_" << ef->getName() << "(";
Stephen Hines38dceea2012-11-13 17:33:55 -0800659
Stephen Hines02a98262012-11-14 12:40:26 -0800660 if (ef->getParamPacketType()) {
661 bool FirstArg = true;
662 for (RSExportFunc::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700663 e = ef->params_end();
664 i != e; i++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800665 RSReflectionTypeData rtd;
666 (*i)->getType()->convertToRTD(&rtd);
667 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700668 mOut << ", ";
Stephen Hines02a98262012-11-14 12:40:26 -0800669 } else {
670 FirstArg = false;
671 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700672 mOut << rtd.type->c_name << " " << (*i)->getName();
Stephen Hines38dceea2012-11-13 17:33:55 -0800673 }
Stephen Hines02a98262012-11-14 12:40:26 -0800674 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800675
Stephen Hines02a98262012-11-14 12:40:26 -0800676 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700677 mOut << ")";
Stephen Hines02a98262012-11-14 12:40:26 -0800678 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700679 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800680 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800681}
682
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700683void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800684 bool FirstArg = true;
685
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700686 for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
687 I != E; I++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800688 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700689 mOut << ",\n";
690 mOut.indent() << string(Offset, ' ');
Stephen Hines7dd6da22012-11-15 19:56:03 -0800691 } else {
692 FirstArg = false;
693 }
694
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700695 mOut << I->first << " " << I->second;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800696 }
697}
698
699bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
700 const char *FieldPackerName) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700701 size_t AllocSize = ET->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800702
703 if (AllocSize > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700704 mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
705 << AllocSize << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800706 return true;
707 }
708
709 return false;
710}
711
712void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
713 const char *VarName,
714 const char *FieldPackerName) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800715 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700716 case RSExportType::ExportClassPrimitive:
717 case RSExportType::ExportClassVector:
718 case RSExportType::ExportClassPointer:
719 case RSExportType::ExportClassMatrix: {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700720 mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700721 break;
722 }
723 case RSExportType::ExportClassConstantArray: {
724 /*const RSExportConstantArrayType *ECAT =
725 static_cast<const RSExportConstantArrayType *>(ET);
726
727 // TODO(zonr): more elegant way. Currently, we obtain the unique index
728 // variable (this method involves recursive call which means
729 // we may have more than one level loop, therefore we can't
730 // always use the same index variable name here) name given
731 // in the for-loop from counting the '.' in @VarName.
732 unsigned Level = 0;
733 size_t LastDotPos = 0;
734 std::string ElementVarName(VarName);
735
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700736 while (LastDotPos != std::string::npos) {
737 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
738 Level++;
739 }
740 std::string IndexVarName("ct");
741 IndexVarName.append(llvm::utostr_32(Level));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800742
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700743 C.indent() << "for (int " << IndexVarName << " = 0; " <<
744 IndexVarName << " < " << ECAT->getSize() << "; " <<
745 IndexVarName << "++)";
746 C.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800747
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700748 ElementVarName.append("[" + IndexVarName + "]");
749 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
750 FieldPackerName);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800751
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700752 C.endBlock();*/
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700753 break;
754 }
755 case RSExportType::ExportClassRecord: {
756 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
757 // Relative pos from now on in field packer
758 unsigned Pos = 0;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800759
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700760 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
761 E = ERT->fields_end();
762 I != E; I++) {
763 const RSExportRecordType::Field *F = *I;
764 std::string FieldName;
765 size_t FieldOffset = F->getOffsetInParent();
766 const RSExportType *T = F->getType();
767 size_t FieldStoreSize = T->getStoreSize();
768 size_t FieldAllocSize = T->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800769
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700770 if (VarName != NULL)
771 FieldName = VarName + ("." + F->getName());
772 else
773 FieldName = F->getName();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800774
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700775 if (FieldOffset > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700776 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
777 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800778 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700779
780 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
781
782 // There is padding in the field type
783 if (FieldAllocSize > FieldStoreSize) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700784 mOut.indent() << FieldPackerName << ".skip("
785 << (FieldAllocSize - FieldStoreSize) << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700786 }
787
788 Pos = FieldOffset + FieldAllocSize;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800789 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700790
791 // There maybe some padding after the struct
792 if (ERT->getAllocSize() > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700793 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
794 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800795 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700796 break;
797 }
798 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800799 }
800}
801
Stephen Hines003ac662013-08-21 00:37:51 -0700802void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
803 const char *VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700804 mOut.indent() << "// Type check for " << VarName << "\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700805
806 if (ET->getClass() == RSExportType::ExportClassPointer) {
807 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700808 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -0700809 ET = EPT->getPointeeType();
810 }
811
812 std::string TypeName;
813 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700814 case RSExportType::ExportClassPrimitive:
815 case RSExportType::ExportClassVector:
816 case RSExportType::ExportClassRecord: {
817 TypeName = ET->getElementName();
818 break;
819 }
Stephen Hines003ac662013-08-21 00:37:51 -0700820
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700821 default:
822 break;
Stephen Hines003ac662013-08-21 00:37:51 -0700823 }
824
825 if (!TypeName.empty()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700826 mOut.indent() << "if (!" << VarName
827 << "->getType()->getElement()->isCompatible("
828 << RS_ELEM_PREFIX << TypeName << "))";
829 mOut.startBlock();
830 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
831 "\"Incompatible type\");\n";
832 mOut.indent() << "return;\n";
833 mOut.endBlock();
Stephen Hines003ac662013-08-21 00:37:51 -0700834 }
835}
836
837void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
838 if (ET->getClass() == RSExportType::ExportClassPointer) {
839 // For pointer parameters to original forEach kernels.
840 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700841 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -0700842 genTypeInstance(EPT->getPointeeType());
843 } else {
844 // For handling pass-by-value kernel parameters.
845 genTypeInstance(ET);
846 }
847}
848
849void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
850 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700851 case RSExportType::ExportClassPrimitive:
852 case RSExportType::ExportClassVector:
853 case RSExportType::ExportClassConstantArray:
854 case RSExportType::ExportClassRecord: {
855 std::string TypeName = ET->getElementName();
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700856 mTypesToCheck.insert(TypeName);
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700857 break;
858 }
Stephen Hines003ac662013-08-21 00:37:51 -0700859
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700860 default:
861 break;
Stephen Hines003ac662013-08-21 00:37:51 -0700862 }
863}
864
Stephen Hines80706832013-08-28 18:08:57 -0700865void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
866 const std::string &VarName,
867 const clang::APValue &Val) {
868 slangAssert(!Val.isUninit() && "Not a valid initializer");
Stephen Hines003ac662013-08-21 00:37:51 -0700869
Stephen Hines80706832013-08-28 18:08:57 -0700870 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700871 case RSExportType::ExportClassPrimitive: {
872 const RSExportPrimitiveType *EPT =
873 static_cast<const RSExportPrimitiveType *>(ET);
874 if (EPT->getType() == DataTypeBoolean) {
875 genInitBoolExportVariable(VarName, Val);
876 } else {
877 genInitPrimitiveExportVariable(VarName, Val);
878 }
879 break;
880 }
881 case RSExportType::ExportClassPointer: {
882 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
883 std::cerr << "Initializer which is non-NULL to pointer type variable "
884 "will be ignored" << std::endl;
885 break;
886 }
887 case RSExportType::ExportClassVector: {
888 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
889 switch (Val.getKind()) {
890 case clang::APValue::Int:
891 case clang::APValue::Float: {
892 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
893 std::string Name = VarName + "." + getVectorAccessor(i);
894 genInitPrimitiveExportVariable(Name, Val);
Stephen Hines80706832013-08-28 18:08:57 -0700895 }
896 break;
897 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700898 case clang::APValue::Vector: {
899 unsigned NumElements = std::min(
900 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
901 for (unsigned i = 0; i < NumElements; i++) {
902 const clang::APValue &ElementVal = Val.getVectorElt(i);
903 std::string Name = VarName + "." + getVectorAccessor(i);
904 genInitPrimitiveExportVariable(Name, ElementVal);
Stephen Hines80706832013-08-28 18:08:57 -0700905 }
906 break;
907 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700908 case clang::APValue::MemberPointer:
909 case clang::APValue::Uninitialized:
910 case clang::APValue::ComplexInt:
911 case clang::APValue::ComplexFloat:
912 case clang::APValue::LValue:
913 case clang::APValue::Array:
914 case clang::APValue::Struct:
915 case clang::APValue::Union:
916 case clang::APValue::AddrLabelDiff: {
917 slangAssert(false && "Unexpected type of value of initializer.");
Stephen Hines80706832013-08-28 18:08:57 -0700918 }
Stephen Hines80706832013-08-28 18:08:57 -0700919 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700920 break;
921 }
922 case RSExportType::ExportClassMatrix:
923 case RSExportType::ExportClassConstantArray:
924 case RSExportType::ExportClassRecord: {
925 slangAssert(false && "Unsupported initializer for record/matrix/constant "
926 "array type variable currently");
927 break;
928 }
929 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines80706832013-08-28 18:08:57 -0700930 }
Stephen Hines80706832013-08-28 18:08:57 -0700931}
932
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700933const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
934 static const char *VectorAccessorMap[] = {/* 0 */ "x",
935 /* 1 */ "y",
936 /* 2 */ "z",
937 /* 3 */ "w",
938 };
939
940 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
941 "Out-of-bound index to access vector member");
942
943 return VectorAccessorMap[Index];
944}
945
Stephen Hines80706832013-08-28 18:08:57 -0700946void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700947 mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
948 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
Stephen Hines80706832013-08-28 18:08:57 -0700949}
950
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700951void
952RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
953 const clang::APValue &Val) {
Stephen Hines80706832013-08-28 18:08:57 -0700954 slangAssert(!Val.isUninit() && "Not a valid initializer");
955
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700956 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
957 genInitValue(Val);
958 mOut << ";\n";
959}
960
961void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
962 switch (Val.getKind()) {
963 case clang::APValue::Int: {
964 llvm::APInt api = Val.getInt();
965 if (asBool) {
966 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
967 } else {
968 // TODO: Handle unsigned correctly for C++
969 mOut << api.getSExtValue();
970 if (api.getBitWidth() > 32) {
971 mOut << "L";
972 }
973 }
974 break;
975 }
976
977 case clang::APValue::Float: {
978 llvm::APFloat apf = Val.getFloat();
979 llvm::SmallString<30> s;
980 apf.toString(s);
981 mOut << s.c_str();
982 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
983 if (s.count('.') == 0) {
984 mOut << ".f";
985 } else {
986 mOut << "f";
987 }
988 }
989 break;
990 }
991
992 case clang::APValue::ComplexInt:
993 case clang::APValue::ComplexFloat:
994 case clang::APValue::LValue:
995 case clang::APValue::Vector: {
996 slangAssert(false && "Primitive type cannot have such kind of initializer");
997 break;
998 }
999
1000 default: { slangAssert(false && "Unknown kind of initializer"); }
1001 }
Stephen Hines80706832013-08-28 18:08:57 -07001002}
1003
1004void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
1005 const clang::APValue &Val) {
1006 slangAssert(!Val.isUninit() && "Not a valid initializer");
1007 slangAssert((Val.getKind() == clang::APValue::Int) &&
1008 "Bool type has wrong initial APValue");
1009
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001010 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
1011 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
1012 << ";";
Stephen Hines80706832013-08-28 18:08:57 -07001013}
Stephen Hines003ac662013-08-21 00:37:51 -07001014
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001015} // namespace slang