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 
validateAnnotations() const114 status_t EnumType::validateAnnotations() const {
115     for (const Annotation* annotation : annotations()) {
116         const std::string name = annotation->name();
117 
118         if (name == "export") {
119             continue;
120         }
121 
122         std::cerr << "WARNING: Unrecognized annotation '" << name << "' for " << typeName()
123                   << " at " << location() << ". Only @export is supported." << std::endl;
124         // This is a warning to avoid breaking downstream unnecessarily.
125         // return UNKNOWN_ERROR;
126     }
127     return OK;
128 }
129 
validateUniqueNames() const130 status_t EnumType::validateUniqueNames() const {
131     std::unordered_map<std::string, const EnumType*> registeredValueNames;
132     for (const auto* type : superTypeChain()) {
133         for (const auto* enumValue : type->mValues) {
134             // No need to check super value uniqueness
135             registeredValueNames[enumValue->name()] = type;
136         }
137     }
138 
139     for (const auto* value : mValues) {
140         auto registered = registeredValueNames.find(value->name());
141 
142         if (registered != registeredValueNames.end()) {
143             const EnumType* definedInType = registered->second;
144 
145             if (definedInType == this) {
146                 // Defined in this enum
147                 std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
148             } else {
149                 // Defined in super enum
150                 std::cerr << "ERROR: Redefinition of value '" << value->name()
151                           << "' defined in enum '" << definedInType->fullName() << "'";
152             }
153             std::cerr << " at " << value->location() << "\n";
154             return UNKNOWN_ERROR;
155         }
156 
157         registeredValueNames[value->name()] = this;
158     }
159 
160     return OK;
161 }
162 
isElidableType() const163 bool EnumType::isElidableType() const {
164     return mStorageType->isElidableType();
165 }
166 
resolveToScalarType() const167 const ScalarType *EnumType::resolveToScalarType() const {
168     return mStorageType->resolveToScalarType();
169 }
170 
typeName() const171 std::string EnumType::typeName() const {
172     return "enum " + definedName();
173 }
174 
isEnum() const175 bool EnumType::isEnum() const {
176     return true;
177 }
178 
deepCanCheckEquality(std::unordered_set<const Type * > *) const179 bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
180     return true;
181 }
182 
getCppType(StorageMode,bool) const183 std::string EnumType::getCppType(StorageMode,
184                                  bool /* specifyNamespaces */) const {
185     return fullName();
186 }
187 
getJavaType(bool forInitializer) const188 std::string EnumType::getJavaType(bool forInitializer) const {
189     return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
190 }
191 
getJavaSuffix() const192 std::string EnumType::getJavaSuffix() const {
193     return mStorageType->resolveToScalarType()->getJavaSuffix();
194 }
195 
getJavaTypeClass() const196 std::string EnumType::getJavaTypeClass() const {
197     return mStorageType->resolveToScalarType()->getJavaTypeClass();
198 }
199 
getVtsType() const200 std::string EnumType::getVtsType() const {
201     return "TYPE_ENUM";
202 }
203 
getBitfieldCppType(StorageMode,bool specifyNamespaces) const204 std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
205     const std::string space = specifyNamespaces ? "::android::hardware::" : "";
206     return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : definedName()) + ">";
207 }
208 
getBitfieldJavaType(bool forInitializer) const209 std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
210     return resolveToScalarType()->getJavaType(forInitializer);
211 }
212 
getBitfieldJavaTypeClass() const213 std::string EnumType::getBitfieldJavaTypeClass() const {
214     return resolveToScalarType()->getJavaTypeClass();
215 }
216 
lookupIdentifier(const std::string & name) const217 LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
218     std::vector<const EnumType*> chain = typeChain();
219     for (auto it = chain.begin(); it != chain.end(); ++it) {
220         const auto &type = *it;
221         for(EnumValue *v : type->values()) {
222             if(v->name() == name) {
223                 return v;
224             }
225         }
226     }
227     return nullptr;
228 }
229 
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const230 void EnumType::emitJavaFieldInitializer(Formatter& out, const std::string& fieldName) const {
231     mStorageType->resolveToScalarType()->emitJavaFieldInitializer(out, fieldName);
232 }
233 
emitJavaFieldDefaultInitialValue(Formatter & out,const std::string & fieldName) const234 void EnumType::emitJavaFieldDefaultInitialValue(Formatter& out,
235                                                 const std::string& fieldName) const {
236     mStorageType->resolveToScalarType()->emitJavaFieldDefaultInitialValue(out, fieldName);
237 }
238 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const239 void EnumType::emitReaderWriter(
240         Formatter &out,
241         const std::string &name,
242         const std::string &parcelObj,
243         bool parcelObjIsPointer,
244         bool isReader,
245         ErrorMode mode) const {
246     const ScalarType *scalarType = mStorageType->resolveToScalarType();
247     CHECK(scalarType != nullptr);
248 
249     scalarType->emitReaderWriterWithCast(
250             out,
251             name,
252             parcelObj,
253             parcelObjIsPointer,
254             isReader,
255             mode,
256             true /* needsCast */);
257 }
258 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const259 void EnumType::emitJavaFieldReaderWriter(
260         Formatter &out,
261         size_t depth,
262         const std::string &parcelName,
263         const std::string &blobName,
264         const std::string &fieldName,
265         const std::string &offset,
266         bool isReader) const {
267     return mStorageType->emitJavaFieldReaderWriter(
268             out, depth, parcelName, blobName, fieldName, offset, isReader);
269 }
270 
emitHidlDefinition(Formatter & out) const271 void EnumType::emitHidlDefinition(Formatter& out) const {
272     if (getDocComment() != nullptr) getDocComment()->emit(out);
273 
274     if (annotations().size() != 0) {
275         out.join(annotations().begin(), annotations().end(), " ",
276                  [&](auto annotation) { annotation->dump(out); });
277         out << "\n";
278     }
279 
280     out << typeName() << " : " << mStorageType.localName() << " {\n";
281 
282     out.indent([&] {
283         for (const EnumValue* val : mValues) {
284             if (val->getDocComment() != nullptr) val->getDocComment()->emit(out);
285             out << val->name();
286             if (!val->isAutoFill()) {
287                 out << " = " << val->constExpr()->expression();
288             }
289             out << ",\n";
290         }
291     });
292 
293     out << "};\n";
294 }
295 
emitTypeDeclarations(Formatter & out) const296 void EnumType::emitTypeDeclarations(Formatter& out) const {
297     const ScalarType *scalarType = mStorageType->resolveToScalarType();
298     CHECK(scalarType != nullptr);
299 
300     const std::string storageType = scalarType->getCppStackType();
301 
302     out << "enum class " << definedName() << " : " << storageType << " {\n";
303 
304     out.indent();
305 
306     std::vector<const EnumType*> chain = typeChain();
307 
308     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
309         const auto &type = *it;
310 
311         for (const auto &entry : type->values()) {
312             entry->emitDocComment(out);
313 
314             out << entry->name();
315 
316             std::string value = entry->cppValue(scalarType->getKind());
317             CHECK(!value.empty()); // use autofilled values for c++.
318             out << " = " << value << ",\n";
319         }
320     }
321 
322     out.unindent();
323     out << "};\n\n";
324 }
325 
emitTypeForwardDeclaration(Formatter & out) const326 void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
327     const ScalarType* scalarType = mStorageType->resolveToScalarType();
328     const std::string storageType = scalarType->getCppStackType();
329 
330     out << "enum class " << definedName() << " : " << storageType << ";\n";
331 }
332 
emitIteratorDeclaration(Formatter & out) const333 void EnumType::emitIteratorDeclaration(Formatter& out) const {
334     size_t elementCount = 0;
335     for (const auto* type : typeChain()) {
336         elementCount += type->mValues.size();
337     }
338 
339     // TODO(pcc): Remove the pragmas once all users of the hidl headers have
340     // been moved to C++17.
341     out << "#pragma clang diagnostic push\n";
342     out << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
343 
344     out << "template<> inline constexpr std::array<" << getCppStackType() << ", " << elementCount
345         << "> hidl_enum_values<" << getCppStackType() << "> = ";
346     out.block([&] {
347         auto enumerators = typeChain();
348         std::reverse(enumerators.begin(), enumerators.end());
349         for (const auto* type : enumerators) {
350             for (const auto* enumValue : type->mValues) {
351                 out << fullName() << "::" << enumValue->name() << ",\n";
352             }
353         }
354     }) << ";\n";
355 
356     out << "#pragma clang diagnostic pop\n";
357 }
358 
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const359 void EnumType::emitEnumBitwiseOperator(
360         Formatter &out,
361         bool lhsIsEnum,
362         bool rhsIsEnum,
363         const std::string &op) const {
364     const ScalarType *scalarType = mStorageType->resolveToScalarType();
365     CHECK(scalarType != nullptr);
366 
367     const std::string storageType = scalarType->getCppStackType();
368 
369     out << "constexpr "
370         << storageType
371         << " operator"
372         << op
373         << "(const "
374         << (lhsIsEnum ? fullName() : storageType)
375         << " lhs, const "
376         << (rhsIsEnum ? fullName() : storageType)
377         << " rhs) {\n";
378 
379     out.indent([&] {
380         out << "return static_cast<"
381             << storageType
382             << ">(";
383 
384         if (lhsIsEnum) {
385             out << "static_cast<"
386                 << storageType
387                 << ">(lhs)";
388         } else {
389             out << "lhs";
390         }
391         out << " " << op << " ";
392         if (rhsIsEnum) {
393             out << "static_cast<"
394                 << storageType
395                 << ">(rhs)";
396         } else {
397             out << "rhs";
398         }
399         out << ");\n";
400     });
401 
402     out << "}\n";
403 }
404 
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const405 void EnumType::emitBitFieldBitwiseAssignmentOperator(
406         Formatter &out,
407         const std::string &op) const {
408     const ScalarType *scalarType = mStorageType->resolveToScalarType();
409     CHECK(scalarType != nullptr);
410 
411     const std::string storageType = scalarType->getCppStackType();
412 
413     out << "constexpr " << storageType << " &operator" << op << "=("
414         << storageType << "& v, const " << fullName() << " e) {\n";
415 
416     out.indent([&] {
417         out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
418         out << "return v;\n";
419     });
420 
421     out << "}\n";
422 }
423 
emitGlobalTypeDeclarations(Formatter & out) const424 void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
425     out << "namespace android {\n";
426     out << "namespace hardware {\n";
427     out << "namespace details {\n";
428 
429     emitIteratorDeclaration(out);
430 
431     out << "}  // namespace details\n";
432     out << "}  // namespace hardware\n";
433     out << "}  // namespace android\n\n";
434 }
435 
emitPackageTypeDeclarations(Formatter & out) const436 void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
437     out << "template<typename>\n"
438         << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
439         << " o);\n";
440     out << "static inline std::string toString(" << getCppArgumentType() << " o);\n";
441     out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os);\n";
442 
443     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
444     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
445     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
446     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
447     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
448     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
449 
450     emitBitFieldBitwiseAssignmentOperator(out, "|");
451     emitBitFieldBitwiseAssignmentOperator(out, "&");
452 
453     out.endl();
454 }
455 
emitPackageTypeHeaderDefinitions(Formatter & out) const456 void EnumType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
457     const ScalarType *scalarType = mStorageType->resolveToScalarType();
458     CHECK(scalarType != nullptr);
459 
460     out << "template<>\n"
461         << "inline std::string toString<" << getCppStackType() << ">("
462         << scalarType->getCppArgumentType() << " o) ";
463     out.block([&] {
464         // include toHexString for scalar types
465         out << "using ::android::hardware::details::toHexString;\n"
466             << "std::string os;\n"
467             << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
468             << "bool first = true;\n";
469         forEachValueFromRoot([&](const EnumValue* value) {
470             std::string valueName = fullName() + "::" + value->name();
471             out.sIf("(o & " + valueName + ")" +
472                     " == static_cast<" + scalarType->getCppStackType() +
473                     ">(" + valueName + ")", [&] {
474                 out << "os += (first ? \"\" : \" | \");\n"
475                     << "os += \"" << value->name() << "\";\n"
476                     << "first = false;\n"
477                     << "flipped |= " << valueName << ";\n";
478             }).endl();
479         });
480         // put remaining bits
481         out.sIf("o != flipped", [&] {
482             out << "os += (first ? \"\" : \" | \");\n";
483             scalarType->emitHexDump(out, "os", "o & (~flipped)");
484         });
485         out << "os += \" (\";\n";
486         scalarType->emitHexDump(out, "os", "o");
487         out << "os += \")\";\n";
488 
489         out << "return os;\n";
490     }).endl().endl();
491 
492     out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
493 
494     out.block([&] {
495         out << "using ::android::hardware::details::toHexString;\n";
496         forEachValueFromRoot([&](const EnumValue* value) {
497             out.sIf("o == " + fullName() + "::" + value->name(), [&] {
498                 out << "return \"" << value->name() << "\";\n";
499             }).endl();
500         });
501         out << "std::string os;\n";
502         scalarType->emitHexDump(out, "os",
503             "static_cast<" + scalarType->getCppStackType() + ">(o)");
504         out << "return os;\n";
505     }).endl().endl();
506 
507     out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os) ";
508 
509     out.block([&] { out << "*os << toString(o);\n"; }).endl().endl();
510 }
511 
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const512 void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
513     const ScalarType *scalarType = mStorageType->resolveToScalarType();
514     CHECK(scalarType != nullptr);
515 
516     out << "public " << (atTopLevel ? "" : "static ") << "final class " << definedName() << " {\n";
517 
518     out.indent();
519 
520     const std::string typeName =
521         scalarType->getJavaType(false /* forInitializer */);
522 
523     std::vector<const EnumType*> chain = typeChain();
524 
525     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
526         const auto &type = *it;
527 
528         for (const auto &entry : type->values()) {
529             entry->emitDocComment(out);
530 
531             out << "public static final "
532                 << typeName
533                 << " "
534                 << entry->name()
535                 << " = ";
536 
537             // javaValue will make the number signed.
538             std::string value = entry->javaValue(scalarType->getKind());
539             CHECK(!value.empty()); // use autofilled values for java.
540             out << value << ";\n";
541         }
542     }
543 
544     out << "public static final String toString("
545         << typeName << " o) ";
546     out.block([&] {
547         forEachValueFromRoot([&](const EnumValue* value) {
548             out.sIf("o == " + value->name(), [&] {
549                 out << "return \"" << value->name() << "\";\n";
550             }).endl();
551         });
552         out << "return \"0x\" + ";
553         scalarType->emitConvertToJavaHexString(out, "o");
554         out << ";\n";
555     }).endl();
556 
557     auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
558     out << "\n"
559         << "public static final String dumpBitfield("
560         << bitfieldType << " o) ";
561     out.block([&] {
562         out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
563         out << bitfieldType << " flipped = 0;\n";
564         forEachValueFromRoot([&](const EnumValue* value) {
565             if (value->constExpr()->castSizeT() == 0) {
566                 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
567                 return;  // continue to next value
568             }
569             out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
570                 out << "list.add(\"" << value->name() << "\");\n";
571                 out << "flipped |= " << value->name() << ";\n";
572             }).endl();
573         });
574         // put remaining bits
575         out.sIf("o != flipped", [&] {
576             out << "list.add(\"0x\" + ";
577             scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
578             out << ");\n";
579         }).endl();
580         out << "return String.join(\" | \", list);\n";
581     }).endl().endl();
582 
583     out.unindent();
584     out << "};\n\n";
585 }
586 
emitVtsTypeDeclarations(Formatter & out) const587 void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
588     const ScalarType *scalarType = mStorageType->resolveToScalarType();
589 
590     out << "name: \"" << fullName() << "\"\n";
591     out << "type: " << getVtsType() << "\n";
592     out << "enum_value: {\n";
593     out.indent();
594 
595     out << "scalar_type: \""
596         << scalarType->getVtsScalarType()
597         << "\"\n\n";
598     std::vector<const EnumType*> chain = typeChain();
599 
600     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
601         const auto &type = *it;
602 
603         for (const auto &entry : type->values()) {
604             out << "enumerator: \"" << entry->name() << "\"\n";
605             out << "scalar_value: {\n";
606             out.indent();
607             // use autofilled values for vts.
608             std::string value = entry->rawValue(scalarType->getKind());
609             CHECK(!value.empty());
610             out << mStorageType->resolveToScalarType()->getVtsScalarType()
611                 << ": "
612                 << value
613                 << "\n";
614             out.unindent();
615             out << "}\n";
616         }
617     }
618 
619     out.unindent();
620     out << "}\n";
621 }
622 
emitVtsAttributeType(Formatter & out) const623 void EnumType::emitVtsAttributeType(Formatter& out) const {
624     out << "type: " << getVtsType() << "\n";
625     out << "predefined_type: \"" << fullName() << "\"\n";
626 }
627 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const628 void EnumType::emitJavaDump(
629         Formatter &out,
630         const std::string &streamName,
631         const std::string &name) const {
632     out << streamName << ".append(" << fqName().javaName() << ".toString("
633         << name << "));\n";
634 }
635 
typeChain() const636 std::vector<const EnumType*> EnumType::typeChain() const {
637     std::vector<const EnumType*> types;
638     for (const EnumType* type = this; type != nullptr;) {
639         types.push_back(type);
640 
641         const Type* superType = type->storageType();
642         if (superType != nullptr && superType->isEnum()) {
643             type = static_cast<const EnumType*>(superType);
644         } else {
645             type = nullptr;
646         }
647     }
648 
649     return types;
650 }
651 
superTypeChain() const652 std::vector<const EnumType*> EnumType::superTypeChain() const {
653     const Type* superType = storageType();
654     if (superType == nullptr || !superType->isEnum()) {
655         return {};
656     }
657     return static_cast<const EnumType*>(superType)->typeChain();
658 }
659 
getAlignmentAndSize(size_t * align,size_t * size) const660 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
661     mStorageType->getAlignmentAndSize(align, size);
662 }
663 
findExportAnnotation() const664 const Annotation *EnumType::findExportAnnotation() const {
665     for (const auto &annotation : annotations()) {
666         if (annotation->name() == "export") {
667             return annotation;
668         }
669     }
670 
671     return nullptr;
672 }
673 
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const674 void EnumType::appendToExportedTypesVector(
675         std::vector<const Type *> *exportedTypes) const {
676     if (findExportAnnotation() != nullptr) {
677         exportedTypes->push_back(this);
678     }
679 }
680 
emitExportedHeader(Formatter & out,bool forJava) const681 void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
682     const Annotation *annotation = findExportAnnotation();
683     CHECK(annotation != nullptr);
684 
685     std::string name = definedName();
686 
687     const AnnotationParam *nameParam = annotation->getParam("name");
688     if (nameParam != nullptr) {
689         name = nameParam->getSingleString();
690     }
691 
692     bool exportParent = true;
693     const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
694     if (exportParentParam != nullptr) {
695         exportParent = exportParentParam->getSingleBool();
696     }
697 
698     std::string valuePrefix;
699     const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
700     if (prefixParam != nullptr) {
701         valuePrefix = prefixParam->getSingleString();
702     }
703 
704     std::string valueSuffix;
705     const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
706     if (suffixParam != nullptr) {
707         valueSuffix = suffixParam->getSingleString();
708     }
709 
710     const ScalarType *scalarType = mStorageType->resolveToScalarType();
711     CHECK(scalarType != nullptr);
712 
713     std::vector<const EnumType *> chain;
714     if (exportParent) {
715         chain = typeChain();
716     } else {
717         chain = { this };
718     }
719 
720     if (forJava) {
721         if (!name.empty()) {
722             out << "public final class "
723                 << name
724                 << " {\n";
725 
726             out.indent();
727         } else {
728             out << "// Values declared in " << definedName() << " follow.\n";
729         }
730 
731         const std::string typeName =
732             scalarType->getJavaType(false /* forInitializer */);
733 
734         for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
735             const auto &type = *it;
736 
737             for (const auto &entry : type->values()) {
738                 out << "public static final "
739                     << typeName
740                     << " "
741                     << valuePrefix
742                     << entry->name()
743                     << valueSuffix
744                     << " = ";
745 
746                 // javaValue will make the number signed.
747                 std::string value = entry->javaValue(scalarType->getKind());
748                 CHECK(!value.empty()); // use autofilled values for java.
749                 out << value << ";\n";
750             }
751         }
752 
753         if (!name.empty()) {
754             out.unindent();
755             out << "};\n";
756         }
757         out << "\n";
758 
759         return;
760     }
761 
762     if (!name.empty()) {
763         out << "typedef ";
764     }
765 
766     out << "enum {\n";
767 
768     out.indent();
769 
770     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
771         const auto &type = *it;
772 
773         for (const auto &entry : type->values()) {
774             out << valuePrefix << entry->name() << valueSuffix;
775 
776             std::string value = entry->cppValue(scalarType->getKind());
777             CHECK(!value.empty()); // use autofilled values for c++.
778             out << " = " << value << ",\n";
779         }
780     }
781 
782     out.unindent();
783     out << "}";
784 
785     if (!name.empty()) {
786         out << " " << name;
787     }
788 
789     out << ";\n\n";
790 }
791 
792 ////////////////////////////////////////////////////////////////////////////////
793 
EnumValue(const std::string & name,ConstantExpression * value,const Location & location)794 EnumValue::EnumValue(const std::string& name, ConstantExpression* value, const Location& location)
795     : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
796 
name() const797 std::string EnumValue::name() const {
798     return mName;
799 }
800 
rawValue(ScalarType::Kind castKind) const801 std::string EnumValue::rawValue(ScalarType::Kind castKind) const {
802     CHECK(mValue != nullptr);
803     return mValue->rawValue(castKind);
804 }
805 
cppValue(ScalarType::Kind castKind) const806 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
807     CHECK(mValue != nullptr);
808     return mValue->cppValue(castKind);
809 }
javaValue(ScalarType::Kind castKind) const810 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
811     CHECK(mValue != nullptr);
812     return mValue->javaValue(castKind);
813 }
814 
constExpr() const815 ConstantExpression *EnumValue::constExpr() const {
816     CHECK(mValue != nullptr);
817     return mValue;
818 }
819 
autofill(const EnumType * prevType,EnumValue * prevValue,const ScalarType * type)820 void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
821     // Value is defined explicitly
822     if (mValue != nullptr) return;
823 
824     CHECK((prevType == nullptr) == (prevValue == nullptr));
825 
826     mIsAutoFill = true;
827     if (prevValue == nullptr) {
828         mValue = ConstantExpression::Zero(type->getKind()).release();
829     } else {
830         std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
831         auto* prevReference = new ReferenceConstantExpression(
832                 Reference<LocalIdentifier>(prevValue->mName, prevValue, mLocation), description);
833         mValue = prevReference->addOne(type->getKind()).release();
834     }
835 }
836 
isAutoFill() const837 bool EnumValue::isAutoFill() const {
838     return mIsAutoFill;
839 }
840 
isEnumValue() const841 bool EnumValue::isEnumValue() const {
842     return true;
843 }
844 
location() const845 const Location& EnumValue::location() const {
846     return mLocation;
847 }
848 
849 ////////////////////////////////////////////////////////////////////////////////
850 
BitFieldType(Scope * parent)851 BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent, "bitfield") {}
852 
isBitField() const853 bool BitFieldType::isBitField() const {
854     return true;
855 }
856 
getElementEnumType() const857 const EnumType* BitFieldType::getElementEnumType() const {
858     CHECK(mElementType.get() != nullptr && mElementType->isEnum());
859     return static_cast<const EnumType*>(mElementType.get());
860 }
861 
templatedTypeName() const862 std::string BitFieldType::templatedTypeName() const {
863     return "mask";
864 }
865 
isCompatibleElementType(const Type * elementType) const866 bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
867     return elementType->isEnum();
868 }
869 
resolveToScalarType() const870 const ScalarType *BitFieldType::resolveToScalarType() const {
871     return mElementType->resolveToScalarType();
872 }
873 
getCppType(StorageMode mode,bool specifyNamespaces) const874 std::string BitFieldType::getCppType(StorageMode mode,
875                                  bool specifyNamespaces) const {
876     return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
877 }
878 
getJavaType(bool forInitializer) const879 std::string BitFieldType::getJavaType(bool forInitializer) const {
880     return getElementEnumType()->getBitfieldJavaType(forInitializer);
881 }
882 
getJavaSuffix() const883 std::string BitFieldType::getJavaSuffix() const {
884     return resolveToScalarType()->getJavaSuffix();
885 }
886 
getJavaTypeClass() const887 std::string BitFieldType::getJavaTypeClass() const {
888     return getElementEnumType()->getBitfieldJavaTypeClass();
889 }
890 
getVtsType() const891 std::string BitFieldType::getVtsType() const {
892     return "TYPE_MASK";
893 }
894 
isElidableType() const895 bool BitFieldType::isElidableType() const {
896     return resolveToScalarType()->isElidableType();
897 }
898 
deepCanCheckEquality(std::unordered_set<const Type * > * visited) const899 bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
900     return resolveToScalarType()->canCheckEquality(visited);
901 }
902 
emitVtsAttributeType(Formatter & out) const903 void BitFieldType::emitVtsAttributeType(Formatter& out) const {
904     out << "type: " << getVtsType() << "\n";
905     out << "scalar_type: \""
906         << mElementType->resolveToScalarType()->getVtsScalarType()
907         << "\"\n";
908     out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
909         << "\"\n";
910 }
911 
getAlignmentAndSize(size_t * align,size_t * size) const912 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
913     resolveToScalarType()->getAlignmentAndSize(align, size);
914 }
915 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const916 void BitFieldType::emitReaderWriter(
917         Formatter &out,
918         const std::string &name,
919         const std::string &parcelObj,
920         bool parcelObjIsPointer,
921         bool isReader,
922         ErrorMode mode) const {
923     resolveToScalarType()->emitReaderWriterWithCast(
924             out,
925             name,
926             parcelObj,
927             parcelObjIsPointer,
928             isReader,
929             mode,
930             true /* needsCast */);
931 }
932 
getEnumType() const933 const EnumType* BitFieldType::getEnumType() const {
934     CHECK(mElementType->isEnum());
935     return static_cast<const EnumType*>(mElementType.get());
936 }
937 
938 // a bitfield maps to the underlying scalar type in C++, so operator<< is
939 // already defined. We can still emit useful information if the bitfield is
940 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const941 void BitFieldType::emitDump(
942         Formatter &out,
943         const std::string &streamName,
944         const std::string &name) const {
945     out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
946         << "::toString<" << getEnumType()->getCppStackType()
947         << ">(" << name << ");\n";
948 }
949 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const950 void BitFieldType::emitJavaDump(
951         Formatter &out,
952         const std::string &streamName,
953         const std::string &name) const {
954     out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
955         << name << "));\n";
956 }
957 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const958 void BitFieldType::emitJavaFieldReaderWriter(
959         Formatter &out,
960         size_t depth,
961         const std::string &parcelName,
962         const std::string &blobName,
963         const std::string &fieldName,
964         const std::string &offset,
965         bool isReader) const {
966     return resolveToScalarType()->emitJavaFieldReaderWriter(
967             out, depth, parcelName, blobName, fieldName, offset, isReader);
968 }
969 
970 }  // namespace android
971 
972