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