1 /*
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
17 #include "EnumType.h"
18
19 #include <hidl-util/Formatter.h>
20 #include <inttypes.h>
21 #include <iostream>
22 #include <string>
23 #include <unordered_map>
24
25 #include "Annotation.h"
26 #include "Location.h"
27 #include "ScalarType.h"
28
29 namespace android {
30
EnumType(const std::string & localName,const FQName & fullName,const Location & location,const Reference<Type> & storageType,Scope * parent)31 EnumType::EnumType(const std::string& localName, const FQName& fullName, const Location& location,
32 const Reference<Type>& storageType, Scope* parent)
33 : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {}
34
storageType() const35 const Type *EnumType::storageType() const {
36 return mStorageType.get();
37 }
38
values() const39 const std::vector<EnumValue *> &EnumType::values() const {
40 return mValues;
41 }
42
forEachValueFromRoot(const std::function<void (const EnumValue *)> f) const43 void EnumType::forEachValueFromRoot(const std::function<void(const EnumValue*)> f) const {
44 std::vector<const EnumType*> chain = typeChain();
45 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
46 const auto& type = *it;
47 for (const EnumValue* v : type->values()) {
48 f(v);
49 }
50 }
51 }
52
numValueNames() const53 size_t EnumType::numValueNames() const {
54 size_t count = 0;
55 for (const auto it : typeChain()) {
56 count += it->values().size();
57 }
58 return count;
59 }
60
addValue(EnumValue * value)61 void EnumType::addValue(EnumValue* value) {
62 CHECK(value != nullptr);
63 mValues.push_back(value);
64 }
65
resolveInheritance()66 status_t EnumType::resolveInheritance() {
67 const EnumType* prevType = nullptr;
68 EnumValue* prevValue = nullptr;
69
70 for (const auto* type : superTypeChain()) {
71 if (!type->values().empty()) {
72 prevType = type;
73 prevValue = type->values().back();
74 break;
75 }
76 }
77
78 for (auto* value : mValues) {
79 value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
80 prevType = this;
81 prevValue = value;
82 }
83
84 return Scope::resolveInheritance();
85 }
86
getReferences() const87 std::vector<const Reference<Type>*> EnumType::getReferences() const {
88 return {&mStorageType};
89 }
90
getConstantExpressions() const91 std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
92 std::vector<const ConstantExpression*> ret;
93 for (const auto* value : mValues) {
94 ret.push_back(value->constExpr());
95 }
96 return ret;
97 }
98
validate() const99 status_t EnumType::validate() const {
100 CHECK(getSubTypes().empty());
101
102 if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
103 std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
104 << ") specified at " << mStorageType.location() << "\n";
105 return UNKNOWN_ERROR;
106 }
107
108 status_t err = validateUniqueNames();
109 if (err != OK) return err;
110
111 return Scope::validate();
112 }
113
validateUniqueNames() const114 status_t EnumType::validateUniqueNames() const {
115 std::unordered_map<std::string, const EnumType*> registeredValueNames;
116 for (const auto* type : superTypeChain()) {
117 for (const auto* enumValue : type->mValues) {
118 // No need to check super value uniqueness
119 registeredValueNames[enumValue->name()] = type;
120 }
121 }
122
123 for (const auto* value : mValues) {
124 auto registered = registeredValueNames.find(value->name());
125
126 if (registered != registeredValueNames.end()) {
127 const EnumType* definedInType = registered->second;
128
129 if (definedInType == this) {
130 // Defined in this enum
131 std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
132 } else {
133 // Defined in super enum
134 std::cerr << "ERROR: Redefinition of value '" << value->name()
135 << "' defined in enum '" << definedInType->fullName() << "'";
136 }
137 std::cerr << " at " << value->location() << "\n";
138 return UNKNOWN_ERROR;
139 }
140
141 registeredValueNames[value->name()] = this;
142 }
143
144 return OK;
145 }
146
isElidableType() const147 bool EnumType::isElidableType() const {
148 return mStorageType->isElidableType();
149 }
150
resolveToScalarType() const151 const ScalarType *EnumType::resolveToScalarType() const {
152 return mStorageType->resolveToScalarType();
153 }
154
typeName() const155 std::string EnumType::typeName() const {
156 return "enum " + definedName();
157 }
158
isEnum() const159 bool EnumType::isEnum() const {
160 return true;
161 }
162
deepCanCheckEquality(std::unordered_set<const Type * > *) const163 bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
164 return true;
165 }
166
getCppType(StorageMode,bool) const167 std::string EnumType::getCppType(StorageMode,
168 bool /* specifyNamespaces */) const {
169 return fullName();
170 }
171
getJavaType(bool forInitializer) const172 std::string EnumType::getJavaType(bool forInitializer) const {
173 return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
174 }
175
getJavaSuffix() const176 std::string EnumType::getJavaSuffix() const {
177 return mStorageType->resolveToScalarType()->getJavaSuffix();
178 }
179
getJavaTypeClass() const180 std::string EnumType::getJavaTypeClass() const {
181 return mStorageType->resolveToScalarType()->getJavaTypeClass();
182 }
183
getVtsType() const184 std::string EnumType::getVtsType() const {
185 return "TYPE_ENUM";
186 }
187
getBitfieldCppType(StorageMode,bool specifyNamespaces) const188 std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
189 const std::string space = specifyNamespaces ? "::android::hardware::" : "";
190 return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : definedName()) + ">";
191 }
192
getBitfieldJavaType(bool forInitializer) const193 std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
194 return resolveToScalarType()->getJavaType(forInitializer);
195 }
196
getBitfieldJavaTypeClass() const197 std::string EnumType::getBitfieldJavaTypeClass() const {
198 return resolveToScalarType()->getJavaTypeClass();
199 }
200
lookupIdentifier(const std::string & name) const201 LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
202 std::vector<const EnumType*> chain = typeChain();
203 for (auto it = chain.begin(); it != chain.end(); ++it) {
204 const auto &type = *it;
205 for(EnumValue *v : type->values()) {
206 if(v->name() == name) {
207 return v;
208 }
209 }
210 }
211 return nullptr;
212 }
213
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const214 void EnumType::emitJavaFieldInitializer(Formatter& out, const std::string& fieldName) const {
215 mStorageType->resolveToScalarType()->emitJavaFieldInitializer(out, fieldName);
216 }
217
emitJavaFieldDefaultInitialValue(Formatter & out,const std::string & fieldName) const218 void EnumType::emitJavaFieldDefaultInitialValue(Formatter& out,
219 const std::string& fieldName) const {
220 mStorageType->resolveToScalarType()->emitJavaFieldDefaultInitialValue(out, fieldName);
221 }
222
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const223 void EnumType::emitReaderWriter(
224 Formatter &out,
225 const std::string &name,
226 const std::string &parcelObj,
227 bool parcelObjIsPointer,
228 bool isReader,
229 ErrorMode mode) const {
230 const ScalarType *scalarType = mStorageType->resolveToScalarType();
231 CHECK(scalarType != nullptr);
232
233 scalarType->emitReaderWriterWithCast(
234 out,
235 name,
236 parcelObj,
237 parcelObjIsPointer,
238 isReader,
239 mode,
240 true /* needsCast */);
241 }
242
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const243 void EnumType::emitJavaFieldReaderWriter(
244 Formatter &out,
245 size_t depth,
246 const std::string &parcelName,
247 const std::string &blobName,
248 const std::string &fieldName,
249 const std::string &offset,
250 bool isReader) const {
251 return mStorageType->emitJavaFieldReaderWriter(
252 out, depth, parcelName, blobName, fieldName, offset, isReader);
253 }
254
emitHidlDefinition(Formatter & out) const255 void EnumType::emitHidlDefinition(Formatter& out) const {
256 if (getDocComment() != nullptr) getDocComment()->emit(out);
257
258 if (annotations().size() != 0) {
259 out.join(annotations().begin(), annotations().end(), " ",
260 [&](auto annotation) { annotation->dump(out); });
261 out << "\n";
262 }
263
264 out << typeName() << " : " << mStorageType.localName() << " {\n";
265
266 out.indent([&] {
267 for (const EnumValue* val : mValues) {
268 if (val->getDocComment() != nullptr) val->getDocComment()->emit(out);
269 out << val->name();
270 if (!val->isAutoFill()) {
271 out << " = " << val->constExpr()->expression();
272 }
273 out << ",\n";
274 }
275 });
276
277 out << "};\n";
278 }
279
emitTypeDeclarations(Formatter & out) const280 void EnumType::emitTypeDeclarations(Formatter& out) const {
281 const ScalarType *scalarType = mStorageType->resolveToScalarType();
282 CHECK(scalarType != nullptr);
283
284 const std::string storageType = scalarType->getCppStackType();
285
286 out << "enum class " << definedName() << " : " << storageType << " {\n";
287
288 out.indent();
289
290 std::vector<const EnumType*> chain = typeChain();
291
292 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
293 const auto &type = *it;
294
295 for (const auto &entry : type->values()) {
296 entry->emitDocComment(out);
297
298 out << entry->name();
299
300 std::string value = entry->cppValue(scalarType->getKind());
301 CHECK(!value.empty()); // use autofilled values for c++.
302 out << " = " << value << ",\n";
303 }
304 }
305
306 out.unindent();
307 out << "};\n\n";
308 }
309
emitTypeForwardDeclaration(Formatter & out) const310 void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
311 const ScalarType* scalarType = mStorageType->resolveToScalarType();
312 const std::string storageType = scalarType->getCppStackType();
313
314 out << "enum class " << definedName() << " : " << storageType << ";\n";
315 }
316
emitIteratorDeclaration(Formatter & out) const317 void EnumType::emitIteratorDeclaration(Formatter& out) const {
318 size_t elementCount = 0;
319 for (const auto* type : typeChain()) {
320 elementCount += type->mValues.size();
321 }
322
323 // TODO(pcc): Remove the pragmas once all users of the hidl headers have
324 // been moved to C++17.
325 out << "#pragma clang diagnostic push\n";
326 out << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
327
328 out << "template<> inline constexpr std::array<" << getCppStackType() << ", " << elementCount
329 << "> hidl_enum_values<" << getCppStackType() << "> = ";
330 out.block([&] {
331 auto enumerators = typeChain();
332 std::reverse(enumerators.begin(), enumerators.end());
333 for (const auto* type : enumerators) {
334 for (const auto* enumValue : type->mValues) {
335 out << fullName() << "::" << enumValue->name() << ",\n";
336 }
337 }
338 }) << ";\n";
339
340 out << "#pragma clang diagnostic pop\n";
341 }
342
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const343 void EnumType::emitEnumBitwiseOperator(
344 Formatter &out,
345 bool lhsIsEnum,
346 bool rhsIsEnum,
347 const std::string &op) const {
348 const ScalarType *scalarType = mStorageType->resolveToScalarType();
349 CHECK(scalarType != nullptr);
350
351 const std::string storageType = scalarType->getCppStackType();
352
353 out << "constexpr "
354 << storageType
355 << " operator"
356 << op
357 << "(const "
358 << (lhsIsEnum ? fullName() : storageType)
359 << " lhs, const "
360 << (rhsIsEnum ? fullName() : storageType)
361 << " rhs) {\n";
362
363 out.indent([&] {
364 out << "return static_cast<"
365 << storageType
366 << ">(";
367
368 if (lhsIsEnum) {
369 out << "static_cast<"
370 << storageType
371 << ">(lhs)";
372 } else {
373 out << "lhs";
374 }
375 out << " " << op << " ";
376 if (rhsIsEnum) {
377 out << "static_cast<"
378 << storageType
379 << ">(rhs)";
380 } else {
381 out << "rhs";
382 }
383 out << ");\n";
384 });
385
386 out << "}\n";
387 }
388
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const389 void EnumType::emitBitFieldBitwiseAssignmentOperator(
390 Formatter &out,
391 const std::string &op) const {
392 const ScalarType *scalarType = mStorageType->resolveToScalarType();
393 CHECK(scalarType != nullptr);
394
395 const std::string storageType = scalarType->getCppStackType();
396
397 out << "constexpr " << storageType << " &operator" << op << "=("
398 << storageType << "& v, const " << fullName() << " e) {\n";
399
400 out.indent([&] {
401 out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
402 out << "return v;\n";
403 });
404
405 out << "}\n";
406 }
407
emitGlobalTypeDeclarations(Formatter & out) const408 void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
409 out << "namespace android {\n";
410 out << "namespace hardware {\n";
411 out << "namespace details {\n";
412
413 emitIteratorDeclaration(out);
414
415 out << "} // namespace details\n";
416 out << "} // namespace hardware\n";
417 out << "} // namespace android\n\n";
418 }
419
emitPackageTypeDeclarations(Formatter & out) const420 void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
421 out << "template<typename>\n"
422 << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
423 << " o);\n";
424 out << "static inline std::string toString(" << getCppArgumentType() << " o);\n";
425 out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os);\n";
426
427 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|");
428 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|");
429 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|");
430 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&");
431 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&");
432 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&");
433
434 emitBitFieldBitwiseAssignmentOperator(out, "|");
435 emitBitFieldBitwiseAssignmentOperator(out, "&");
436
437 out.endl();
438 }
439
emitPackageTypeHeaderDefinitions(Formatter & out) const440 void EnumType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
441 const ScalarType *scalarType = mStorageType->resolveToScalarType();
442 CHECK(scalarType != nullptr);
443
444 out << "template<>\n"
445 << "inline std::string toString<" << getCppStackType() << ">("
446 << scalarType->getCppArgumentType() << " o) ";
447 out.block([&] {
448 // include toHexString for scalar types
449 out << "using ::android::hardware::details::toHexString;\n"
450 << "std::string os;\n"
451 << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
452 << "bool first = true;\n";
453 forEachValueFromRoot([&](const EnumValue* value) {
454 std::string valueName = fullName() + "::" + value->name();
455 out.sIf("(o & " + valueName + ")" +
456 " == static_cast<" + scalarType->getCppStackType() +
457 ">(" + valueName + ")", [&] {
458 out << "os += (first ? \"\" : \" | \");\n"
459 << "os += \"" << value->name() << "\";\n"
460 << "first = false;\n"
461 << "flipped |= " << valueName << ";\n";
462 }).endl();
463 });
464 // put remaining bits
465 out.sIf("o != flipped", [&] {
466 out << "os += (first ? \"\" : \" | \");\n";
467 scalarType->emitHexDump(out, "os", "o & (~flipped)");
468 });
469 out << "os += \" (\";\n";
470 scalarType->emitHexDump(out, "os", "o");
471 out << "os += \")\";\n";
472
473 out << "return os;\n";
474 }).endl().endl();
475
476 out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
477
478 out.block([&] {
479 out << "using ::android::hardware::details::toHexString;\n";
480 forEachValueFromRoot([&](const EnumValue* value) {
481 out.sIf("o == " + fullName() + "::" + value->name(), [&] {
482 out << "return \"" << value->name() << "\";\n";
483 }).endl();
484 });
485 out << "std::string os;\n";
486 scalarType->emitHexDump(out, "os",
487 "static_cast<" + scalarType->getCppStackType() + ">(o)");
488 out << "return os;\n";
489 }).endl().endl();
490
491 out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os) ";
492
493 out.block([&] { out << "*os << toString(o);\n"; }).endl().endl();
494 }
495
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const496 void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
497 const ScalarType *scalarType = mStorageType->resolveToScalarType();
498 CHECK(scalarType != nullptr);
499
500 out << "public " << (atTopLevel ? "" : "static ") << "final class " << definedName() << " {\n";
501
502 out.indent();
503
504 const std::string typeName =
505 scalarType->getJavaType(false /* forInitializer */);
506
507 std::vector<const EnumType*> chain = typeChain();
508
509 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
510 const auto &type = *it;
511
512 for (const auto &entry : type->values()) {
513 entry->emitDocComment(out);
514
515 out << "public static final "
516 << typeName
517 << " "
518 << entry->name()
519 << " = ";
520
521 // javaValue will make the number signed.
522 std::string value = entry->javaValue(scalarType->getKind());
523 CHECK(!value.empty()); // use autofilled values for java.
524 out << value << ";\n";
525 }
526 }
527
528 out << "public static final String toString("
529 << typeName << " o) ";
530 out.block([&] {
531 forEachValueFromRoot([&](const EnumValue* value) {
532 out.sIf("o == " + value->name(), [&] {
533 out << "return \"" << value->name() << "\";\n";
534 }).endl();
535 });
536 out << "return \"0x\" + ";
537 scalarType->emitConvertToJavaHexString(out, "o");
538 out << ";\n";
539 }).endl();
540
541 auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
542 out << "\n"
543 << "public static final String dumpBitfield("
544 << bitfieldType << " o) ";
545 out.block([&] {
546 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
547 out << bitfieldType << " flipped = 0;\n";
548 forEachValueFromRoot([&](const EnumValue* value) {
549 if (value->constExpr()->castSizeT() == 0) {
550 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
551 return; // continue to next value
552 }
553 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
554 out << "list.add(\"" << value->name() << "\");\n";
555 out << "flipped |= " << value->name() << ";\n";
556 }).endl();
557 });
558 // put remaining bits
559 out.sIf("o != flipped", [&] {
560 out << "list.add(\"0x\" + ";
561 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
562 out << ");\n";
563 }).endl();
564 out << "return String.join(\" | \", list);\n";
565 }).endl().endl();
566
567 out.unindent();
568 out << "};\n\n";
569 }
570
emitVtsTypeDeclarations(Formatter & out) const571 void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
572 const ScalarType *scalarType = mStorageType->resolveToScalarType();
573
574 out << "name: \"" << fullName() << "\"\n";
575 out << "type: " << getVtsType() << "\n";
576 out << "enum_value: {\n";
577 out.indent();
578
579 out << "scalar_type: \""
580 << scalarType->getVtsScalarType()
581 << "\"\n\n";
582 std::vector<const EnumType*> chain = typeChain();
583
584 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
585 const auto &type = *it;
586
587 for (const auto &entry : type->values()) {
588 out << "enumerator: \"" << entry->name() << "\"\n";
589 out << "scalar_value: {\n";
590 out.indent();
591 // use autofilled values for vts.
592 std::string value = entry->rawValue(scalarType->getKind());
593 CHECK(!value.empty());
594 out << mStorageType->resolveToScalarType()->getVtsScalarType()
595 << ": "
596 << value
597 << "\n";
598 out.unindent();
599 out << "}\n";
600 }
601 }
602
603 out.unindent();
604 out << "}\n";
605 }
606
emitVtsAttributeType(Formatter & out) const607 void EnumType::emitVtsAttributeType(Formatter& out) const {
608 out << "type: " << getVtsType() << "\n";
609 out << "predefined_type: \"" << fullName() << "\"\n";
610 }
611
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const612 void EnumType::emitJavaDump(
613 Formatter &out,
614 const std::string &streamName,
615 const std::string &name) const {
616 out << streamName << ".append(" << fqName().javaName() << ".toString("
617 << name << "));\n";
618 }
619
typeChain() const620 std::vector<const EnumType*> EnumType::typeChain() const {
621 std::vector<const EnumType*> types;
622 for (const EnumType* type = this; type != nullptr;) {
623 types.push_back(type);
624
625 const Type* superType = type->storageType();
626 if (superType != nullptr && superType->isEnum()) {
627 type = static_cast<const EnumType*>(superType);
628 } else {
629 type = nullptr;
630 }
631 }
632
633 return types;
634 }
635
superTypeChain() const636 std::vector<const EnumType*> EnumType::superTypeChain() const {
637 const Type* superType = storageType();
638 if (superType == nullptr || !superType->isEnum()) {
639 return {};
640 }
641 return static_cast<const EnumType*>(superType)->typeChain();
642 }
643
getAlignmentAndSize(size_t * align,size_t * size) const644 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
645 mStorageType->getAlignmentAndSize(align, size);
646 }
647
findExportAnnotation() const648 const Annotation *EnumType::findExportAnnotation() const {
649 for (const auto &annotation : annotations()) {
650 if (annotation->name() == "export") {
651 return annotation;
652 }
653 }
654
655 return nullptr;
656 }
657
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const658 void EnumType::appendToExportedTypesVector(
659 std::vector<const Type *> *exportedTypes) const {
660 if (findExportAnnotation() != nullptr) {
661 exportedTypes->push_back(this);
662 }
663 }
664
emitExportedHeader(Formatter & out,bool forJava) const665 void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
666 const Annotation *annotation = findExportAnnotation();
667 CHECK(annotation != nullptr);
668
669 std::string name = definedName();
670
671 const AnnotationParam *nameParam = annotation->getParam("name");
672 if (nameParam != nullptr) {
673 name = nameParam->getSingleString();
674 }
675
676 bool exportParent = true;
677 const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
678 if (exportParentParam != nullptr) {
679 exportParent = exportParentParam->getSingleBool();
680 }
681
682 std::string valuePrefix;
683 const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
684 if (prefixParam != nullptr) {
685 valuePrefix = prefixParam->getSingleString();
686 }
687
688 std::string valueSuffix;
689 const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
690 if (suffixParam != nullptr) {
691 valueSuffix = suffixParam->getSingleString();
692 }
693
694 const ScalarType *scalarType = mStorageType->resolveToScalarType();
695 CHECK(scalarType != nullptr);
696
697 std::vector<const EnumType *> chain;
698 if (exportParent) {
699 chain = typeChain();
700 } else {
701 chain = { this };
702 }
703
704 if (forJava) {
705 if (!name.empty()) {
706 out << "public final class "
707 << name
708 << " {\n";
709
710 out.indent();
711 } else {
712 out << "// Values declared in " << definedName() << " follow.\n";
713 }
714
715 const std::string typeName =
716 scalarType->getJavaType(false /* forInitializer */);
717
718 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
719 const auto &type = *it;
720
721 for (const auto &entry : type->values()) {
722 out << "public static final "
723 << typeName
724 << " "
725 << valuePrefix
726 << entry->name()
727 << valueSuffix
728 << " = ";
729
730 // javaValue will make the number signed.
731 std::string value = entry->javaValue(scalarType->getKind());
732 CHECK(!value.empty()); // use autofilled values for java.
733 out << value << ";\n";
734 }
735 }
736
737 if (!name.empty()) {
738 out.unindent();
739 out << "};\n";
740 }
741 out << "\n";
742
743 return;
744 }
745
746 if (!name.empty()) {
747 out << "typedef ";
748 }
749
750 out << "enum {\n";
751
752 out.indent();
753
754 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
755 const auto &type = *it;
756
757 for (const auto &entry : type->values()) {
758 out << valuePrefix << entry->name() << valueSuffix;
759
760 std::string value = entry->cppValue(scalarType->getKind());
761 CHECK(!value.empty()); // use autofilled values for c++.
762 out << " = " << value << ",\n";
763 }
764 }
765
766 out.unindent();
767 out << "}";
768
769 if (!name.empty()) {
770 out << " " << name;
771 }
772
773 out << ";\n\n";
774 }
775
776 ////////////////////////////////////////////////////////////////////////////////
777
EnumValue(const std::string & name,ConstantExpression * value,const Location & location)778 EnumValue::EnumValue(const std::string& name, ConstantExpression* value, const Location& location)
779 : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
780
name() const781 std::string EnumValue::name() const {
782 return mName;
783 }
784
rawValue(ScalarType::Kind castKind) const785 std::string EnumValue::rawValue(ScalarType::Kind castKind) const {
786 CHECK(mValue != nullptr);
787 return mValue->rawValue(castKind);
788 }
789
cppValue(ScalarType::Kind castKind) const790 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
791 CHECK(mValue != nullptr);
792 return mValue->cppValue(castKind);
793 }
javaValue(ScalarType::Kind castKind) const794 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
795 CHECK(mValue != nullptr);
796 return mValue->javaValue(castKind);
797 }
798
constExpr() const799 ConstantExpression *EnumValue::constExpr() const {
800 CHECK(mValue != nullptr);
801 return mValue;
802 }
803
autofill(const EnumType * prevType,EnumValue * prevValue,const ScalarType * type)804 void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
805 // Value is defined explicitly
806 if (mValue != nullptr) return;
807
808 CHECK((prevType == nullptr) == (prevValue == nullptr));
809
810 mIsAutoFill = true;
811 if (prevValue == nullptr) {
812 mValue = ConstantExpression::Zero(type->getKind()).release();
813 } else {
814 std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
815 auto* prevReference = new ReferenceConstantExpression(
816 Reference<LocalIdentifier>(prevValue->mName, prevValue, mLocation), description);
817 mValue = prevReference->addOne(type->getKind()).release();
818 }
819 }
820
isAutoFill() const821 bool EnumValue::isAutoFill() const {
822 return mIsAutoFill;
823 }
824
isEnumValue() const825 bool EnumValue::isEnumValue() const {
826 return true;
827 }
828
location() const829 const Location& EnumValue::location() const {
830 return mLocation;
831 }
832
833 ////////////////////////////////////////////////////////////////////////////////
834
BitFieldType(Scope * parent)835 BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent, "bitfield") {}
836
isBitField() const837 bool BitFieldType::isBitField() const {
838 return true;
839 }
840
getElementEnumType() const841 const EnumType* BitFieldType::getElementEnumType() const {
842 CHECK(mElementType.get() != nullptr && mElementType->isEnum());
843 return static_cast<const EnumType*>(mElementType.get());
844 }
845
templatedTypeName() const846 std::string BitFieldType::templatedTypeName() const {
847 return "mask";
848 }
849
isCompatibleElementType(const Type * elementType) const850 bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
851 return elementType->isEnum();
852 }
853
resolveToScalarType() const854 const ScalarType *BitFieldType::resolveToScalarType() const {
855 return mElementType->resolveToScalarType();
856 }
857
getCppType(StorageMode mode,bool specifyNamespaces) const858 std::string BitFieldType::getCppType(StorageMode mode,
859 bool specifyNamespaces) const {
860 return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
861 }
862
getJavaType(bool forInitializer) const863 std::string BitFieldType::getJavaType(bool forInitializer) const {
864 return getElementEnumType()->getBitfieldJavaType(forInitializer);
865 }
866
getJavaSuffix() const867 std::string BitFieldType::getJavaSuffix() const {
868 return resolveToScalarType()->getJavaSuffix();
869 }
870
getJavaTypeClass() const871 std::string BitFieldType::getJavaTypeClass() const {
872 return getElementEnumType()->getBitfieldJavaTypeClass();
873 }
874
getVtsType() const875 std::string BitFieldType::getVtsType() const {
876 return "TYPE_MASK";
877 }
878
isElidableType() const879 bool BitFieldType::isElidableType() const {
880 return resolveToScalarType()->isElidableType();
881 }
882
deepCanCheckEquality(std::unordered_set<const Type * > * visited) const883 bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
884 return resolveToScalarType()->canCheckEquality(visited);
885 }
886
emitVtsAttributeType(Formatter & out) const887 void BitFieldType::emitVtsAttributeType(Formatter& out) const {
888 out << "type: " << getVtsType() << "\n";
889 out << "scalar_type: \""
890 << mElementType->resolveToScalarType()->getVtsScalarType()
891 << "\"\n";
892 out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
893 << "\"\n";
894 }
895
getAlignmentAndSize(size_t * align,size_t * size) const896 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
897 resolveToScalarType()->getAlignmentAndSize(align, size);
898 }
899
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const900 void BitFieldType::emitReaderWriter(
901 Formatter &out,
902 const std::string &name,
903 const std::string &parcelObj,
904 bool parcelObjIsPointer,
905 bool isReader,
906 ErrorMode mode) const {
907 resolveToScalarType()->emitReaderWriterWithCast(
908 out,
909 name,
910 parcelObj,
911 parcelObjIsPointer,
912 isReader,
913 mode,
914 true /* needsCast */);
915 }
916
getEnumType() const917 const EnumType* BitFieldType::getEnumType() const {
918 CHECK(mElementType->isEnum());
919 return static_cast<const EnumType*>(mElementType.get());
920 }
921
922 // a bitfield maps to the underlying scalar type in C++, so operator<< is
923 // already defined. We can still emit useful information if the bitfield is
924 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const925 void BitFieldType::emitDump(
926 Formatter &out,
927 const std::string &streamName,
928 const std::string &name) const {
929 out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
930 << "::toString<" << getEnumType()->getCppStackType()
931 << ">(" << name << ");\n";
932 }
933
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const934 void BitFieldType::emitJavaDump(
935 Formatter &out,
936 const std::string &streamName,
937 const std::string &name) const {
938 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
939 << name << "));\n";
940 }
941
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const942 void BitFieldType::emitJavaFieldReaderWriter(
943 Formatter &out,
944 size_t depth,
945 const std::string &parcelName,
946 const std::string &blobName,
947 const std::string &fieldName,
948 const std::string &offset,
949 bool isReader) const {
950 return resolveToScalarType()->emitJavaFieldReaderWriter(
951 out, depth, parcelName, blobName, fieldName, offset, isReader);
952 }
953
954 } // namespace android
955
956