blob: 2410784d062b461b79b7acd4c6eb4c1b2f1e00da [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 "CompoundType.h"
18
Yifan Hongec102272016-12-20 18:10:07 -080019#include "ArrayType.h"
Nirav Atre0ab82652018-06-04 11:49:14 -070020#include "ScalarType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070021#include "VectorType.h"
Timur Iskhakovcec46c42017-08-09 00:22:02 -070022
Andreas Huber5a545442016-08-03 10:44:56 -070023#include <android-base/logging.h>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070024#include <hidl-util/Formatter.h>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070025#include <iostream>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070026#include <unordered_set>
Andreas Huber5a545442016-08-03 10:44:56 -070027
Andreas Huberc9410c72016-07-28 12:18:40 -070028namespace android {
29
Timur Iskhakov565b0132017-09-06 18:07:11 -070030CompoundType::CompoundType(Style style, const char* localName, const FQName& fullName,
31 const Location& location, Scope* parent)
32 : Scope(localName, fullName, location, parent), mStyle(style), mFields(NULL) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070033
Yifan Hong27e85db2016-11-09 15:45:52 -080034CompoundType::Style CompoundType::style() const {
35 return mStyle;
36}
37
Timur Iskhakovcec46c42017-08-09 00:22:02 -070038void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070039 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070040}
Andreas Huber5a545442016-08-03 10:44:56 -070041
Timur Iskhakovb58f4182017-08-29 15:19:24 -070042std::vector<const Reference<Type>*> CompoundType::getReferences() const {
43 std::vector<const Reference<Type>*> ret;
44 ret.insert(ret.begin(), mFields->begin(), mFields->end());
Timur Iskhakov33431e62017-08-21 17:31:23 -070045 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070046}
47
48status_t CompoundType::validate() const {
49 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070050 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070051
Howard Chenecfb4512017-11-21 18:28:53 +080052 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070053 std::cerr << "ERROR: Struct/Union must not contain references to interfaces at "
54 << field->location() << "\n";
55 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070056 }
57
Andreas Huber5a545442016-08-03 10:44:56 -070058 if (mStyle == STYLE_UNION) {
59 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070060 std::cerr << "ERROR: Union must not contain any types that need fixup at "
61 << field->location() << "\n";
62 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070063 }
Andreas Huber5a545442016-08-03 10:44:56 -070064 }
65 }
66
Timur Iskhakovcec46c42017-08-09 00:22:02 -070067 status_t err = validateUniqueNames();
68 if (err != OK) return err;
69
Nirav Atre0ab82652018-06-04 11:49:14 -070070 err = validateSubTypeNames();
71 if (err != OK) return err;
72
Timur Iskhakovcec46c42017-08-09 00:22:02 -070073 return Scope::validate();
74}
75
76status_t CompoundType::validateUniqueNames() const {
77 std::unordered_set<std::string> names;
78
79 for (const auto* field : *mFields) {
80 if (names.find(field->name()) != names.end()) {
81 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
82 << field->location() << "\n";
83 return UNKNOWN_ERROR;
84 }
85 names.insert(field->name());
86 }
87
88 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -070089}
90
Nirav Atre0ab82652018-06-04 11:49:14 -070091void CompoundType::emitInvalidSubTypeNamesError(const std::string& subTypeName,
92 const Location& location) const {
93 std::cerr << "ERROR: Type name '" << subTypeName << "' defined at "
94 << location << " conflicts with a member function of "
95 << "safe_union " << localName() << ". Consider renaming or "
96 << "moving its definition outside the safe_union scope.\n";
97}
98
99status_t CompoundType::validateSubTypeNames() const {
100 if (mStyle != STYLE_SAFE_UNION) { return OK; }
101 const auto& subTypes = Scope::getSubTypes();
102
103 for (const auto& subType : subTypes) {
104 if (subType->localName() == "getDiscriminator") {
105 emitInvalidSubTypeNamesError(subType->localName(),
106 subType->location());
107 return UNKNOWN_ERROR;
108 }
109 }
110
111 return OK;
112}
113
Andreas Huberf630bc82016-09-09 14:52:25 -0700114bool CompoundType::isCompoundType() const {
115 return true;
116}
117
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700118bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800119 if (mStyle == STYLE_UNION) {
120 return false;
121 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700122 for (const auto* field : *mFields) {
123 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800124 return false;
125 }
126 }
127 return true;
128}
129
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700130std::string CompoundType::typeName() const {
131 switch (mStyle) {
132 case STYLE_STRUCT: {
133 return "struct " + localName();
134 }
135 case STYLE_UNION: {
136 return "union " + localName();
137 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700138 case STYLE_SAFE_UNION: {
139 return "safe_union " + localName();
140 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700141 }
142 CHECK(!"Should not be here");
143}
144
Andreas Huber881227d2016-08-02 14:20:21 -0700145std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700146 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700147 bool /* specifyNamespaces */) const {
148 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700149
150 switch (mode) {
151 case StorageMode_Stack:
152 return base;
153
154 case StorageMode_Argument:
155 return "const " + base + "&";
156
157 case StorageMode_Result:
Howard Chenecfb4512017-11-21 18:28:53 +0800158 return base + (containsInterface()?"":"*");
Andreas Huber881227d2016-08-02 14:20:21 -0700159 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700160 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -0700161}
162
Yifan Hong4ed13472016-11-02 10:44:11 -0700163std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700164 return fullJavaName();
165}
166
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700167std::string CompoundType::getVtsType() const {
168 switch (mStyle) {
169 case STYLE_STRUCT:
170 {
171 return "TYPE_STRUCT";
172 }
173 case STYLE_UNION:
174 {
175 return "TYPE_UNION";
176 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700177 case STYLE_SAFE_UNION:
178 {
179 return "TYPE_SAFE_UNION";
180 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700181 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700182 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700183}
184
Howard Chenecfb4512017-11-21 18:28:53 +0800185bool CompoundType::containsInterface() const {
186 for (const auto& field : *mFields) {
187 if (field->type().isCompoundType()) {
188 const Type& t = field->type();
189 const CompoundType* ct = static_cast<const CompoundType*>(&t);
190 if (ct->containsInterface()) {
191 return true;
192 }
193 }
194 if (field->type().isInterface()) {
195 return true;
196 }
197 }
198 return false;
199}
200
Andreas Huber881227d2016-08-02 14:20:21 -0700201void CompoundType::emitReaderWriter(
202 Formatter &out,
203 const std::string &name,
204 const std::string &parcelObj,
205 bool parcelObjIsPointer,
206 bool isReader,
207 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700208
209 const std::string parcelObjDeref =
210 parcelObj + (parcelObjIsPointer ? "->" : ".");
211
Howard Chenecfb4512017-11-21 18:28:53 +0800212 if(containsInterface()){
213 for (const auto& field : *mFields) {
214 field->type().emitReaderWriter(out, name + "." + field->name(),
215 parcelObj, parcelObjIsPointer, isReader, mode);
216 }
Andreas Huber881227d2016-08-02 14:20:21 -0700217 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800218 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700219
Howard Chenecfb4512017-11-21 18:28:53 +0800220 out << "size_t " << parentName << ";\n\n";
221
222 if (isReader) {
223 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
224 << "sizeof(*" << name << "), &" << parentName << ", "
225 << " const_cast<const void**>(reinterpret_cast<void **>("
226 << "&" << name << ")));\n";
227 handleError(out, mode);
228 } else {
229 out << "_hidl_err = "
230 << parcelObjDeref
231 << "writeBuffer(&"
232 << name
233 << ", sizeof("
234 << name
235 << "), &"
236 << parentName
237 << ");\n";
238 handleError(out, mode);
239 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700240
241 bool needEmbeddedReadWrite = needsEmbeddedReadWrite();
242 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite);
243
244 if (needEmbeddedReadWrite) {
Howard Chenecfb4512017-11-21 18:28:53 +0800245 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
246 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
247 isReader, mode, parentName, "0 /* parentOffset */");
248 }
Andreas Huber881227d2016-08-02 14:20:21 -0700249 }
Andreas Huber881227d2016-08-02 14:20:21 -0700250}
251
252void CompoundType::emitReaderWriterEmbedded(
253 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700254 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700255 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700256 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700257 bool nameIsPointer,
258 const std::string &parcelObj,
259 bool parcelObjIsPointer,
260 bool isReader,
261 ErrorMode mode,
262 const std::string &parentName,
263 const std::string &offsetText) const {
264 emitReaderWriterEmbeddedForTypeName(
265 out,
266 name,
267 nameIsPointer,
268 parcelObj,
269 parcelObjIsPointer,
270 isReader,
271 mode,
272 parentName,
273 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700274 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800275 "" /* childName */,
276 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700277}
278
Andreas Huber85eabdb2016-08-25 11:24:49 -0700279void CompoundType::emitJavaReaderWriter(
280 Formatter &out,
281 const std::string &parcelObj,
282 const std::string &argName,
283 bool isReader) const {
284 if (isReader) {
285 out << "new " << fullJavaName() << "();\n";
286 }
287
288 out << argName
289 << "."
290 << (isReader ? "readFromParcel" : "writeToParcel")
291 << "("
292 << parcelObj
293 << ");\n";
294}
295
296void CompoundType::emitJavaFieldInitializer(
297 Formatter &out, const std::string &fieldName) const {
298 out << "final "
299 << fullJavaName()
300 << " "
301 << fieldName
302 << " = new "
303 << fullJavaName()
304 << "();\n";
305}
306
307void CompoundType::emitJavaFieldReaderWriter(
308 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700309 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700310 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700311 const std::string &blobName,
312 const std::string &fieldName,
313 const std::string &offset,
314 bool isReader) const {
315 if (isReader) {
316 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700317 << ".readEmbeddedFromParcel("
318 << parcelName
319 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700320 << blobName
321 << ", "
322 << offset
323 << ");\n";
324
325 return;
326 }
327
328 out << fieldName
329 << ".writeEmbeddedToBlob("
330 << blobName
331 << ", "
332 << offset
333 << ");\n";
334}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700335void CompoundType::emitResolveReferences(
336 Formatter &out,
337 const std::string &name,
338 bool nameIsPointer,
339 const std::string &parcelObj,
340 bool parcelObjIsPointer,
341 bool isReader,
342 ErrorMode mode) const {
343 emitResolveReferencesEmbedded(
344 out,
345 0 /* depth */,
346 name,
347 name /* sanitizedName */,
348 nameIsPointer,
349 parcelObj,
350 parcelObjIsPointer,
351 isReader,
352 mode,
353 "_hidl_" + name + "_parent",
354 "0 /* parentOffset */");
355}
356
357void CompoundType::emitResolveReferencesEmbedded(
358 Formatter &out,
359 size_t /* depth */,
360 const std::string &name,
361 const std::string &/* sanitizedName */,
362 bool nameIsPointer,
363 const std::string &parcelObj,
364 bool parcelObjIsPointer,
365 bool isReader,
366 ErrorMode mode,
367 const std::string &parentName,
368 const std::string &offsetText) const {
369 CHECK(needsResolveReferences());
370
371 const std::string parcelObjDeref =
372 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
373
374 const std::string parcelObjPointer =
375 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
376
Yifan Hong244e82d2016-11-11 11:13:57 -0800377 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700378 const std::string namePointer = nameIsPointer ? name : ("&" + name);
379
380 out << "_hidl_err = ";
381
382 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800383 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700384 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800385 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700386 }
387
Yifan Hong33223ca2016-12-13 15:07:35 -0800388 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800389 if (isReader) {
390 out << "const_cast<"
391 << fullName()
392 << " *"
393 << ">("
394 << namePointer
395 << "),\n"
396 << parcelObjDeref;
397 } else {
398 out << nameDerefed
399 << ",\n"
400 << parcelObjPointer;
401 }
402
403 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700404 << parentName
405 << ",\n"
406 << offsetText
407 << ");\n\n";
408 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700409
410 handleError(out, mode);
411}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700412
Nirav Atre0ab82652018-06-04 11:49:14 -0700413void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout,
414 const std::string& layoutName) const {
415 out << "static_assert(sizeof("
416 << fullName()
417 << layoutName
418 << ") == "
419 << layout.size
420 << ", \"wrong size\");\n";
421
422 out << "static_assert(__alignof("
423 << fullName()
424 << layoutName
425 << ") == "
426 << layout.align
427 << ", \"wrong alignment\");\n";
428}
429
430void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
431 out << "struct "
432 << localName()
433 << " final {\n";
434
435 out.indent();
436
437 Scope::emitTypeDeclarations(out);
438
Nirav Atre12c597a2018-06-28 09:35:24 -0700439 bool hasPointer = containsPointer();
440 CompoundLayout layout = hasPointer
441 ? CompoundLayout()
442 : getCompoundAlignmentAndSize();
443
Nirav Atre0ab82652018-06-04 11:49:14 -0700444 if (mFields->empty()) {
445 out.unindent();
446 out << "};\n\n";
447
448 emitLayoutAsserts(out, layout.overall, "");
449 out << "\n";
450 return;
451 }
452
453 out << "enum class hidl_discriminator : "
454 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
455 << " ";
456
457 out.block([&] {
458 for (const auto& field : *mFields) {
459 out << field->name() << ",\n";
460 }
461 out << "hidl_no_init\n";
462 });
463 out << ";\n\n";
464
465 out << localName() << "();\n"
466 << "~" << localName() << "();\n"
467 << localName() << "(const " << localName() << "&);\n\n";
468
469 for (const auto& field : *mFields) {
470 out << "void "
471 << field->name()
472 << "("
473 << field->type().getCppArgumentType()
474 << ");\n";
475
476 out << field->type().getCppStackType()
477 << "& "
478 << field->name()
479 << "();\n";
480
481 out << field->type().getCppArgumentType()
482 << " "
483 << field->name()
484 << "() const;\n\n";
485 }
486
Nirav Atre12c597a2018-06-28 09:35:24 -0700487 out << "// Utility methods\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700488 out << "hidl_discriminator getDiscriminator() const;\n\n";
489
Nirav Atre12c597a2018-06-28 09:35:24 -0700490 out << "constexpr size_t hidl_getUnionOffset() const ";
491 out.block([&] {
492 out << "return offsetof(" << fullName() << ", hidl_u);\n";
493 }).endl().endl();
494
Nirav Atre0ab82652018-06-04 11:49:14 -0700495 out.unindent();
496 out << "private:\n";
497 out.indent();
498
499 out << "void hidl_destructUnion();\n\n";
Nirav Atre12c597a2018-06-28 09:35:24 -0700500
501 out << "hidl_discriminator hidl_d";
502 if (!hasPointer) {
503 out << " __attribute__ ((aligned("
504 << layout.discriminator.align << "))) ";
505 }
506 out << "{hidl_discriminator::hidl_no_init};\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700507 out << "union hidl_union final {\n";
508 out.indent();
509
Nirav Atre0ab82652018-06-04 11:49:14 -0700510 for (const auto& field : *mFields) {
511
512 size_t fieldAlign, fieldSize;
513 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
514
515 out << field->type().getCppStackType()
516 << " "
517 << field->name();
518
519 if (!hasPointer) {
520 out << " __attribute__ ((aligned("
521 << fieldAlign
522 << ")))";
523 }
524 out << ";\n";
525 }
526
527 out << "\n"
528 << "hidl_union();\n"
529 << "~hidl_union();\n";
530
531 out.unindent();
Nirav Atre12c597a2018-06-28 09:35:24 -0700532 out << "} hidl_u;\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700533
534 if (!hasPointer) {
535 out << "\n";
536
537 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union");
538 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator");
539 }
540
541 out.unindent();
542 out << "};\n\n";
543
544 if (!hasPointer) {
545 emitLayoutAsserts(out, layout.overall, "");
546 out << "\n";
547 }
548}
549
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800550void CompoundType::emitTypeDeclarations(Formatter& out) const {
Nirav Atre0ab82652018-06-04 11:49:14 -0700551 if (mStyle == STYLE_SAFE_UNION) {
552 emitSafeUnionTypeDeclarations(out);
553 return;
554 }
555
Andreas Huber881227d2016-08-02 14:20:21 -0700556 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
557 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700558 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800559 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700560
561 out.indent();
562
563 Scope::emitTypeDeclarations(out);
564
Andreas Huber60d3b222017-03-30 09:10:56 -0700565 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800566 for (const auto &field : *mFields) {
Steven Moreland073269e2018-05-17 15:45:26 -0700567 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800568 out << field->type().getCppStackType()
569 << " "
570 << field->name()
571 << ";\n";
572 }
573
574 out.unindent();
575 out << "};\n\n";
576
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800577 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700578 }
579
Andreas Huberca4bc892017-01-09 14:58:12 -0800580 for (int pass = 0; pass < 2; ++pass) {
581 size_t offset = 0;
582 for (const auto &field : *mFields) {
583 size_t fieldAlign, fieldSize;
584 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
585
Nirav Atre0ab82652018-06-04 11:49:14 -0700586 offset += Layout::getPad(offset, fieldAlign);
Andreas Huberca4bc892017-01-09 14:58:12 -0800587
588 if (pass == 0) {
589 out << field->type().getCppStackType()
590 << " "
591 << field->name()
592 << " __attribute__ ((aligned("
593 << fieldAlign
594 << ")));\n";
595 } else {
596 out << "static_assert(offsetof("
597 << fullName()
598 << ", "
599 << field->name()
600 << ") == "
601 << offset
602 << ", \"wrong offset\");\n";
603 }
604
Andreas Huber60d3b222017-03-30 09:10:56 -0700605 if (mStyle == STYLE_STRUCT) {
606 offset += fieldSize;
607 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800608 }
609
610 if (pass == 0) {
611 out.unindent();
612 out << "};\n\n";
613 }
614 }
615
Nirav Atre0ab82652018-06-04 11:49:14 -0700616 CompoundLayout layout = getCompoundAlignmentAndSize();
617 emitLayoutAsserts(out, layout.overall, "");
618 out << "\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800619}
620
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700621void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
Nirav Atre0ab82652018-06-04 11:49:14 -0700622 switch (mStyle) {
623 case STYLE_UNION: {
624 out << "union";
625 break;
626 }
627 case STYLE_STRUCT:
628 case STYLE_SAFE_UNION: {
629 out << "struct";
630 break;
631 }
632 default: {
633 CHECK(!"Should not be here");
634 }
635 }
636 out << " " << localName() << ";\n";
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700637}
Yifan Hong244e82d2016-11-11 11:13:57 -0800638
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800639void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800640 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800641
Steven Morelandbf714212017-10-27 18:29:01 -0700642 // TODO(b/65200821): remove these ifdefs
643 out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
Steven Moreland3d98bc42017-06-23 21:36:41 +0000644 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800645 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000646 << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700647 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000648 out << "bool operator==("
649 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700650
Steven Morelandf91048a2017-06-23 21:38:35 +0000651 out << "bool operator!=("
652 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700653 }
654 out << "#else\n";
655 out << "static inline std::string toString("
656 << getCppArgumentType()
657 << (mFields->empty() ? "" : " o")
658 << ") ";
659
660 out.block([&] {
661 // include toString for scalar types
662 out << "using ::android::hardware::toString;\n"
663 << "std::string os;\n";
664 out << "os += \"{\";\n";
665
Nirav Atre0ab82652018-06-04 11:49:14 -0700666 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
667 out << "\nswitch (o.getDiscriminator()) {\n";
668 out.indent();
Steven Morelandbf714212017-10-27 18:29:01 -0700669 }
670
Nirav Atre0ab82652018-06-04 11:49:14 -0700671 for (const NamedReference<Type>* field : *mFields) {
672 if (mStyle == STYLE_SAFE_UNION) {
673 out << "case "
674 << fullName()
675 << "::hidl_discriminator::"
676 << field->name()
677 << ": ";
678
679 out.block([&] {
680 out << "os += \"."
681 << field->name()
682 << " = \";\n"
683 << "os += toString(o."
684 << field->name()
685 << "());\n"
686 << "break;\n";
687 }).endl();
688 } else {
689 out << "os += \"";
690 if (field != *(mFields->begin())) {
691 out << ", ";
692 }
693 out << "." << field->name() << " = \";\n";
694 field->type().emitDump(out, "os", "o." + field->name());
695 }
696 }
697
698 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
699 out << "case " << fullName() << "::hidl_discriminator::"
700 << "hidl_no_init: ";
701
702 out.block([&] {
703 out << "break;\n";
704 }).endl();
705
706 out << "default: ";
707 out.block([&] {
708 out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
709 }).endl();
710
711 out.unindent();
712 out << "}\n";
713 }
Steven Morelandbf714212017-10-27 18:29:01 -0700714 out << "os += \"}\"; return os;\n";
715 }).endl().endl();
716
717 if (canCheckEquality()) {
718 out << "static inline bool operator==("
719 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
720 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
721 out.block([&] {
Nirav Atre0ab82652018-06-04 11:49:14 -0700722 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
723 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
Steven Morelandbf714212017-10-27 18:29:01 -0700724 out << "return false;\n";
725 }).endl();
Nirav Atre0ab82652018-06-04 11:49:14 -0700726
727 out << "switch (lhs.getDiscriminator()) {\n";
728 out.indent();
729 }
730
731 for (const auto& field : *mFields) {
732 if (mStyle == STYLE_SAFE_UNION) {
733 out << "case "
734 << fullName()
735 << "::hidl_discriminator::"
736 << field->name()
737 << ": ";
738
739 out.block([&] {
740 out << "return (lhs."
741 << field->name()
742 << "() == rhs."
743 << field->name()
744 << "());\n";
745 }).endl();
746 } else {
747 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
748 out << "return false;\n";
749 }).endl();
750 }
751 }
752
753 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
754 out << "case " << fullName() << "::hidl_discriminator::"
755 << "hidl_no_init: ";
756
757 out.block([&] {
758 out << "return false;\n";
759 }).endl();
760
761 out << "default: ";
762 out.block([&] {
763 out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
764 }).endl();
765
766 out.unindent();
767 out << "}\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700768 }
769 out << "return true;\n";
770 }).endl().endl();
771
772 out << "static inline bool operator!=("
773 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
774 out.block([&] {
775 out << "return !(lhs == rhs);\n";
776 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700777 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000778 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800779 }
Steven Morelandbf714212017-10-27 18:29:01 -0700780 out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800781}
782
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800783void CompoundType::emitPackageHwDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700784 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800785 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700786
Yifan Hong0a68a282016-10-21 16:32:34 -0700787 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700788
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700789 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800790 << "const ::android::hardware::Parcel &parcel,\n"
791 << "size_t parentHandle,\n"
792 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700793
Yifan Hong0a68a282016-10-21 16:32:34 -0700794 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700795
796 out << "::android::status_t writeEmbeddedToParcel(\n";
797
Yifan Hong0a68a282016-10-21 16:32:34 -0700798 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700799
Yifan Hong244e82d2016-11-11 11:13:57 -0800800 out << "const " << fullName() << " &obj,\n"
801 << "::android::hardware::Parcel *parcel,\n"
802 << "size_t parentHandle,\n"
803 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700804
Yifan Hong0a68a282016-10-21 16:32:34 -0700805 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700806 }
807
Yifan Hongbf459bc2016-08-23 16:50:37 -0700808 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700809 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700810 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800811 out << fullName() << " *obj,\n"
812 << "const ::android::hardware::Parcel &parcel,\n"
813 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700814 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700815 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700816 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800817 out << "const " << fullName() << " &obj,\n"
818 << "::android::hardware::Parcel *,\n"
819 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700820 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700821 }
Andreas Huber881227d2016-08-02 14:20:21 -0700822}
823
Nirav Atre0ab82652018-06-04 11:49:14 -0700824void emitSafeUnionGetterDefinition(const std::string& fieldName,
825 Formatter& out) {
826 out.block([&] {
827 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::"
828 << fieldName
829 << ")) ";
830
831 out.block([&] {
832 out << "details::logAlwaysFatal(\"Bad safe_union access.\");\n";
833 }).endl().endl();
834
835 out << "return hidl_u."
836 << fieldName
837 << ";\n";
838 }).endl().endl();
839}
840
841void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const {
842
843 // Default constructor
844 out << fullName()
845 << "::"
846 << localName()
Nirav Atre12c597a2018-06-28 09:35:24 -0700847 << "() ";
848
849 out.block([&] {
850 out << "static_assert(offsetof("
851 << fullName()
852 << ", hidl_d) == 0, \"wrong offset\");\n";
853
854 if (!containsPointer()) {
855 CompoundLayout layout = getCompoundAlignmentAndSize();
856 out << "static_assert(offsetof("
857 << fullName()
858 << ", hidl_u) == "
859 << layout.innerStruct.offset
860 << ", \"wrong offset\");\n";
861 }
862 }).endl().endl();
Nirav Atre0ab82652018-06-04 11:49:14 -0700863
864 // Destructor
865 out << fullName()
866 << "::~"
867 << localName()
868 << "() ";
869
870 out.block([&] {
871 out << "hidl_destructUnion();\n";
872 }).endl().endl();
873
874 // Copy constructor
875 out << fullName()
876 << "::"
877 << localName()
878 << "(const "
879 << localName()
880 << "& other) ";
881
882 out.block([&] {
883 out << "switch(other.hidl_d) ";
884 out.block([&] {
885
886 for (const auto& field : *mFields) {
887 out << "case hidl_discriminator::"
888 << field->name()
889 << ": ";
890
891 out.block([&] {
892 out << "new (&hidl_u."
893 << field->name()
894 << ") "
895 << field->type().getCppStackType()
896 << "(other.hidl_u."
897 << field->name()
898 << ");\n"
899 << "break;\n";
900 }).endl();
901 }
902
903 out << "case hidl_discriminator::hidl_no_init: { break; }\n";
904 out << "default: { details::logAlwaysFatal("
905 << "\"Unknown union discriminator.\"); }\n";
906 }).endl().endl();
907
908 out << "hidl_d = other.hidl_d;\n";
909 }).endl().endl();
910}
911
912void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
913 if (mFields->empty()) { return; }
914 emitSafeUnionTypeConstructors(out);
915
916 out << "void "
917 << fullName()
918 << "::hidl_destructUnion() ";
919
920 out.block([&] {
921 out << "switch(hidl_d) ";
922 out.block([&] {
923
924 for (const auto& field : *mFields) {
925 out << "case hidl_discriminator::"
926 << field->name()
927 << ": ";
928
929 out.block([&] {
930 const std::string fullFieldName = "hidl_u." + field->name();
931 field->type().emitTypeDestructorCall(out, fullFieldName);
932 out << "break;\n";
933 }).endl();
934 }
935
936 out << "case hidl_discriminator::hidl_no_init: { break; }\n";
937 out << "default: { details::logAlwaysFatal("
938 << "\"Unknown union discriminator.\"); }\n";
939 }).endl().endl();
940
941 out << "hidl_d = hidl_discriminator::hidl_no_init;\n";
942 }).endl().endl();
943
Nirav Atre0ab82652018-06-04 11:49:14 -0700944 for (const NamedReference<Type>* field : *mFields) {
945 // Setter
946 out << "void "
947 << fullName()
948 << "::"
949 << field->name()
950 << "("
951 << field->type().getCppArgumentType()
952 << " o) ";
953
954 out.block([&] {
955 out << "if (hidl_d != hidl_discriminator::"
956 << field->name()
957 << ") ";
958
959 out.block([&] {
960 out << "hidl_destructUnion();\n"
961 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n";
962
963 out << "new (&hidl_u."
964 << field->name()
965 << ") "
966 << field->type().getCppStackType()
967 << "(o);\n";
968
969 out << "hidl_d = hidl_discriminator::"
970 << field->name()
971 << ";\n";
972 }).endl();
973
974 out << "else if (&(hidl_u."
975 << field->name()
976 << ") != &o) ";
977
978 out.block([&] {
979 out << "hidl_u."
980 << field->name()
981 << " = o;\n";
982 }).endl();
983 }).endl().endl();
984
985 // Getter (mutable)
986 out << field->type().getCppStackType()
987 << "& ("
988 << fullName()
989 << "::"
990 << field->name()
991 << ")() ";
992
993 emitSafeUnionGetterDefinition(field->name(), out);
994
995 // Getter (immutable)
996 out << field->type().getCppArgumentType()
997 << " ("
998 << fullName()
999 << "::"
1000 << field->name()
1001 << ")() const ";
1002
1003 emitSafeUnionGetterDefinition(field->name(), out);
1004 }
1005
1006 // Trivial constructor/destructor for internal union
1007 out << fullName() << "::hidl_union::hidl_union() {}\n\n"
1008 << fullName() << "::hidl_union::~hidl_union() {}\n\n";
1009
1010 // Utility method
1011 out << fullName() << "::hidl_discriminator "
1012 << localName() << "::getDiscriminator() const ";
1013
1014 out.block([&] {
Nirav Atre0ab82652018-06-04 11:49:14 -07001015 out << "\nreturn hidl_d;\n";
1016 }).endl().endl();
1017}
1018
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001019void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -07001020 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001021 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -07001022
Yifan Hongbf459bc2016-08-23 16:50:37 -07001023 if (needsEmbeddedReadWrite()) {
1024 emitStructReaderWriter(out, prefix, true /* isReader */);
1025 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -07001026 }
1027
Yifan Hongbf459bc2016-08-23 16:50:37 -07001028 if (needsResolveReferences()) {
1029 emitResolveReferenceDef(out, prefix, true /* isReader */);
1030 emitResolveReferenceDef(out, prefix, false /* isReader */);
1031 }
Andreas Huber881227d2016-08-02 14:20:21 -07001032
Steven Morelandbf714212017-10-27 18:29:01 -07001033 // TODO(b/65200821): remove toString + operator== from .cpp once all prebuilts are rebuilt
Nirav Atre0ab82652018-06-04 11:49:14 -07001034 // For safe unions (which have no legacy users), skip emitting these definitions to .cpp.
1035 if (mStyle == STYLE_SAFE_UNION) {
1036 emitSafeUnionTypeDefinitions(out);
1037 return;
1038 }
Steven Morelandbf714212017-10-27 18:29:01 -07001039
Steven Moreland3d98bc42017-06-23 21:36:41 +00001040 out << "std::string toString("
1041 << getCppArgumentType()
1042 << (mFields->empty() ? "" : " o")
1043 << ") ";
1044
1045 out.block([&] {
1046 // include toString for scalar types
1047 out << "using ::android::hardware::toString;\n"
1048 << "std::string os;\n";
1049 out << "os += \"{\";\n";
1050
Timur Iskhakov7fa79f62017-08-09 11:04:54 -07001051 for (const NamedReference<Type>* field : *mFields) {
Steven Moreland3d98bc42017-06-23 21:36:41 +00001052 out << "os += \"";
1053 if (field != *(mFields->begin())) {
1054 out << ", ";
1055 }
1056 out << "." << field->name() << " = \";\n";
1057 field->type().emitDump(out, "os", "o." + field->name());
1058 }
1059
1060 out << "os += \"}\"; return os;\n";
1061 }).endl().endl();
1062
Steven Morelandf91048a2017-06-23 21:38:35 +00001063 if (canCheckEquality()) {
1064 out << "bool operator==("
1065 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
1066 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
1067 out.block([&] {
1068 for (const auto &field : *mFields) {
1069 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
1070 out << "return false;\n";
1071 }).endl();
1072 }
1073 out << "return true;\n";
1074 }).endl().endl();
1075
1076 out << "bool operator!=("
1077 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
1078 out.block([&] {
1079 out << "return !(lhs == rhs);\n";
1080 }).endl().endl();
1081 } else {
1082 out << "// operator== and operator!= are not generated for " << localName() << "\n";
1083 }
Andreas Huber881227d2016-08-02 14:20:21 -07001084}
1085
Nirav Atre0ab82652018-06-04 11:49:14 -07001086// TODO(b/79878527): Implement Java bindings for safe unions
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001087void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -07001088 out << "public final ";
1089
1090 if (!atTopLevel) {
1091 out << "static ";
1092 }
1093
1094 out << "class "
1095 << localName()
1096 << " {\n";
1097
1098 out.indent();
1099
1100 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
1101
Steven Moreland073269e2018-05-17 15:45:26 -07001102 for (const auto& field : *mFields) {
1103 field->emitDocComment(out);
1104
Andreas Huber85eabdb2016-08-25 11:24:49 -07001105 out << "public ";
1106
1107 field->type().emitJavaFieldInitializer(out, field->name());
1108 }
1109
1110 if (!mFields->empty()) {
1111 out << "\n";
1112 }
1113
Yifan Hongec102272016-12-20 18:10:07 -08001114 ////////////////////////////////////////////////////////////////////////////
1115
1116 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001117 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -08001118 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001119 out.sIf("this == otherObject", [&] {
1120 out << "return true;\n";
1121 }).endl();
1122 out.sIf("otherObject == null", [&] {
1123 out << "return false;\n";
1124 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -07001125 // Though class is final, we use getClass instead of instanceof to be explicit.
1126 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001127 out << "return false;\n";
1128 }).endl();
1129 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -08001130 for (const auto &field : *mFields) {
Yifan Hong45b331b2017-03-27 12:59:54 -07001131 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -08001132 ? "this." + field->name() + " != other." + field->name()
Yifan Hong45b331b2017-03-27 12:59:54 -07001133 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -08001134 + ", other." + field->name() + ")");
1135 out.sIf(condition, [&] {
1136 out << "return false;\n";
1137 }).endl();
1138 }
1139 out << "return true;\n";
1140 }).endl().endl();
1141
Yifan Hong7d1839f2017-02-22 13:24:29 -08001142 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -08001143 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001144 out << "return java.util.Objects.hash(\n";
1145 out.indent(2, [&] {
Yifan Hong932464e2017-03-30 15:40:22 -07001146 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong45b331b2017-03-27 12:59:54 -07001147 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong932464e2017-03-30 15:40:22 -07001148 });
Yifan Hong7d1839f2017-02-22 13:24:29 -08001149 });
Yifan Hongec102272016-12-20 18:10:07 -08001150 out << ");\n";
1151 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -07001152 } else {
1153 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -08001154 }
1155
1156 ////////////////////////////////////////////////////////////////////////////
1157
Yifan Honge45b5302017-02-22 10:49:07 -08001158 out << "@Override\npublic final String toString() ";
1159 out.block([&] {
1160 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
1161 << "builder.append(\"{\");\n";
1162 for (const auto &field : *mFields) {
1163 out << "builder.append(\"";
1164 if (field != *(mFields->begin())) {
1165 out << ", ";
1166 }
1167 out << "." << field->name() << " = \");\n";
1168 field->type().emitJavaDump(out, "builder", "this." + field->name());
1169 }
1170 out << "builder.append(\"}\");\nreturn builder.toString();\n";
1171 }).endl().endl();
1172
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001173 size_t structAlign, structSize;
1174 getAlignmentAndSize(&structAlign, &structSize);
1175
Yifan Honge45b5302017-02-22 10:49:07 -08001176 ////////////////////////////////////////////////////////////////////////////
1177
Yifan Hong1af73532016-11-09 14:32:58 -08001178 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001179 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +08001180 if (containsInterface()) {
1181 for (const auto& field : *mFields) {
1182 out << field->name() << " = ";
1183 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
1184 }
1185 } else {
1186 out << "android.os.HwBlob blob = parcel.readBuffer(";
1187 out << structSize << "/* size */);\n";
1188 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
1189 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001190 out.unindent();
1191 out << "}\n\n";
1192
Andreas Huberf630bc82016-09-09 14:52:25 -07001193 ////////////////////////////////////////////////////////////////////////////
1194
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001195 size_t vecAlign, vecSize;
1196 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
1197
Howard Chenaf084db2017-12-27 18:46:39 +08001198 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -08001199 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001200 out.indent();
1201
Howard Chenaf084db2017-12-27 18:46:39 +08001202 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001203
Howard Chenaf084db2017-12-27 18:46:39 +08001204 if (containsInterface()) {
1205 out << "int size = parcel.readInt32();\n";
1206 out << "for(int i = 0 ; i < size; i ++) {\n";
1207 out.indent();
1208 out << fullJavaName() << " tmp = ";
1209 emitJavaReaderWriter(out, "parcel", "tmp", true);
1210 out << "_hidl_vec.add(tmp);\n";
1211 out.unindent();
1212 out << "}\n";
1213 } else {
1214 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
1215 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001216
Howard Chenaf084db2017-12-27 18:46:39 +08001217 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1218 "_hidl_blob", "_hidl_vec", "0",
1219 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001220 }
Howard Chenaf084db2017-12-27 18:46:39 +08001221 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001222 out.unindent();
1223 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001224 ////////////////////////////////////////////////////////////////////////////
1225 if (containsInterface()) {
1226 out << "// readEmbeddedFromParcel is not generated()\n";
1227 } else {
1228 out << "public final void readEmbeddedFromParcel(\n";
1229 out.indent(2);
1230 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1231 out.unindent();
1232 size_t offset = 0;
1233 for (const auto& field : *mFields) {
1234 size_t fieldAlign, fieldSize;
1235 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1236
Nirav Atre0ab82652018-06-04 11:49:14 -07001237 offset += Layout::getPad(offset, fieldAlign);
Howard Chenaf084db2017-12-27 18:46:39 +08001238
1239 field->type().emitJavaFieldReaderWriter(
1240 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1241 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1242 offset += fieldSize;
1243 }
1244 out.unindent();
1245 out << "}\n\n";
1246 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001247
Andreas Huberf630bc82016-09-09 14:52:25 -07001248 ////////////////////////////////////////////////////////////////////////////
1249
Yifan Hong1af73532016-11-09 14:32:58 -08001250 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001251 out.indent();
1252
Howard Chenaf084db2017-12-27 18:46:39 +08001253 if (containsInterface()) {
1254 for (const auto& field : *mFields) {
1255 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
1256 }
1257 } else {
1258 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << structSize
1259 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001260
Howard Chenaf084db2017-12-27 18:46:39 +08001261 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
1262 << "parcel.writeBuffer(_hidl_blob);\n";
1263 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001264 out.unindent();
1265 out << "}\n\n";
1266
Andreas Huberf630bc82016-09-09 14:52:25 -07001267 ////////////////////////////////////////////////////////////////////////////
1268
Andreas Huberf630bc82016-09-09 14:52:25 -07001269 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001270 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +08001271 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001272 out.unindent();
1273
Howard Chenaf084db2017-12-27 18:46:39 +08001274 if (containsInterface()) {
1275 out << "parcel.writeInt32(_hidl_vec.size());\n";
1276 out << "for(" << fullJavaName() << " tmp: _hidl_vec)\n";
1277 out.indent();
1278 emitJavaReaderWriter(out, "parcel", "tmp", false);
1279 out.unindent();
1280 } else {
1281 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
1282 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001283
Howard Chenaf084db2017-12-27 18:46:39 +08001284 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1285 "_hidl_blob", "_hidl_vec", "0",
1286 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -07001287
Howard Chenaf084db2017-12-27 18:46:39 +08001288 out << "\nparcel.writeBuffer(_hidl_blob);\n";
1289 }
Andreas Huberf630bc82016-09-09 14:52:25 -07001290 out.unindent();
1291 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001292 ////////////////////////////////////////////////////////////////////////////
1293
Howard Chenaf084db2017-12-27 18:46:39 +08001294 if (containsInterface()) {
1295 out << "// writeEmbeddedFromParcel() is not generated\n";
1296 } else {
1297 out << "public final void writeEmbeddedToBlob(\n";
1298 out.indent(2);
1299 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1300 out.unindent();
1301 size_t offset = 0;
1302 for (const auto& field : *mFields) {
1303 size_t fieldAlign, fieldSize;
1304 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre0ab82652018-06-04 11:49:14 -07001305
1306 offset += Layout::getPad(offset, fieldAlign);
1307
Howard Chenaf084db2017-12-27 18:46:39 +08001308 field->type().emitJavaFieldReaderWriter(
1309 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1310 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1311 offset += fieldSize;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001312 }
1313
Howard Chenaf084db2017-12-27 18:46:39 +08001314 out.unindent();
1315 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001316 }
1317
1318 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001319 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001320}
1321
Andreas Huber881227d2016-08-02 14:20:21 -07001322void CompoundType::emitStructReaderWriter(
1323 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001324
1325 std::string space = prefix.empty() ? "" : (prefix + "::");
1326
Andreas Huber881227d2016-08-02 14:20:21 -07001327 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -08001328 << (isReader ? "readEmbeddedFromParcel"
1329 : "writeEmbeddedToParcel")
1330 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001331
Yifan Hong0a68a282016-10-21 16:32:34 -07001332 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001333
Yifan Hong244e82d2016-11-11 11:13:57 -08001334 bool useName = false;
1335 for (const auto &field : *mFields) {
1336 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
1337 useName = true;
1338 break;
1339 }
1340 }
1341 std::string name = useName ? "obj" : "/* obj */";
1342 // if not useName, then obj should not be used at all,
1343 // then the #error should not be emitted.
1344 std::string error = useName ? "" : "\n#error\n";
1345
Andreas Huber881227d2016-08-02 14:20:21 -07001346 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001347 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001348 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001349 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001350 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001351 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001352 }
1353
1354 out << "size_t parentHandle,\n"
1355 << "size_t parentOffset)";
1356
Andreas Huber881227d2016-08-02 14:20:21 -07001357 out << " {\n";
1358
Yifan Hong0a68a282016-10-21 16:32:34 -07001359 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001360 out.indent();
1361
Iliyan Malchev549e2592016-08-10 08:59:12 -07001362 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001363
Nirav Atre0ab82652018-06-04 11:49:14 -07001364 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1365 out << "switch (" << name << ".getDiscriminator()) {\n";
1366 out.indent();
1367 }
1368
Andreas Huber881227d2016-08-02 14:20:21 -07001369 for (const auto &field : *mFields) {
1370 if (!field->type().needsEmbeddedReadWrite()) {
1371 continue;
1372 }
1373
Nirav Atre0ab82652018-06-04 11:49:14 -07001374 if (mStyle == STYLE_SAFE_UNION) {
1375 out << "case " << fullName() << "::hidl_discriminator::"
1376 << field->name() << ": {\n";
1377 out.indent();
1378 }
1379
1380 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
1381 ? (name + "." + field->name() + "()" + error)
1382 : (name + "." + field->name() + error);
1383
1384 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001385 ? (name + ".hidl_getUnionOffset() " +
1386 "/* safe_union: union offset into struct */")
Nirav Atre0ab82652018-06-04 11:49:14 -07001387 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1388
Andreas Huber881227d2016-08-02 14:20:21 -07001389 field->type().emitReaderWriterEmbedded(
1390 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -07001391 0 /* depth */,
Nirav Atre0ab82652018-06-04 11:49:14 -07001392 fieldName,
Yifan Hongbe2a3732016-10-05 13:33:41 -07001393 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -07001394 false /* nameIsPointer */,
1395 "parcel",
1396 !isReader /* parcelObjIsPointer */,
1397 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -07001398 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -07001399 "parentHandle",
Nirav Atre0ab82652018-06-04 11:49:14 -07001400 "parentOffset + " + fieldOffset);
1401
1402 if (mStyle == STYLE_SAFE_UNION) {
1403 out << "break;\n";
1404 out.unindent();
1405 out << "}\n";
1406 }
1407 }
1408
1409 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1410 out << "default: { break; }\n";
1411 out.unindent();
1412 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001413 }
1414
Iliyan Malchev549e2592016-08-10 08:59:12 -07001415 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001416
1417 out.unindent();
1418 out << "}\n\n";
1419}
1420
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -07001421void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
1422 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001423 out << "::android::status_t ";
1424 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -07001425
1426 bool useParent = false;
1427 for (const auto &field : *mFields) {
1428 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
1429 useParent = true;
1430 break;
1431 }
1432 }
1433
1434 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
1435 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
1436
Yifan Hongbf459bc2016-08-23 16:50:37 -07001437 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -08001438 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001439 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001440 out << space + localName() + " *obj,\n"
1441 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001442 << "size_t " << parentHandleName << ", "
1443 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001444 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001445 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001446 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001447 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001448 out << "const " << space + localName() + " &obj,\n"
1449 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001450 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -08001451 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001452 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001453 }
1454
1455 out << " {\n";
1456
1457 out.indent();
1458
1459 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
1460
Yifan Hong244e82d2016-11-11 11:13:57 -08001461 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -07001462 // if not useParent, then parentName and offsetText
1463 // should not be used at all, then the #error should not be emitted.
1464 std::string error = useParent ? "" : "\n#error\n";
1465
Nirav Atre0ab82652018-06-04 11:49:14 -07001466 if (mStyle == STYLE_SAFE_UNION) {
1467 out << "switch (" << nameDeref << "getDiscriminator()) {\n";
1468 out.indent();
1469 }
1470
Yifan Hongbf459bc2016-08-23 16:50:37 -07001471 for (const auto &field : *mFields) {
1472 if (!field->type().needsResolveReferences()) {
1473 continue;
1474 }
1475
Nirav Atre0ab82652018-06-04 11:49:14 -07001476 if (mStyle == STYLE_SAFE_UNION) {
1477 out << "case " << fullName() << "::hidl_discriminator::"
1478 << field->name() << ": {\n";
1479 out.indent();
1480 }
1481
1482 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
1483 ? (nameDeref + field->name() + "()")
1484 : (nameDeref + field->name());
1485
1486 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001487 ? (nameDeref + "hidl_getUnionOffset() " +
1488 "/* safe_union: union offset into struct */")
Nirav Atre0ab82652018-06-04 11:49:14 -07001489 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1490
Yifan Hongbf459bc2016-08-23 16:50:37 -07001491 field->type().emitResolveReferencesEmbedded(
1492 out,
1493 0 /* depth */,
Nirav Atre0ab82652018-06-04 11:49:14 -07001494 fieldName,
Yifan Hongbf459bc2016-08-23 16:50:37 -07001495 field->name() /* sanitizedName */,
1496 false, // nameIsPointer
1497 "parcel", // const std::string &parcelObj,
1498 !isReader, // bool parcelObjIsPointer,
1499 isReader, // bool isReader,
1500 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07001501 parentHandleName + error,
1502 parentOffsetName
Nirav Atre0ab82652018-06-04 11:49:14 -07001503 + " + "
1504 + fieldOffset
Yifan Hong00f47172016-09-30 14:40:45 -07001505 + error);
Nirav Atre0ab82652018-06-04 11:49:14 -07001506
1507 if (mStyle == STYLE_SAFE_UNION) {
1508 out << "break;\n";
1509 out.unindent();
1510 out << "}\n";
1511 }
1512 }
1513
1514 if (mStyle == STYLE_SAFE_UNION) {
1515 out << "default: { _hidl_err = ::android::BAD_VALUE; break; }\n";
1516 out.unindent();
1517 out << "}\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -07001518 }
1519
Yifan Hongbf459bc2016-08-23 16:50:37 -07001520 out << "return _hidl_err;\n";
1521
1522 out.unindent();
1523 out << "}\n\n";
1524}
1525
Andreas Huber881227d2016-08-02 14:20:21 -07001526bool CompoundType::needsEmbeddedReadWrite() const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001527 if (mStyle == STYLE_UNION) {
Andreas Huber881227d2016-08-02 14:20:21 -07001528 return false;
1529 }
1530
1531 for (const auto &field : *mFields) {
1532 if (field->type().needsEmbeddedReadWrite()) {
1533 return true;
1534 }
1535 }
1536
1537 return false;
1538}
1539
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001540bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001541 if (mStyle == STYLE_UNION) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001542 return false;
1543 }
1544
1545 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001546 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001547 return true;
1548 }
1549 }
1550
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001551 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001552}
1553
Andreas Huber881227d2016-08-02 14:20:21 -07001554bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08001555 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07001556}
1557
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001558void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001559 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001560 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001561
1562 // Emit declaration for each subtype.
1563 for (const auto &type : getSubTypes()) {
1564 switch (mStyle) {
1565 case STYLE_STRUCT:
1566 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001567 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001568 break;
1569 }
1570 case STYLE_UNION:
1571 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001572 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001573 break;
1574 }
Nirav Atre0ab82652018-06-04 11:49:14 -07001575 case STYLE_SAFE_UNION:
1576 {
1577 out << "sub_safe_union: {\n";
1578 break;
1579 }
1580 default:
1581 {
1582 CHECK(!"Should not be here");
1583 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001584 }
1585 out.indent();
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001586 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001587 out.unindent();
1588 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001589 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001590
1591 // Emit declaration for each field.
1592 for (const auto &field : *mFields) {
1593 switch (mStyle) {
1594 case STYLE_STRUCT:
1595 {
1596 out << "struct_value: {\n";
1597 break;
1598 }
1599 case STYLE_UNION:
1600 {
1601 out << "union_value: {\n";
1602 break;
1603 }
Nirav Atre0ab82652018-06-04 11:49:14 -07001604 case STYLE_SAFE_UNION:
1605 {
1606 out << "safe_union_value: {\n";
1607 break;
1608 }
1609 default:
1610 {
1611 CHECK(!"Should not be here");
1612 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001613 }
1614 out.indent();
1615 out << "name: \"" << field->name() << "\"\n";
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001616 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001617 out.unindent();
1618 out << "}\n";
1619 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001620}
1621
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001622void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001623 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001624 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001625}
1626
Nirav Atre89463bd2018-06-12 21:33:31 -07001627void CompoundType::emitTypeDestructorCall(Formatter& out, const std::string& objName) const {
1628 out << objName << ".~" << localName() << "();\n";
1629}
1630
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001631bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001632 if (mStyle != STYLE_STRUCT) { // TODO(natre): Update
Andreas Huber0fa9e392016-08-31 09:05:44 -07001633 return false;
1634 }
1635
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001636 for (const auto* field : *mFields) {
1637 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001638 return false;
1639 }
1640 }
1641
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001642 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001643}
1644
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001645bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
1646 for (const auto* field : *mFields) {
1647 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07001648 return true;
1649 }
1650 }
1651
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001652 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07001653}
1654
Andreas Huber85eabdb2016-08-25 11:24:49 -07001655void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001656 CompoundLayout layout = getCompoundAlignmentAndSize();
1657 *align = layout.overall.align;
1658 *size = layout.overall.size;
1659}
Andreas Huber85eabdb2016-08-25 11:24:49 -07001660
Nirav Atre0ab82652018-06-04 11:49:14 -07001661CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const {
1662 CompoundLayout compoundLayout;
1663
1664 // Local aliases for convenience
1665 Layout& overall = compoundLayout.overall;
1666 Layout& innerStruct = compoundLayout.innerStruct;
1667 Layout& discriminator = compoundLayout.discriminator;
1668
Nirav Atre12c597a2018-06-28 09:35:24 -07001669 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1670 getUnionDiscriminatorType()->getAlignmentAndSize(
1671 &(discriminator.align), &(discriminator.size));
1672
1673 innerStruct.offset = discriminator.size;
1674 }
1675
Andreas Huber85eabdb2016-08-25 11:24:49 -07001676 for (const auto &field : *mFields) {
Nirav Atre0ab82652018-06-04 11:49:14 -07001677
Andreas Huber85eabdb2016-08-25 11:24:49 -07001678 // Each field is aligned according to its alignment requirement.
1679 // The surrounding structure's alignment is the maximum of its
1680 // fields' aligments.
Andreas Huber85eabdb2016-08-25 11:24:49 -07001681 size_t fieldAlign, fieldSize;
1682 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre0ab82652018-06-04 11:49:14 -07001683 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001684
Nirav Atre0ab82652018-06-04 11:49:14 -07001685 innerStruct.size = (mStyle == STYLE_STRUCT)
1686 ? (innerStruct.size + lPad + fieldSize)
1687 : std::max(innerStruct.size, fieldSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001688
Nirav Atre0ab82652018-06-04 11:49:14 -07001689 innerStruct.align = std::max(innerStruct.align, fieldAlign);
1690 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001691
Nirav Atre12c597a2018-06-28 09:35:24 -07001692 // Pad the inner structure's size
Nirav Atre0ab82652018-06-04 11:49:14 -07001693 innerStruct.size += Layout::getPad(innerStruct.size,
1694 innerStruct.align);
1695
Nirav Atre12c597a2018-06-28 09:35:24 -07001696 // Compute its final offset
1697 innerStruct.offset += Layout::getPad(innerStruct.offset,
1698 innerStruct.align);
Nirav Atre0ab82652018-06-04 11:49:14 -07001699
Nirav Atre12c597a2018-06-28 09:35:24 -07001700 overall.size = innerStruct.offset + innerStruct.size;
Nirav Atre0ab82652018-06-04 11:49:14 -07001701
1702 // An empty struct/union still occupies a byte of space in C++.
1703 if (overall.size == 0) {
1704 overall.size = 1;
1705 }
1706
Nirav Atre12c597a2018-06-28 09:35:24 -07001707 // Pad the overall structure's size
Nirav Atre0ab82652018-06-04 11:49:14 -07001708 overall.align = std::max(innerStruct.align, discriminator.align);
1709 overall.size += Layout::getPad(overall.size, overall.align);
1710
1711 return compoundLayout;
1712}
1713
1714std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
1715 static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
1716 {8, ScalarType::Kind::KIND_UINT8},
1717 {16, ScalarType::Kind::KIND_UINT16},
1718 {32, ScalarType::Kind::KIND_UINT32},
1719 };
1720
1721 size_t numFields = mFields->size() + 1; // +1 for no_init
1722 auto kind = ScalarType::Kind::KIND_UINT64;
1723
1724 for (const auto& scalar : scalars) {
1725 if (numFields <= (1ULL << scalar.first)) {
1726 kind = scalar.second; break;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001727 }
1728 }
1729
Nirav Atre0ab82652018-06-04 11:49:14 -07001730 return std::unique_ptr<ScalarType>(new ScalarType(kind, NULL));
1731}
Andreas Huber85eabdb2016-08-25 11:24:49 -07001732
Nirav Atre0ab82652018-06-04 11:49:14 -07001733size_t CompoundType::Layout::getPad(size_t offset, size_t align) {
1734 size_t remainder = offset % align;
1735 return (remainder > 0) ? (align - remainder) : 0;
Andreas Huber70a59e12016-08-16 12:57:01 -07001736}
1737
Andreas Huberc9410c72016-07-28 12:18:40 -07001738} // namespace android
1739