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