• 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 <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             auto name = entry->name();
313 
314             // The math.h header defines a NAN macro that breaks that declaration of a NAN
315             // enumerator in the wifi HAL. Undefine that macro before declaring the enumerator.
316             // This change strictly improves the situation, because the enum won't compile if the
317             // NAN macro is defined. It does not fix attempts to use NAN, because the include order
318             // of math.h versus a HIDL header determines which NAN is declared. Code that wants to
319             // use the wifi NAN may still need to #undef the math.h macro. This special handling
320             // only happens for NAN, because we might want to diagnose other macro<->enum conflicts.
321             if (name == "NAN") {
322                 out << "#undef NAN // avoid conflict with math.h NAN\n";
323             }
324             // The same hack is also needed for math.h OVERFLOW.
325             if (name == "OVERFLOW") {
326                 out << "#undef OVERFLOW // avoid conflict with math.h OVERFLOW\n";
327             }
328 
329             entry->emitDocComment(out);
330 
331             out << name;
332 
333             std::string value = entry->cppValue(scalarType->getKind());
334             CHECK(!value.empty()); // use autofilled values for c++.
335             out << " = " << value << ",\n";
336         }
337     }
338 
339     out.unindent();
340     out << "};\n\n";
341 }
342 
emitTypeForwardDeclaration(Formatter & out) const343 void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
344     const ScalarType* scalarType = mStorageType->resolveToScalarType();
345     const std::string storageType = scalarType->getCppStackType();
346 
347     out << "enum class " << definedName() << " : " << storageType << ";\n";
348 }
349 
emitIteratorDeclaration(Formatter & out) const350 void EnumType::emitIteratorDeclaration(Formatter& out) const {
351     size_t elementCount = 0;
352     for (const auto* type : typeChain()) {
353         elementCount += type->mValues.size();
354     }
355 
356     // TODO(pcc): Remove the pragmas once all users of the hidl headers have
357     // been moved to C++17.
358     out << "#pragma clang diagnostic push\n";
359     out << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
360 
361     out << "template<> inline constexpr std::array<" << getCppStackType() << ", " << elementCount
362         << "> hidl_enum_values<" << getCppStackType() << "> = ";
363     out.block([&] {
364         auto enumerators = typeChain();
365         std::reverse(enumerators.begin(), enumerators.end());
366         for (const auto* type : enumerators) {
367             for (const auto* enumValue : type->mValues) {
368                 out << fullName() << "::" << enumValue->name() << ",\n";
369             }
370         }
371     }) << ";\n";
372 
373     out << "#pragma clang diagnostic pop\n";
374 }
375 
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const376 void EnumType::emitEnumBitwiseOperator(
377         Formatter &out,
378         bool lhsIsEnum,
379         bool rhsIsEnum,
380         const std::string &op) const {
381     const ScalarType *scalarType = mStorageType->resolveToScalarType();
382     CHECK(scalarType != nullptr);
383 
384     const std::string storageType = scalarType->getCppStackType();
385 
386     out << "constexpr "
387         << storageType
388         << " operator"
389         << op
390         << "(const "
391         << (lhsIsEnum ? fullName() : storageType)
392         << " lhs, const "
393         << (rhsIsEnum ? fullName() : storageType)
394         << " rhs) {\n";
395 
396     out.indent([&] {
397         out << "return static_cast<"
398             << storageType
399             << ">(";
400 
401         if (lhsIsEnum) {
402             out << "static_cast<"
403                 << storageType
404                 << ">(lhs)";
405         } else {
406             out << "lhs";
407         }
408         out << " " << op << " ";
409         if (rhsIsEnum) {
410             out << "static_cast<"
411                 << storageType
412                 << ">(rhs)";
413         } else {
414             out << "rhs";
415         }
416         out << ");\n";
417     });
418 
419     out << "}\n";
420 }
421 
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const422 void EnumType::emitBitFieldBitwiseAssignmentOperator(
423         Formatter &out,
424         const std::string &op) const {
425     const ScalarType *scalarType = mStorageType->resolveToScalarType();
426     CHECK(scalarType != nullptr);
427 
428     const std::string storageType = scalarType->getCppStackType();
429 
430     out << "constexpr " << storageType << " &operator" << op << "=("
431         << storageType << "& v, const " << fullName() << " e) {\n";
432 
433     out.indent([&] {
434         out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
435         out << "return v;\n";
436     });
437 
438     out << "}\n";
439 }
440 
emitGlobalTypeDeclarations(Formatter & out) const441 void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
442     out << "namespace android {\n";
443     out << "namespace hardware {\n";
444     out << "namespace details {\n";
445 
446     emitIteratorDeclaration(out);
447 
448     out << "}  // namespace details\n";
449     out << "}  // namespace hardware\n";
450     out << "}  // namespace android\n\n";
451 }
452 
emitPackageTypeDeclarations(Formatter & out) const453 void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
454     out << "template<typename>\n"
455         << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
456         << " o);\n";
457     out << "static inline std::string toString(" << getCppArgumentType() << " o);\n";
458     out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os);\n";
459 
460     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
461     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
462     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
463     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
464     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
465     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
466 
467     emitBitFieldBitwiseAssignmentOperator(out, "|");
468     emitBitFieldBitwiseAssignmentOperator(out, "&");
469 
470     out.endl();
471 }
472 
emitPackageTypeHeaderDefinitions(Formatter & out) const473 void EnumType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
474     const ScalarType *scalarType = mStorageType->resolveToScalarType();
475     CHECK(scalarType != nullptr);
476 
477     out << "template<>\n"
478         << "inline std::string toString<" << getCppStackType() << ">("
479         << scalarType->getCppArgumentType() << " o) ";
480     out.block([&] {
481         // include toHexString for scalar types
482         out << "using ::android::hardware::details::toHexString;\n"
483             << "std::string os;\n"
484             << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
485             << "bool first = true;\n";
486         forEachValueFromRoot([&](const EnumValue* value) {
487             std::string valueName = fullName() + "::" + value->name();
488             out.sIf("(o & " + valueName + ")" +
489                     " == static_cast<" + scalarType->getCppStackType() +
490                     ">(" + valueName + ")", [&] {
491                 out << "os += (first ? \"\" : \" | \");\n"
492                     << "os += \"" << value->name() << "\";\n"
493                     << "first = false;\n"
494                     << "flipped |= " << valueName << ";\n";
495             }).endl();
496         });
497         // put remaining bits
498         out.sIf("o != flipped", [&] {
499             out << "os += (first ? \"\" : \" | \");\n";
500             scalarType->emitHexDump(out, "os", "o & (~flipped)");
501         });
502         out << "os += \" (\";\n";
503         scalarType->emitHexDump(out, "os", "o");
504         out << "os += \")\";\n";
505 
506         out << "return os;\n";
507     }).endl().endl();
508 
509     out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
510 
511     out.block([&] {
512         out << "using ::android::hardware::details::toHexString;\n";
513         forEachValueFromRoot([&](const EnumValue* value) {
514             out.sIf("o == " + fullName() + "::" + value->name(), [&] {
515                 out << "return \"" << value->name() << "\";\n";
516             }).endl();
517         });
518         out << "std::string os;\n";
519         scalarType->emitHexDump(out, "os",
520             "static_cast<" + scalarType->getCppStackType() + ">(o)");
521         out << "return os;\n";
522     }).endl().endl();
523 
524     out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os) ";
525 
526     out.block([&] { out << "*os << toString(o);\n"; }).endl().endl();
527 }
528 
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const529 void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
530     const ScalarType *scalarType = mStorageType->resolveToScalarType();
531     CHECK(scalarType != nullptr);
532 
533     out << "public " << (atTopLevel ? "" : "static ") << "final class " << definedName() << " {\n";
534 
535     out.indent();
536 
537     const std::string typeName =
538         scalarType->getJavaType(false /* forInitializer */);
539 
540     std::vector<const EnumType*> chain = typeChain();
541 
542     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
543         const auto &type = *it;
544 
545         for (const auto &entry : type->values()) {
546             entry->emitDocComment(out);
547 
548             out << "public static final "
549                 << typeName
550                 << " "
551                 << entry->name()
552                 << " = ";
553 
554             // javaValue will make the number signed.
555             std::string value = entry->javaValue(scalarType->getKind());
556             CHECK(!value.empty()); // use autofilled values for java.
557             out << value << ";\n";
558         }
559     }
560 
561     out << "public static final String toString("
562         << typeName << " o) ";
563     out.block([&] {
564         forEachValueFromRoot([&](const EnumValue* value) {
565             out.sIf("o == " + value->name(), [&] {
566                 out << "return \"" << value->name() << "\";\n";
567             }).endl();
568         });
569         out << "return \"0x\" + ";
570         scalarType->emitConvertToJavaHexString(out, "o");
571         out << ";\n";
572     }).endl();
573 
574     auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
575     out << "\n"
576         << "public static final String dumpBitfield("
577         << bitfieldType << " o) ";
578     out.block([&] {
579         out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
580         out << bitfieldType << " flipped = 0;\n";
581         forEachValueFromRoot([&](const EnumValue* value) {
582             if (value->constExpr()->castSizeT() == 0) {
583                 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
584                 return;  // continue to next value
585             }
586             out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
587                 out << "list.add(\"" << value->name() << "\");\n";
588                 out << "flipped |= " << value->name() << ";\n";
589             }).endl();
590         });
591         // put remaining bits
592         out.sIf("o != flipped", [&] {
593             out << "list.add(\"0x\" + ";
594             scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
595             out << ");\n";
596         }).endl();
597         out << "return String.join(\" | \", list);\n";
598     }).endl().endl();
599 
600     out.unindent();
601     out << "};\n\n";
602 }
603 
emitVtsTypeDeclarations(Formatter & out) const604 void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
605     const ScalarType *scalarType = mStorageType->resolveToScalarType();
606 
607     out << "name: \"" << fullName() << "\"\n";
608     out << "type: " << getVtsType() << "\n";
609     out << "enum_value: {\n";
610     out.indent();
611 
612     out << "scalar_type: \""
613         << scalarType->getVtsScalarType()
614         << "\"\n\n";
615     std::vector<const EnumType*> chain = typeChain();
616 
617     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
618         const auto &type = *it;
619 
620         for (const auto &entry : type->values()) {
621             out << "enumerator: \"" << entry->name() << "\"\n";
622             out << "scalar_value: {\n";
623             out.indent();
624             // use autofilled values for vts.
625             std::string value = entry->rawValue(scalarType->getKind());
626             CHECK(!value.empty());
627             out << mStorageType->resolveToScalarType()->getVtsScalarType()
628                 << ": "
629                 << value
630                 << "\n";
631             out.unindent();
632             out << "}\n";
633         }
634     }
635 
636     out.unindent();
637     out << "}\n";
638 }
639 
emitVtsAttributeType(Formatter & out) const640 void EnumType::emitVtsAttributeType(Formatter& out) const {
641     out << "type: " << getVtsType() << "\n";
642     out << "predefined_type: \"" << fullName() << "\"\n";
643 }
644 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const645 void EnumType::emitJavaDump(
646         Formatter &out,
647         const std::string &streamName,
648         const std::string &name) const {
649     out << streamName << ".append(" << fqName().javaName() << ".toString("
650         << name << "));\n";
651 }
652 
typeChain() const653 std::vector<const EnumType*> EnumType::typeChain() const {
654     std::vector<const EnumType*> types;
655     for (const EnumType* type = this; type != nullptr;) {
656         types.push_back(type);
657 
658         const Type* superType = type->storageType();
659         if (superType != nullptr && superType->isEnum()) {
660             type = static_cast<const EnumType*>(superType);
661         } else {
662             type = nullptr;
663         }
664     }
665 
666     return types;
667 }
668 
superTypeChain() const669 std::vector<const EnumType*> EnumType::superTypeChain() const {
670     const Type* superType = storageType();
671     if (superType == nullptr || !superType->isEnum()) {
672         return {};
673     }
674     return static_cast<const EnumType*>(superType)->typeChain();
675 }
676 
getAlignmentAndSize(size_t * align,size_t * size) const677 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
678     mStorageType->getAlignmentAndSize(align, size);
679 }
680 
findExportAnnotation() const681 const Annotation *EnumType::findExportAnnotation() const {
682     for (const auto &annotation : annotations()) {
683         if (annotation->name() == "export") {
684             return annotation;
685         }
686     }
687 
688     return nullptr;
689 }
690 
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const691 void EnumType::appendToExportedTypesVector(
692         std::vector<const Type *> *exportedTypes) const {
693     if (findExportAnnotation() != nullptr) {
694         exportedTypes->push_back(this);
695     }
696 }
697 
emitExportedHeader(Formatter & out,bool forJava) const698 void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
699     const Annotation *annotation = findExportAnnotation();
700     CHECK(annotation != nullptr);
701 
702     std::string name = definedName();
703 
704     const AnnotationParam *nameParam = annotation->getParam("name");
705     if (nameParam != nullptr) {
706         name = nameParam->getSingleString();
707     }
708 
709     bool exportParent = true;
710     const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
711     if (exportParentParam != nullptr) {
712         exportParent = exportParentParam->getSingleBool();
713     }
714 
715     std::string valuePrefix;
716     const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
717     if (prefixParam != nullptr) {
718         valuePrefix = prefixParam->getSingleString();
719     }
720 
721     std::string valueSuffix;
722     const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
723     if (suffixParam != nullptr) {
724         valueSuffix = suffixParam->getSingleString();
725     }
726 
727     const ScalarType *scalarType = mStorageType->resolveToScalarType();
728     CHECK(scalarType != nullptr);
729 
730     std::vector<const EnumType *> chain;
731     if (exportParent) {
732         chain = typeChain();
733     } else {
734         chain = { this };
735     }
736 
737     if (forJava) {
738         if (!name.empty()) {
739             out << "public final class "
740                 << name
741                 << " {\n";
742 
743             out.indent();
744         } else {
745             out << "// Values declared in " << definedName() << " follow.\n";
746         }
747 
748         const std::string typeName =
749             scalarType->getJavaType(false /* forInitializer */);
750 
751         for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
752             const auto &type = *it;
753 
754             for (const auto &entry : type->values()) {
755                 out << "public static final "
756                     << typeName
757                     << " "
758                     << valuePrefix
759                     << entry->name()
760                     << valueSuffix
761                     << " = ";
762 
763                 // javaValue will make the number signed.
764                 std::string value = entry->javaValue(scalarType->getKind());
765                 CHECK(!value.empty()); // use autofilled values for java.
766                 out << value << ";\n";
767             }
768         }
769 
770         if (!name.empty()) {
771             out.unindent();
772             out << "};\n";
773         }
774         out << "\n";
775 
776         return;
777     }
778 
779     if (!name.empty()) {
780         out << "typedef ";
781     }
782 
783     out << "enum {\n";
784 
785     out.indent();
786 
787     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
788         const auto &type = *it;
789 
790         for (const auto &entry : type->values()) {
791             out << valuePrefix << entry->name() << valueSuffix;
792 
793             std::string value = entry->cppValue(scalarType->getKind());
794             CHECK(!value.empty()); // use autofilled values for c++.
795             out << " = " << value << ",\n";
796         }
797     }
798 
799     out.unindent();
800     out << "}";
801 
802     if (!name.empty()) {
803         out << " " << name;
804     }
805 
806     out << ";\n\n";
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 
EnumValue(const std::string & name,ConstantExpression * value,const Location & location)811 EnumValue::EnumValue(const std::string& name, ConstantExpression* value, const Location& location)
812     : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
813 
name() const814 std::string EnumValue::name() const {
815     return mName;
816 }
817 
rawValue(ScalarType::Kind castKind) const818 std::string EnumValue::rawValue(ScalarType::Kind castKind) const {
819     CHECK(mValue != nullptr);
820     return mValue->rawValue(castKind);
821 }
822 
cppValue(ScalarType::Kind castKind) const823 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
824     CHECK(mValue != nullptr);
825     return mValue->cppValue(castKind);
826 }
javaValue(ScalarType::Kind castKind) const827 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
828     CHECK(mValue != nullptr);
829     return mValue->javaValue(castKind);
830 }
831 
constExpr() const832 ConstantExpression *EnumValue::constExpr() const {
833     CHECK(mValue != nullptr);
834     return mValue;
835 }
836 
autofill(const EnumType * prevType,EnumValue * prevValue,const ScalarType * type)837 void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
838     // Value is defined explicitly
839     if (mValue != nullptr) return;
840 
841     CHECK((prevType == nullptr) == (prevValue == nullptr));
842 
843     mIsAutoFill = true;
844     if (prevValue == nullptr) {
845         mValue = ConstantExpression::Zero(type->getKind()).release();
846     } else {
847         std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
848         auto* prevReference = new ReferenceConstantExpression(
849                 Reference<LocalIdentifier>(prevValue->mName, prevValue, mLocation), description);
850         mValue = prevReference->addOne(type->getKind()).release();
851     }
852 }
853 
isAutoFill() const854 bool EnumValue::isAutoFill() const {
855     return mIsAutoFill;
856 }
857 
isEnumValue() const858 bool EnumValue::isEnumValue() const {
859     return true;
860 }
861 
location() const862 const Location& EnumValue::location() const {
863     return mLocation;
864 }
865 
866 ////////////////////////////////////////////////////////////////////////////////
867 
BitFieldType(Scope * parent)868 BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent, "bitfield") {}
869 
isBitField() const870 bool BitFieldType::isBitField() const {
871     return true;
872 }
873 
getElementEnumType() const874 const EnumType* BitFieldType::getElementEnumType() const {
875     CHECK(mElementType.get() != nullptr && mElementType->isEnum());
876     return static_cast<const EnumType*>(mElementType.get());
877 }
878 
templatedTypeName() const879 std::string BitFieldType::templatedTypeName() const {
880     return "mask";
881 }
882 
isCompatibleElementType(const Type * elementType) const883 bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
884     return elementType->isEnum();
885 }
886 
resolveToScalarType() const887 const ScalarType *BitFieldType::resolveToScalarType() const {
888     return mElementType->resolveToScalarType();
889 }
890 
getCppType(StorageMode mode,bool specifyNamespaces) const891 std::string BitFieldType::getCppType(StorageMode mode,
892                                  bool specifyNamespaces) const {
893     return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
894 }
895 
getJavaType(bool forInitializer) const896 std::string BitFieldType::getJavaType(bool forInitializer) const {
897     return getElementEnumType()->getBitfieldJavaType(forInitializer);
898 }
899 
getJavaSuffix() const900 std::string BitFieldType::getJavaSuffix() const {
901     return resolveToScalarType()->getJavaSuffix();
902 }
903 
getJavaTypeClass() const904 std::string BitFieldType::getJavaTypeClass() const {
905     return getElementEnumType()->getBitfieldJavaTypeClass();
906 }
907 
getVtsType() const908 std::string BitFieldType::getVtsType() const {
909     return "TYPE_MASK";
910 }
911 
isElidableType() const912 bool BitFieldType::isElidableType() const {
913     return resolveToScalarType()->isElidableType();
914 }
915 
deepCanCheckEquality(std::unordered_set<const Type * > * visited) const916 bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
917     return resolveToScalarType()->canCheckEquality(visited);
918 }
919 
emitVtsAttributeType(Formatter & out) const920 void BitFieldType::emitVtsAttributeType(Formatter& out) const {
921     out << "type: " << getVtsType() << "\n";
922     out << "scalar_type: \""
923         << mElementType->resolveToScalarType()->getVtsScalarType()
924         << "\"\n";
925     out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
926         << "\"\n";
927 }
928 
getAlignmentAndSize(size_t * align,size_t * size) const929 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
930     resolveToScalarType()->getAlignmentAndSize(align, size);
931 }
932 
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const933 void BitFieldType::emitReaderWriter(
934         Formatter &out,
935         const std::string &name,
936         const std::string &parcelObj,
937         bool parcelObjIsPointer,
938         bool isReader,
939         ErrorMode mode) const {
940     resolveToScalarType()->emitReaderWriterWithCast(
941             out,
942             name,
943             parcelObj,
944             parcelObjIsPointer,
945             isReader,
946             mode,
947             true /* needsCast */);
948 }
949 
getEnumType() const950 const EnumType* BitFieldType::getEnumType() const {
951     CHECK(mElementType->isEnum());
952     return static_cast<const EnumType*>(mElementType.get());
953 }
954 
955 // a bitfield maps to the underlying scalar type in C++, so operator<< is
956 // already defined. We can still emit useful information if the bitfield is
957 // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const958 void BitFieldType::emitDump(
959         Formatter &out,
960         const std::string &streamName,
961         const std::string &name) const {
962     out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
963         << "::toString<" << getEnumType()->getCppStackType()
964         << ">(" << name << ");\n";
965 }
966 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const967 void BitFieldType::emitJavaDump(
968         Formatter &out,
969         const std::string &streamName,
970         const std::string &name) const {
971     out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
972         << name << "));\n";
973 }
974 
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const975 void BitFieldType::emitJavaFieldReaderWriter(
976         Formatter &out,
977         size_t depth,
978         const std::string &parcelName,
979         const std::string &blobName,
980         const std::string &fieldName,
981         const std::string &offset,
982         bool isReader) const {
983     return resolveToScalarType()->emitJavaFieldReaderWriter(
984             out, depth, parcelName, blobName, fieldName, offset, isReader);
985 }
986 
987 }  // namespace android
988 
989