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