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