blob: 6b4a01b4ae9d3ea3af9024b52c0342cb2f5bb179 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "ArrayType.h"
18
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070019#include <hidl-util/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070020#include <android-base/logging.h>
21
Yifan Hongf24fa852016-09-23 11:03:15 -070022#include "ConstantExpression.h"
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Hongf24fa852016-09-23 11:03:15 -070026ArrayType::ArrayType(ArrayType *srcArray, ConstantExpression *size)
Andreas Huber709b62d2016-09-19 11:21:18 -070027 : mElementType(srcArray->mElementType),
Yifan Hongf24fa852016-09-23 11:03:15 -070028 mSizes(srcArray->mSizes),
29 mSizeComments(srcArray->mSizeComments) {
Andreas Huber709b62d2016-09-19 11:21:18 -070030 addDimension(size);
31}
32
Yifan Hongf24fa852016-09-23 11:03:15 -070033ArrayType::ArrayType(Type *elementType, ConstantExpression *size)
Andreas Huber709b62d2016-09-19 11:21:18 -070034 : mElementType(elementType) {
35 addDimension(size);
36}
37
Yifan Hongf24fa852016-09-23 11:03:15 -070038void ArrayType::addDimension(ConstantExpression *size) {
Yifan Honge77ca132016-09-27 10:49:05 -070039 mSizes.insert(mSizes.begin(), size->castSizeT());
Yifan Hongf24fa852016-09-23 11:03:15 -070040 mSizeComments.insert(mSizeComments.begin(), size->description());
Andreas Huberc9410c72016-07-28 12:18:40 -070041}
42
Steven Moreland979e0992016-09-07 09:18:08 -070043void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const {
44 mElementType->addNamedTypesToSet(set);
45}
46
Andreas Huber709b62d2016-09-19 11:21:18 -070047bool ArrayType::isArray() const {
48 return true;
49}
50
Steven Moreland979e0992016-09-07 09:18:08 -070051std::string ArrayType::getCppType(StorageMode mode,
52 std::string *extra,
53 bool specifyNamespaces) const {
54 const std::string base = mElementType->getCppType(extra, specifyNamespaces);
Andreas Huber709b62d2016-09-19 11:21:18 -070055 CHECK(extra->empty());
Andreas Huber881227d2016-08-02 14:20:21 -070056
Andreas Huber709b62d2016-09-19 11:21:18 -070057 size_t numArrayElements = 1;
58 for (auto size : mSizes) {
59 numArrayElements *= size;
60 }
61
Yifan Hongf24fa852016-09-23 11:03:15 -070062 std::string sizeComments = " /* " + base;
63 for (auto e : mSizeComments) {
64 sizeComments += "[" + e + "]";
65 }
66 sizeComments += " */";
Andreas Huber881227d2016-08-02 14:20:21 -070067
68 switch (mode) {
69 case StorageMode_Stack:
Yifan Hongf24fa852016-09-23 11:03:15 -070070 {
71 *extra += "[";
72 *extra += std::to_string(numArrayElements);
73 *extra += "]";
74 *extra += sizeComments;
Andreas Huber881227d2016-08-02 14:20:21 -070075 return base;
Yifan Hongf24fa852016-09-23 11:03:15 -070076 }
Andreas Huber881227d2016-08-02 14:20:21 -070077
78 case StorageMode_Argument:
Andreas Huber881227d2016-08-02 14:20:21 -070079 case StorageMode_Result:
80 {
Yifan Hongf24fa852016-09-23 11:03:15 -070081 *extra += sizeComments;
Andreas Huber881227d2016-08-02 14:20:21 -070082 return "const " + base + "*";
83 }
84 }
85}
86
Andreas Huber4c865b72016-09-14 15:26:27 -070087std::string ArrayType::getJavaType(
88 std::string *extra, bool forInitializer) const {
89 std::string baseExtra;
90 const std::string base =
91 mElementType->getJavaType(&baseExtra, forInitializer);
92
Andreas Huber709b62d2016-09-19 11:21:18 -070093 CHECK(baseExtra.empty());
94
95 extra->clear();
96
Yifan Hongf24fa852016-09-23 11:03:15 -070097 CHECK(mSizes.size() == mSizeComments.size());
98 for (size_t i = 0; i < mSizes.size(); ++i) {
Andreas Huber709b62d2016-09-19 11:21:18 -070099 *extra += "[";
100
101 if (forInitializer) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700102 *extra += std::to_string(mSizes[i]);
103 *extra += " ";
Andreas Huber709b62d2016-09-19 11:21:18 -0700104 }
105
Yifan Hongf24fa852016-09-23 11:03:15 -0700106 *extra += "/* " + mSizeComments[i] + " */";
107
Andreas Huber709b62d2016-09-19 11:21:18 -0700108 *extra += "]";
Andreas Huber4c865b72016-09-14 15:26:27 -0700109 }
Andreas Huber4c865b72016-09-14 15:26:27 -0700110
111 return base;
Andreas Huber2831d512016-08-15 09:33:47 -0700112}
113
Andreas Huber881227d2016-08-02 14:20:21 -0700114void ArrayType::emitReaderWriter(
115 Formatter &out,
116 const std::string &name,
117 const std::string &parcelObj,
118 bool parcelObjIsPointer,
119 bool isReader,
120 ErrorMode mode) const {
121 std::string baseExtra;
122 std::string baseType = mElementType->getCppType(&baseExtra);
Andreas Huber709b62d2016-09-19 11:21:18 -0700123 CHECK(baseExtra.empty());
Andreas Huber881227d2016-08-02 14:20:21 -0700124
Iliyan Malchev549e2592016-08-10 08:59:12 -0700125 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700126
127 out << "size_t " << parentName << ";\n\n";
128
129 const std::string parcelObjDeref =
130 parcelObj + (parcelObjIsPointer ? "->" : ".");
131
132 if (isReader) {
133 out << name
134 << " = (const "
135 << baseType
136 << " *)"
137 << parcelObjDeref
138 << "readBuffer(&"
139 << parentName
140 << ");\n\n";
141
142 out << "if (" << name << " == nullptr) {\n";
143
144 out.indent();
145
Iliyan Malchev549e2592016-08-10 08:59:12 -0700146 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700147 handleError2(out, mode);
148
149 out.unindent();
150 out << "}\n\n";
151 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700152 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700153 << parcelObjDeref
154 << "writeBuffer("
155 << name
Andreas Huber709b62d2016-09-19 11:21:18 -0700156 << ", ";
157
158 for (auto size : mSizes) {
159 out << size << " * ";
160 }
161
162 out << "sizeof("
Andreas Huber881227d2016-08-02 14:20:21 -0700163 << baseType
164 << "), &"
165 << parentName
166 << ");\n";
167
168 handleError(out, mode);
169 }
170
171 emitReaderWriterEmbedded(
172 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700173 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700174 name,
175 isReader /* nameIsPointer */,
176 parcelObj,
177 parcelObjIsPointer,
178 isReader,
179 mode,
180 parentName,
181 "0 /* parentOffset */");
182}
183
184void ArrayType::emitReaderWriterEmbedded(
185 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700186 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700187 const std::string &name,
188 bool nameIsPointer,
189 const std::string &parcelObj,
190 bool parcelObjIsPointer,
191 bool isReader,
192 ErrorMode mode,
193 const std::string &parentName,
194 const std::string &offsetText) const {
195 if (!mElementType->needsEmbeddedReadWrite()) {
196 return;
197 }
198
199 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
200
201 std::string baseExtra;
202 std::string baseType = mElementType->getCppType(&baseExtra);
Andreas Huber709b62d2016-09-19 11:21:18 -0700203 CHECK(baseExtra.empty());
Andreas Huber881227d2016-08-02 14:20:21 -0700204
Andreas Huberf9d49f12016-09-12 14:58:36 -0700205 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
206
Andreas Huber709b62d2016-09-19 11:21:18 -0700207 size_t numArrayElements = 1;
208 for (auto size : mSizes) {
209 numArrayElements *= size;
210 }
211
Andreas Huberf9d49f12016-09-12 14:58:36 -0700212 out << "for (size_t "
213 << iteratorName
214 << " = 0; "
215 << iteratorName
216 << " < "
Andreas Huber709b62d2016-09-19 11:21:18 -0700217 << numArrayElements
Andreas Huberf9d49f12016-09-12 14:58:36 -0700218 << "; ++"
219 << iteratorName
220 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700221
222 out.indent();
223
224 mElementType->emitReaderWriterEmbedded(
225 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700226 depth + 1,
227 name + "[" + iteratorName + "]",
Andreas Huber881227d2016-08-02 14:20:21 -0700228 false /* nameIsPointer */,
229 parcelObj,
230 parcelObjIsPointer,
231 isReader,
232 mode,
233 parentName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700234 offsetText
235 + " + " + iteratorName + " * sizeof("
236 + baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -0700237 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700238
239 out.unindent();
240
241 out << "}\n\n";
242}
243
244bool ArrayType::needsEmbeddedReadWrite() const {
245 return mElementType->needsEmbeddedReadWrite();
246}
247
Andreas Huber2831d512016-08-15 09:33:47 -0700248void ArrayType::emitJavaReaderWriter(
249 Formatter &out,
250 const std::string &parcelObj,
251 const std::string &argName,
252 bool isReader) const {
Andreas Huber709b62d2016-09-19 11:21:18 -0700253 if (isReader) {
254 std::string extra;
255 out << "new "
256 << getJavaType(&extra, true /* forInitializer */)
257 << extra
258 << ";\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700259 }
260
Andreas Huber709b62d2016-09-19 11:21:18 -0700261 out << "{\n";
262 out.indent();
263
264 out << "HwBlob _hidl_blob = ";
265
266 if (isReader) {
267 out << parcelObj
268 << ".readBuffer();\n";
269 } else {
270 size_t align, size;
271 getAlignmentAndSize(&align, &size);
272
273 out << "new HwBlob("
274 << size
275 << " /* size */);\n";
276 }
277
278 emitJavaFieldReaderWriter(
Andreas Huber2831d512016-08-15 09:33:47 -0700279 out,
Andreas Huber709b62d2016-09-19 11:21:18 -0700280 0 /* depth */,
Andreas Huber2831d512016-08-15 09:33:47 -0700281 parcelObj,
Andreas Huber709b62d2016-09-19 11:21:18 -0700282 "_hidl_blob",
Andreas Huber2831d512016-08-15 09:33:47 -0700283 argName,
Andreas Huber709b62d2016-09-19 11:21:18 -0700284 "0 /* offset */",
285 isReader);
286
287 if (!isReader) {
288 out << parcelObj << ".writeBuffer(_hidl_blob);\n";
289 }
290
291 out.unindent();
292 out << "}\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700293}
294
Andreas Huber85eabdb2016-08-25 11:24:49 -0700295void ArrayType::emitJavaFieldInitializer(
296 Formatter &out, const std::string &fieldName) const {
Andreas Huber4c865b72016-09-14 15:26:27 -0700297 std::string extra;
298 std::string typeName = getJavaType(&extra, false /* forInitializer */);
299
300 std::string extraInit;
301 getJavaType(&extraInit, true /* forInitializer */);
302
Andreas Hubercd5e6662016-08-30 15:02:59 -0700303 out << "final "
Andreas Huber4c865b72016-09-14 15:26:27 -0700304 << typeName
305 << extra
306 << " "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700307 << fieldName
308 << " = new "
Andreas Huber4c865b72016-09-14 15:26:27 -0700309 << typeName
310 << extraInit
311 << ";\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700312}
313
314void ArrayType::emitJavaFieldReaderWriter(
315 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700316 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700317 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700318 const std::string &blobName,
319 const std::string &fieldName,
320 const std::string &offset,
321 bool isReader) const {
Andreas Huber90e8fc22016-09-21 16:36:15 -0700322 out << "{\n";
323 out.indent();
324
Andreas Huber709b62d2016-09-19 11:21:18 -0700325 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth);
326 out << "long " << offsetName << " = " << offset << ";\n";
Andreas Huber4c865b72016-09-14 15:26:27 -0700327
Andreas Huber709b62d2016-09-19 11:21:18 -0700328 std::string indexString;
329 for (size_t dim = 0; dim < mSizes.size(); ++dim) {
330 std::string iteratorName =
331 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700332
Andreas Huber709b62d2016-09-19 11:21:18 -0700333 out << "for (int "
334 << iteratorName
335 << " = 0; "
336 << iteratorName
337 << " < "
338 << mSizes[dim]
339 << "; ++"
340 << iteratorName
341 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700342
Andreas Huber709b62d2016-09-19 11:21:18 -0700343 out.indent();
344
345 indexString += "[" + iteratorName + "]";
346 }
347
348 if (isReader && mElementType->isCompoundType()) {
349 std::string extra;
350 std::string typeName =
351 mElementType->getJavaType(&extra, false /* forInitializer */);
352
353 CHECK(extra.empty());
354
355 out << fieldName
356 << indexString
357 << " = new "
358 << typeName
359 << "();\n";
360 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700361
362 mElementType->emitJavaFieldReaderWriter(
363 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700364 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700365 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700366 blobName,
Andreas Huber709b62d2016-09-19 11:21:18 -0700367 fieldName + indexString,
368 offsetName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700369 isReader);
370
Andreas Huber709b62d2016-09-19 11:21:18 -0700371 size_t elementAlign, elementSize;
372 mElementType->getAlignmentAndSize(&elementAlign, &elementSize);
373
374 out << offsetName << " += " << std::to_string(elementSize) << ";\n";
375
376 for (size_t dim = 0; dim < mSizes.size(); ++dim) {
377 out.unindent();
378 out << "}\n";
379 }
Andreas Huber90e8fc22016-09-21 16:36:15 -0700380
381 out.unindent();
382 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700383}
384
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700385status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const {
Andreas Huber709b62d2016-09-19 11:21:18 -0700386 if (mSizes.size() > 1) {
387 // Multi-dimensional arrays are yet to be supported in VTS.
388 return UNKNOWN_ERROR;
389 }
390
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700391 out << "type: TYPE_ARRAY\n" << "vector_value: {\n";
392 out.indent();
Andreas Huber709b62d2016-09-19 11:21:18 -0700393 out << "size: " << mSizes[0] << "\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700394 status_t err = mElementType->emitVtsTypeDeclarations(out);
395 if (err != OK) {
396 return err;
397 }
398 out.unindent();
399 out << "}\n";
400 return OK;
401}
402
Andreas Huber70a59e12016-08-16 12:57:01 -0700403bool ArrayType::isJavaCompatible() const {
404 return mElementType->isJavaCompatible();
405}
406
Andreas Huber85eabdb2016-08-25 11:24:49 -0700407void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const {
408 mElementType->getAlignmentAndSize(align, size);
409
Andreas Huber709b62d2016-09-19 11:21:18 -0700410 for (auto sizeInDimension : mSizes) {
411 (*size) *= sizeInDimension;
412 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700413}
414
Andreas Huberc9410c72016-07-28 12:18:40 -0700415} // namespace android
416