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 "Type.h" 18 19 #include "ConstantExpression.h" 20 #include "NamedType.h" 21 #include "ScalarType.h" 22 #include "Scope.h" 23 24 #include <android-base/logging.h> 25 #include <hidl-util/Formatter.h> 26 #include <algorithm> 27 #include <iostream> 28 29 namespace android { 30 31 Type::Type(Scope* parent) : mParent(parent) {} 32 33 Type::~Type() {} 34 35 bool Type::isScope() const { 36 return false; 37 } 38 39 bool Type::isInterface() const { 40 return false; 41 } 42 43 bool Type::isScalar() const { 44 return false; 45 } 46 47 bool Type::isString() const { 48 return false; 49 } 50 51 bool Type::isEnum() const { 52 return false; 53 } 54 55 bool Type::isBitField() const { 56 return false; 57 } 58 59 bool Type::isHandle() const { 60 return false; 61 } 62 63 bool Type::isTypeDef() const { 64 return false; 65 } 66 67 bool Type::isBinder() const { 68 return false; 69 } 70 71 bool Type::isNamedType() const { 72 return false; 73 } 74 75 bool Type::isMemory() const { 76 return false; 77 } 78 79 bool Type::isCompoundType() const { 80 return false; 81 } 82 83 bool Type::isArray() const { 84 return false; 85 } 86 87 bool Type::isVector() const { 88 return false; 89 } 90 91 bool Type::isTemplatedType() const { 92 return false; 93 } 94 95 bool Type::isPointer() const { 96 return false; 97 } 98 99 Type* Type::resolve() { 100 return const_cast<Type*>(static_cast<const Type*>(this)->resolve()); 101 } 102 103 const Type* Type::resolve() const { 104 return this; 105 } 106 107 std::vector<Type*> Type::getDefinedTypes() { 108 const auto& constRet = static_cast<const Type*>(this)->getDefinedTypes(); 109 std::vector<Type*> ret(constRet.size()); 110 std::transform(constRet.begin(), constRet.end(), ret.begin(), 111 [](const auto* type) { return const_cast<Type*>(type); }); 112 return ret; 113 } 114 115 std::vector<const Type*> Type::getDefinedTypes() const { 116 return {}; 117 } 118 119 std::vector<Reference<Type>*> Type::getReferences() { 120 const auto& constRet = static_cast<const Type*>(this)->getReferences(); 121 std::vector<Reference<Type>*> ret(constRet.size()); 122 std::transform(constRet.begin(), constRet.end(), ret.begin(), 123 [](const auto* ref) { return const_cast<Reference<Type>*>(ref); }); 124 return ret; 125 } 126 127 std::vector<const Reference<Type>*> Type::getReferences() const { 128 return {}; 129 } 130 131 std::vector<ConstantExpression*> Type::getConstantExpressions() { 132 const auto& constRet = static_cast<const Type*>(this)->getConstantExpressions(); 133 std::vector<ConstantExpression*> ret(constRet.size()); 134 std::transform(constRet.begin(), constRet.end(), ret.begin(), 135 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); }); 136 return ret; 137 } 138 139 std::vector<const ConstantExpression*> Type::getConstantExpressions() const { 140 return {}; 141 } 142 143 std::vector<Reference<Type>*> Type::getStrongReferences() { 144 const auto& constRet = static_cast<const Type*>(this)->getStrongReferences(); 145 std::vector<Reference<Type>*> ret(constRet.size()); 146 std::transform(constRet.begin(), constRet.end(), ret.begin(), 147 [](const auto* ref) { return const_cast<Reference<Type>*>(ref); }); 148 return ret; 149 } 150 151 std::vector<const Reference<Type>*> Type::getStrongReferences() const { 152 std::vector<const Reference<Type>*> ret; 153 for (const auto* ref : getReferences()) { 154 if (!ref->shallowGet()->isNeverStrongReference()) { 155 ret.push_back(ref); 156 } 157 } 158 return ret; 159 } 160 161 status_t Type::recursivePass(const std::function<status_t(Type*)>& func, 162 std::unordered_set<const Type*>* visited) { 163 if (mIsPostParseCompleted) return OK; 164 165 if (visited->find(this) != visited->end()) return OK; 166 visited->insert(this); 167 168 status_t err = func(this); 169 if (err != OK) return err; 170 171 for (auto* nextType : getDefinedTypes()) { 172 err = nextType->recursivePass(func, visited); 173 if (err != OK) return err; 174 } 175 176 for (auto* nextRef : getReferences()) { 177 err = nextRef->shallowGet()->recursivePass(func, visited); 178 if (err != OK) return err; 179 } 180 181 return OK; 182 } 183 184 status_t Type::recursivePass(const std::function<status_t(const Type*)>& func, 185 std::unordered_set<const Type*>* visited) const { 186 if (mIsPostParseCompleted) return OK; 187 188 if (visited->find(this) != visited->end()) return OK; 189 visited->insert(this); 190 191 status_t err = func(this); 192 if (err != OK) return err; 193 194 for (const auto* nextType : getDefinedTypes()) { 195 err = nextType->recursivePass(func, visited); 196 if (err != OK) return err; 197 } 198 199 for (const auto* nextRef : getReferences()) { 200 err = nextRef->shallowGet()->recursivePass(func, visited); 201 if (err != OK) return err; 202 } 203 204 return OK; 205 } 206 207 status_t Type::resolveInheritance() { 208 return OK; 209 } 210 211 status_t Type::validate() const { 212 return OK; 213 } 214 215 Type::CheckAcyclicStatus::CheckAcyclicStatus(status_t status, const Type* cycleEnd) 216 : status(status), cycleEnd(cycleEnd) { 217 CHECK(cycleEnd == nullptr || status != OK); 218 } 219 220 Type::CheckAcyclicStatus Type::topologicalOrder( 221 std::unordered_map<const Type*, size_t>* reversedOrder, 222 std::unordered_set<const Type*>* stack) const { 223 if (stack->find(this) != stack->end()) { 224 std::cerr << "ERROR: Cyclic declaration:\n"; 225 return CheckAcyclicStatus(UNKNOWN_ERROR, this); 226 } 227 228 if (reversedOrder->find(this) != reversedOrder->end()) return CheckAcyclicStatus(OK); 229 stack->insert(this); 230 231 for (const auto* nextType : getDefinedTypes()) { 232 auto err = nextType->topologicalOrder(reversedOrder, stack); 233 234 if (err.status != OK) { 235 if (err.cycleEnd == nullptr) return err; 236 237 std::cerr << " '" << nextType->typeName() << "' in '" << typeName() << "'"; 238 if (nextType->isNamedType()) { 239 std::cerr << " at " << static_cast<const NamedType*>(nextType)->location(); 240 } 241 std::cerr << "\n"; 242 243 if (err.cycleEnd == this) { 244 return CheckAcyclicStatus(err.status); 245 } 246 return err; 247 } 248 } 249 250 for (const auto* nextRef : getStrongReferences()) { 251 const auto* nextType = nextRef->shallowGet(); 252 auto err = nextType->topologicalOrder(reversedOrder, stack); 253 254 if (err.status != OK) { 255 if (err.cycleEnd == nullptr) return err; 256 257 std::cerr << " '" << nextType->typeName() << "' in '" << typeName() << "' at " 258 << nextRef->location() << "\n"; 259 260 if (err.cycleEnd == this) { 261 return CheckAcyclicStatus(err.status); 262 } 263 return err; 264 } 265 } 266 267 CHECK(stack->find(this) != stack->end()); 268 stack->erase(this); 269 270 CHECK(reversedOrder->find(this) == reversedOrder->end()); 271 // Do not call insert and size in one statement to not rely on 272 // evaluation order. 273 size_t index = reversedOrder->size(); 274 reversedOrder->insert({this, index}); 275 276 return CheckAcyclicStatus(OK); 277 } 278 279 status_t Type::checkForwardReferenceRestrictions(const Reference<Type>& ref) const { 280 const Location& refLoc = ref.location(); 281 const Type* refType = ref.shallowGet(); 282 283 // Not NamedTypes are avaiable everywhere. 284 // Only ArrayType and TemplatedType contain additional types in 285 // their reference (which is actually a part of type definition), 286 // so they are proceeded in this case. 287 // 288 // If we support named templated types one day, we will need to change 289 // this logic. 290 if (!refType->isNamedType()) { 291 for (const Reference<Type>* innerRef : refType->getReferences()) { 292 status_t err = checkForwardReferenceRestrictions(*innerRef); 293 if (err != OK) return err; 294 } 295 return OK; 296 } 297 298 const Location& typeLoc = static_cast<const NamedType*>(refType)->location(); 299 300 // If referenced type is declared in another file or before reference, 301 // there is no forward reference here. 302 if (!Location::inSameFile(refLoc, typeLoc) || 303 (!Location::intersect(refLoc, typeLoc) && typeLoc < refLoc)) { 304 return OK; 305 } 306 307 // Type must be declared somewhere in the current stack to make it 308 // available for forward referencing. 309 const Type* refTypeParent = refType->parent(); 310 for (const Type* ancestor = this; ancestor != nullptr; ancestor = ancestor->parent()) { 311 if (ancestor == refTypeParent) return OK; 312 } 313 314 std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at " << ref.location() 315 << " is not supported.\n" 316 << "C++ forward declaration doesn't support inner types.\n"; 317 318 return UNKNOWN_ERROR; 319 } 320 321 const ScalarType *Type::resolveToScalarType() const { 322 return NULL; 323 } 324 325 bool Type::isValidEnumStorageType() const { 326 const ScalarType *scalarType = resolveToScalarType(); 327 328 if (scalarType == NULL) { 329 return false; 330 } 331 332 return scalarType->isValidEnumStorageType(); 333 } 334 335 bool Type::isElidableType() const { 336 return false; 337 } 338 339 bool Type::canCheckEquality() const { 340 std::unordered_set<const Type*> visited; 341 return canCheckEquality(&visited); 342 } 343 344 bool Type::canCheckEquality(std::unordered_set<const Type*>* visited) const { 345 // See isJavaCompatible for similar structure. 346 if (visited->find(this) != visited->end()) { 347 return true; 348 } 349 visited->insert(this); 350 return deepCanCheckEquality(visited); 351 } 352 353 bool Type::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const { 354 return false; 355 } 356 357 void Type::setPostParseCompleted() { 358 CHECK(!mIsPostParseCompleted); 359 mIsPostParseCompleted = true; 360 } 361 362 Scope* Type::parent() { 363 return mParent; 364 } 365 366 const Scope* Type::parent() const { 367 return mParent; 368 } 369 370 std::string Type::getCppType(StorageMode, bool) const { 371 CHECK(!"Should not be here"); 372 return std::string(); 373 } 374 375 std::string Type::decorateCppName( 376 const std::string &name, StorageMode mode, bool specifyNamespaces) const { 377 return getCppType(mode, specifyNamespaces) + " " + name; 378 } 379 380 std::string Type::getJavaType(bool /* forInitializer */) const { 381 CHECK(!"Should not be here"); 382 return std::string(); 383 } 384 385 std::string Type::getJavaWrapperType() const { 386 return getJavaType(); 387 } 388 389 std::string Type::getJavaSuffix() const { 390 CHECK(!"Should not be here"); 391 return std::string(); 392 } 393 394 std::string Type::getVtsType() const { 395 CHECK(!"Should not be here"); 396 return std::string(); 397 } 398 399 std::string Type::getVtsValueName() const { 400 CHECK(!"Should not be here"); 401 return std::string(); 402 } 403 404 void Type::emitReaderWriter( 405 Formatter &, 406 const std::string &, 407 const std::string &, 408 bool, 409 bool, 410 ErrorMode) const { 411 CHECK(!"Should not be here"); 412 } 413 414 void Type::emitResolveReferences( 415 Formatter &, 416 const std::string &, 417 bool, 418 const std::string &, 419 bool, 420 bool, 421 ErrorMode) const { 422 CHECK(!"Should not be here"); 423 } 424 425 void Type::emitResolveReferencesEmbedded( 426 Formatter &, 427 size_t, 428 const std::string &, 429 const std::string &, 430 bool, 431 const std::string &, 432 bool, 433 bool, 434 ErrorMode, 435 const std::string &, 436 const std::string &) const { 437 CHECK(!"Should not be here"); 438 } 439 440 void Type::emitDump( 441 Formatter &out, 442 const std::string &streamName, 443 const std::string &name) const { 444 emitDumpWithMethod(out, streamName, "::android::hardware::toString", name); 445 } 446 447 void Type::emitDumpWithMethod( 448 Formatter &out, 449 const std::string &streamName, 450 const std::string &methodName, 451 const std::string &name) const { 452 out << streamName 453 << " += " 454 << methodName 455 << "(" 456 << name 457 << ");\n"; 458 } 459 460 void Type::emitJavaDump( 461 Formatter &out, 462 const std::string &streamName, 463 const std::string &name) const { 464 out << streamName << ".append(" << name << ");\n"; 465 } 466 467 bool Type::useParentInEmitResolveReferencesEmbedded() const { 468 return needsResolveReferences(); 469 } 470 471 bool Type::useNameInEmitReaderWriterEmbedded(bool) const { 472 return needsEmbeddedReadWrite(); 473 } 474 475 void Type::emitReaderWriterEmbedded( 476 Formatter &, 477 size_t, 478 const std::string &, 479 const std::string &, 480 bool, 481 const std::string &, 482 bool, 483 bool, 484 ErrorMode, 485 const std::string &, 486 const std::string &) const { 487 CHECK(!"Should not be here"); 488 } 489 490 void Type::emitJavaReaderWriter( 491 Formatter &out, 492 const std::string &parcelObj, 493 const std::string &argName, 494 bool isReader) const { 495 emitJavaReaderWriterWithSuffix( 496 out, 497 parcelObj, 498 argName, 499 isReader, 500 getJavaSuffix(), 501 "" /* extra */); 502 } 503 504 void Type::emitJavaFieldInitializer( 505 Formatter &out, 506 const std::string &fieldName) const { 507 out << getJavaType() 508 << " " 509 << fieldName 510 << ";\n"; 511 } 512 513 void Type::emitJavaFieldReaderWriter( 514 Formatter &, 515 size_t, 516 const std::string &, 517 const std::string &, 518 const std::string &, 519 const std::string &, 520 bool) const { 521 CHECK(!"Should not be here"); 522 } 523 524 void Type::handleError(Formatter &out, ErrorMode mode) const { 525 switch (mode) { 526 case ErrorMode_Ignore: 527 { 528 out << "/* _hidl_err ignored! */\n\n"; 529 break; 530 } 531 532 case ErrorMode_Goto: 533 { 534 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n"; 535 break; 536 } 537 538 case ErrorMode_Break: 539 { 540 out << "if (_hidl_err != ::android::OK) { break; }\n\n"; 541 break; 542 } 543 544 case ErrorMode_Return: 545 { 546 out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n"; 547 break; 548 } 549 } 550 } 551 552 void Type::emitReaderWriterEmbeddedForTypeName( 553 Formatter &out, 554 const std::string &name, 555 bool nameIsPointer, 556 const std::string &parcelObj, 557 bool parcelObjIsPointer, 558 bool isReader, 559 ErrorMode mode, 560 const std::string &parentName, 561 const std::string &offsetText, 562 const std::string &typeName, 563 const std::string &childName, 564 const std::string &funcNamespace) const { 565 566 const std::string parcelObjDeref = 567 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj; 568 569 const std::string parcelObjPointer = 570 parcelObjIsPointer ? parcelObj : ("&" + parcelObj); 571 572 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name; 573 const std::string namePointer = nameIsPointer ? name : ("&" + name); 574 575 out << "_hidl_err = "; 576 577 if (!funcNamespace.empty()) { 578 out << funcNamespace << "::"; 579 } 580 581 out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n"); 582 583 out.indent(); 584 out.indent(); 585 586 if (isReader) { 587 out << "const_cast<" 588 << typeName 589 << " &>(" 590 << nameDerefed 591 << "),\n"; 592 } else { 593 out << nameDerefed 594 << ",\n"; 595 } 596 597 out << (isReader ? parcelObjDeref : parcelObjPointer) 598 << ",\n" 599 << parentName 600 << ",\n" 601 << offsetText; 602 603 if (!childName.empty()) { 604 out << ", &" 605 << childName; 606 } 607 608 out << ");\n\n"; 609 610 out.unindent(); 611 out.unindent(); 612 613 handleError(out, mode); 614 } 615 616 void Type::emitTypeDeclarations(Formatter&) const {} 617 618 void Type::emitTypeForwardDeclaration(Formatter&) const {} 619 620 void Type::emitGlobalTypeDeclarations(Formatter&) const {} 621 622 void Type::emitPackageTypeDeclarations(Formatter&) const {} 623 624 void Type::emitPackageHwDeclarations(Formatter&) const {} 625 626 void Type::emitTypeDefinitions(Formatter&, const std::string&) const {} 627 628 void Type::emitJavaTypeDeclarations(Formatter&, bool) const {} 629 630 bool Type::needsEmbeddedReadWrite() const { 631 return false; 632 } 633 634 bool Type::resultNeedsDeref() const { 635 return false; 636 } 637 638 bool Type::needsResolveReferences() const { 639 std::unordered_set<const Type*> visited; 640 return needsResolveReferences(&visited); 641 } 642 643 bool Type::needsResolveReferences(std::unordered_set<const Type*>* visited) const { 644 // See isJavaCompatible for similar structure. 645 if (visited->find(this) != visited->end()) { 646 return false; 647 } 648 visited->insert(this); 649 return deepNeedsResolveReferences(visited); 650 } 651 652 bool Type::deepNeedsResolveReferences(std::unordered_set<const Type*>* /* visited */) const { 653 return false; 654 } 655 656 std::string Type::getCppStackType(bool specifyNamespaces) const { 657 return getCppType(StorageMode_Stack, specifyNamespaces); 658 } 659 660 std::string Type::getCppResultType(bool specifyNamespaces) const { 661 return getCppType(StorageMode_Result, specifyNamespaces); 662 } 663 664 std::string Type::getCppArgumentType(bool specifyNamespaces) const { 665 return getCppType(StorageMode_Argument, specifyNamespaces); 666 } 667 668 void Type::emitJavaReaderWriterWithSuffix( 669 Formatter &out, 670 const std::string &parcelObj, 671 const std::string &argName, 672 bool isReader, 673 const std::string &suffix, 674 const std::string &extra) const { 675 out << parcelObj 676 << "." 677 << (isReader ? "read" : "write") 678 << suffix 679 << "("; 680 681 if (isReader) { 682 out << extra; 683 } else { 684 out << (extra.empty() ? "" : (extra + ", ")); 685 out << argName; 686 } 687 688 out << ");\n"; 689 } 690 691 void Type::emitVtsTypeDeclarations(Formatter&) const {} 692 693 void Type::emitVtsAttributeType(Formatter& out) const { 694 emitVtsTypeDeclarations(out); 695 } 696 697 bool Type::isJavaCompatible() const { 698 std::unordered_set<const Type*> visited; 699 return isJavaCompatible(&visited); 700 } 701 702 bool Type::containsPointer() const { 703 std::unordered_set<const Type*> visited; 704 return containsPointer(&visited); 705 } 706 707 bool Type::isJavaCompatible(std::unordered_set<const Type*>* visited) const { 708 // We need to find al least one path from requested vertex 709 // to not java compatible. 710 // That means that if we have already visited some vertex, 711 // there is no need to determine whether it is java compatible 712 // (and we can assume that it is java compatible), 713 // as if not, the information about that would appear in the 714 // requested vertex through another path. 715 if (visited->find(this) != visited->end()) { 716 return true; 717 } 718 visited->insert(this); 719 return deepIsJavaCompatible(visited); 720 } 721 722 bool Type::containsPointer(std::unordered_set<const Type*>* visited) const { 723 // See isJavaCompatible for similar structure. 724 if (visited->find(this) != visited->end()) { 725 return false; 726 } 727 visited->insert(this); 728 return deepContainsPointer(visited); 729 } 730 731 bool Type::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const { 732 return true; 733 } 734 735 bool Type::deepContainsPointer(std::unordered_set<const Type*>* /* visited */) const { 736 return false; 737 } 738 739 void Type::getAlignmentAndSize( 740 size_t * /* align */, size_t * /* size */) const { 741 CHECK(!"Should not be here."); 742 } 743 744 void Type::appendToExportedTypesVector( 745 std::vector<const Type *> * /* exportedTypes */) const { 746 } 747 748 void Type::emitExportedHeader(Formatter& /* out */, bool /* forJava */) const {} 749 750 bool Type::isNeverStrongReference() const { 751 return false; 752 } 753 754 //////////////////////////////////////// 755 756 TemplatedType::TemplatedType(Scope* parent) : Type(parent) {} 757 758 std::string TemplatedType::typeName() const { 759 return templatedTypeName() + " of " + mElementType->typeName(); 760 } 761 762 void TemplatedType::setElementType(const Reference<Type>& elementType) { 763 // can only be set once. 764 CHECK(mElementType.isEmptyReference()); 765 CHECK(!elementType.isEmptyReference()); 766 767 mElementType = elementType; 768 } 769 770 const Type* TemplatedType::getElementType() const { 771 return mElementType.get(); 772 } 773 774 bool TemplatedType::isTemplatedType() const { 775 return true; 776 } 777 778 std::vector<const Reference<Type>*> TemplatedType::getReferences() const { 779 return {&mElementType}; 780 } 781 782 status_t TemplatedType::validate() const { 783 if (!isCompatibleElementType(mElementType.get())) { 784 std::cerr << "ERROR: " << typeName() /* contains element type */ 785 << " is not supported at " << mElementType.location() << "\n"; 786 return UNKNOWN_ERROR; 787 } 788 789 return Type::validate(); 790 } 791 792 void TemplatedType::emitVtsTypeDeclarations(Formatter& out) const { 793 out << "type: " << getVtsType() << "\n"; 794 out << getVtsValueName() << ": {\n"; 795 out.indent(); 796 mElementType->emitVtsTypeDeclarations(out); 797 out.unindent(); 798 out << "}\n"; 799 } 800 801 void TemplatedType::emitVtsAttributeType(Formatter& out) const { 802 out << "type: " << getVtsType() << "\n"; 803 out << getVtsValueName() << ": {\n"; 804 out.indent(); 805 mElementType->emitVtsAttributeType(out); 806 out.unindent(); 807 out << "}\n"; 808 } 809 810 } // namespace android 811 812