slang_rs_export_element.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2010, 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. #include "slang_rs_export_element.h"
  17. #include "clang/AST/Decl.h"
  18. #include "clang/AST/Type.h"
  19. #include "clang/Basic/SourceLocation.h"
  20. #include "clang/Basic/IdentifierTable.h"
  21. #include "slang_assert.h"
  22. #include "slang_rs_context.h"
  23. #include "slang_rs_export_type.h"
  24. namespace slang {
  25. bool RSExportElement::Initialized = false;
  26. RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
  27. struct DataElementInfo {
  28. const char *name;
  29. DataType dataType;
  30. bool normalized;
  31. int vsize;
  32. };
  33. static DataElementInfo DataElementInfoTable[] = {
  34. {"rs_pixel_l", DataTypeUnsigned8, true, 1},
  35. {"rs_pixel_a", DataTypeUnsigned8, true, 1},
  36. {"rs_pixel_la", DataTypeUnsigned8, true, 2},
  37. {"rs_pixel_rgb", DataTypeUnsigned8, true, 3},
  38. {"rs_pixel_rgba", DataTypeUnsigned8, true, 4},
  39. {"rs_pixel_rgb565", DataTypeUnsigned8, true, 3},
  40. {"rs_pixel_rgb5551", DataTypeUnsigned8, true, 4},
  41. {"rs_pixel_rgb4444", DataTypeUnsigned8, true, 4},
  42. };
  43. const int DataElementInfoTableCount = sizeof(DataElementInfoTable) / sizeof(DataElementInfoTable[0]);
  44. // TODO Rename RSExportElement to RSExportDataElement
  45. void RSExportElement::Init() {
  46. if (!Initialized) {
  47. // Initialize ElementInfoMap
  48. for (int i = 0; i < DataElementInfoTableCount; i++) {
  49. ElementInfo *EI = new ElementInfo;
  50. EI->type = DataElementInfoTable[i].dataType;
  51. EI->normalized = DataElementInfoTable[i].normalized;
  52. EI->vsize = DataElementInfoTable[i].vsize;
  53. llvm::StringRef Name(DataElementInfoTable[i].name);
  54. ElementInfoMap.insert(ElementInfoMapTy::value_type::Create(
  55. Name, ElementInfoMap.getAllocator(), EI));
  56. }
  57. Initialized = true;
  58. }
  59. }
  60. RSExportType *RSExportElement::Create(RSContext *Context,
  61. const clang::Type *T,
  62. const ElementInfo *EI) {
  63. // Create RSExportType corresponded to the @T first and then verify
  64. llvm::StringRef TypeName;
  65. RSExportType *ET = nullptr;
  66. if (!Initialized)
  67. Init();
  68. slangAssert(EI != nullptr && "Element info not found");
  69. if (!RSExportType::NormalizeType(T, TypeName, Context, nullptr,
  70. NotLegacyKernelArgument))
  71. return nullptr;
  72. switch (T->getTypeClass()) {
  73. case clang::Type::Builtin:
  74. case clang::Type::Pointer: {
  75. slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
  76. "check your macro)");
  77. RSExportPrimitiveType *EPT =
  78. RSExportPrimitiveType::Create(Context,
  79. T,
  80. TypeName,
  81. EI->normalized);
  82. // Verify
  83. slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
  84. ET = EPT;
  85. break;
  86. }
  87. case clang::Type::ExtVector: {
  88. slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
  89. "your macro)");
  90. RSExportVectorType *EVT =
  91. RSExportVectorType::Create(Context,
  92. static_cast<const clang::ExtVectorType*>(
  93. T->getCanonicalTypeInternal()
  94. .getTypePtr()),
  95. TypeName,
  96. EI->normalized);
  97. // Verify
  98. slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
  99. slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
  100. "size of vector");
  101. ET = EVT;
  102. break;
  103. }
  104. default: {
  105. // TODO(zonr): warn that type is not exportable
  106. fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
  107. T->getTypeClassName());
  108. break;
  109. }
  110. }
  111. return ET;
  112. }
  113. RSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
  114. const clang::DeclaratorDecl *DD) {
  115. const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
  116. const clang::Type* CT = GetCanonicalType(T);
  117. const ElementInfo* EI = nullptr;
  118. // Note: RS element like rs_pixel_rgb elements are either in the type of
  119. // primitive or vector.
  120. if ((CT->getTypeClass() != clang::Type::Builtin) &&
  121. (CT->getTypeClass() != clang::Type::ExtVector)) {
  122. return RSExportType::Create(Context, T, NotLegacyKernelArgument);
  123. }
  124. // Following the typedef chain to see whether it's an element name like
  125. // rs_pixel_rgb or its alias (via typedef).
  126. while (T != CT) {
  127. if (T->getTypeClass() != clang::Type::Typedef) {
  128. break;
  129. } else {
  130. const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
  131. const clang::TypedefNameDecl *TD = TT->getDecl();
  132. EI = GetElementInfo(TD->getName());
  133. if (EI != nullptr)
  134. break;
  135. T = TD->getUnderlyingType().getTypePtr();
  136. }
  137. }
  138. if (EI == nullptr) {
  139. return RSExportType::Create(Context, T, NotLegacyKernelArgument);
  140. } else {
  141. return RSExportElement::Create(Context, T, EI);
  142. }
  143. }
  144. const RSExportElement::ElementInfo *
  145. RSExportElement::GetElementInfo(const llvm::StringRef &Name) {
  146. if (!Initialized)
  147. Init();
  148. ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
  149. if (I == ElementInfoMap.end())
  150. return nullptr;
  151. else
  152. return I->getValue();
  153. }
  154. } // namespace slang