• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <unordered_map>
23 
24 #include "Annotation.h"
25 #include "Location.h"
26 #include "ScalarType.h"
27 
28 namespace android {
29 
EnumType(const char * localName,const FQName & fullName,const Location & location,const Reference<Type> & storageType,Scope * parent)30 EnumType::EnumType(const char* localName, const FQName& fullName, const Location& location,
31                    const Reference<Type>& storageType, Scope* parent)
32     : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {}
33 
storageType() const34 const Type *EnumType::storageType() const {
35     return mStorageType.get();
36 }
37 
values() const38 const std::vector<EnumValue *> &EnumType::values() const {
39     return mValues;
40 }
41 
forEachValueFromRoot(const std::function<void (EnumValue *)> f) const42 void EnumType::forEachValueFromRoot(const std::function<void(EnumValue*)> f) const {
43     std::vector<const EnumType*> chain = typeChain();
44     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
45         const auto& type = *it;
46         for (EnumValue* v : type->values()) {
47             f(v);
48         }
49     }
50 }
51 
numValueNames() const52 size_t EnumType::numValueNames() const {
53     size_t count = 0;
54     for (const auto it : typeChain()) {
55         count += it->values().size();
56     }
57     return count;
58 }
59 
addValue(EnumValue * value)60 void EnumType::addValue(EnumValue* value) {
61     CHECK(value != nullptr);
62     mValues.push_back(value);
63 }
64 
resolveInheritance()65 status_t EnumType::resolveInheritance() {
66     const EnumType* prevType = nullptr;
67     EnumValue* prevValue = nullptr;
68 
69     for (const auto* type : superTypeChain()) {
70         if (!type->values().empty()) {
71             prevType = type;
72             prevValue = type->values().back();
73             break;
74         }
75     }
76 
77     for (auto* value : mValues) {
78         value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
79         prevType = this;
80         prevValue = value;
81     }
82 
83     return Scope::resolveInheritance();
84 }
85 
getReferences() const86 std::vector<const Reference<Type>*> EnumType::getReferences() const {
87     return {&mStorageType};
88 }
89 
getConstantExpressions() const90 std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
91     std::vector<const ConstantExpression*> ret;
92     for (const auto* value : mValues) {
93         ret.push_back(value->constExpr());
94     }
95     return ret;
96 }
97 
validate() const98 status_t EnumType::validate() const {
99     CHECK(getSubTypes().empty());
100 
101     if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
102         std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
103                   << ") specified at " << mStorageType.location() << "\n";
104         return UNKNOWN_ERROR;
105     }
106 
107     status_t err = validateUniqueNames();
108     if (err != OK) return err;
109 
110     return Scope::validate();
111 }
112 
validateUniqueNames() const113 status_t EnumType::validateUniqueNames() const {
114     std::unordered_map<std::string, const EnumType*> registeredValueNames;
115     for (const auto* type : superTypeChain()) {
116         for (const auto* enumValue : type->mValues) {
117             // No need to check super value uniqueness
118             registeredValueNames[enumValue->name()] = type;
119         }
120     }
121 
122     for (const auto* value : mValues) {
123         auto registered = registeredValueNames.find(value->name());
124 
125         if (registered != registeredValueNames.end()) {
126             const EnumType* definedInType = registered->second;
127 
128             if (definedInType == this) {
129                 // Defined in this enum
130                 std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
131             } else {
132                 // Defined in super enum
133                 std::cerr << "ERROR: Redefinition of value '" << value->name()
134                           << "' defined in enum '" << definedInType->fullName() << "'";
135             }
136             std::cerr << " at " << value->location() << "\n";
137             return UNKNOWN_ERROR;
138         }
139 
140         registeredValueNames[value->name()] = this;
141     }
142 
143     return OK;
144 }
145 
isElidableType() const146 bool EnumType::isElidableType() const {
147     return mStorageType->isElidableType();
148 }
149 
resolveToScalarType() const150 const ScalarType *EnumType::resolveToScalarType() const {
151     return mStorageType->resolveToScalarType();
152 }
153 
typeName() const154 std::string EnumType::typeName() const {
155     return "enum " + localName();
156 }
157 
isEnum() const158 bool EnumType::isEnum() const {
159     return true;
160 }
161 
deepCanCheckEquality(std::unordered_set<const Type * > *) const162 bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
163     return true;
164 }
165 
getCppType(StorageMode,bool) const166 std::string EnumType::getCppType(StorageMode,
167                                  bool /* specifyNamespaces */) const {
168     return fullName();
169 }
170 
getJavaType(bool forInitializer) const171 std::string EnumType::getJavaType(bool forInitializer) const {
172     return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
173 }
174 
getJavaSuffix() const175 std::string EnumType::getJavaSuffix() const {
176     return mStorageType->resolveToScalarType()->getJavaSuffix();
177 }
178 
getJavaTypeClass() const179 std::string EnumType::getJavaTypeClass() const {
180     return mStorageType->resolveToScalarType()->getJavaTypeClass();
181 }
182 
getVtsType() const183 std::string EnumType::getVtsType() const {
184     return "TYPE_ENUM";
185 }
186 
getBitfieldCppType(StorageMode,bool specifyNamespaces) const187 std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
188     const std::string space = specifyNamespaces ? "::android::hardware::" : "";
189     return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : localName()) + ">";
190 }
191 
getBitfieldJavaType(bool forInitializer) const192 std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
193     return resolveToScalarType()->getJavaType(forInitializer);
194 }
195 
getBitfieldJavaTypeClass() const196 std::string EnumType::getBitfieldJavaTypeClass() const {
197     return resolveToScalarType()->getJavaTypeClass();
198 }
199 
lookupIdentifier(const std::string & name) const200 LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
201     std::vector<const EnumType*> chain = typeChain();
202     for (auto it = chain.begin(); it != chain.end(); ++it) {
203         const auto &type = *it;
204         for(EnumValue *v : type->values()) {
205             if(v->name() == name) {
206                 return v;
207             }
208         }
209     }
210     return nullptr;
211 }
212 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const213 void EnumType::emitReaderWriter(
214         Formatter &out,
215         const std::string &name,
216         const std::string &parcelObj,
217         bool parcelObjIsPointer,
218         bool isReader,
219         ErrorMode mode) const {
220     const ScalarType *scalarType = mStorageType->resolveToScalarType();
221     CHECK(scalarType != nullptr);
222 
223     scalarType->emitReaderWriterWithCast(
224             out,
225             name,
226             parcelObj,
227             parcelObjIsPointer,
228             isReader,
229             mode,
230             true /* needsCast */);
231 }
232 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const233 void EnumType::emitJavaFieldReaderWriter(
234         Formatter &out,
235         size_t depth,
236         const std::string &parcelName,
237         const std::string &blobName,
238         const std::string &fieldName,
239         const std::string &offset,
240         bool isReader) const {
241     return mStorageType->emitJavaFieldReaderWriter(
242             out, depth, parcelName, blobName, fieldName, offset, isReader);
243 }
244 
emitTypeDeclarations(Formatter & out) const245 void EnumType::emitTypeDeclarations(Formatter& out) const {
246     const ScalarType *scalarType = mStorageType->resolveToScalarType();
247     CHECK(scalarType != nullptr);
248 
249     const std::string storageType = scalarType->getCppStackType();
250 
251     out << "enum class "
252         << localName()
253         << " : "
254         << storageType
255         << " {\n";
256 
257     out.indent();
258 
259     std::vector<const EnumType*> chain = typeChain();
260 
261     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
262         const auto &type = *it;
263 
264         for (const auto &entry : type->values()) {
265             entry->emitDocComment(out);
266 
267             out << entry->name();
268 
269             std::string value = entry->cppValue(scalarType->getKind());
270             CHECK(!value.empty()); // use autofilled values for c++.
271             out << " = " << value << ",\n";
272         }
273     }
274 
275     out.unindent();
276     out << "};\n\n";
277 }
278 
emitTypeForwardDeclaration(Formatter & out) const279 void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
280     const ScalarType* scalarType = mStorageType->resolveToScalarType();
281     const std::string storageType = scalarType->getCppStackType();
282 
283     out << "enum class " << localName() << " : " << storageType << ";\n";
284 }
285 
emitIteratorDeclaration(Formatter & out) const286 void EnumType::emitIteratorDeclaration(Formatter& out) const {
287     size_t elementCount = 0;
288     for (const auto* type : typeChain()) {
289         elementCount += type->mValues.size();
290     }
291 
292     out << "template<> constexpr std::array<" << getCppStackType() << ", " << elementCount
293         << "> hidl_enum_values<" << getCppStackType() << "> = ";
294     out.block([&] {
295         auto enumerators = typeChain();
296         std::reverse(enumerators.begin(), enumerators.end());
297         for (const auto* type : enumerators) {
298             for (const auto* enumValue : type->mValues) {
299                 out << fullName() << "::" << enumValue->name() << ",\n";
300             }
301         }
302     }) << ";\n";
303 }
304 
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const305 void EnumType::emitEnumBitwiseOperator(
306         Formatter &out,
307         bool lhsIsEnum,
308         bool rhsIsEnum,
309         const std::string &op) const {
310     const ScalarType *scalarType = mStorageType->resolveToScalarType();
311     CHECK(scalarType != nullptr);
312 
313     const std::string storageType = scalarType->getCppStackType();
314 
315     out << "constexpr "
316         << storageType
317         << " operator"
318         << op
319         << "(const "
320         << (lhsIsEnum ? fullName() : storageType)
321         << " lhs, const "
322         << (rhsIsEnum ? fullName() : storageType)
323         << " rhs) {\n";
324 
325     out.indent([&] {
326         out << "return static_cast<"
327             << storageType
328             << ">(";
329 
330         if (lhsIsEnum) {
331             out << "static_cast<"
332                 << storageType
333                 << ">(lhs)";
334         } else {
335             out << "lhs";
336         }
337         out << " " << op << " ";
338         if (rhsIsEnum) {
339             out << "static_cast<"
340                 << storageType
341                 << ">(rhs)";
342         } else {
343             out << "rhs";
344         }
345         out << ");\n";
346     });
347 
348     out << "}\n";
349 }
350 
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const351 void EnumType::emitBitFieldBitwiseAssignmentOperator(
352         Formatter &out,
353         const std::string &op) const {
354     const ScalarType *scalarType = mStorageType->resolveToScalarType();
355     CHECK(scalarType != nullptr);
356 
357     const std::string storageType = scalarType->getCppStackType();
358 
359     out << "constexpr " << storageType << " &operator" << op << "=("
360         << storageType << "& v, const " << fullName() << " e) {\n";
361 
362     out.indent([&] {
363         out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
364         out << "return v;\n";
365     });
366 
367     out << "}\n";
368 }
369 
emitGlobalTypeDeclarations(Formatter & out) const370 void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
371     out << "namespace android {\n";
372     out << "namespace hardware {\n";
373     out << "namespace details {\n";
374 
375     emitIteratorDeclaration(out);
376 
377     out << "}  // namespace details\n";
378     out << "}  // namespace hardware\n";
379     out << "}  // namespace android\n\n";
380 }
381 
emitPackageTypeDeclarations(Formatter & out) const382 void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
383     out << "template<typename>\n"
384         << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
385         << " o);\n";
386     out << "static inline std::string toString(" << getCppArgumentType() << " o);\n\n";
387 
388     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
389     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
390     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
391     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
392     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
393     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
394 
395     emitBitFieldBitwiseAssignmentOperator(out, "|");
396     emitBitFieldBitwiseAssignmentOperator(out, "&");
397 
398     out.endl();
399 }
400 
emitPackageTypeHeaderDefinitions(Formatter & out) const401 void EnumType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
402     const ScalarType *scalarType = mStorageType->resolveToScalarType();
403     CHECK(scalarType != nullptr);
404 
405     out << "template<>\n"
406         << "inline std::string toString<" << getCppStackType() << ">("
407         << scalarType->getCppArgumentType() << " o) ";
408     out.block([&] {
409         // include toHexString for scalar types
410         out << "using ::android::hardware::details::toHexString;\n"
411             << "std::string os;\n"
412             << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
413             << "bool first = true;\n";
414         forEachValueFromRoot([&](EnumValue* value) {
415             std::string valueName = fullName() + "::" + value->name();
416             out.sIf("(o & " + valueName + ")" +
417                     " == static_cast<" + scalarType->getCppStackType() +
418                     ">(" + valueName + ")", [&] {
419                 out << "os += (first ? \"\" : \" | \");\n"
420                     << "os += \"" << value->name() << "\";\n"
421                     << "first = false;\n"
422                     << "flipped |= " << valueName << ";\n";
423             }).endl();
424         });
425         // put remaining bits
426         out.sIf("o != flipped", [&] {
427             out << "os += (first ? \"\" : \" | \");\n";
428             scalarType->emitHexDump(out, "os", "o & (~flipped)");
429         });
430         out << "os += \" (\";\n";
431         scalarType->emitHexDump(out, "os", "o");
432         out << "os += \")\";\n";
433 
434         out << "return os;\n";
435     }).endl().endl();
436 
437     out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
438 
439     out.block([&] {
440         out << "using ::android::hardware::details::toHexString;\n";
441         forEachValueFromRoot([&](EnumValue* value) {
442             out.sIf("o == " + fullName() + "::" + value->name(), [&] {
443                 out << "return \"" << value->name() << "\";\n";
444             }).endl();
445         });
446         out << "std::string os;\n";
447         scalarType->emitHexDump(out, "os",
448             "static_cast<" + scalarType->getCppStackType() + ">(o)");
449         out << "return os;\n";
450     }).endl().endl();
451 }
452 
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const453 void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
454     const ScalarType *scalarType = mStorageType->resolveToScalarType();
455     CHECK(scalarType != nullptr);
456 
457     out << "public "
458         << (atTopLevel ? "" : "static ")
459         << "final class "
460         << localName()
461         << " {\n";
462 
463     out.indent();
464 
465     const std::string typeName =
466         scalarType->getJavaType(false /* forInitializer */);
467 
468     std::vector<const EnumType*> chain = typeChain();
469 
470     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
471         const auto &type = *it;
472 
473         for (const auto &entry : type->values()) {
474             entry->emitDocComment(out);
475 
476             out << "public static final "
477                 << typeName
478                 << " "
479                 << entry->name()
480                 << " = ";
481 
482             // javaValue will make the number signed.
483             std::string value = entry->javaValue(scalarType->getKind());
484             CHECK(!value.empty()); // use autofilled values for java.
485             out << value << ";\n";
486         }
487     }
488 
489     out << "public static final String toString("
490         << typeName << " o) ";
491     out.block([&] {
492         forEachValueFromRoot([&](EnumValue* value) {
493             out.sIf("o == " + value->name(), [&] {
494                 out << "return \"" << value->name() << "\";\n";
495             }).endl();
496         });
497         out << "return \"0x\" + ";
498         scalarType->emitConvertToJavaHexString(out, "o");
499         out << ";\n";
500     }).endl();
501 
502     auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
503     out << "\n"
504         << "public static final String dumpBitfield("
505         << bitfieldType << " o) ";
506     out.block([&] {
507         out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
508         out << bitfieldType << " flipped = 0;\n";
509         forEachValueFromRoot([&](EnumValue* value) {
510             if (value->constExpr()->castSizeT() == 0) {
511                 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
512                 return;  // continue to next value
513             }
514             out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
515                 out << "list.add(\"" << value->name() << "\");\n";
516                 out << "flipped |= " << value->name() << ";\n";
517             }).endl();
518         });
519         // put remaining bits
520         out.sIf("o != flipped", [&] {
521             out << "list.add(\"0x\" + ";
522             scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
523             out << ");\n";
524         }).endl();
525         out << "return String.join(\" | \", list);\n";
526     }).endl().endl();
527 
528     out.unindent();
529     out << "};\n\n";
530 }
531 
emitVtsTypeDeclarations(Formatter & out) const532 void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
533     const ScalarType *scalarType = mStorageType->resolveToScalarType();
534 
535     out << "name: \"" << fullName() << "\"\n";
536     out << "type: " << getVtsType() << "\n";
537     out << "enum_value: {\n";
538     out.indent();
539 
540     out << "scalar_type: \""
541         << scalarType->getVtsScalarType()
542         << "\"\n\n";
543     std::vector<const EnumType*> chain = typeChain();
544 
545     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
546         const auto &type = *it;
547 
548         for (const auto &entry : type->values()) {
549             out << "enumerator: \"" << entry->name() << "\"\n";
550             out << "scalar_value: {\n";
551             out.indent();
552             // use autofilled values for vts.
553             std::string value = entry->rawValue(scalarType->getKind());
554             CHECK(!value.empty());
555             out << mStorageType->resolveToScalarType()->getVtsScalarType()
556                 << ": "
557                 << value
558                 << "\n";
559             out.unindent();
560             out << "}\n";
561         }
562     }
563 
564     out.unindent();
565     out << "}\n";
566 }
567 
emitVtsAttributeType(Formatter & out) const568 void EnumType::emitVtsAttributeType(Formatter& out) const {
569     out << "type: " << getVtsType() << "\n";
570     out << "predefined_type: \"" << fullName() << "\"\n";
571 }
572 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const573 void EnumType::emitJavaDump(
574         Formatter &out,
575         const std::string &streamName,
576         const std::string &name) const {
577     out << streamName << ".append(" << fqName().javaName() << ".toString("
578         << name << "));\n";
579 }
580 
typeChain() const581 std::vector<const EnumType*> EnumType::typeChain() const {
582     std::vector<const EnumType*> types;
583     for (const EnumType* type = this; type != nullptr;) {
584         types.push_back(type);
585 
586         const Type* superType = type->storageType();
587         if (superType != nullptr && superType->isEnum()) {
588             type = static_cast<const EnumType*>(superType);
589         } else {
590             type = nullptr;
591         }
592     }
593 
594     return types;
595 }
596 
superTypeChain() const597 std::vector<const EnumType*> EnumType::superTypeChain() const {
598     const Type* superType = storageType();
599     if (superType == nullptr || !superType->isEnum()) {
600         return {};
601     }
602     return static_cast<const EnumType*>(superType)->typeChain();
603 }
604 
getAlignmentAndSize(size_t * align,size_t * size) const605 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
606     mStorageType->getAlignmentAndSize(align, size);
607 }
608 
findExportAnnotation() const609 const Annotation *EnumType::findExportAnnotation() const {
610     for (const auto &annotation : annotations()) {
611         if (annotation->name() == "export") {
612             return annotation;
613         }
614     }
615 
616     return nullptr;
617 }
618 
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const619 void EnumType::appendToExportedTypesVector(
620         std::vector<const Type *> *exportedTypes) const {
621     if (findExportAnnotation() != nullptr) {
622         exportedTypes->push_back(this);
623     }
624 }
625 
emitExportedHeader(Formatter & out,bool forJava) const626 void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
627     const Annotation *annotation = findExportAnnotation();
628     CHECK(annotation != nullptr);
629 
630     std::string name = localName();
631 
632     const AnnotationParam *nameParam = annotation->getParam("name");
633     if (nameParam != nullptr) {
634         name = nameParam->getSingleString();
635     }
636 
637     bool exportParent = true;
638     const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
639     if (exportParentParam != nullptr) {
640         exportParent = exportParentParam->getSingleBool();
641     }
642 
643     std::string valuePrefix;
644     const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
645     if (prefixParam != nullptr) {
646         valuePrefix = prefixParam->getSingleString();
647     }
648 
649     std::string valueSuffix;
650     const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
651     if (suffixParam != nullptr) {
652         valueSuffix = suffixParam->getSingleString();
653     }
654 
655     const ScalarType *scalarType = mStorageType->resolveToScalarType();
656     CHECK(scalarType != nullptr);
657 
658     std::vector<const EnumType *> chain;
659     if (exportParent) {
660         chain = typeChain();
661     } else {
662         chain = { this };
663     }
664 
665     if (forJava) {
666         if (!name.empty()) {
667             out << "public final class "
668                 << name
669                 << " {\n";
670 
671             out.indent();
672         } else {
673             out << "// Values declared in " << localName() << " follow.\n";
674         }
675 
676         const std::string typeName =
677             scalarType->getJavaType(false /* forInitializer */);
678 
679         for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
680             const auto &type = *it;
681 
682             for (const auto &entry : type->values()) {
683                 out << "public static final "
684                     << typeName
685                     << " "
686                     << valuePrefix
687                     << entry->name()
688                     << valueSuffix
689                     << " = ";
690 
691                 // javaValue will make the number signed.
692                 std::string value = entry->javaValue(scalarType->getKind());
693                 CHECK(!value.empty()); // use autofilled values for java.
694                 out << value << ";\n";
695             }
696         }
697 
698         if (!name.empty()) {
699             out.unindent();
700             out << "};\n";
701         }
702         out << "\n";
703 
704         return;
705     }
706 
707     if (!name.empty()) {
708         out << "typedef ";
709     }
710 
711     out << "enum {\n";
712 
713     out.indent();
714 
715     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
716         const auto &type = *it;
717 
718         for (const auto &entry : type->values()) {
719             out << valuePrefix << entry->name() << valueSuffix;
720 
721             std::string value = entry->cppValue(scalarType->getKind());
722             CHECK(!value.empty()); // use autofilled values for c++.
723             out << " = " << value << ",\n";
724         }
725     }
726 
727     out.unindent();
728     out << "}";
729 
730     if (!name.empty()) {
731         out << " " << name;
732     }
733 
734     out << ";\n\n";
735 }
736 
737 ////////////////////////////////////////////////////////////////////////////////
738 
EnumValue(const char * name,ConstantExpression * value,const Location & location)739 EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location)
740     : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
741 
name() const742 std::string EnumValue::name() const {
743     return mName;
744 }
745 
rawValue(ScalarType::Kind castKind) const746 std::string EnumValue::rawValue(ScalarType::Kind castKind) const {
747     CHECK(mValue != nullptr);
748     return mValue->rawValue(castKind);
749 }
750 
cppValue(ScalarType::Kind castKind) const751 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
752     CHECK(mValue != nullptr);
753     return mValue->cppValue(castKind);
754 }
javaValue(ScalarType::Kind castKind) const755 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
756     CHECK(mValue != nullptr);
757     return mValue->javaValue(castKind);
758 }
759 
constExpr() const760 ConstantExpression *EnumValue::constExpr() const {
761     CHECK(mValue != nullptr);
762     return mValue;
763 }
764 
autofill(const EnumType * prevType,EnumValue * prevValue,const ScalarType * type)765 void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
766     // Value is defined explicitly
767     if (mValue != nullptr) return;
768 
769     CHECK((prevType == nullptr) == (prevValue == nullptr));
770 
771     mIsAutoFill = true;
772     if (prevValue == nullptr) {
773         mValue = ConstantExpression::Zero(type->getKind()).release();
774     } else {
775         std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
776         auto* prevReference = new ReferenceConstantExpression(
777             Reference<LocalIdentifier>(prevValue, mLocation), description);
778         mValue = prevReference->addOne(type->getKind()).release();
779     }
780 }
781 
isAutoFill() const782 bool EnumValue::isAutoFill() const {
783     return mIsAutoFill;
784 }
785 
isEnumValue() const786 bool EnumValue::isEnumValue() const {
787     return true;
788 }
789 
location() const790 const Location& EnumValue::location() const {
791     return mLocation;
792 }
793 
794 ////////////////////////////////////////////////////////////////////////////////
795 
BitFieldType(Scope * parent)796 BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent) {}
797 
isBitField() const798 bool BitFieldType::isBitField() const {
799     return true;
800 }
801 
getElementEnumType() const802 const EnumType* BitFieldType::getElementEnumType() const {
803     CHECK(mElementType.get() != nullptr && mElementType->isEnum());
804     return static_cast<const EnumType*>(mElementType.get());
805 }
806 
templatedTypeName() const807 std::string BitFieldType::templatedTypeName() const {
808     return "mask";
809 }
810 
isCompatibleElementType(const Type * elementType) const811 bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
812     return elementType->isEnum();
813 }
814 
resolveToScalarType() const815 const ScalarType *BitFieldType::resolveToScalarType() const {
816     return mElementType->resolveToScalarType();
817 }
818 
getCppType(StorageMode mode,bool specifyNamespaces) const819 std::string BitFieldType::getCppType(StorageMode mode,
820                                  bool specifyNamespaces) const {
821     return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
822 }
823 
getJavaType(bool forInitializer) const824 std::string BitFieldType::getJavaType(bool forInitializer) const {
825     return getElementEnumType()->getBitfieldJavaType(forInitializer);
826 }
827 
getJavaSuffix() const828 std::string BitFieldType::getJavaSuffix() const {
829     return resolveToScalarType()->getJavaSuffix();
830 }
831 
getJavaTypeClass() const832 std::string BitFieldType::getJavaTypeClass() const {
833     return getElementEnumType()->getBitfieldJavaTypeClass();
834 }
835 
getVtsType() const836 std::string BitFieldType::getVtsType() const {
837     return "TYPE_MASK";
838 }
839 
isElidableType() const840 bool BitFieldType::isElidableType() const {
841     return resolveToScalarType()->isElidableType();
842 }
843 
deepCanCheckEquality(std::unordered_set<const Type * > * visited) const844 bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
845     return resolveToScalarType()->canCheckEquality(visited);
846 }
847 
emitVtsAttributeType(Formatter & out) const848 void BitFieldType::emitVtsAttributeType(Formatter& out) const {
849     out << "type: " << getVtsType() << "\n";
850     out << "scalar_type: \""
851         << mElementType->resolveToScalarType()->getVtsScalarType()
852         << "\"\n";
853     out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
854         << "\"\n";
855 }
856 
getAlignmentAndSize(size_t * align,size_t * size) const857 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
858     resolveToScalarType()->getAlignmentAndSize(align, size);
859 }
860 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const861 void BitFieldType::emitReaderWriter(
862         Formatter &out,
863         const std::string &name,
864         const std::string &parcelObj,
865         bool parcelObjIsPointer,
866         bool isReader,
867         ErrorMode mode) const {
868     resolveToScalarType()->emitReaderWriterWithCast(
869             out,
870             name,
871             parcelObj,
872             parcelObjIsPointer,
873             isReader,
874             mode,
875             true /* needsCast */);
876 }
877 
getEnumType() const878 const EnumType* BitFieldType::getEnumType() const {
879     CHECK(mElementType->isEnum());
880     return static_cast<const EnumType*>(mElementType.get());
881 }
882 
883 // a bitfield maps to the underlying scalar type in C++, so operator<< is
884 // already defined. We can still emit useful information if the bitfield is
885 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const886 void BitFieldType::emitDump(
887         Formatter &out,
888         const std::string &streamName,
889         const std::string &name) const {
890     out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
891         << "::toString<" << getEnumType()->getCppStackType()
892         << ">(" << name << ");\n";
893 }
894 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const895 void BitFieldType::emitJavaDump(
896         Formatter &out,
897         const std::string &streamName,
898         const std::string &name) const {
899     out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
900         << name << "));\n";
901 }
902 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const903 void BitFieldType::emitJavaFieldReaderWriter(
904         Formatter &out,
905         size_t depth,
906         const std::string &parcelName,
907         const std::string &blobName,
908         const std::string &fieldName,
909         const std::string &offset,
910         bool isReader) const {
911     return resolveToScalarType()->emitJavaFieldReaderWriter(
912             out, depth, parcelName, blobName, fieldName, offset, isReader);
913 }
914 
915 }  // namespace android
916 
917