EnumType.cpp revision db1b1b638865a2043c9cddd8c865751e9742b181
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 "Annotation.h" 20#include "ScalarType.h" 21 22#include <inttypes.h> 23#include <hidl-util/Formatter.h> 24#include <android-base/logging.h> 25 26namespace android { 27 28EnumType::EnumType( 29 const char *localName, 30 const Location &location, 31 Type *storageType) 32 : Scope(localName, location), 33 mValues(), 34 mStorageType(storageType) { 35} 36 37const Type *EnumType::storageType() const { 38 return mStorageType; 39} 40 41const std::vector<EnumValue *> &EnumType::values() const { 42 return mValues; 43} 44 45void EnumType::addValue(EnumValue *value) { 46 CHECK(value != nullptr); 47 48 EnumValue *prev = nullptr; 49 std::vector<const EnumType *> chain; 50 getTypeChain(&chain); 51 for (auto it = chain.begin(); it != chain.end(); ++it) { 52 const auto &type = *it; 53 if(!type->values().empty()) { 54 prev = type->values().back(); 55 break; 56 } 57 } 58 59 value->autofill(prev, resolveToScalarType()); 60 mValues.push_back(value); 61} 62 63bool EnumType::isElidableType() const { 64 return mStorageType->isElidableType(); 65} 66 67const ScalarType *EnumType::resolveToScalarType() const { 68 return mStorageType->resolveToScalarType(); 69} 70 71std::string EnumType::typeName() const { 72 return "enum " + localName(); 73} 74 75bool EnumType::isEnum() const { 76 return true; 77} 78 79bool EnumType::canCheckEquality() const { 80 return true; 81} 82 83std::string EnumType::getCppType(StorageMode, 84 bool specifyNamespaces) const { 85 return specifyNamespaces ? fullName() : partialCppName(); 86} 87 88std::string EnumType::getJavaType(bool forInitializer) const { 89 return mStorageType->resolveToScalarType()->getJavaType(forInitializer); 90} 91 92std::string EnumType::getJavaSuffix() const { 93 return mStorageType->resolveToScalarType()->getJavaSuffix(); 94} 95 96std::string EnumType::getJavaWrapperType() const { 97 return mStorageType->resolveToScalarType()->getJavaWrapperType(); 98} 99 100std::string EnumType::getVtsType() const { 101 return "TYPE_ENUM"; 102} 103 104LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const { 105 std::vector<const EnumType *> chain; 106 getTypeChain(&chain); 107 for (auto it = chain.begin(); it != chain.end(); ++it) { 108 const auto &type = *it; 109 for(EnumValue *v : type->values()) { 110 if(v->name() == name) { 111 return v; 112 } 113 } 114 } 115 return nullptr; 116} 117 118void EnumType::emitReaderWriter( 119 Formatter &out, 120 const std::string &name, 121 const std::string &parcelObj, 122 bool parcelObjIsPointer, 123 bool isReader, 124 ErrorMode mode) const { 125 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 126 CHECK(scalarType != NULL); 127 128 scalarType->emitReaderWriterWithCast( 129 out, 130 name, 131 parcelObj, 132 parcelObjIsPointer, 133 isReader, 134 mode, 135 true /* needsCast */); 136} 137 138void EnumType::emitJavaFieldReaderWriter( 139 Formatter &out, 140 size_t depth, 141 const std::string &parcelName, 142 const std::string &blobName, 143 const std::string &fieldName, 144 const std::string &offset, 145 bool isReader) const { 146 return mStorageType->emitJavaFieldReaderWriter( 147 out, depth, parcelName, blobName, fieldName, offset, isReader); 148} 149 150status_t EnumType::emitTypeDeclarations(Formatter &out) const { 151 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 152 CHECK(scalarType != nullptr); 153 154 const std::string storageType = scalarType->getCppStackType(); 155 156 out << "enum class " 157 << localName() 158 << " : " 159 << storageType 160 << " {\n"; 161 162 out.indent(); 163 164 std::vector<const EnumType *> chain; 165 getTypeChain(&chain); 166 167 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 168 const auto &type = *it; 169 170 for (const auto &entry : type->values()) { 171 out << entry->name(); 172 173 std::string value = entry->cppValue(scalarType->getKind()); 174 CHECK(!value.empty()); // use autofilled values for c++. 175 out << " = " << value; 176 177 out << ","; 178 179 std::string comment = entry->comment(); 180 if (!comment.empty() && comment != value) { 181 out << " // " << comment; 182 } 183 184 out << "\n"; 185 } 186 } 187 188 out.unindent(); 189 out << "};\n\n"; 190 191 return OK; 192} 193 194void EnumType::emitEnumBitwiseOperator( 195 Formatter &out, 196 bool lhsIsEnum, 197 bool rhsIsEnum, 198 const std::string &op) const { 199 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 200 CHECK(scalarType != nullptr); 201 202 const std::string storageType = scalarType->getCppStackType(); 203 204 out << "constexpr " 205 << storageType 206 << " operator" 207 << op 208 << "(const " 209 << (lhsIsEnum ? fullName() : storageType) 210 << " lhs, const " 211 << (rhsIsEnum ? fullName() : storageType) 212 << " rhs) {\n"; 213 214 out.indent([&] { 215 out << "return static_cast<" 216 << storageType 217 << ">("; 218 219 if (lhsIsEnum) { 220 out << "static_cast<" 221 << storageType 222 << ">(lhs)"; 223 } else { 224 out << "lhs"; 225 } 226 out << " " << op << " "; 227 if (rhsIsEnum) { 228 out << "static_cast<" 229 << storageType 230 << ">(rhs)"; 231 } else { 232 out << "rhs"; 233 } 234 out << ");\n"; 235 }); 236 237 out << "}\n\n"; 238} 239 240void EnumType::emitBitFieldBitwiseAssignmentOperator( 241 Formatter &out, 242 const std::string &op) const { 243 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 244 CHECK(scalarType != nullptr); 245 246 const std::string storageType = scalarType->getCppStackType(); 247 248 out << "constexpr " << storageType << " &operator" << op << "=(" 249 << storageType << "& v, const " << fullName() << " e) {\n"; 250 251 out.indent([&] { 252 out << "v " << op << "= static_cast<" << storageType << ">(e);\n"; 253 out << "return v;\n"; 254 }); 255 256 out << "}\n\n"; 257} 258 259status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const { 260 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 261 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 262 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|"); 263 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 264 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 265 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&"); 266 267 emitBitFieldBitwiseAssignmentOperator(out, "|"); 268 emitBitFieldBitwiseAssignmentOperator(out, "&"); 269 270 return OK; 271} 272 273status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool) const { 274 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 275 CHECK(scalarType != NULL); 276 277 out << "public final class " 278 << localName() 279 << " {\n"; 280 281 out.indent(); 282 283 const std::string typeName = 284 scalarType->getJavaType(false /* forInitializer */); 285 286 std::vector<const EnumType *> chain; 287 getTypeChain(&chain); 288 289 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 290 const auto &type = *it; 291 292 for (const auto &entry : type->values()) { 293 out << "public static final " 294 << typeName 295 << " " 296 << entry->name() 297 << " = "; 298 299 // javaValue will make the number signed. 300 std::string value = entry->javaValue(scalarType->getKind()); 301 CHECK(!value.empty()); // use autofilled values for java. 302 out << value; 303 304 out << ";"; 305 306 std::string comment = entry->comment(); 307 if (!comment.empty() && comment != value) { 308 out << " // " << comment; 309 } 310 311 out << "\n"; 312 } 313 } 314 315 out.unindent(); 316 out << "};\n\n"; 317 318 return OK; 319} 320 321status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const { 322 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 323 324 out << "name: \"" << fullName() << "\"\n"; 325 out << "type: " << getVtsType() << "\n"; 326 out << "enum_value: {\n"; 327 out.indent(); 328 329 out << "scalar_type: \"" 330 << scalarType->getVtsScalarType() 331 << "\"\n\n"; 332 std::vector<const EnumType *> chain; 333 getTypeChain(&chain); 334 335 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 336 const auto &type = *it; 337 338 for (const auto &entry : type->values()) { 339 out << "enumerator: \"" << entry->name() << "\"\n"; 340 out << "scalar_value: {\n"; 341 out.indent(); 342 // use autofilled values for vts. 343 std::string value = entry->value(scalarType->getKind()); 344 CHECK(!value.empty()); 345 out << mStorageType->resolveToScalarType()->getVtsScalarType() 346 << ": " 347 << value 348 << "\n"; 349 out.unindent(); 350 out << "}\n"; 351 } 352 } 353 354 out.unindent(); 355 out << "}\n"; 356 return OK; 357} 358 359status_t EnumType::emitVtsAttributeType(Formatter &out) const { 360 out << "type: " << getVtsType() << "\n"; 361 out << "predefined_type: \"" << fullName() << "\"\n"; 362 return OK; 363} 364 365void EnumType::getTypeChain(std::vector<const EnumType *> *out) const { 366 out->clear(); 367 const EnumType *type = this; 368 for (;;) { 369 out->push_back(type); 370 371 const Type *superType = type->storageType(); 372 if (superType == NULL || !superType->isEnum()) { 373 break; 374 } 375 376 type = static_cast<const EnumType *>(superType); 377 } 378} 379 380void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const { 381 mStorageType->getAlignmentAndSize(align, size); 382} 383 384const Annotation *EnumType::findExportAnnotation() const { 385 for (const auto &annotation : annotations()) { 386 if (annotation->name() == "export") { 387 return annotation; 388 } 389 } 390 391 return nullptr; 392} 393 394void EnumType::appendToExportedTypesVector( 395 std::vector<const Type *> *exportedTypes) const { 396 if (findExportAnnotation() != nullptr) { 397 exportedTypes->push_back(this); 398 } 399} 400 401status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const { 402 const Annotation *annotation = findExportAnnotation(); 403 CHECK(annotation != nullptr); 404 405 std::string name = localName(); 406 407 const AnnotationParam *nameParam = annotation->getParam("name"); 408 if (nameParam != nullptr) { 409 name = nameParam->getSingleString(); 410 } 411 412 bool exportParent = true; 413 const AnnotationParam *exportParentParam = annotation->getParam("export_parent"); 414 if (exportParentParam != nullptr) { 415 exportParent = exportParentParam->getSingleBool(); 416 } 417 418 std::string valuePrefix; 419 const AnnotationParam *prefixParam = annotation->getParam("value_prefix"); 420 if (prefixParam != nullptr) { 421 valuePrefix = prefixParam->getSingleString(); 422 } 423 424 std::string valueSuffix; 425 const AnnotationParam *suffixParam = annotation->getParam("value_suffix"); 426 if (suffixParam != nullptr) { 427 valueSuffix = suffixParam->getSingleString(); 428 } 429 430 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 431 CHECK(scalarType != nullptr); 432 433 std::vector<const EnumType *> chain; 434 if (exportParent) { 435 getTypeChain(&chain); 436 } else { 437 chain = { this }; 438 } 439 440 if (forJava) { 441 if (!name.empty()) { 442 out << "public final class " 443 << name 444 << " {\n"; 445 446 out.indent(); 447 } else { 448 out << "// Values declared in " << localName() << " follow.\n"; 449 } 450 451 const std::string typeName = 452 scalarType->getJavaType(false /* forInitializer */); 453 454 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 455 const auto &type = *it; 456 457 for (const auto &entry : type->values()) { 458 out << "public static final " 459 << typeName 460 << " " 461 << valuePrefix 462 << entry->name() 463 << valueSuffix 464 << " = "; 465 466 // javaValue will make the number signed. 467 std::string value = entry->javaValue(scalarType->getKind()); 468 CHECK(!value.empty()); // use autofilled values for java. 469 out << value; 470 471 out << ";"; 472 473 std::string comment = entry->comment(); 474 if (!comment.empty() && comment != value) { 475 out << " // " << comment; 476 } 477 478 out << "\n"; 479 } 480 } 481 482 if (!name.empty()) { 483 out.unindent(); 484 out << "};\n"; 485 } 486 out << "\n"; 487 488 return OK; 489 } 490 491 if (!name.empty()) { 492 out << "typedef "; 493 } 494 495 out << "enum {\n"; 496 497 out.indent(); 498 499 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 500 const auto &type = *it; 501 502 for (const auto &entry : type->values()) { 503 out << valuePrefix << entry->name() << valueSuffix; 504 505 std::string value = entry->cppValue(scalarType->getKind()); 506 CHECK(!value.empty()); // use autofilled values for c++. 507 out << " = " << value; 508 509 out << ","; 510 511 std::string comment = entry->comment(); 512 if (!comment.empty() && comment != value) { 513 out << " // " << comment; 514 } 515 516 out << "\n"; 517 } 518 } 519 520 out.unindent(); 521 out << "}"; 522 523 if (!name.empty()) { 524 out << " " << name; 525 } 526 527 out << ";\n\n"; 528 529 return OK; 530} 531 532//////////////////////////////////////////////////////////////////////////////// 533 534EnumValue::EnumValue(const char *name, ConstantExpression *value) 535 : mName(name), 536 mValue(value), 537 mIsAutoFill(false) { 538} 539 540std::string EnumValue::name() const { 541 return mName; 542} 543 544std::string EnumValue::value(ScalarType::Kind castKind) const { 545 CHECK(mValue != nullptr); 546 return mValue->value(castKind); 547} 548 549std::string EnumValue::cppValue(ScalarType::Kind castKind) const { 550 CHECK(mValue != nullptr); 551 return mValue->cppValue(castKind); 552} 553std::string EnumValue::javaValue(ScalarType::Kind castKind) const { 554 CHECK(mValue != nullptr); 555 return mValue->javaValue(castKind); 556} 557 558std::string EnumValue::comment() const { 559 CHECK(mValue != nullptr); 560 return mValue->description(); 561} 562 563ConstantExpression *EnumValue::constExpr() const { 564 CHECK(mValue != nullptr); 565 return mValue; 566} 567 568void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) { 569 if(mValue != nullptr) 570 return; 571 mIsAutoFill = true; 572 ConstantExpression *value = new ConstantExpression(); 573 if(prev == nullptr) { 574 *value = ConstantExpression::Zero(type->getKind()); 575 } else { 576 CHECK(prev->mValue != nullptr); 577 *value = prev->mValue->addOne(); 578 } 579 mValue = value; 580} 581 582bool EnumValue::isAutoFill() const { 583 return mIsAutoFill; 584} 585 586bool EnumValue::isEnumValue() const { 587 return true; 588} 589 590//////////////////////////////////////////////////////////////////////////////// 591 592bool BitFieldType::isBitField() const { 593 return true; 594} 595 596std::string BitFieldType::typeName() const { 597 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName())); 598} 599 600void BitFieldType::addNamedTypesToSet(std::set<const FQName> &) const { 601} 602 603bool BitFieldType::isCompatibleElementType(Type *elementType) const { 604 return elementType->isEnum(); 605} 606 607const ScalarType *BitFieldType::resolveToScalarType() const { 608 return mElementType->resolveToScalarType(); 609} 610 611std::string BitFieldType::getCppType(StorageMode mode, 612 bool specifyNamespaces) const { 613 return resolveToScalarType()->getCppType(mode, specifyNamespaces); 614} 615 616std::string BitFieldType::getJavaType(bool forInitializer) const { 617 return resolveToScalarType()->getJavaType(forInitializer); 618} 619 620std::string BitFieldType::getJavaSuffix() const { 621 return resolveToScalarType()->getJavaSuffix(); 622} 623 624std::string BitFieldType::getJavaWrapperType() const { 625 return resolveToScalarType()->getJavaWrapperType(); 626} 627 628std::string BitFieldType::getVtsType() const { 629 return "TYPE_MASK"; 630} 631 632bool BitFieldType::isElidableType() const { 633 return resolveToScalarType()->isElidableType(); 634} 635 636status_t BitFieldType::emitVtsTypeDeclarations(Formatter &out) const { 637 out << "type: " << getVtsType() << "\n"; 638 out << "enum_value: {\n"; 639 out.indent(); 640 status_t err = mElementType->emitVtsTypeDeclarations(out); 641 if (err != OK) { 642 return err; 643 } 644 out.unindent(); 645 out << "}\n"; 646 return OK; 647} 648 649status_t BitFieldType::emitVtsAttributeType(Formatter &out) const { 650 out << "type: " << getVtsType() << "\n"; 651 out << "enum_value: {\n"; 652 out.indent(); 653 status_t err = mElementType->emitVtsAttributeType(out); 654 if (err != OK) { 655 return err; 656 } 657 out.unindent(); 658 out << "}\n"; 659 return OK; 660} 661 662void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const { 663 resolveToScalarType()->getAlignmentAndSize(align, size); 664} 665 666void BitFieldType::emitReaderWriter( 667 Formatter &out, 668 const std::string &name, 669 const std::string &parcelObj, 670 bool parcelObjIsPointer, 671 bool isReader, 672 ErrorMode mode) const { 673 resolveToScalarType()->emitReaderWriterWithCast( 674 out, 675 name, 676 parcelObj, 677 parcelObjIsPointer, 678 isReader, 679 mode, 680 true /* needsCast */); 681} 682 683void BitFieldType::emitJavaFieldReaderWriter( 684 Formatter &out, 685 size_t depth, 686 const std::string &parcelName, 687 const std::string &blobName, 688 const std::string &fieldName, 689 const std::string &offset, 690 bool isReader) const { 691 return resolveToScalarType()->emitJavaFieldReaderWriter( 692 out, depth, parcelName, blobName, fieldName, offset, isReader); 693} 694 695} // namespace android 696 697