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