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