1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
25bfec8dd08b3bde9ba3b331e2115210b0e910eaeStephen Hines * Copyright 2010, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_export_element.h"
18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/Decl.h"
209ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/AST/Type.h"
21462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
22e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/Basic/SourceLocation.h"
23e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "clang/Basic/IdentifierTable.h"
24e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
256e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
266315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_context.h"
276315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_export_type.h"
286315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
29e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
30462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
31462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaobool RSExportElement::Initialized = false;
32462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei LiaoRSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
33462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
34474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletstruct DataElementInfo {
35474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet  const char *name;
36cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType dataType;
37474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet  bool normalized;
38474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet  int vsize;
39474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet};
40474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet
41474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletstatic DataElementInfo DataElementInfoTable[] = {
42cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_l", DataTypeUnsigned8, true, 1},
43cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_a", DataTypeUnsigned8, true, 1},
44cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_la", DataTypeUnsigned8, true, 2},
45cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_rgb", DataTypeUnsigned8, true, 3},
46cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_rgba", DataTypeUnsigned8, true, 4},
47cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_rgb565", DataTypeUnsigned8, true, 3},
48cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_rgb5551", DataTypeUnsigned8, true, 4},
49cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    {"rs_pixel_rgb4444", DataTypeUnsigned8, true, 4},
50474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet};
51474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet
52474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletconst int DataElementInfoTableCount = sizeof(DataElementInfoTable) / sizeof(DataElementInfoTable[0]);
53474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet
54474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet// TODO Rename RSExportElement to RSExportDataElement
55462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaovoid RSExportElement::Init() {
569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized) {
579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Initialize ElementInfoMap
58474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet    for (int i = 0; i < DataElementInfoTableCount; i++) {
59474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      ElementInfo *EI = new ElementInfo;
60474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      EI->type = DataElementInfoTable[i].dataType;
61474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      EI->normalized = DataElementInfoTable[i].normalized;
62474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      EI->vsize = DataElementInfoTable[i].vsize;
63474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      llvm::StringRef Name(DataElementInfoTable[i].name);
64474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      ElementInfoMap.insert(ElementInfoMapTy::value_type::Create(
657ac9d0de26d325071ad3f26f8d34514efca2d3d6Stephen Hines          Name, ElementInfoMap.getAllocator(), EI));
669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Initialized = true;
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
69462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
70462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
719ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportType *RSExportElement::Create(RSContext *Context,
729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                      const clang::Type *T,
739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                      const ElementInfo *EI) {
749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create RSExportType corresponded to the @T first and then verify
759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::StringRef TypeName;
779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportType *ET = NULL;
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized)
809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Init();
819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
826e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(EI != NULL && "Element info not found");
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
8448d893dc7794b3cfb74f35955ca763ee4170f9adStephen Hines  if (!RSExportType::NormalizeType(T, TypeName, Context, NULL))
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return NULL;
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
876315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  switch (T->getTypeClass()) {
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::Builtin:
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::Pointer: {
906e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
916e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                    "check your macro)");
929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      RSExportPrimitiveType *EPT =
939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          RSExportPrimitiveType::Create(Context,
949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        T,
959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        TypeName,
969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        EI->normalized);
979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Verify
986e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      ET = EPT;
1009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
1019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::ExtVector: {
1036e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
1046e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                   "your macro)");
1059ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      RSExportVectorType *EVT =
1069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          RSExportVectorType::Create(Context,
107be27482cdeaf08576bc39b72a15d35d13014a636Logan                                     static_cast<const clang::ExtVectorType*>(
1089ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                         T->getCanonicalTypeInternal()
1099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                             .getTypePtr()),
1109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     TypeName,
1119ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     EI->normalized);
1129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Verify
1136e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
1146e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
1156e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                                       "size of vector");
1169ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      ET = EVT;
1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
1189ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    default: {
1206315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      // TODO(zonr): warn that type is not exportable
1219ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
1229ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao              T->getTypeClassName());
1239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
124f8149d9e5a3795e9952717ee6346789a134c55c7Shih-wei Liao    }
1259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
126462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return ET;
128462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
129462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1309ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
1319ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                              const clang::DeclaratorDecl *DD) {
1329ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
133b095e05fef8f0230ab42eaed7a06c3b2d698189aJean-Luc Brouillet  const clang::Type* CT = GetCanonicalType(T);
1349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const ElementInfo* EI = NULL;
1359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
13691a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // Note: RS element like rs_pixel_rgb elements are either in the type of
13791a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // primitive or vector.
1389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if ((CT->getTypeClass() != clang::Type::Builtin) &&
13992b344a51c6c4934e96882bd401e4b13d6d03db8Zonr Chang      (CT->getTypeClass() != clang::Type::ExtVector)) {
1409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportType::Create(Context, T);
1419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
14391a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // Following the typedef chain to see whether it's an element name like
14491a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // rs_pixel_rgb or its alias (via typedef).
1459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  while (T != CT) {
1469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (T->getTypeClass() != clang::Type::Typedef) {
1479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
1489ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    } else {
1499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
15083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao      const clang::TypedefNameDecl *TD = TT->getDecl();
1519ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      EI = GetElementInfo(TD->getName());
1529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      if (EI != NULL)
1539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
154462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      T = TD->getUnderlyingType().getTypePtr();
156462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
1579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
158462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (EI == NULL) {
1609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportType::Create(Context, T);
1619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
1629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportElement::Create(Context, T, EI);
1639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
164462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
165462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaoconst RSExportElement::ElementInfo *
1676315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrRSExportElement::GetElementInfo(const llvm::StringRef &Name) {
1689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized)
1699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Init();
170462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
1729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (I == ElementInfoMap.end())
1739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return NULL;
1749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
1759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return I->getValue();
176462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
177e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
178e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
179