1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * 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
34462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaovoid RSExportElement::Init() {
359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized) {
369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Initialize ElementInfoMap
37a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang#define ENUM_RS_DATA_ELEMENT(_name, _dk, _dt, _norm, _vsize)  \
38a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang    {                                                         \
39a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      ElementInfo *EI = new ElementInfo;                      \
40a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      EI->kind = RSExportPrimitiveType::DataKind ## _dk;      \
41a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      EI->type = RSExportPrimitiveType::DataType ## _dt;      \
42a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      EI->normalized = _norm;                                 \
43a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      EI->vsize = _vsize;                                     \
44a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang                                                              \
45a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      llvm::StringRef Name(_name);                            \
46a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang      ElementInfoMap.insert(                                  \
47a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang          ElementInfoMapTy::value_type::Create(               \
48a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang              Name.begin(),                                   \
49a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang              Name.end(),                                     \
50a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang              ElementInfoMap.getAllocator(),                  \
51a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang              EI));                                           \
529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
53a65ec168e41e3ee9c6e8ac04cde694bbbfc2590aZonr Chang#include "RSDataElementEnums.inc"
54462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Initialized = true;
569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return;
58462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
59462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
609ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportType *RSExportElement::Create(RSContext *Context,
619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                      const clang::Type *T,
629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                      const ElementInfo *EI) {
639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Create RSExportType corresponded to the @T first and then verify
649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  llvm::StringRef TypeName;
669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSExportType *ET = NULL;
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized)
699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Init();
709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
716e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(EI != NULL && "Element info not found");
729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
7378e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines  if (!RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(),
7478e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines                                   NULL))
759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return NULL;
769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
776315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  switch (T->getTypeClass()) {
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::Builtin:
799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::Pointer: {
806e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
816e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                    "check your macro)");
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      RSExportPrimitiveType *EPT =
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          RSExportPrimitiveType::Create(Context,
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        T,
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        TypeName,
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        EI->kind,
879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                        EI->normalized);
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Verify
896e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      ET = EPT;
919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case clang::Type::ExtVector: {
946e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
956e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                   "your macro)");
969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      RSExportVectorType *EVT =
979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          RSExportVectorType::Create(Context,
98be27482cdeaf08576bc39b72a15d35d13014a636Logan                                     static_cast<const clang::ExtVectorType*>(
999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                         T->getCanonicalTypeInternal()
1009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                             .getTypePtr()),
1019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     TypeName,
1029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     EI->kind,
1039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                     EI->normalized);
1049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Verify
1056e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
1066e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
1076e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                                                       "size of vector");
1089ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      ET = EVT;
1099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
1109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1119ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    default: {
1126315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      // TODO(zonr): warn that type is not exportable
1139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
1149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao              T->getTypeClassName());
1159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
116f8149d9e5a3795e9952717ee6346789a134c55c7Shih-wei Liao    }
1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
118462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return ET;
120462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
121462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1229ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoRSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
1239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                              const clang::DeclaratorDecl *DD) {
1249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
1259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const clang::Type* CT = GET_CANONICAL_TYPE(T);
1269ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  const ElementInfo* EI = NULL;
1279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
12891a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // Note: RS element like rs_pixel_rgb elements are either in the type of
12991a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // primitive or vector.
1309ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if ((CT->getTypeClass() != clang::Type::Builtin) &&
13192b344a51c6c4934e96882bd401e4b13d6d03db8Zonr Chang      (CT->getTypeClass() != clang::Type::ExtVector)) {
1329ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportType::Create(Context, T);
1339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
13591a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // Following the typedef chain to see whether it's an element name like
13691a3783ce1f4eb9ad6e9c1ecdbd27f3d6dc58634Shih-wei Liao  // rs_pixel_rgb or its alias (via typedef).
1379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  while (T != CT) {
1389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (T->getTypeClass() != clang::Type::Typedef) {
1399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
1409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    } else {
1419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
14283f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao      const clang::TypedefNameDecl *TD = TT->getDecl();
1439ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      EI = GetElementInfo(TD->getName());
1449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      if (EI != NULL)
1459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
146462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      T = TD->getUnderlyingType().getTypePtr();
148462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
1499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
150462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1519ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (EI == NULL) {
1529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportType::Create(Context, T);
1539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
1549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return RSExportElement::Create(Context, T, EI);
1559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
156462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
157462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaoconst RSExportElement::ElementInfo *
1596315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrRSExportElement::GetElementInfo(const llvm::StringRef &Name) {
1609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (!Initialized)
1619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    Init();
162462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
1639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
1649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (I == ElementInfoMap.end())
1659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return NULL;
1669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
1679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return I->getValue();
168462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
169e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
170e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
171