Home | History | Annotate | Download | only in slang
      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