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