blob: 7d296276c2e3c0a08e42275c71f91ffbfdbac1f7 [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
Stephen Hines7dd6da22012-11-15 19:56:03 -080063static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
64 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070065 case RSExportType::ExportClassPrimitive: {
66 const RSExportPrimitiveType *EPT =
67 static_cast<const RSExportPrimitiveType *>(ET);
68 if (EPT->isRSObjectType()) {
69 return std::string("android::RSC::sp<const android::RSC::") +
70 RSExportPrimitiveType::getRSReflectionType(EPT)->c_name + ">";
71 } else {
72 return RSExportPrimitiveType::getRSReflectionType(EPT)->c_name;
Stephen Hines7dd6da22012-11-15 19:56:03 -080073 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070074 }
75 case RSExportType::ExportClassPointer: {
76 const RSExportType *PointeeType =
77 static_cast<const RSExportPointerType *>(ET)->getPointeeType();
Stephen Hines7dd6da22012-11-15 19:56:03 -080078
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070079 if (PointeeType->getClass() != RSExportType::ExportClassRecord)
Matt Wala1c6b9272015-08-03 14:06:07 -070080 return kAllocationSp;
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -070081 else
82 return PointeeType->getElementName();
83 }
84 case RSExportType::ExportClassVector: {
85 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
86 std::stringstream VecName;
87 VecName << EVT->getRSReflectionType(EVT)->rs_c_vector_prefix
88 << EVT->getNumElement();
89 return VecName.str();
90 }
91 case RSExportType::ExportClassMatrix: {
92 return GetMatrixTypeName(static_cast<const RSExportMatrixType *>(ET));
93 }
94 case RSExportType::ExportClassConstantArray: {
95 // TODO: Fix this for C arrays!
96 const RSExportConstantArrayType *CAT =
97 static_cast<const RSExportConstantArrayType *>(ET);
98 std::string ElementTypeName = GetTypeName(CAT->getElementType());
99 if (Brackets) {
100 ElementTypeName.append("[]");
Stephen Hines7dd6da22012-11-15 19:56:03 -0800101 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700102 return ElementTypeName;
103 }
104 case RSExportType::ExportClassRecord: {
105 // TODO: Fix for C structs!
Matt Wala1c6b9272015-08-03 14:06:07 -0700106 return ET->getElementName() + "." + kRsTypeItemClassName;
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700107 }
108 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800109 }
110
111 return "";
112}
113
Matt Wala1c6b9272015-08-03 14:06:07 -0700114static bool canExportReduceArrayVariant(const RSExportType *Type) {
115 // FIXME: No half types available for C++ reflection yet
116 if (Type->getElementName().find("F16") == 0) {
117 return false;
118 }
119 return Type->getClass() == RSExportType::ExportClassPrimitive ||
120 Type->getClass() == RSExportType::ExportClassVector;
121}
122
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700123RSReflectionCpp::RSReflectionCpp(const RSContext *Context,
124 const string &OutputDirectory,
125 const string &RSSourceFileName,
126 const string &BitCodeFileName)
127 : mRSContext(Context), mRSSourceFilePath(RSSourceFileName),
128 mBitCodeFilePath(BitCodeFileName), mOutputDirectory(OutputDirectory),
Matt Wala1c6b9272015-08-03 14:06:07 -0700129 mNextExportVarSlot(0), mNextExportFuncSlot(0), mNextExportForEachSlot(0),
130 mNextExportReduceSlot(0) {
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700131 mCleanedRSFileName = RootNameFromRSFileName(mRSSourceFilePath);
132 mClassName = "ScriptC_" + mCleanedRSFileName;
Jason Sams1b6a0882012-03-12 15:07:58 -0700133}
134
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700135RSReflectionCpp::~RSReflectionCpp() {}
Jason Sams1b6a0882012-03-12 15:07:58 -0700136
Jean-Luc Brouillet59f22c32014-06-04 14:53:48 -0700137bool RSReflectionCpp::reflect() {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700138 writeHeaderFile();
139 writeImplementationFile();
Jason Sams1b6a0882012-03-12 15:07:58 -0700140
Stephen Hines02a98262012-11-14 12:40:26 -0800141 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700142}
143
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700144#define RS_TYPE_CLASS_NAME_PREFIX "ScriptField_"
Jason Sams1b6a0882012-03-12 15:07:58 -0700145
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700146bool RSReflectionCpp::writeHeaderFile() {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700147 // Create the file and write the license note.
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700148 if (!mOut.startFile(mOutputDirectory, mClassName + ".h", mRSSourceFilePath,
Stephen Hinesfc4f78b2014-06-10 18:07:10 -0700149 mRSContext->getLicenseNote(), false,
150 mRSContext->getVerbose())) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700151 return false;
152 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700153
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700154 mOut.indent() << "#include \"RenderScript.h\"\n\n";
155 mOut.indent() << "using namespace android::RSC;\n\n";
Jason Sams1b6a0882012-03-12 15:07:58 -0700156
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700157 mOut.comment("This class encapsulates access to the exported elements of the script. "
158 "Typically, you would instantiate this class once, call the set_* methods "
159 "for each of the exported global variables you want to change, then call "
160 "one of the forEach_ methods to invoke a kernel.");
161 mOut.indent() << "class " << mClassName << " : public android::RSC::ScriptC";
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700162 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800163
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700164 mOut.decreaseIndent();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700165 mOut.indent() << "private:\n";
166 mOut.increaseIndent();
167
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700168 genFieldsToStoreExportVariableValues();
169 genTypeInstancesUsedInForEach();
Matt Wala1c6b9272015-08-03 14:06:07 -0700170 genTypeInstancesUsedInReduce();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700171 genFieldsForAllocationTypeVerification();
Stephen Hines80706832013-08-28 18:08:57 -0700172
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700173 mOut.decreaseIndent();
174 mOut.indent() << "public:\n";
175 mOut.increaseIndent();
176
177 // Generate the constructor and destructor declarations.
178 mOut.indent() << mClassName << "(android::RSC::sp<android::RSC::RS> rs);\n";
179 mOut.indent() << "virtual ~" << mClassName << "();\n\n";
180
181 genExportVariablesGetterAndSetter();
182 genForEachDeclarations();
Matt Wala1c6b9272015-08-03 14:06:07 -0700183 genReduceDeclarations();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700184 genExportFunctionDeclarations();
185
186 mOut.endBlock(true);
187 mOut.closeFile();
188 return true;
189}
190
191void RSReflectionCpp::genTypeInstancesUsedInForEach() {
Matt Wala1c6b9272015-08-03 14:06:07 -0700192 for (auto I = mRSContext->export_foreach_begin(),
193 E = mRSContext->export_foreach_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700194 I != E; I++) {
Stephen Hines003ac662013-08-21 00:37:51 -0700195 const RSExportForEach *EF = *I;
Stephen Hines003ac662013-08-21 00:37:51 -0700196 const RSExportType *OET = EF->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700197
Stephen Hines003ac662013-08-21 00:37:51 -0700198 if (OET) {
199 genTypeInstanceFromPointer(OET);
200 }
Chris Wailesc9454af2014-06-13 17:25:40 -0700201
202 const RSExportForEach::InTypeVec &InTypes = EF->getInTypes();
203
204 for (RSExportForEach::InTypeIter BI = InTypes.begin(),
205 EI = InTypes.end(); BI != EI; BI++) {
206
207 genTypeInstanceFromPointer(*BI);
208 }
Stephen Hines003ac662013-08-21 00:37:51 -0700209 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700210}
Stephen Hines003ac662013-08-21 00:37:51 -0700211
Matt Wala1c6b9272015-08-03 14:06:07 -0700212// Ensure that the type of the reduce kernel is reflected.
213void RSReflectionCpp::genTypeInstancesUsedInReduce() {
214 for (auto I = mRSContext->export_reduce_begin(),
215 E = mRSContext->export_reduce_end();
216 I != E; ++I) {
217 genTypeInstance((*I)->getType());
218 }
219}
220
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700221void RSReflectionCpp::genFieldsForAllocationTypeVerification() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700222 bool CommentAdded = false;
Stephen Hines003ac662013-08-21 00:37:51 -0700223 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
224 E = mTypesToCheck.end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700225 I != E; I++) {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700226 if (!CommentAdded) {
227 mOut.comment("The following elements are used to verify the types of "
228 "allocations passed to kernels.");
229 CommentAdded = true;
230 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700231 mOut.indent() << "android::RSC::sp<const android::RSC::Element> "
Matt Wala1c6b9272015-08-03 14:06:07 -0700232 << kRsElemPrefix << *I << ";\n";
Stephen Hines003ac662013-08-21 00:37:51 -0700233 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700234}
Stephen Hines003ac662013-08-21 00:37:51 -0700235
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700236void RSReflectionCpp::genFieldsToStoreExportVariableValues() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700237 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800238 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700239 E = mRSContext->export_vars_end();
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700240 I != E; I++) {
241 const RSExportVar *ev = *I;
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700242 if (ev->isConst()) {
243 continue;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700244 }
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700245 if (!CommentAdded) {
246 mOut.comment("For each non-const variable exported by the script, we "
247 "have an equivalent field. This field contains the last "
248 "value this variable was set to using the set_ method. "
249 "This may not be current value of the variable in the "
250 "script, as the script is free to modify its internal "
251 "variable without changing this field. If the script "
252 "initializes the exported variable, the constructor will "
253 "initialize this field to the same value.");
254 CommentAdded = true;
255 }
256 mOut.indent() << GetTypeName(ev->getType()) << " " RS_EXPORT_VAR_PREFIX
257 << ev->getName() << ";\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800258 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700259}
Jason Sams1b6a0882012-03-12 15:07:58 -0700260
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700261void RSReflectionCpp::genForEachDeclarations() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700262 bool CommentAdded = false;
Stephen Hines02a98262012-11-14 12:40:26 -0800263 for (RSContext::const_export_foreach_iterator
264 I = mRSContext->export_foreach_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700265 E = mRSContext->export_foreach_end();
266 I != E; I++) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700267 const RSExportForEach *ForEach = *I;
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700268
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700269 if (ForEach->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700270 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800271 continue;
272 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700273
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700274 if (!CommentAdded) {
275 mOut.comment("For each kernel of the script corresponds one method. "
276 "That method queues the kernel for execution. The kernel "
277 "may not have completed nor even started by the time this "
278 "function returns. Calls that extract the data out of the "
279 "output allocation will wait for the kernels to complete.");
280 CommentAdded = true;
281 }
282
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700283 std::string FunctionStart = "void forEach_" + ForEach->getName() + "(";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700284 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800285
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700286 ArgumentList Arguments;
Chris Wailesc9454af2014-06-13 17:25:40 -0700287 const RSExportForEach::InVec &Ins = ForEach->getIns();
288 for (RSExportForEach::InIter BI = Ins.begin(), EI = Ins.end();
289 BI != EI; BI++) {
290
Matt Wala1c6b9272015-08-03 14:06:07 -0700291 Arguments.push_back(Argument(kAllocationSp, (*BI)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800292 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700293
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700294 if (ForEach->hasOut() || ForEach->hasReturn()) {
Matt Wala1c6b9272015-08-03 14:06:07 -0700295 Arguments.push_back(Argument(kAllocationSp, "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800296 }
297
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700298 const RSExportRecordType *ERT = ForEach->getParamPacketType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800299 if (ERT) {
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700300 for (RSExportForEach::const_param_iterator i = ForEach->params_begin(),
301 e = ForEach->params_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700302 i != e; i++) {
Jason Sams192392f2012-03-13 16:22:12 -0700303 RSReflectionTypeData rtd;
Stephen Hines02a98262012-11-14 12:40:26 -0800304 (*i)->getType()->convertToRTD(&rtd);
Matt Wala1c6b9272015-08-03 14:06:07 -0700305 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
Stephen Hines02a98262012-11-14 12:40:26 -0800306 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700307 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700308 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700309 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800310 }
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700311}
Jason Sams1b6a0882012-03-12 15:07:58 -0700312
Matt Wala1c6b9272015-08-03 14:06:07 -0700313void RSReflectionCpp::genReduceDeclarations() {
314 bool CommentAdded = false;
315 for (auto I = mRSContext->export_reduce_begin(),
316 E = mRSContext->export_reduce_end(); I != E; I++) {
317 if (!CommentAdded) {
318 mOut.comment("For each reduce kernel of the script, there is an entry "
319 "point to call the reduce kernel.");
320 CommentAdded = true;
321 }
322
323 makeReduceSignatureAllocationVariant(false, *I);
324 makeReduceSignatureArrayVariant(false, *I);
325 }
326}
327
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700328void RSReflectionCpp::genExportFunctionDeclarations() {
Stephen Hines02a98262012-11-14 12:40:26 -0800329 for (RSContext::const_export_func_iterator
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700330 I = mRSContext->export_funcs_begin(),
331 E = mRSContext->export_funcs_end();
332 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800333 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700334
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700335 makeFunctionSignature(false, ef);
Stephen Hines02a98262012-11-14 12:40:26 -0800336 }
Jason Sams1b6a0882012-03-12 15:07:58 -0700337}
338
Matt Wala1c6b9272015-08-03 14:06:07 -0700339// forEach_* implementation
340void RSReflectionCpp::genExportForEachBodies() {
Stephen Hines02a98262012-11-14 12:40:26 -0800341 uint32_t slot = 0;
Matt Wala1c6b9272015-08-03 14:06:07 -0700342 for (auto I = mRSContext->export_foreach_begin(),
343 E = mRSContext->export_foreach_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700344 I != E; I++, slot++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800345 const RSExportForEach *ef = *I;
346 if (ef->isDummyRoot()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700347 mOut.indent() << "// No forEach_root(...)\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800348 continue;
349 }
350
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700351 ArgumentList Arguments;
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700352 std::string FunctionStart =
353 "void " + mClassName + "::forEach_" + ef->getName() + "(";
354 mOut.indent() << FunctionStart;
Stephen Hines7dd6da22012-11-15 19:56:03 -0800355
Chris Wailesc9454af2014-06-13 17:25:40 -0700356 if (ef->hasIns()) {
357 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700358 slangAssert(ef->getIns().size() == 1);
Matt Wala1c6b9272015-08-03 14:06:07 -0700359 Arguments.push_back(Argument(kAllocationSp, "ain"));
Stephen Hines02a98262012-11-14 12:40:26 -0800360 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800361
362 if (ef->hasOut() || ef->hasReturn()) {
Matt Wala1c6b9272015-08-03 14:06:07 -0700363 Arguments.push_back(Argument(kAllocationSp, "aout"));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800364 }
365
366 const RSExportRecordType *ERT = ef->getParamPacketType();
367 if (ERT) {
368 for (RSExportForEach::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700369 e = ef->params_end();
370 i != e; i++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800371 RSReflectionTypeData rtd;
372 (*i)->getType()->convertToRTD(&rtd);
Matt Wala1c6b9272015-08-03 14:06:07 -0700373 Arguments.push_back(Argument(rtd.type->c_name, (*i)->getName()));
Stephen Hines7dd6da22012-11-15 19:56:03 -0800374 }
375 }
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700376 genArguments(Arguments, FunctionStart.length());
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700377 mOut << ")";
378 mOut.startBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800379
Stephen Hines003ac662013-08-21 00:37:51 -0700380 const RSExportType *OET = ef->getOutType();
Chris Wailesc9454af2014-06-13 17:25:40 -0700381 const RSExportForEach::InTypeVec &InTypes = ef->getInTypes();
382 if (ef->hasIns()) {
383 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700384 slangAssert(ef->getIns().size() == 1);
Chris Wailesc9454af2014-06-13 17:25:40 -0700385 genTypeCheck(InTypes[0], "ain");
Stephen Hines003ac662013-08-21 00:37:51 -0700386 }
Stephen Hines003ac662013-08-21 00:37:51 -0700387 if (OET) {
388 genTypeCheck(OET, "aout");
389 }
Stephen Hines003ac662013-08-21 00:37:51 -0700390
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -0700391 // TODO Add the appropriate dimension checking code, as seen in
392 // slang_rs_reflection.cpp.
393
Stephen Hines7dd6da22012-11-15 19:56:03 -0800394 std::string FieldPackerName = ef->getName() + "_fp";
395 if (ERT) {
396 if (genCreateFieldPacker(ERT, FieldPackerName.c_str())) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700397 genPackVarOfType(ERT, nullptr, FieldPackerName.c_str());
Stephen Hines7dd6da22012-11-15 19:56:03 -0800398 }
Stephen Hines02a98262012-11-14 12:40:26 -0800399 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700400 mOut.indent() << "forEach(" << slot << ", ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800401
Chris Wailesc9454af2014-06-13 17:25:40 -0700402 if (ef->hasIns()) {
403 // FIXME: Add support for kernels with multiple inputs.
David Gross85dc6962015-05-29 14:55:30 -0700404 slangAssert(ef->getIns().size() == 1);
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700405 mOut << "ain, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800406 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700407 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800408 }
409
410 if (ef->hasOut() || ef->hasReturn()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700411 mOut << "aout, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800412 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700413 mOut << "NULL, ";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800414 }
415
Stephen Hines003ac662013-08-21 00:37:51 -0700416 // FIXME (no support for usrData with C++ kernels)
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700417 mOut << "NULL, 0);\n";
418 mOut.endBlock();
Stephen Hines02a98262012-11-14 12:40:26 -0800419 }
Matt Wala1c6b9272015-08-03 14:06:07 -0700420}
Jason Sams1b6a0882012-03-12 15:07:58 -0700421
Matt Wala1c6b9272015-08-03 14:06:07 -0700422// reduce_* implementation
423void RSReflectionCpp::genExportReduceBodies() {
424 for (auto I = mRSContext->export_reduce_begin(),
425 E = mRSContext->export_reduce_end();
426 I != E; ++I) {
427 const RSExportReduce &Reduce = **I;
428 const RSExportType *Type = Reduce.getType();
429
430 // Allocation variant
431 //
432 // void reduce_foo(sp<Allocation> ain, sp<Allocation> aout,
433 // const RsScriptCall *sc);
434 makeReduceSignatureAllocationVariant(true, &Reduce);
435 mOut.startBlock();
436
437 // Type check
438 genTypeCheck(Type, "ain");
439 genTypeCheck(Type, "aout");
440
441 // Dimension check
442 gen1DCheck("ain");
443
444 const uint32_t Slot = getNextExportReduceSlot();
445
446 // Call into RenderScript.
447 mOut.indent() << "reduce(" << Slot << ", "
448 << "ain, aout, sc);\n";
449 mOut.endBlock();
450
451 if (!canExportReduceArrayVariant(Type)) {
452 continue;
453 }
454
455 // Array variant
456 //
457 // Ty reduce_foo(const ElemTy[] in, uint32_t x1, uint32_t x2, uint32_t inLen);
458 // "Ty" could be different from "ElemTy" in the case of vectors.
459 makeReduceSignatureArrayVariant(true, &Reduce);
460 mOut.startBlock();
461
462 const std::string ReturnType = GetTypeName(Type);
463 const std::string DefaultReturnValue = ReturnType + "()";
464
465 genNullOrEmptyArrayCheck("in", "inLen", DefaultReturnValue);
466
467 RSReflectionTypeData TypeData;
468 Type->convertToRTD(&TypeData);
469 const uint32_t VecSize = TypeData.vecSize;
470 std::string InLength = "inLen";
471 // Adjust the length so that it corresponds to the number of elements in the allocation.
472 if (VecSize > 1) {
473 InLength += " / " + std::to_string(VecSize);
474 }
475 genVectorLengthCompatibilityCheck("inLen", VecSize, DefaultReturnValue);
476
477 mOut.indent() << "if (x1 >= x2 || x2 > " << InLength << ")";
478 mOut.startBlock();
479 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
480 << "\"Input bounds are invalid\");\n";
481 mOut.indent() << "return " << DefaultReturnValue << ";\n";
482 mOut.endBlock();
483
484 mOut.indent() << kAllocationSp
485 << " ain = android::RSC::Allocation::createSized(mRS, "
486 << kRsElemPrefix << Type->getElementName() << ", "
487 << "x2 - x1);\n";
488
489 mOut.indent() << "ain->setAutoPadding(true);\n";
490
491 mOut.indent() << kAllocationSp
492 << " aout = android::RSC::Allocation::createSized(mRS, "
493 << kRsElemPrefix << Type->getElementName() << ", 1);\n";
494
495 mOut.indent() << "aout->setAutoPadding(true);\n";
496
497 const std::string ArrayElementType = TypeData.type->c_name;
498
499 std::string StartOffset = "x1";
500 if (VecSize > 1) {
501 StartOffset += " * " + std::to_string(VecSize);
502 }
503 mOut.indent() << "ain->copy1DRangeFrom(0, x2 - x1, &in[" << StartOffset << "]);\n";
504 mOut.indent() << "reduce_" << Reduce.getName() << "(ain, aout);\n";
505 mOut.indent() << ArrayElementType << " outArray[" << VecSize << "];\n";
506
507 mOut.indent() << "aout->copy1DRangeTo(0, 1, &outArray[0]);\n";
508
509 mOut.indent() << "return " << ReturnType << "(";
510 for (uint32_t VecElem = 0; VecElem < VecSize; ++VecElem) {
511 if (VecElem > 0) mOut << ", ";
512 mOut << "outArray[" << VecElem << "]";
513 }
514 mOut << ");\n";
515 mOut.endBlock();
516 }
517}
518
519// invoke_* implementation
520void RSReflectionCpp::genExportFunctionBodies() {
521 uint32_t slot = 0;
Stephen Hines02a98262012-11-14 12:40:26 -0800522 // Reflect export function
Matt Wala1c6b9272015-08-03 14:06:07 -0700523 for (auto I = mRSContext->export_funcs_begin(),
524 E = mRSContext->export_funcs_end();
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700525 I != E; I++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800526 const RSExportFunc *ef = *I;
Jason Sams1b6a0882012-03-12 15:07:58 -0700527
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700528 makeFunctionSignature(true, ef);
529 mOut.startBlock();
Stephen Hines713377e2012-11-14 19:32:43 -0800530 const RSExportRecordType *params = ef->getParamPacketType();
531 size_t param_len = 0;
532 if (params) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700533 param_len = params->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800534 if (genCreateFieldPacker(params, "__fp")) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700535 genPackVarOfType(params, nullptr, "__fp");
Stephen Hines713377e2012-11-14 19:32:43 -0800536 }
Stephen Hines713377e2012-11-14 19:32:43 -0800537 }
538
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700539 mOut.indent() << "invoke(" << slot;
Stephen Hines713377e2012-11-14 19:32:43 -0800540 if (params) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700541 mOut << ", __fp.getData(), " << param_len << ");\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800542 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700543 mOut << ", NULL, 0);\n";
Stephen Hines713377e2012-11-14 19:32:43 -0800544 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700545 mOut.endBlock();
Jason Sams1b6a0882012-03-12 15:07:58 -0700546
Stephen Hines02a98262012-11-14 12:40:26 -0800547 slot++;
548 }
Matt Wala1c6b9272015-08-03 14:06:07 -0700549}
550
551bool RSReflectionCpp::genEncodedBitCode() {
552 FILE *pfin = fopen(mBitCodeFilePath.c_str(), "rb");
553 if (pfin == nullptr) {
554 fprintf(stderr, "Error: could not read file %s\n",
555 mBitCodeFilePath.c_str());
556 return false;
557 }
558
559 unsigned char buf[16];
560 int read_length;
561 mOut.indent() << "static const unsigned char __txt[] =";
562 mOut.startBlock();
563 while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
564 mOut.indent();
565 for (int i = 0; i < read_length; i++) {
566 char buf2[16];
567 snprintf(buf2, sizeof(buf2), "0x%02x,", buf[i]);
568 mOut << buf2;
569 }
570 mOut << "\n";
571 }
572 mOut.endBlock(true);
573 mOut << "\n";
574 return true;
575}
576
577bool RSReflectionCpp::writeImplementationFile() {
578 if (!mOut.startFile(mOutputDirectory, mClassName + ".cpp", mRSSourceFilePath,
579 mRSContext->getLicenseNote(), false,
580 mRSContext->getVerbose())) {
581 return false;
582 }
583
584 // Front matter
585 mOut.indent() << "#include \"" << mClassName << ".h\"\n\n";
586
587 genEncodedBitCode();
588 mOut.indent() << "\n\n";
589
590 // Constructor
591 const std::string &packageName = mRSContext->getReflectJavaPackageName();
592 mOut.indent() << mClassName << "::" << mClassName
593 << "(android::RSC::sp<android::RSC::RS> rs):\n"
594 " ScriptC(rs, __txt, sizeof(__txt), \""
595 << mCleanedRSFileName << "\", " << mCleanedRSFileName.length()
596 << ", \"/data/data/" << packageName << "/app\", sizeof(\""
597 << packageName << "\"))";
598 mOut.startBlock();
599 for (std::set<std::string>::iterator I = mTypesToCheck.begin(),
600 E = mTypesToCheck.end();
601 I != E; I++) {
602 mOut.indent() << kRsElemPrefix << *I << " = android::RSC::Element::" << *I
603 << "(mRS);\n";
604 }
605
606 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
607 E = mRSContext->export_vars_end();
608 I != E; I++) {
609 const RSExportVar *EV = *I;
610 if (!EV->getInit().isUninit()) {
611 genInitExportVariable(EV->getType(), EV->getName(), EV->getInit());
612 } else {
613 genZeroInitExportVariable(EV->getName());
614 }
615 }
616 mOut.endBlock();
617
618 // Destructor
619 mOut.indent() << mClassName << "::~" << mClassName << "()";
620 mOut.startBlock();
621 mOut.endBlock();
622
623 // Function bodies
624 genExportForEachBodies();
625 genExportReduceBodies();
626 genExportFunctionBodies();
Jason Sams1b6a0882012-03-12 15:07:58 -0700627
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700628 mOut.closeFile();
Stephen Hines02a98262012-11-14 12:40:26 -0800629 return true;
Jason Sams1b6a0882012-03-12 15:07:58 -0700630}
631
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700632void RSReflectionCpp::genExportVariablesGetterAndSetter() {
Jean-Luc Brouilletc83b7902014-07-25 15:50:32 -0700633 mOut.comment("Methods to set and get the variables exported by the script. "
634 "Const variables will not have a setter.\n\n"
635 "Note that the value returned by the getter may not be the "
636 "current value of the variable in the script. The getter will "
637 "return the initial value of the variable (as defined in the "
638 "script) or the the last value set by using the setter method. "
639 "The script is free to modify its value independently.");
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700640 for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
641 E = mRSContext->export_vars_end();
642 I != E; I++) {
643 const RSExportVar *EV = *I;
644 const RSExportType *ET = EV->getType();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800645
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700646 switch (ET->getClass()) {
647 case RSExportType::ExportClassPrimitive: {
648 genGetterAndSetter(static_cast<const RSExportPrimitiveType *>(ET), EV);
649 break;
650 }
651 case RSExportType::ExportClassPointer: {
652 // TODO Deprecate this.
653 genPointerTypeExportVariable(EV);
654 break;
655 }
656 case RSExportType::ExportClassVector: {
657 genGetterAndSetter(static_cast<const RSExportVectorType *>(ET), EV);
658 break;
659 }
660 case RSExportType::ExportClassMatrix: {
661 genMatrixTypeExportVariable(EV);
662 break;
663 }
664 case RSExportType::ExportClassConstantArray: {
665 genGetterAndSetter(static_cast<const RSExportConstantArrayType *>(ET),
666 EV);
667 break;
668 }
669 case RSExportType::ExportClassRecord: {
670 genGetterAndSetter(static_cast<const RSExportRecordType *>(ET), EV);
671 break;
672 }
673 default: { slangAssert(false && "Unknown class of type"); }
674 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800675 }
676}
677
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700678void RSReflectionCpp::genGetterAndSetter(const RSExportPrimitiveType *EPT,
679 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800680 RSReflectionTypeData rtd;
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800681 EPT->convertToRTD(&rtd);
682 std::string TypeName = GetTypeName(EPT, false);
Stephen Hines7dd6da22012-11-15 19:56:03 -0800683
684 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700685 mOut.indent() << "void set_" << EV->getName() << "(" << TypeName << " v)";
686 mOut.startBlock();
687 mOut.indent() << "setVar(" << getNextExportVarSlot() << ", ";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800688 if (EPT->isRSObjectType()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700689 mOut << "v";
Matt Wala1c6b9272015-08-03 14:06:07 -0700690 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700691 mOut << "&v, sizeof(v)";
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800692 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700693 mOut << ");\n";
694 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
695 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800696 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700697 mOut.indent() << TypeName << " get_" << EV->getName() << "() const";
698 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800699 if (EV->isConst()) {
700 const clang::APValue &val = EV->getInit();
Stephen Hinesd6f36b12013-11-20 22:03:35 -0800701 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700702 mOut.indent() << "return ";
703 genInitValue(val, isBool);
704 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800705 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700706 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
707 << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800708 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700709 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800710}
711
712void RSReflectionCpp::genPointerTypeExportVariable(const RSExportVar *EV) {
713 const RSExportType *ET = EV->getType();
714
715 slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
716 "Variable should be type of pointer here");
717
718 std::string TypeName = GetTypeName(ET);
719 std::string VarName = EV->getName();
720
721 RSReflectionTypeData rtd;
722 EV->getType()->convertToRTD(&rtd);
723 uint32_t slot = getNextExportVarSlot();
724
725 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700726 mOut.indent() << "void bind_" << VarName << "(" << TypeName << " v)";
727 mOut.startBlock();
728 mOut.indent() << "bindAllocation(v, " << slot << ");\n";
729 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;\n";
730 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800731 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700732 mOut.indent() << TypeName << " get_" << VarName << "() const";
733 mOut.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800734 if (EV->isConst()) {
735 const clang::APValue &val = EV->getInit();
736 bool isBool = !strcmp(TypeName.c_str(), "bool");
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700737 mOut.indent() << "return ";
738 genInitValue(val, isBool);
739 mOut << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800740 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700741 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << VarName << ";\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800742 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700743 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800744}
745
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700746void RSReflectionCpp::genGetterAndSetter(const RSExportVectorType *EVT,
747 const RSExportVar *EV) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700748 slangAssert(EVT != nullptr);
Stephen Hines80706832013-08-28 18:08:57 -0700749
750 RSReflectionTypeData rtd;
751 EVT->convertToRTD(&rtd);
752
Stephen Hines80706832013-08-28 18:08:57 -0700753 if (!EV->isConst()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700754 mOut.indent() << "void set_" << EV->getName() << "("
755 << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
756 << " v)";
757 mOut.startBlock();
758 mOut.indent() << "setVar(" << getNextExportVarSlot()
759 << ", &v, sizeof(v));\n";
760 mOut.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;\n";
761 mOut.endBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700762 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700763 mOut.indent() << rtd.type->rs_c_vector_prefix << EVT->getNumElement()
764 << " get_" << EV->getName() << "() const";
765 mOut.startBlock();
Stephen Hines80706832013-08-28 18:08:57 -0700766 if (EV->isConst()) {
767 const clang::APValue &val = EV->getInit();
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700768 mOut.indent() << "return ";
769 genInitValue(val, false);
770 mOut << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700771 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700772 mOut.indent() << "return " << RS_EXPORT_VAR_PREFIX << EV->getName()
773 << ";\n";
Stephen Hines80706832013-08-28 18:08:57 -0700774 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700775 mOut.endBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800776}
777
778void RSReflectionCpp::genMatrixTypeExportVariable(const RSExportVar *EV) {
779 slangAssert(false);
780}
781
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700782void RSReflectionCpp::genGetterAndSetter(const RSExportConstantArrayType *AT,
783 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800784 slangAssert(false);
785}
786
Jean-Luc Brouillet1cea2712014-06-05 13:54:11 -0700787void RSReflectionCpp::genGetterAndSetter(const RSExportRecordType *ERT,
788 const RSExportVar *EV) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800789 slangAssert(false);
790}
791
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700792void RSReflectionCpp::makeFunctionSignature(bool isDefinition,
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700793 const RSExportFunc *ef) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700794 mOut.indent() << "void ";
Stephen Hines02a98262012-11-14 12:40:26 -0800795 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700796 mOut << mClassName << "::";
Stephen Hines02a98262012-11-14 12:40:26 -0800797 }
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700798 mOut << "invoke_" << ef->getName() << "(";
Stephen Hines38dceea2012-11-13 17:33:55 -0800799
Stephen Hines02a98262012-11-14 12:40:26 -0800800 if (ef->getParamPacketType()) {
801 bool FirstArg = true;
802 for (RSExportFunc::const_param_iterator i = ef->params_begin(),
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700803 e = ef->params_end();
804 i != e; i++) {
Stephen Hines02a98262012-11-14 12:40:26 -0800805 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700806 mOut << ", ";
Stephen Hines02a98262012-11-14 12:40:26 -0800807 } else {
808 FirstArg = false;
809 }
Stephen Hines19879e82015-06-30 16:11:34 -0700810 mOut << GetTypeName((*i)->getType(), false) << " " << (*i)->getName();
Stephen Hines38dceea2012-11-13 17:33:55 -0800811 }
Stephen Hines02a98262012-11-14 12:40:26 -0800812 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800813
Stephen Hines02a98262012-11-14 12:40:26 -0800814 if (isDefinition) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700815 mOut << ")";
Stephen Hines02a98262012-11-14 12:40:26 -0800816 } else {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700817 mOut << ");\n";
Stephen Hines02a98262012-11-14 12:40:26 -0800818 }
Stephen Hines38dceea2012-11-13 17:33:55 -0800819}
820
Matt Wala1c6b9272015-08-03 14:06:07 -0700821void RSReflectionCpp::makeReduceSignatureAllocationVariant(bool IsDefinition,
822 const RSExportReduce *ER) {
823 // void reduce_foo(sp<Allocation> ain, sp<Allocation> aout,
824 // const RsScriptCall *sc = nullptr);
825 std::string FunctionStart = "void ";
826 if (IsDefinition) {
827 FunctionStart += mClassName + "::";
828 }
829 FunctionStart += "reduce_" + ER->getName() + "(";
830
831 ArgumentList Arguments{
832 Argument(kAllocationSp, "ain"),
833 Argument(kAllocationSp, "aout"),
834 Argument(kConstRsScriptCall, "*sc", IsDefinition ? "" : "nullptr")
835 };
836
837 mOut.indent() << FunctionStart;
838
839 genArguments(Arguments, FunctionStart.length());
840
841 if (IsDefinition) {
842 mOut << ")";
843 } else {
844 mOut << ");\n\n";
845 }
846}
847
848void RSReflectionCpp::makeReduceSignatureArrayVariant(bool IsDefinition,
849 const RSExportReduce *ER) {
850 // Ty reduce_foo(const ElemTy[] in, uint32_t x1, uint32_t x2, size_t inLen);
851 // "Ty" could be different from "ElemTy" in the case of vectors.
852
853 const RSExportType *Type = ER->getType();
854 if (!canExportReduceArrayVariant(Type)) {
855 return;
856 }
857
858 RSReflectionTypeData TypeData;
859 Type->convertToRTD(&TypeData);
860
861 const std::string ReturnType = GetTypeName(Type);
862 std::string FunctionStart = ReturnType + " ";
863 if (IsDefinition) {
864 FunctionStart += mClassName + "::";
865 }
866 FunctionStart += "reduce_" + ER->getName() + "(";
867
868 const std::string ArrayElementType = TypeData.type->c_name;
869
870 ArgumentList Arguments{
871 Argument("const " + ArrayElementType, "in[]"),
872 Argument("uint32_t", "x1"),
873 Argument("uint32_t", "x2"),
874 Argument("size_t", "inLen")
875 };
876
877 mOut.indent() << FunctionStart;
878 genArguments(Arguments, FunctionStart.size());
879
880 if (IsDefinition) {
881 mOut << ")";
882 } else {
883 mOut << ");\n\n";
884 }
885
886 if (!IsDefinition) {
887 // We reflect three more variants in the header. First, there is
888 //
889 // Ty reduce_foo(const ElemTy[] in, size_t inLen);
890 //
891 // Note the inLen is the number of primitive elements in the array, as opposed to the
892 // bounds whose units are allocation elements. The other variants use templates to infer
893 // the array length statically:
894 //
895 // template<size_t inLen> Ty reduce_foo(const ElemTy (&in)[inLen]);
896 // template<size_t inLen> Ty reduce_foo(const ElemTy (&in)[inLen], uint32_t x1, uint32_t x2);
897
898 // Generate inLen variant
899 const uint32_t VecSize = TypeData.vecSize;
900 std::string X2 = "inLen";
901
902 const std::string FunctionName = ER->getName();
903
904 auto ForwardReduce = [this, &FunctionName](const std::string &x1,
905 const std::string &x2,
906 const std::string &inLen) {
907 this->mOut.indent() << " return reduce_" << FunctionName << "(in, "
908 << x1 << ", " << x2 << ", " << inLen << ");\n";
909 this->mOut.indent() << "}\n\n";
910 };
911
912 const std::string DefaultValue = ReturnType + "()";
913
914 ArgumentList InLenVariantArguments{
915 Argument("const " + ArrayElementType, "in[]"), Argument("size_t", "inLen")
916 };
917 mOut.indent() << FunctionStart;
918 genArguments(InLenVariantArguments, FunctionStart.size());
919 mOut << ") {\n";
920 if (VecSize > 1) {
921 genVectorLengthCompatibilityCheck("inLen", VecSize, DefaultValue, 2);
922 X2 += " / " + std::to_string(VecSize);
923 }
924 ForwardReduce("0", X2, "inLen");
925
926 // Generate template variants
927 ArgumentList TemplateVariantArguments{
928 Argument("const " + ArrayElementType, "(&in)[inLen]")
929 };
930
931 mOut.indent() << "template<size_t inLen>\n";
932 mOut.indent() << FunctionStart;
933 genArguments(TemplateVariantArguments, FunctionStart.size());
934 mOut << ") {\n return reduce_" << FunctionName << "(in, inLen);\n }\n\n";
935
936 TemplateVariantArguments.push_back(Argument("uint32_t", "x1"));
937 TemplateVariantArguments.push_back(Argument("uint32_t", "x2"));
938 mOut.indent() << "template<size_t inLen>\n";
939 mOut.indent() << FunctionStart;
940 genArguments(TemplateVariantArguments, FunctionStart.size());
941 mOut << ") {\n";
942 ForwardReduce("x1", "x2", "inLen");
943 }
944}
945
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700946void RSReflectionCpp::genArguments(const ArgumentList &Arguments, int Offset) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800947 bool FirstArg = true;
948
Jean-Luc Brouilleteb8b99e2014-06-03 20:59:01 -0700949 for (ArgumentList::const_iterator I = Arguments.begin(), E = Arguments.end();
950 I != E; I++) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800951 if (!FirstArg) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700952 mOut << ",\n";
953 mOut.indent() << string(Offset, ' ');
Stephen Hines7dd6da22012-11-15 19:56:03 -0800954 } else {
955 FirstArg = false;
956 }
957
Matt Wala1c6b9272015-08-03 14:06:07 -0700958 mOut << I->Type << " " << I->Name;
959 if (!I->DefaultValue.empty()) {
960 mOut << " = " << I->DefaultValue;
961 }
Stephen Hines7dd6da22012-11-15 19:56:03 -0800962 }
963}
964
965bool RSReflectionCpp::genCreateFieldPacker(const RSExportType *ET,
966 const char *FieldPackerName) {
Jean-Luc Brouilletc95381a2014-05-14 21:24:45 -0700967 size_t AllocSize = ET->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -0800968
969 if (AllocSize > 0) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700970 mOut.indent() << "android::RSC::FieldPacker " << FieldPackerName << "("
971 << AllocSize << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -0800972 return true;
973 }
974
975 return false;
976}
977
978void RSReflectionCpp::genPackVarOfType(const RSExportType *ET,
979 const char *VarName,
980 const char *FieldPackerName) {
Stephen Hines7dd6da22012-11-15 19:56:03 -0800981 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700982 case RSExportType::ExportClassPrimitive:
983 case RSExportType::ExportClassVector:
984 case RSExportType::ExportClassPointer:
985 case RSExportType::ExportClassMatrix: {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -0700986 mOut.indent() << FieldPackerName << ".add(" << VarName << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -0700987 break;
988 }
989 case RSExportType::ExportClassConstantArray: {
990 /*const RSExportConstantArrayType *ECAT =
991 static_cast<const RSExportConstantArrayType *>(ET);
992
993 // TODO(zonr): more elegant way. Currently, we obtain the unique index
994 // variable (this method involves recursive call which means
995 // we may have more than one level loop, therefore we can't
996 // always use the same index variable name here) name given
997 // in the for-loop from counting the '.' in @VarName.
998 unsigned Level = 0;
999 size_t LastDotPos = 0;
1000 std::string ElementVarName(VarName);
1001
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001002 while (LastDotPos != std::string::npos) {
1003 LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
1004 Level++;
1005 }
1006 std::string IndexVarName("ct");
1007 IndexVarName.append(llvm::utostr_32(Level));
Stephen Hines7dd6da22012-11-15 19:56:03 -08001008
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001009 C.indent() << "for (int " << IndexVarName << " = 0; " <<
1010 IndexVarName << " < " << ECAT->getSize() << "; " <<
1011 IndexVarName << "++)";
1012 C.startBlock();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001013
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001014 ElementVarName.append("[" + IndexVarName + "]");
1015 genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
1016 FieldPackerName);
Stephen Hines7dd6da22012-11-15 19:56:03 -08001017
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001018 C.endBlock();*/
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001019 break;
1020 }
1021 case RSExportType::ExportClassRecord: {
1022 const RSExportRecordType *ERT = static_cast<const RSExportRecordType *>(ET);
1023 // Relative pos from now on in field packer
1024 unsigned Pos = 0;
Stephen Hines7dd6da22012-11-15 19:56:03 -08001025
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001026 for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1027 E = ERT->fields_end();
1028 I != E; I++) {
1029 const RSExportRecordType::Field *F = *I;
1030 std::string FieldName;
1031 size_t FieldOffset = F->getOffsetInParent();
1032 const RSExportType *T = F->getType();
1033 size_t FieldStoreSize = T->getStoreSize();
1034 size_t FieldAllocSize = T->getAllocSize();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001035
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001036 if (VarName != nullptr)
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001037 FieldName = VarName + ("." + F->getName());
1038 else
1039 FieldName = F->getName();
Stephen Hines7dd6da22012-11-15 19:56:03 -08001040
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001041 if (FieldOffset > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001042 mOut.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos)
1043 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -08001044 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001045
1046 genPackVarOfType(F->getType(), FieldName.c_str(), FieldPackerName);
1047
1048 // There is padding in the field type
1049 if (FieldAllocSize > FieldStoreSize) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001050 mOut.indent() << FieldPackerName << ".skip("
1051 << (FieldAllocSize - FieldStoreSize) << ");\n";
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001052 }
1053
1054 Pos = FieldOffset + FieldAllocSize;
Stephen Hines7dd6da22012-11-15 19:56:03 -08001055 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001056
1057 // There maybe some padding after the struct
1058 if (ERT->getAllocSize() > Pos) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001059 mOut.indent() << FieldPackerName << ".skip(" << ERT->getAllocSize() - Pos
1060 << ");\n";
Stephen Hines7dd6da22012-11-15 19:56:03 -08001061 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001062 break;
1063 }
1064 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines7dd6da22012-11-15 19:56:03 -08001065 }
1066}
1067
Stephen Hines003ac662013-08-21 00:37:51 -07001068void RSReflectionCpp::genTypeCheck(const RSExportType *ET,
1069 const char *VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001070 mOut.indent() << "// Type check for " << VarName << "\n";
Stephen Hines003ac662013-08-21 00:37:51 -07001071
1072 if (ET->getClass() == RSExportType::ExportClassPointer) {
1073 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001074 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -07001075 ET = EPT->getPointeeType();
1076 }
1077
1078 std::string TypeName;
1079 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001080 case RSExportType::ExportClassPrimitive:
1081 case RSExportType::ExportClassVector:
1082 case RSExportType::ExportClassRecord: {
1083 TypeName = ET->getElementName();
1084 break;
1085 }
Stephen Hines003ac662013-08-21 00:37:51 -07001086
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001087 default:
1088 break;
Stephen Hines003ac662013-08-21 00:37:51 -07001089 }
1090
1091 if (!TypeName.empty()) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001092 mOut.indent() << "if (!" << VarName
1093 << "->getType()->getElement()->isCompatible("
Matt Wala1c6b9272015-08-03 14:06:07 -07001094 << kRsElemPrefix << TypeName << "))";
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001095 mOut.startBlock();
1096 mOut.indent() << "mRS->throwError(RS_ERROR_RUNTIME_ERROR, "
1097 "\"Incompatible type\");\n";
1098 mOut.indent() << "return;\n";
1099 mOut.endBlock();
Stephen Hines003ac662013-08-21 00:37:51 -07001100 }
1101}
1102
Matt Wala1c6b9272015-08-03 14:06:07 -07001103// Ensure that the input is 1 dimensional.
1104void RSReflectionCpp::gen1DCheck(const std::string &VarName) {
1105 mOut.indent() << "// check that " << VarName << " is 1d\n";
1106 mOut.indent() << "sp<const Type> t0 = " << VarName << "->getType();\n";
1107 mOut.indent() << "if (t0->getY() != 0 ||\n";
1108 mOut.indent() << " t0->hasFaces() ||\n";
1109 mOut.indent() << " t0->hasMipmaps())";
1110 mOut.startBlock();
1111 mOut.indent() << "mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1112 << "\"" << VarName << " is not 1D!\");\n";
1113 mOut.indent() << "return;\n";
1114 mOut.endBlock();
1115}
1116
1117// Generates code to ensure that the supplied array length is a multiple of the vector size.
1118void RSReflectionCpp::genVectorLengthCompatibilityCheck(const std::string &Length,
1119 unsigned VecSize,
1120 const std::string &ValueToReturn,
1121 unsigned IndentLevels) {
1122 auto Indenter = [this, IndentLevels]() -> std::ofstream& {
1123 GeneratedFile &Out = this->mOut;
1124 for (unsigned Level = 0; Level < IndentLevels; ++Level) {
1125 Out.indent();
1126 }
1127 return Out;
1128 };
1129
1130 Indenter() << "// Verify that the array length is a multiple of the vector size.\n";
1131 Indenter() << "if (" << Length << " % " << std::to_string(VecSize) << " != 0) {\n";
1132 Indenter() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1133 << "\"Input array length is not a multiple of "
1134 << std::to_string(VecSize) << "\");\n";
1135 Indenter() << " return " << ValueToReturn << ";\n";
1136 Indenter() << "}\n\n";
1137}
1138
1139// Generates code to ensure that the supplied array is non-null and nonzero in length.
1140void RSReflectionCpp::genNullOrEmptyArrayCheck(const std::string &ArrayName,
1141 const std::string &Length,
1142 const std::string &ValueToReturn) {
1143 mOut.indent() << "// Verify that the array is non-null and non-empty.\n";
1144 mOut.indent() << "if (" << ArrayName << " == nullptr) {\n";
1145 mOut.indent() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1146 << "\"Input array is null\");\n";
1147 mOut.indent() << " return " << ValueToReturn << ";\n";
1148 mOut.indent() << "}\n\n";
1149
1150 mOut.indent() << "if (" << Length << " == 0) {\n";
1151 mOut.indent() << " mRS->throwError(RS_ERROR_INVALID_PARAMETER, "
1152 << "\"Input array is zero-length\");\n";
1153 mOut.indent() << " return " << ValueToReturn << ";\n";
1154 mOut.indent() << "}\n\n";
1155}
1156
Stephen Hines003ac662013-08-21 00:37:51 -07001157void RSReflectionCpp::genTypeInstanceFromPointer(const RSExportType *ET) {
1158 if (ET->getClass() == RSExportType::ExportClassPointer) {
1159 // For pointer parameters to original forEach kernels.
1160 const RSExportPointerType *EPT =
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001161 static_cast<const RSExportPointerType *>(ET);
Stephen Hines003ac662013-08-21 00:37:51 -07001162 genTypeInstance(EPT->getPointeeType());
1163 } else {
1164 // For handling pass-by-value kernel parameters.
1165 genTypeInstance(ET);
1166 }
1167}
1168
1169void RSReflectionCpp::genTypeInstance(const RSExportType *ET) {
1170 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001171 case RSExportType::ExportClassPrimitive:
1172 case RSExportType::ExportClassVector:
1173 case RSExportType::ExportClassConstantArray:
1174 case RSExportType::ExportClassRecord: {
1175 std::string TypeName = ET->getElementName();
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001176 mTypesToCheck.insert(TypeName);
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001177 break;
1178 }
Stephen Hines003ac662013-08-21 00:37:51 -07001179
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001180 default:
1181 break;
Stephen Hines003ac662013-08-21 00:37:51 -07001182 }
1183}
1184
Stephen Hines80706832013-08-28 18:08:57 -07001185void RSReflectionCpp::genInitExportVariable(const RSExportType *ET,
1186 const std::string &VarName,
1187 const clang::APValue &Val) {
1188 slangAssert(!Val.isUninit() && "Not a valid initializer");
Stephen Hines003ac662013-08-21 00:37:51 -07001189
Stephen Hines80706832013-08-28 18:08:57 -07001190 switch (ET->getClass()) {
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001191 case RSExportType::ExportClassPrimitive: {
1192 const RSExportPrimitiveType *EPT =
1193 static_cast<const RSExportPrimitiveType *>(ET);
1194 if (EPT->getType() == DataTypeBoolean) {
1195 genInitBoolExportVariable(VarName, Val);
1196 } else {
1197 genInitPrimitiveExportVariable(VarName, Val);
1198 }
1199 break;
1200 }
1201 case RSExportType::ExportClassPointer: {
1202 if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
1203 std::cerr << "Initializer which is non-NULL to pointer type variable "
1204 "will be ignored" << std::endl;
1205 break;
1206 }
1207 case RSExportType::ExportClassVector: {
1208 const RSExportVectorType *EVT = static_cast<const RSExportVectorType *>(ET);
1209 switch (Val.getKind()) {
1210 case clang::APValue::Int:
1211 case clang::APValue::Float: {
1212 for (unsigned i = 0; i < EVT->getNumElement(); i++) {
1213 std::string Name = VarName + "." + getVectorAccessor(i);
1214 genInitPrimitiveExportVariable(Name, Val);
Stephen Hines80706832013-08-28 18:08:57 -07001215 }
1216 break;
1217 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001218 case clang::APValue::Vector: {
1219 unsigned NumElements = std::min(
1220 static_cast<unsigned>(EVT->getNumElement()), Val.getVectorLength());
1221 for (unsigned i = 0; i < NumElements; i++) {
1222 const clang::APValue &ElementVal = Val.getVectorElt(i);
1223 std::string Name = VarName + "." + getVectorAccessor(i);
1224 genInitPrimitiveExportVariable(Name, ElementVal);
Stephen Hines80706832013-08-28 18:08:57 -07001225 }
1226 break;
1227 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001228 case clang::APValue::MemberPointer:
1229 case clang::APValue::Uninitialized:
1230 case clang::APValue::ComplexInt:
1231 case clang::APValue::ComplexFloat:
1232 case clang::APValue::LValue:
1233 case clang::APValue::Array:
1234 case clang::APValue::Struct:
1235 case clang::APValue::Union:
1236 case clang::APValue::AddrLabelDiff: {
1237 slangAssert(false && "Unexpected type of value of initializer.");
Stephen Hines80706832013-08-28 18:08:57 -07001238 }
Stephen Hines80706832013-08-28 18:08:57 -07001239 }
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001240 break;
1241 }
1242 case RSExportType::ExportClassMatrix:
1243 case RSExportType::ExportClassConstantArray:
1244 case RSExportType::ExportClassRecord: {
1245 slangAssert(false && "Unsupported initializer for record/matrix/constant "
1246 "array type variable currently");
1247 break;
1248 }
1249 default: { slangAssert(false && "Unknown class of type"); }
Stephen Hines80706832013-08-28 18:08:57 -07001250 }
Stephen Hines80706832013-08-28 18:08:57 -07001251}
1252
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001253const char *RSReflectionCpp::getVectorAccessor(unsigned Index) {
1254 static const char *VectorAccessorMap[] = {/* 0 */ "x",
1255 /* 1 */ "y",
1256 /* 2 */ "z",
1257 /* 3 */ "w",
1258 };
1259
1260 slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char *))) &&
1261 "Out-of-bound index to access vector member");
1262
1263 return VectorAccessorMap[Index];
1264}
1265
Stephen Hines80706832013-08-28 18:08:57 -07001266void RSReflectionCpp::genZeroInitExportVariable(const std::string &VarName) {
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001267 mOut.indent() << "memset(&" << RS_EXPORT_VAR_PREFIX << VarName
1268 << ", 0, sizeof(" << RS_EXPORT_VAR_PREFIX << VarName << "));\n";
Stephen Hines80706832013-08-28 18:08:57 -07001269}
1270
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001271void
1272RSReflectionCpp::genInitPrimitiveExportVariable(const std::string &VarName,
1273 const clang::APValue &Val) {
Stephen Hines80706832013-08-28 18:08:57 -07001274 slangAssert(!Val.isUninit() && "Not a valid initializer");
1275
Jean-Luc Brouilletefcff102014-06-03 16:13:51 -07001276 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
1277 genInitValue(Val);
1278 mOut << ";\n";
1279}
1280
1281void RSReflectionCpp::genInitValue(const clang::APValue &Val, bool asBool) {
1282 switch (Val.getKind()) {
1283 case clang::APValue::Int: {
1284 llvm::APInt api = Val.getInt();
1285 if (asBool) {
1286 mOut << ((api.getSExtValue() == 0) ? "false" : "true");
1287 } else {
1288 // TODO: Handle unsigned correctly for C++
1289 mOut << api.getSExtValue();
1290 if (api.getBitWidth() > 32) {
1291 mOut << "L";
1292 }
1293 }
1294 break;
1295 }
1296
1297 case clang::APValue::Float: {
1298 llvm::APFloat apf = Val.getFloat();
1299 llvm::SmallString<30> s;
1300 apf.toString(s);
1301 mOut << s.c_str();
1302 if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
1303 if (s.count('.') == 0) {
1304 mOut << ".f";
1305 } else {
1306 mOut << "f";
1307 }
1308 }
1309 break;
1310 }
1311
1312 case clang::APValue::ComplexInt:
1313 case clang::APValue::ComplexFloat:
1314 case clang::APValue::LValue:
1315 case clang::APValue::Vector: {
1316 slangAssert(false && "Primitive type cannot have such kind of initializer");
1317 break;
1318 }
1319
1320 default: { slangAssert(false && "Unknown kind of initializer"); }
1321 }
Stephen Hines80706832013-08-28 18:08:57 -07001322}
1323
1324void RSReflectionCpp::genInitBoolExportVariable(const std::string &VarName,
1325 const clang::APValue &Val) {
1326 slangAssert(!Val.isUninit() && "Not a valid initializer");
1327 slangAssert((Val.getKind() == clang::APValue::Int) &&
1328 "Bool type has wrong initial APValue");
1329
Jean-Luc Brouillet1f9d1212014-06-02 20:27:29 -07001330 mOut.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = "
1331 << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
1332 << ";";
Stephen Hines80706832013-08-28 18:08:57 -07001333}
Stephen Hines003ac662013-08-21 00:37:51 -07001334
Jean-Luc Brouillet2ce118e2014-05-27 17:41:22 -07001335} // namespace slang