blob: 15c48fafd00f724bddb22a9a1d7d703d590a382c [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>
Jason Sams1b6a0882012-03-12 15:07:58 -070028
29#include "os_sep.h"
30#include "slang_rs_context.h"
31#include "slang_rs_export_var.h"
32#include "slang_rs_export_foreach.h"
33#include "slang_rs_export_func.h"
Matt Wala1c6b9272015-08-03 14:06:07 -070034#include "slang_rs_export_reduce.h"
Jason Sams1b6a0882012-03-12 15:07:58 -070035#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
Matt Wala1c6b9272015-08-03 14:06:07 -070044const char kRsTypeItemClassName[] = "Item";
45const char kRsElemPrefix[] = "__rs_elem_";
46// The name of the Allocation type that is reflected in C++
47const char kAllocationSp[] = "android::RSC::sp<android::RSC::Allocation>";
48const char kConstRsScriptCall[] = "const RsScriptCall";
Stephen Hines003ac662013-08-21 00:37:51 -070049
Stephen Hines7dd6da22012-11-15 19:56:03 -080050static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
51 static const char *MatrixTypeCNameMap[] = {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070052 "rs_matrix2x2", "rs_matrix3x3", "rs_matrix4x4",
Stephen Hines7dd6da22012-11-15 19:56:03 -080053 };
54 unsigned Dim = EMT->getDim();
55
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070056 if ((Dim - 2) < (sizeof(MatrixTypeCNameMap) / sizeof(const char *)))
57 return MatrixTypeCNameMap[EMT->getDim() - 2];
Stephen Hines7dd6da22012-11-15 19:56:03 -080058
59 slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
Chris Wailes5abbe0e2014-08-12 15:58:29 -070060 return nullptr;
Stephen Hines7dd6da22012-11-15 19:56:03 -080061}
62
Nicolas Collin5f3da4b2015-10-21 10:22:51 +010063static std::string GetTypeName(const RSExportType *ET, bool PreIdentifier = true) {
64 if((!PreIdentifier) && (ET->getClass() != RSExportType::ExportClassConstantArray)) {
65 slangAssert(false && "Non-array type post identifier?");
66 return "";
67 }
Stephen Hines7dd6da22012-11-15 19:56:03 -080068 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070069 case RSExportType::ExportClassPrimitive: {
70 const RSExportPrimitiveType *EPT =
71 static_cast<const RSExportPrimitiveType *>(ET);
72 if (EPT->isRSObjectType()) {
73 return std::string("android::RSC::sp<const android::RSC::") +
74 RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
75 } else {
76 return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
Stephen Hines7dd6da22012-11-15 19:56:03 -080077 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070078 }
79 case RSExportType::ExportClassPointer: {
80 const RSExportType *PointeeType =
81 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
Stephen Hines7dd6da22012-11-15 19:56:03 -080082
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070083 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
Matt Wala1c6b9272015-08-03 14:06:07 -070084 return kAllocationSp;
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070085 else
86 return PointeeType->getElementName();
87 }
88 case RSExportType::ExportClassVector: {
89 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
90 std::stringstream VecName;
91 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
92 << EVT->getNumElement();
93 return VecName.str();
94 }
95 case RSExportType::ExportClassMatrix: {
96 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
97 }
98 case RSExportType::ExportClassConstantArray: {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070099 const RSExportConstantArrayType *CAT =
100 static_cast<const RSExportConstantArrayType *>(ET);
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100101 if (PreIdentifier) {
102 std::string ElementTypeName = GetTypeName(CAT->getElementType());
103 return ElementTypeName;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800104 }
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100105 else {
106 std::stringstream ArraySpec;
107 ArraySpec << "[" << CAT->getSize() << "]";
108 return ArraySpec.str();
109 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700110 }
111 case RSExportType::ExportClassRecord: {
112 // TODO: Fix for C structs!
Matt Wala1c6b9272015-08-03 14:06:07 -0700113 return ET->getElementName() + "." + kRsTypeItemClassName;
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700114 }
115 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800116 }
117
118 return "";
119}
120
Matt Wala1c6b9272015-08-03 14:06:07 -0700121static bool canExportReduceArrayVariant(const RSExportType *Type) {
122 // FIXME: No half types available for C++ reflection yet
123 if (Type->getElementName().find("F16") == 0) {
124 return false;
125 }
126 return Type->getClass() == RSExportType::ExportClassPrimitive ||
127 Type->getClass() == RSExportType::ExportClassVector;
128}
129
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700130RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
131 const string &OutputDirectory,
132 const string &RSSourceFileName,
133 const string &BitCodeFileName)
134 : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
135 mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
Matt Wala1c6b9272015-08-03 14:06:07 -0700136 mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0),
137 mNextExportReduceSlot(0) {
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700138 mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
139 mClassName = "ScriptC_" + mCleanedRSFileName;
Jason Sams1b6a0882012-03-12 15:07:58 -0700140}
141
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700142RSReflectionCpp::~RSReflectionCpp() {}
Jason Sams1b6a0882012-03-12 15:07:58 -0700143
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700144bool RSReflectionCpp::reflect() {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700145 writeHeaderFile();
146 writeImplementationFile();
Jason Sams1b6a0882012-03-12 15:07:58 -0700147
Stephen Hines02a98262012-11-14 12:40:26 -0800148 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700149}
150
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700151#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
Jason Sams1b6a0882012-03-12 15:07:58 -0700152
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700153bool RSReflectionCpp::writeHeaderFile() {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700154 // Create the file and write the license note.
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700155 if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700156 mRSContext->getLicenseNote(), false,
157 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700158 return false;
159 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700160
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700161 mOut.indent() << "#include \"RenderScript.h\"\n\n";
162 mOut.indent() << "using namespace android::RSC;\n\n";
Jason Sams1b6a0882012-03-12 15:07:58 -0700163
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700164 mOut.comment("This class encapsulates access to the exported elements of the script. "
165 "Typically, you would instantiate this class once, call the set_* methods "
166 "for each of the exported global variables you want to change, then call "
167 "one of the forEach_ methods to invoke a kernel.");
168 mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700169 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800170
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700171 mOut.decreaseIndent();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700172 mOut.indent() << "private:\n";
173 mOut.increaseIndent();
174
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700175 genFieldsToStoreExportVariableValues();
176 genTypeInstancesUsedInForEach();
Matt Wala1c6b9272015-08-03 14:06:07 -0700177 genTypeInstancesUsedInReduce();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700178 genFieldsForAllocationTypeVerification();
Stephen Hines80706832013-08-28 18:08:57 -0700179
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700180 mOut.decreaseIndent();
181 mOut.indent() << "public:\n";
182 mOut.increaseIndent();
183
184 // Generate the constructor and destructor declarations.
185 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
186 mOut.indent() << "virtual ~" << mClassName << "();\n\n";
187
188 genExportVariablesGetterAndSetter();
189 genForEachDeclarations();
Matt Wala1c6b9272015-08-03 14:06:07 -0700190 genReduceDeclarations();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700191 genExportFunctionDeclarations();
192
193 mOut.endBlock(true);
194 mOut.closeFile();
195 return true;
196}
197
198void RSReflectionCpp::genTypeInstancesUsedInForEach() {
Matt Wala1c6b9272015-08-03 14:06:07 -0700199 for (auto I = mRSContext->export_foreach_begin(),
200 E = mRSContext->export_foreach_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700201 I != E; I++) {
Stephen Hines003ac662013-08-21 00:37:51 -0700202 const RSExportForEach *EF = *I;
Stephen Hines003ac662013-08-21 00:37:51 -0700203 const RSExportType *OET = EF->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700204
Stephen Hines003ac662013-08-21 00:37:51 -0700205 if (OET) {
206 genTypeInstanceFromPointer(OET);
207 }
Chris Wailesc9454af2014-06-13 17:25:40 -0700208
209 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
210
211 for (RSExportForEach::InTypeIter BI = InTypes.begin(),
212 EI = InTypes.end(); BI != EI; BI++) {
213
214 genTypeInstanceFromPointer(*BI);
215 }
Stephen Hines003ac662013-08-21 00:37:51 -0700216 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700217}
Stephen Hines003ac662013-08-21 00:37:51 -0700218
Matt Wala1c6b9272015-08-03 14:06:07 -0700219// Ensure that the type of the reduce kernel is reflected.
220void RSReflectionCpp::genTypeInstancesUsedInReduce() {
221 for (auto I = mRSContext->export_reduce_begin(),
222 E = mRSContext->export_reduce_end();
223 I != E; ++I) {
224 genTypeInstance((*I)->getType());
225 }
226}
227
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700228void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700229 bool CommentAdded = false;
Stephen Hines003ac662013-08-21 00:37:51 -0700230 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
231 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700232 I != E; I++) {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700233 if (!CommentAdded) {
234 mOut.comment("The following elements are used to verify the types of "
235 "allocations passed to kernels.");
236 CommentAdded = true;
237 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700238 mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
Matt Wala1c6b9272015-08-03 14:06:07 -0700239 << kRsElemPrefix << *I << ";\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700240 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700241}
Stephen Hines003ac662013-08-21 00:37:51 -0700242
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700243void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700244 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800245 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700246 E = mRSContext->export_vars_end();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700247 I != E; I++) {
248 const RSExportVar *ev = *I;
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700249 if (ev->isConst()) {
250 continue;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700251 }
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700252 if (!CommentAdded) {
253 mOut.comment("For each non-const variable exported by the script, we "
254 "have an equivalent field. This field contains the last "
255 "value this variable was set to using the set_ method. "
256 "This may not be current value of the variable in the "
257 "script, as the script is free to modify its internal "
258 "variable without changing this field. If the script "
259 "initializes the exported variable, the constructor will "
260 "initialize this field to the same value.");
261 CommentAdded = true;
262 }
263 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
264 << ev->getName() << ";\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800265 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700266}
Jason Sams1b6a0882012-03-12 15:07:58 -0700267
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700268void RSReflectionCpp::genForEachDeclarations() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700269 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800270 for (RSContext::const_export_foreach_iterator
271 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700272 E = mRSContext->export_foreach_end();
273 I != E; I++) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700274 const RSExportForEach *ForEach = *I;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700275
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700276 if (ForEach->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700277 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800278 continue;
279 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700280
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700281 if (!CommentAdded) {
282 mOut.comment("For each kernel of the script corresponds one method. "
283 "That method queues the kernel for execution. The kernel "
284 "may not have completed nor even started by the time this "
285 "function returns. Calls that extract the data out of the "
286 "output allocation will wait for the kernels to complete.");
287 CommentAdded = true;
288 }
289
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700290 std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700291 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800292
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700293 ArgumentList Arguments;
Chris Wailesc9454af2014-06-13 17:25:40 -0700294 const RSExportForEach::InVec &Ins = ForEach->getIns();
295 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
296 BI != EI; BI++) {
297
Matt Wala1c6b9272015-08-03 14:06:07 -0700298 Arguments.push_back(Argument(kAllocationSp, (*BI)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800299 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700300
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700301 if (ForEach->hasOut() || ForEach->hasReturn()) {
Matt Wala1c6b9272015-08-03 14:06:07 -0700302 Arguments.push_back(Argument(kAllocationSp, "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800303 }
304
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700305 const RSExportRecordType *ERT = ForEach->getParamPacketType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800306 if (ERT) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700307 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
308 e = ForEach->params_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700309 i != e; i++) {
Jason Sams192392f2012-03-13 16:22:12 -0700310 RSReflectionTypeData rtd;
Stephen Hines02a98262012-11-14 12:40:26 -0800311 (*i)->getType()->convertToRTD(&rtd);
Matt Wala1c6b9272015-08-03 14:06:07 -0700312 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800313 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700314 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700315 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700316 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800317 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700318}
Jason Sams1b6a0882012-03-12 15:07:58 -0700319
Matt Wala1c6b9272015-08-03 14:06:07 -0700320void RSReflectionCpp::genReduceDeclarations() {
321 bool CommentAdded = false;
322 for (auto I = mRSContext->export_reduce_begin(),
323 E = mRSContext->export_reduce_end(); I != E; I++) {
324 if (!CommentAdded) {
325 mOut.comment("For each reduce kernel of the script, there is an entry "
326 "point to call the reduce kernel.");
327 CommentAdded = true;
328 }
329
330 makeReduceSignatureAllocationVariant(false, *I);
331 makeReduceSignatureArrayVariant(false, *I);
332 }
333}
334
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700335void RSReflectionCpp::genExportFunctionDeclarations() {
Stephen Hines02a98262012-11-14 12:40:26 -0800336 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700337 I = mRSContext->export_funcs_begin(),
338 E = mRSContext->export_funcs_end();
339 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800340 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700341
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700342 makeFunctionSignature(false, ef);
Stephen Hines02a98262012-11-14 12:40:26 -0800343 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700344}
345
Matt Wala1c6b9272015-08-03 14:06:07 -0700346// forEach_* implementation
347void RSReflectionCpp::genExportForEachBodies() {
Stephen Hines02a98262012-11-14 12:40:26 -0800348 uint32_t slot = 0;
Matt Wala1c6b9272015-08-03 14:06:07 -0700349 for (auto I = mRSContext->export_foreach_begin(),
350 E = mRSContext->export_foreach_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700351 I != E; I++, slot++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800352 const RSExportForEach *ef = *I;
353 if (ef->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700354 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800355 continue;
356 }
357
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700358 ArgumentList Arguments;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700359 std::string FunctionStart =
360 "void " + mClassName + "::forEach_" + ef->getName() + "(";
361 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800362
Chris Wailesc9454af2014-06-13 17:25:40 -0700363 if (ef->hasIns()) {
364 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700365 slangAssert(ef->getIns().size() == 1);
Matt Wala1c6b9272015-08-03 14:06:07 -0700366 Arguments.push_back(Argument(kAllocationSp, "ain"));
Stephen Hines02a98262012-11-14 12:40:26 -0800367 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800368
369 if (ef->hasOut() || ef->hasReturn()) {
Matt Wala1c6b9272015-08-03 14:06:07 -0700370 Arguments.push_back(Argument(kAllocationSp, "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800371 }
372
373 const RSExportRecordType *ERT = ef->getParamPacketType();
374 if (ERT) {
375 for (RSExportForEach::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700376 e = ef->params_end();
377 i != e; i++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800378 RSReflectionTypeData rtd;
379 (*i)->getType()->convertToRTD(&rtd);
Matt Wala1c6b9272015-08-03 14:06:07 -0700380 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800381 }
382 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700383 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700384 mOut << ")";
385 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800386
Stephen Hines003ac662013-08-21 00:37:51 -0700387 const RSExportType *OET = ef->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700388 const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
389 if (ef->hasIns()) {
390 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700391 slangAssert(ef->getIns().size() == 1);
Chris Wailesc9454af2014-06-13 17:25:40 -0700392 genTypeCheck(InTypes[0], "ain");
Stephen Hines003ac662013-08-21 00:37:51 -0700393 }
Stephen Hines003ac662013-08-21 00:37:51 -0700394 if (OET) {
395 genTypeCheck(OET, "aout");
396 }
Stephen Hines003ac662013-08-21 00:37:51 -0700397
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700398 // TODO Add the appropriate dimension checking code, as seen in
399 // slang_rs_reflection.cpp.
400
Stephen Hines7dd6da22012-11-15 19:56:03 -0800401 std::string FieldPackerName = ef->getName() + "_fp";
402 if (ERT) {
403 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700404 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
Stephen Hines7dd6da22012-11-15 19:56:03 -0800405 }
Stephen Hines02a98262012-11-14 12:40:26 -0800406 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700407 mOut.indent() << "forEach(" << slot << ", ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800408
Chris Wailesc9454af2014-06-13 17:25:40 -0700409 if (ef->hasIns()) {
410 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700411 slangAssert(ef->getIns().size() == 1);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700412 mOut << "ain, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800413 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700414 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800415 }
416
417 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700418 mOut << "aout, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800419 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700420 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800421 }
422
Stephen Hines003ac662013-08-21 00:37:51 -0700423 // FIXME (no support for usrData with C++ kernels)
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700424 mOut << "NULL, 0);\n";
425 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800426 }
Matt Wala1c6b9272015-08-03 14:06:07 -0700427}
Jason Sams1b6a0882012-03-12 15:07:58 -0700428
Matt Wala1c6b9272015-08-03 14:06:07 -0700429// reduce_* implementation
430void RSReflectionCpp::genExportReduceBodies() {
431 for (auto I = mRSContext->export_reduce_begin(),
432 E = mRSContext->export_reduce_end();
433 I != E; ++I) {
434 const RSExportReduce &Reduce = **I;
435 const RSExportType *Type = Reduce.getType();
436
437 // Allocation variant
438 //
439 // void reduce_foo(sp<Allocation> ain, sp<Allocation> aout,
440 // const RsScriptCall *sc);
441 makeReduceSignatureAllocationVariant(true, &Reduce);
442 mOut.startBlock();
443
444 // Type check
445 genTypeCheck(Type, "ain");
446 genTypeCheck(Type, "aout");
447
448 // Dimension check
449 gen1DCheck("ain");
450
451 const uint32_t Slot = getNextExportReduceSlot();
452
453 // Call into RenderScript.
454 mOut.indent() << "reduce(" << Slot << ", "
455 << "ain, aout, sc);\n";
456 mOut.endBlock();
457
458 if (!canExportReduceArrayVariant(Type)) {
459 continue;
460 }
461
462 // Array variant
463 //
464 // Ty reduce_foo(const ElemTy[] in, uint32_t x1, uint32_t x2, uint32_t inLen);
465 // "Ty" could be different from "ElemTy" in the case of vectors.
466 makeReduceSignatureArrayVariant(true, &Reduce);
467 mOut.startBlock();
468
469 const std::string ReturnType = GetTypeName(Type);
470 const std::string DefaultReturnValue = ReturnType + "()";
471
472 genNullOrEmptyArrayCheck("in", "inLen", DefaultReturnValue);
473
474 RSReflectionTypeData TypeData;
475 Type->convertToRTD(&TypeData);
476 const uint32_t VecSize = TypeData.vecSize;
477 std::string InLength = "inLen";
478 // Adjust the length so that it corresponds to the number of elements in the allocation.
479 if (VecSize > 1) {
480 InLength += " / " + std::to_string(VecSize);
481 }
482 genVectorLengthCompatibilityCheck("inLen", VecSize, DefaultReturnValue);
483
484 mOut.indent() << "if (x1 >= x2 || x2 > " << InLength << ")";
485 mOut.startBlock();
486 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
487 << "\"Input bounds are invalid\");\n";
488 mOut.indent() << "return " << DefaultReturnValue << ";\n";
489 mOut.endBlock();
490
491 mOut.indent() << kAllocationSp
492 << " ain = android::RSC::Allocation::createSized(mRS, "
493 << kRsElemPrefix << Type->getElementName() << ", "
494 << "x2 - x1);\n";
495
496 mOut.indent() << "ain->setAutoPadding(true);\n";
497
498 mOut.indent() << kAllocationSp
499 << " aout = android::RSC::Allocation::createSized(mRS, "
500 << kRsElemPrefix << Type->getElementName() << ", 1);\n";
501
502 mOut.indent() << "aout->setAutoPadding(true);\n";
503
504 const std::string ArrayElementType = TypeData.type->c_name;
505
506 std::string StartOffset = "x1";
507 if (VecSize > 1) {
508 StartOffset += " * " + std::to_string(VecSize);
509 }
510 mOut.indent() << "ain->copy1DRangeFrom(0, x2 - x1, &in[" << StartOffset << "]);\n";
511 mOut.indent() << "reduce_" << Reduce.getName() << "(ain, aout);\n";
512 mOut.indent() << ArrayElementType << " outArray[" << VecSize << "];\n";
513
514 mOut.indent() << "aout->copy1DRangeTo(0, 1, &outArray[0]);\n";
515
516 mOut.indent() << "return " << ReturnType << "(";
517 for (uint32_t VecElem = 0; VecElem < VecSize; ++VecElem) {
518 if (VecElem > 0) mOut << ", ";
519 mOut << "outArray[" << VecElem << "]";
520 }
521 mOut << ");\n";
522 mOut.endBlock();
523 }
524}
525
526// invoke_* implementation
527void RSReflectionCpp::genExportFunctionBodies() {
528 uint32_t slot = 0;
Stephen Hines02a98262012-11-14 12:40:26 -0800529 // Reflect export function
Matt Wala1c6b9272015-08-03 14:06:07 -0700530 for (auto I = mRSContext->export_funcs_begin(),
531 E = mRSContext->export_funcs_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700532 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800533 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700534
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700535 makeFunctionSignature(true, ef);
536 mOut.startBlock();
Stephen Hines713377e2012-11-14 19:32:43 -0800537 const RSExportRecordType *params = ef->getParamPacketType();
538 size_t param_len = 0;
539 if (params) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700540 param_len = params->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800541 if (genCreateFieldPacker(params, "__fp")) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700542 genPackVarOfType(params, nullptr, "__fp");
Stephen Hines713377e2012-11-14 19:32:43 -0800543 }
Stephen Hines713377e2012-11-14 19:32:43 -0800544 }
545
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700546 mOut.indent() << "invoke(" << slot;
Stephen Hines713377e2012-11-14 19:32:43 -0800547 if (params) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700548 mOut << ", __fp.getData(), " << param_len << ");\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800549 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700550 mOut << ", NULL, 0);\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800551 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700552 mOut.endBlock();
Jason Sams1b6a0882012-03-12 15:07:58 -0700553
Stephen Hines02a98262012-11-14 12:40:26 -0800554 slot++;
555 }
Matt Wala1c6b9272015-08-03 14:06:07 -0700556}
557
558bool RSReflectionCpp::genEncodedBitCode() {
559 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
560 if (pfin == nullptr) {
561 fprintf(stderr, "Error: could not read file %s\n",
562 mBitCodeFilePath.c_str());
563 return false;
564 }
565
566 unsigned char buf[16];
567 int read_length;
568 mOut.indent() << "static const unsigned char __txt[] =";
569 mOut.startBlock();
570 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
571 mOut.indent();
572 for (int i = 0; i < read_length; i++) {
573 char buf2[16];
574 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
575 mOut << buf2;
576 }
577 mOut << "\n";
578 }
579 mOut.endBlock(true);
580 mOut << "\n";
581 return true;
582}
583
584bool RSReflectionCpp::writeImplementationFile() {
585 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
586 mRSContext->getLicenseNote(), false,
587 mRSContext->getVerbose())) {
588 return false;
589 }
590
591 // Front matter
592 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
593
594 genEncodedBitCode();
595 mOut.indent() << "\n\n";
596
597 // Constructor
598 const std::string &packageName = mRSContext->getReflectJavaPackageName();
599 mOut.indent() << mClassName << "::" << mClassName
600 << "(android::RSC::sp<android::RSC::RS> rs):\n"
601 " ScriptC(rs, __txt, sizeof(__txt), \""
602 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
603 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
604 << packageName << "\"))";
605 mOut.startBlock();
606 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
607 E = mTypesToCheck.end();
608 I != E; I++) {
609 mOut.indent() << kRsElemPrefix << *I << " = android::RSC::Element::" << *I
610 << "(mRS);\n";
611 }
612
613 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
614 E = mRSContext->export_vars_end();
615 I != E; I++) {
616 const RSExportVar *EV = *I;
617 if (!EV->getInit().isUninit()) {
618 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
619 } else {
620 genZeroInitExportVariable(EV->getName());
621 }
622 }
623 mOut.endBlock();
624
625 // Destructor
626 mOut.indent() << mClassName << "::~" << mClassName << "()";
627 mOut.startBlock();
628 mOut.endBlock();
629
630 // Function bodies
631 genExportForEachBodies();
632 genExportReduceBodies();
633 genExportFunctionBodies();
Jason Sams1b6a0882012-03-12 15:07:58 -0700634
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700635 mOut.closeFile();
Stephen Hines02a98262012-11-14 12:40:26 -0800636 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700637}
638
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700639void RSReflectionCpp::genExportVariablesGetterAndSetter() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700640 mOut.comment("Methods to set and get the variables exported by the script. "
641 "Const variables will not have a setter.\n\n"
642 "Note that the value returned by the getter may not be the "
643 "current value of the variable in the script. The getter will "
644 "return the initial value of the variable (as defined in the "
645 "script) or the the last value set by using the setter method. "
646 "The script is free to modify its value independently.");
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700647 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
648 E = mRSContext->export_vars_end();
649 I != E; I++) {
650 const RSExportVar *EV = *I;
651 const RSExportType *ET = EV->getType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800652
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700653 switch (ET->getClass()) {
654 case RSExportType::ExportClassPrimitive: {
655 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
656 break;
657 }
658 case RSExportType::ExportClassPointer: {
659 // TODO Deprecate this.
660 genPointerTypeExportVariable(EV);
661 break;
662 }
663 case RSExportType::ExportClassVector: {
664 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
665 break;
666 }
667 case RSExportType::ExportClassMatrix: {
668 genMatrixTypeExportVariable(EV);
669 break;
670 }
671 case RSExportType::ExportClassConstantArray: {
672 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
673 EV);
674 break;
675 }
676 case RSExportType::ExportClassRecord: {
677 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
678 break;
679 }
680 default: { slangAssert(false && "Unknown class of type"); }
681 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800682 }
683}
684
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700685void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
686 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800687 RSReflectionTypeData rtd;
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800688 EPT->convertToRTD(&rtd);
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100689 std::string TypeName = GetTypeName(EPT);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800690
691 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700692 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
693 mOut.startBlock();
694 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800695 if (EPT->isRSObjectType()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700696 mOut << "v";
Matt Wala1c6b9272015-08-03 14:06:07 -0700697 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700698 mOut << "&v, sizeof(v)";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800699 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700700 mOut << ");\n";
701 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
702 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800703 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700704 mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
705 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800706 if (EV->isConst()) {
707 const clang::APValue &val = EV->getInit();
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800708 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700709 mOut.indent() << "return ";
710 genInitValue(val, isBool);
711 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800712 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700713 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
714 << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800715 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700716 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800717}
718
719void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
720 const RSExportType *ET = EV->getType();
721
722 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
723 "Variable should be type of pointer here");
724
725 std::string TypeName = GetTypeName(ET);
726 std::string VarName = EV->getName();
727
728 RSReflectionTypeData rtd;
729 EV->getType()->convertToRTD(&rtd);
730 uint32_t slot = getNextExportVarSlot();
731
732 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700733 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
734 mOut.startBlock();
735 mOut.indent() << "bindAllocation(v, " << slot << ");\n";
736 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
737 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800738 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700739 mOut.indent() << TypeName << " get_" << VarName << "() const";
740 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800741 if (EV->isConst()) {
742 const clang::APValue &val = EV->getInit();
743 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700744 mOut.indent() << "return ";
745 genInitValue(val, isBool);
746 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800747 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700748 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800749 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700750 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800751}
752
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700753void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
754 const RSExportVar *EV) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700755 slangAssert(EVT != nullptr);
Stephen Hines80706832013-08-28 18:08:57 -0700756
757 RSReflectionTypeData rtd;
758 EVT->convertToRTD(&rtd);
759
Stephen Hines80706832013-08-28 18:08:57 -0700760 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700761 mOut.indent() << "void set_" << EV->getName() << "("
762 << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
763 << " v)";
764 mOut.startBlock();
765 mOut.indent() << "setVar(" << getNextExportVarSlot()
766 << ", &v, sizeof(v));\n";
767 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
768 mOut.endBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700769 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700770 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
771 << " get_" << EV->getName() << "() const";
772 mOut.startBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700773 if (EV->isConst()) {
774 const clang::APValue &val = EV->getInit();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700775 mOut.indent() << "return ";
776 genInitValue(val, false);
777 mOut << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700778 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700779 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
780 << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700781 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700782 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800783}
784
785void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100786 uint32_t slot = getNextExportVarSlot();
787 stringstream tmp;
788 tmp << slot;
789
790 const RSExportType *ET = EV->getType();
791 if (ET->getName() == "rs_matrix4x4") {
792 mOut.indent() << "void set_" << EV->getName() << "(float v[16])";
793 mOut.startBlock();
794 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*16);\n";
795 mOut.endBlock();
796 } else if (ET->getName() == "rs_matrix3x3") {
797 mOut.indent() << "void set_" << EV->getName() << "(float v[9])";
798 mOut.startBlock();
799 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*9);";
800 mOut.endBlock();
801 } else if (ET->getName() == "rs_matrix2x2") {
802 mOut.indent() << "void set_" << EV->getName() << "(float v[4])";
803 mOut.startBlock();
804 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(float)*4);";
805 mOut.endBlock();
806 } else {
807 mOut.indent() << "#error: TODO: " << ET->getName();
808 slangAssert(false);
809 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800810}
811
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700812void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
813 const RSExportVar *EV) {
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100814 std::stringstream ArraySpec;
815 const RSExportType *ET = EV->getType();
816
817 const RSExportConstantArrayType *CAT =
818 static_cast<const RSExportConstantArrayType *>(ET);
819
820 uint32_t slot = getNextExportVarSlot();
821 stringstream tmp;
822 tmp << slot;
823
824 ArraySpec << CAT->getSize();
825 mOut.indent() << "void set_" << EV->getName() << "(" << GetTypeName(EV->getType()) << " v "
826 << GetTypeName(EV->getType(), false) << ")";
827 mOut.startBlock();
828 mOut.indent() << "setVar(" << tmp.str() << ", v, sizeof(" << GetTypeName(EV->getType()) + ") *"
829 << ArraySpec.str() << ");";
830 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800831}
832
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700833void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
834 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800835 slangAssert(false);
836}
837
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700838void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700839 const RSExportFunc *ef) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700840 mOut.indent() << "void ";
Stephen Hines02a98262012-11-14 12:40:26 -0800841 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700842 mOut << mClassName << "::";
Stephen Hines02a98262012-11-14 12:40:26 -0800843 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700844 mOut << "invoke_" << ef->getName() << "(";
Stephen Hines38dceea2012-11-13 17:33:55 -0800845
Stephen Hines02a98262012-11-14 12:40:26 -0800846 if (ef->getParamPacketType()) {
847 bool FirstArg = true;
848 for (RSExportFunc::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700849 e = ef->params_end();
850 i != e; i++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800851 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700852 mOut << ", ";
Stephen Hines02a98262012-11-14 12:40:26 -0800853 } else {
854 FirstArg = false;
855 }
Nicolas Collin5f3da4b2015-10-21 10:22:51 +0100856 mOut << GetTypeName((*i)->getType()) << " " << (*i)->getName();
Stephen Hines38dceea2012-11-13 17:33:55 -0800857 }
Stephen Hines02a98262012-11-14 12:40:26 -0800858 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800859
Stephen Hines02a98262012-11-14 12:40:26 -0800860 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700861 mOut << ")";
Stephen Hines02a98262012-11-14 12:40:26 -0800862 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700863 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800864 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800865}
866
Matt Wala1c6b9272015-08-03 14:06:07 -0700867void RSReflectionCpp::makeReduceSignatureAllocationVariant(bool IsDefinition,
868 const RSExportReduce *ER) {
869 // void reduce_foo(sp<Allocation> ain, sp<Allocation> aout,
870 // const RsScriptCall *sc = nullptr);
871 std::string FunctionStart = "void ";
872 if (IsDefinition) {
873 FunctionStart += mClassName + "::";
874 }
875 FunctionStart += "reduce_" + ER->getName() + "(";
876
877 ArgumentList Arguments{
878 Argument(kAllocationSp, "ain"),
879 Argument(kAllocationSp, "aout"),
880 Argument(kConstRsScriptCall, "*sc", IsDefinition ? "" : "nullptr")
881 };
882
883 mOut.indent() << FunctionStart;
884
885 genArguments(Arguments, FunctionStart.length());
886
887 if (IsDefinition) {
888 mOut << ")";
889 } else {
890 mOut << ");\n\n";
891 }
892}
893
894void RSReflectionCpp::makeReduceSignatureArrayVariant(bool IsDefinition,
895 const RSExportReduce *ER) {
896 // Ty reduce_foo(const ElemTy[] in, uint32_t x1, uint32_t x2, size_t inLen);
897 // "Ty" could be different from "ElemTy" in the case of vectors.
898
899 const RSExportType *Type = ER->getType();
900 if (!canExportReduceArrayVariant(Type)) {
901 return;
902 }
903
904 RSReflectionTypeData TypeData;
905 Type->convertToRTD(&TypeData);
906
907 const std::string ReturnType = GetTypeName(Type);
908 std::string FunctionStart = ReturnType + " ";
909 if (IsDefinition) {
910 FunctionStart += mClassName + "::";
911 }
912 FunctionStart += "reduce_" + ER->getName() + "(";
913
914 const std::string ArrayElementType = TypeData.type->c_name;
915
916 ArgumentList Arguments{
917 Argument("const " + ArrayElementType, "in[]"),
918 Argument("uint32_t", "x1"),
919 Argument("uint32_t", "x2"),
920 Argument("size_t", "inLen")
921 };
922
923 mOut.indent() << FunctionStart;
924 genArguments(Arguments, FunctionStart.size());
925
926 if (IsDefinition) {
927 mOut << ")";
928 } else {
929 mOut << ");\n\n";
930 }
931
932 if (!IsDefinition) {
933 // We reflect three more variants in the header. First, there is
934 //
935 // Ty reduce_foo(const ElemTy[] in, size_t inLen);
936 //
937 // Note the inLen is the number of primitive elements in the array, as opposed to the
938 // bounds whose units are allocation elements. The other variants use templates to infer
939 // the array length statically:
940 //
941 // template<size_t inLen> Ty reduce_foo(const ElemTy (&in)[inLen]);
942 // template<size_t inLen> Ty reduce_foo(const ElemTy (&in)[inLen], uint32_t x1, uint32_t x2);
943
944 // Generate inLen variant
945 const uint32_t VecSize = TypeData.vecSize;
946 std::string X2 = "inLen";
947
948 const std::string FunctionName = ER->getName();
949
950 auto ForwardReduce = [this, &FunctionName](const std::string &x1,
951 const std::string &x2,
952 const std::string &inLen) {
953 this->mOut.indent() << " return reduce_" << FunctionName << "(in, "
954 << x1 << ", " << x2 << ", " << inLen << ");\n";
955 this->mOut.indent() << "}\n\n";
956 };
957
958 const std::string DefaultValue = ReturnType + "()";
959
960 ArgumentList InLenVariantArguments{
961 Argument("const " + ArrayElementType, "in[]"), Argument("size_t", "inLen")
962 };
963 mOut.indent() << FunctionStart;
964 genArguments(InLenVariantArguments, FunctionStart.size());
965 mOut << ") {\n";
966 if (VecSize > 1) {
967 genVectorLengthCompatibilityCheck("inLen", VecSize, DefaultValue, 2);
968 X2 += " / " + std::to_string(VecSize);
969 }
970 ForwardReduce("0", X2, "inLen");
971
972 // Generate template variants
973 ArgumentList TemplateVariantArguments{
974 Argument("const " + ArrayElementType, "(&in)[inLen]")
975 };
976
977 mOut.indent() << "template<size_t inLen>\n";
978 mOut.indent() << FunctionStart;
979 genArguments(TemplateVariantArguments, FunctionStart.size());
980 mOut << ") {\n return reduce_" << FunctionName << "(in, inLen);\n }\n\n";
981
982 TemplateVariantArguments.push_back(Argument("uint32_t", "x1"));
983 TemplateVariantArguments.push_back(Argument("uint32_t", "x2"));
984 mOut.indent() << "template<size_t inLen>\n";
985 mOut.indent() << FunctionStart;
986 genArguments(TemplateVariantArguments, FunctionStart.size());
987 mOut << ") {\n";
988 ForwardReduce("x1", "x2", "inLen");
989 }
990}
991
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700992void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800993 bool FirstArg = true;
994
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700995 for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
996 I != E; I++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800997 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700998 mOut << ",\n";
999 mOut.indent() << string(Offset, ' ');
Stephen Hines7dd6da22012-11-15 19:56:03 -08001000 } else {
1001 FirstArg = false;
1002 }
1003
Matt Wala1c6b9272015-08-03 14:06:07 -07001004 mOut << I->Type << " " << I->Name;
1005 if (!I->DefaultValue.empty()) {
1006 mOut << " = " << I->DefaultValue;
1007 }
Stephen Hines7dd6da22012-11-15 19:56:03 -08001008 }
1009}
1010
1011bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
1012 const char *FieldPackerName) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -07001013 size_t AllocSize = ET->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001014
1015 if (AllocSize > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001016 mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
1017 << AllocSize << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -08001018 return true;
1019 }
1020
1021 return false;
1022}
1023
1024void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
1025 const char *VarName,
1026 const char *FieldPackerName) {
Stephen Hines7dd6da22012-11-15 19:56:03 -08001027 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001028 case RSExportType::ExportClassPrimitive:
1029 case RSExportType::ExportClassVector:
1030 case RSExportType::ExportClassPointer:
1031 case RSExportType::ExportClassMatrix: {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001032 mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001033 break;
1034 }
1035 case RSExportType::ExportClassConstantArray: {
1036 /*const RSExportConstantArrayType *ECAT =
1037 static_cast<const RSExportConstantArrayType *>(ET);
1038
1039 // TODO(zonr): more elegant way. Currently, we obtain the unique index
1040 // variable (this method involves recursive call which means
1041 // we may have more than one level loop, therefore we can't
1042 // always use the same index variable name here) name given
1043 // in the for-loop from counting the '.' in @VarName.
1044 unsigned Level = 0;
1045 size_t LastDotPos = 0;
1046 std::string ElementVarName(VarName);
1047
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001048 while (LastDotPos != std::string::npos) {
1049 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
1050 Level++;
1051 }
1052 std::string IndexVarName("ct");
1053 IndexVarName.append(llvm::utostr_32(Level));
Stephen Hines7dd6da22012-11-15 19:56:03 -08001054
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001055 C.indent() << "for (int " << IndexVarName << " = 0; " <<
1056 IndexVarName << " < " << ECAT->getSize() << "; " <<
1057 IndexVarName << "++)";
1058 C.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001059
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001060 ElementVarName.append("[" + IndexVarName + "]");
1061 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
1062 FieldPackerName);
Stephen Hines7dd6da22012-11-15 19:56:03 -08001063
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001064 C.endBlock();*/
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001065 break;
1066 }
1067 case RSExportType::ExportClassRecord: {
1068 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
1069 // Relative pos from now on in field packer
1070 unsigned Pos = 0;
Stephen Hines7dd6da22012-11-15 19:56:03 -08001071
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001072 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1073 E = ERT->fields_end();
1074 I != E; I++) {
1075 const RSExportRecordType::Field *F = *I;
1076 std::string FieldName;
1077 size_t FieldOffset = F->getOffsetInParent();
1078 const RSExportType *T = F->getType();
1079 size_t FieldStoreSize = T->getStoreSize();
1080 size_t FieldAllocSize = T->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001081
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001082 if (VarName != nullptr)
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001083 FieldName = VarName + ("." + F->getName());
1084 else
1085 FieldName = F->getName();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001086
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001087 if (FieldOffset > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001088 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
1089 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -08001090 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001091
1092 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
1093
1094 // There is padding in the field type
1095 if (FieldAllocSize > FieldStoreSize) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001096 mOut.indent() << FieldPackerName << ".skip("
1097 << (FieldAllocSize - FieldStoreSize) << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001098 }
1099
1100 Pos = FieldOffset + FieldAllocSize;
Stephen Hines7dd6da22012-11-15 19:56:03 -08001101 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001102
1103 // There maybe some padding after the struct
1104 if (ERT->getAllocSize() > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001105 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
1106 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -08001107 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001108 break;
1109 }
1110 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -08001111 }
1112}
1113
Stephen Hines003ac662013-08-21 00:37:51 -07001114void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
1115 const char *VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001116 mOut.indent() << "// Type check for " << VarName << "\n";
Stephen Hines003ac662013-08-21 00:37:51 -07001117
1118 if (ET->getClass() == RSExportType::ExportClassPointer) {
1119 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001120 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -07001121 ET = EPT->getPointeeType();
1122 }
1123
1124 std::string TypeName;
1125 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001126 case RSExportType::ExportClassPrimitive:
1127 case RSExportType::ExportClassVector:
1128 case RSExportType::ExportClassRecord: {
1129 TypeName = ET->getElementName();
1130 break;
1131 }
Stephen Hines003ac662013-08-21 00:37:51 -07001132
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001133 default:
1134 break;
Stephen Hines003ac662013-08-21 00:37:51 -07001135 }
1136
1137 if (!TypeName.empty()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001138 mOut.indent() << "if (!" << VarName
1139 << "->getType()->getElement()->isCompatible("
Matt Wala1c6b9272015-08-03 14:06:07 -07001140 << kRsElemPrefix << TypeName << "))";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001141 mOut.startBlock();
1142 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
1143 "\"Incompatible type\");\n";
1144 mOut.indent() << "return;\n";
1145 mOut.endBlock();
Stephen Hines003ac662013-08-21 00:37:51 -07001146 }
1147}
1148
Matt Wala1c6b9272015-08-03 14:06:07 -07001149// Ensure that the input is 1 dimensional.
1150void RSReflectionCpp::gen1DCheck(const std::string &VarName) {
1151 mOut.indent() << "// check that " << VarName << " is 1d\n";
1152 mOut.indent() << "sp<const Type> t0 = " << VarName << "->getType();\n";
1153 mOut.indent() << "if (t0->getY() != 0 ||\n";
1154 mOut.indent() << " t0->hasFaces() ||\n";
1155 mOut.indent() << " t0->hasMipmaps())";
1156 mOut.startBlock();
1157 mOut.indent() << "mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1158 << "\"" << VarName << " is not 1D!\");\n";
1159 mOut.indent() << "return;\n";
1160 mOut.endBlock();
1161}
1162
1163// Generates code to ensure that the supplied array length is a multiple of the vector size.
1164void RSReflectionCpp::genVectorLengthCompatibilityCheck(const std::string &Length,
1165 unsigned VecSize,
1166 const std::string &ValueToReturn,
1167 unsigned IndentLevels) {
1168 auto Indenter = [this, IndentLevels]() -> std::ofstream& {
1169 GeneratedFile &Out = this->mOut;
1170 for (unsigned Level = 0; Level < IndentLevels; ++Level) {
1171 Out.indent();
1172 }
1173 return Out;
1174 };
1175
1176 Indenter() << "// Verify that the array length is a multiple of the vector size.\n";
1177 Indenter() << "if (" << Length << " % " << std::to_string(VecSize) << " != 0) {\n";
1178 Indenter() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1179 << "\"Input array length is not a multiple of "
1180 << std::to_string(VecSize) << "\");\n";
1181 Indenter() << " return " << ValueToReturn << ";\n";
1182 Indenter() << "}\n\n";
1183}
1184
1185// Generates code to ensure that the supplied array is non-null and nonzero in length.
1186void RSReflectionCpp::genNullOrEmptyArrayCheck(const std::string &ArrayName,
1187 const std::string &Length,
1188 const std::string &ValueToReturn) {
1189 mOut.indent() << "// Verify that the array is non-null and non-empty.\n";
1190 mOut.indent() << "if (" << ArrayName << " == nullptr) {\n";
1191 mOut.indent() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1192 << "\"Input array is null\");\n";
1193 mOut.indent() << " return " << ValueToReturn << ";\n";
1194 mOut.indent() << "}\n\n";
1195
1196 mOut.indent() << "if (" << Length << " == 0) {\n";
1197 mOut.indent() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1198 << "\"Input array is zero-length\");\n";
1199 mOut.indent() << " return " << ValueToReturn << ";\n";
1200 mOut.indent() << "}\n\n";
1201}
1202
Stephen Hines003ac662013-08-21 00:37:51 -07001203void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
1204 if (ET->getClass() == RSExportType::ExportClassPointer) {
1205 // For pointer parameters to original forEach kernels.
1206 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001207 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -07001208 genTypeInstance(EPT->getPointeeType());
1209 } else {
1210 // For handling pass-by-value kernel parameters.
1211 genTypeInstance(ET);
1212 }
1213}
1214
1215void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
1216 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001217 case RSExportType::ExportClassPrimitive:
1218 case RSExportType::ExportClassVector:
1219 case RSExportType::ExportClassConstantArray:
1220 case RSExportType::ExportClassRecord: {
1221 std::string TypeName = ET->getElementName();
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001222 mTypesToCheck.insert(TypeName);
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001223 break;
1224 }
Stephen Hines003ac662013-08-21 00:37:51 -07001225
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001226 default:
1227 break;
Stephen Hines003ac662013-08-21 00:37:51 -07001228 }
1229}
1230
Stephen Hines80706832013-08-28 18:08:57 -07001231void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
1232 const std::string &VarName,
1233 const clang::APValue &Val) {
1234 slangAssert(!Val.isUninit() && "Not a valid initializer");
Stephen Hines003ac662013-08-21 00:37:51 -07001235
Stephen Hines80706832013-08-28 18:08:57 -07001236 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001237 case RSExportType::ExportClassPrimitive: {
1238 const RSExportPrimitiveType *EPT =
1239 static_cast<const RSExportPrimitiveType *>(ET);
1240 if (EPT->getType() == DataTypeBoolean) {
1241 genInitBoolExportVariable(VarName, Val);
1242 } else {
1243 genInitPrimitiveExportVariable(VarName, Val);
1244 }
1245 break;
1246 }
1247 case RSExportType::ExportClassPointer: {
1248 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
1249 std::cerr << "Initializer which is non-NULL to pointer type variable "
1250 "will be ignored" << std::endl;
1251 break;
1252 }
1253 case RSExportType::ExportClassVector: {
1254 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
1255 switch (Val.getKind()) {
1256 case clang::APValue::Int:
1257 case clang::APValue::Float: {
1258 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
1259 std::string Name = VarName + "." + getVectorAccessor(i);
1260 genInitPrimitiveExportVariable(Name, Val);
Stephen Hines80706832013-08-28 18:08:57 -07001261 }
1262 break;
1263 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001264 case clang::APValue::Vector: {
1265 unsigned NumElements = std::min(
1266 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
1267 for (unsigned i = 0; i < NumElements; i++) {
1268 const clang::APValue &ElementVal = Val.getVectorElt(i);
1269 std::string Name = VarName + "." + getVectorAccessor(i);
1270 genInitPrimitiveExportVariable(Name, ElementVal);
Stephen Hines80706832013-08-28 18:08:57 -07001271 }
1272 break;
1273 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001274 case clang::APValue::MemberPointer:
1275 case clang::APValue::Uninitialized:
1276 case clang::APValue::ComplexInt:
1277 case clang::APValue::ComplexFloat:
1278 case clang::APValue::LValue:
1279 case clang::APValue::Array:
1280 case clang::APValue::Struct:
1281 case clang::APValue::Union:
1282 case clang::APValue::AddrLabelDiff: {
1283 slangAssert(false && "Unexpected type of value of initializer.");
Stephen Hines80706832013-08-28 18:08:57 -07001284 }
Stephen Hines80706832013-08-28 18:08:57 -07001285 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001286 break;
1287 }
1288 case RSExportType::ExportClassMatrix:
1289 case RSExportType::ExportClassConstantArray:
1290 case RSExportType::ExportClassRecord: {
1291 slangAssert(false && "Unsupported initializer for record/matrix/constant "
1292 "array type variable currently");
1293 break;
1294 }
1295 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines80706832013-08-28 18:08:57 -07001296 }
Stephen Hines80706832013-08-28 18:08:57 -07001297}
1298
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001299const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
1300 static const char *VectorAccessorMap[] = {/* 0 */ "x",
1301 /* 1 */ "y",
1302 /* 2 */ "z",
1303 /* 3 */ "w",
1304 };
1305
1306 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
1307 "Out-of-bound index to access vector member");
1308
1309 return VectorAccessorMap[Index];
1310}
1311
Stephen Hines80706832013-08-28 18:08:57 -07001312void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001313 mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
1314 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
Stephen Hines80706832013-08-28 18:08:57 -07001315}
1316
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001317void
1318RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
1319 const clang::APValue &Val) {
Stephen Hines80706832013-08-28 18:08:57 -07001320 slangAssert(!Val.isUninit() && "Not a valid initializer");
1321
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001322 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
1323 genInitValue(Val);
1324 mOut << ";\n";
1325}
1326
1327void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
1328 switch (Val.getKind()) {
1329 case clang::APValue::Int: {
1330 llvm::APInt api = Val.getInt();
1331 if (asBool) {
1332 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
1333 } else {
1334 // TODO: Handle unsigned correctly for C++
1335 mOut << api.getSExtValue();
1336 if (api.getBitWidth() > 32) {
1337 mOut << "L";
1338 }
1339 }
1340 break;
1341 }
1342
1343 case clang::APValue::Float: {
1344 llvm::APFloat apf = Val.getFloat();
1345 llvm::SmallString<30> s;
1346 apf.toString(s);
1347 mOut << s.c_str();
1348 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
1349 if (s.count('.') == 0) {
1350 mOut << ".f";
1351 } else {
1352 mOut << "f";
1353 }
1354 }
1355 break;
1356 }
1357
1358 case clang::APValue::ComplexInt:
1359 case clang::APValue::ComplexFloat:
1360 case clang::APValue::LValue:
1361 case clang::APValue::Vector: {
1362 slangAssert(false && "Primitive type cannot have such kind of initializer");
1363 break;
1364 }
1365
1366 default: { slangAssert(false && "Unknown kind of initializer"); }
1367 }
Stephen Hines80706832013-08-28 18:08:57 -07001368}
1369
1370void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
1371 const clang::APValue &Val) {
1372 slangAssert(!Val.isUninit() && "Not a valid initializer");
1373 slangAssert((Val.getKind() == clang::APValue::Int) &&
1374 "Bool type has wrong initial APValue");
1375
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001376 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
1377 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
1378 << ";";
Stephen Hines80706832013-08-28 18:08:57 -07001379}
Stephen Hines003ac662013-08-21 00:37:51 -07001380
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001381} // namespace slang