slang_rs_export_element.cpp revision 6e6578a360497f78a181e63d7783422a9c9bfb15
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright 2010, The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *     http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
169ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
171212a022fa5f8ef9585d765b1809521812af882cIan Rogers#include "slang_rs_export_element.h"
189ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
1967f99418f648c3a95256ed3dcd8e8b64eef0b372Anwar Ghuloum#include "clang/AST/Decl.h"
2067f99418f648c3a95256ed3dcd8e8b64eef0b372Anwar Ghuloum#include "clang/AST/Type.h"
21d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
2267f99418f648c3a95256ed3dcd8e8b64eef0b372Anwar Ghuloum#include "clang/Basic/SourceLocation.h"
23d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include "clang/Basic/IdentifierTable.h"
2439c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison
2527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include "slang_assert.h"
261aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "slang_rs_context.h"
27a84395489098e4531619b1cffd1afc282b14510eSameer Abu Asal#include "slang_rs_export_type.h"
289ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
29b34f69ab43aaf7a6e6045c95f398baf566ef5023Nicolas Geoffraynamespace slang {
30be0e546730e532ef0987cd4bde2c6f5a1b14dd2aVladimir Marko
3189756f21c107d96e6d1bbc75811bd33078c8ceeeIan Rogersbool RSExportElement::Initialized = false;
324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian RogersRSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
33c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
342730db03beee4d6687ddfb5000c33c0370fbc6ebVladimir Markovoid RSExportElement::Init() {
352bc47809febcf36369dd40877b8226318642b428Vladimir Marko  if (!Initialized) {
36ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Initialize ElementInfoMap
379baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom#define ENUM_RS_DATA_ELEMENT(_name, _dk, _dt, _norm, _vsize)  \
386d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    {                                                         \
391f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom      ElementInfo *EI = new ElementInfo;                      \
401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      EI->kind = RSExportPrimitiveType::DataKind ## _dk;      \
411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      EI->type = RSExportPrimitiveType::DataType ## _dt;      \
421d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      EI->normalized = _norm;                                 \
43ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      EI->vsize = _vsize;                                     \
44ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                                              \
452dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      llvm::StringRef Name(_name);                            \
462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      ElementInfoMap.insert(                                  \
4739ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers          ElementInfoMapTy::value_type::Create(               \
482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers              Name.begin(),                                   \
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers              Name.end(),                                     \
502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers              ElementInfoMap.getAllocator(),                  \
5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers              EI));                                           \
5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
53c645f1ddb7c40bea6a38eda4b3f83f6b6dec405bMathieu Chartier#include "RSDataElementEnums.inc"
5450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers
550e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier    Initialized = true;
56848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  }
57d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  return;
58776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers}
592bc47809febcf36369dd40877b8226318642b428Vladimir Marko
609ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian CarlstromRSExportType *RSExportElement::Create(RSContext *Context,
619ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom                                      const clang::Type *T,
629ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom                                      const ElementInfo *EI) {
63996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  // Create RSExportType corresponded to the @T first and then verify
64398f64b5805246765b699839b439e18c0dfbf2eeElliott Hughes
65996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  llvm::StringRef TypeName;
66996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  RSExportType *ET = NULL;
67996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
68996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (!Initialized)
69996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    Init();
70996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
71e732ef1c0192acd71925bd0ff1ab09640d45531dIan Rogers  slangAssert(EI != NULL && "Element info not found");
72996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
73996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (!RSExportType::NormalizeType(T, TypeName, NULL, NULL, NULL))
74f096aad9203d7c50b2f9cbe1c1215a50c265a059Vladimir Marko    return NULL;
75c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
76ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers  switch (T->getTypeClass()) {
77ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers    case clang::Type::Builtin:
78ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers    case clang::Type::Pointer: {
79ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers      slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
80ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers                                    "check your macro)");
81ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers      RSExportPrimitiveType *EPT =
8202c42237741b5573f9d790a5a0f17f408dceb543Sameer Abu Asal          RSExportPrimitiveType::Create(Context,
83fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers                                        T,
84fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers                                        TypeName,
852ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                        EI->kind,
86c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                        EI->normalized);
87c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      // Verify
882ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
892ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      ET = EPT;
902ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      break;
91b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes    }
92c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    case clang::Type::ExtVector: {
93c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
94c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                   "your macro)");
95c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      RSExportVectorType *EVT =
96c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers          RSExportVectorType::Create(Context,
97c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                     static_cast<clang::ExtVectorType*>(
98c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                         T->getCanonicalTypeInternal()
99c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                             .getTypePtr()),
100c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                     TypeName,
101c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                     EI->kind,
102c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers                                     EI->normalized);
103fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers      // Verify
104fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers      slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
105fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers      slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
106fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers                                                       "size of vector");
107fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers      ET = EVT;
108fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers      break;
109fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers    }
110fae370a044f5817f69937cccfd2d12a16b374266Ian Rogers    default: {
111c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      // TODO(zonr): warn that type is not exportable
1122ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
113c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers              T->getTypeClassName());
1142ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      break;
115c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    }
1162ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
1172ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
1182ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  return ET;
1192ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers}
1202ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
1212ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian RogersRSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
1222ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                              const clang::DeclaratorDecl *DD) {
1232ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
1242ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  const clang::Type* CT = GET_CANONICAL_TYPE(T);
1252ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  const ElementInfo* EI = NULL;
1262ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
1272ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  // Note: RS element like rs_pixel_rgb elements are either in the type of
1282ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  // primitive or vector.
1292ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  if ((CT->getTypeClass() != clang::Type::Builtin) &&
1302ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      (CT->getTypeClass() != clang::Type::ExtVector)) {
1312ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    return RSExportType::Create(Context, T);
1322ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
1332ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
1342ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  // Following the typedef chain to see whether it's an element name like
1352ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  // rs_pixel_rgb or its alias (via typedef).
1362ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  while (T != CT) {
137c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    if (T->getTypeClass() != clang::Type::Typedef) {
138c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      break;
139996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    } else {
14050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
141996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers      const clang::TypedefDecl *TD = TT->getDecl();
14250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers      EI = GetElementInfo(TD->getName());
143996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers      if (EI != NULL)
144996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers        break;
145996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
146996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers      T = TD->getUnderlyingType().getTypePtr();
147c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    }
148c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
149c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
150c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  if (EI == NULL) {
151996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    return RSExportType::Create(Context, T);
152c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  } else {
153c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    return RSExportElement::Create(Context, T, EI);
154c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
155c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers}
156996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
157c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogersconst RSExportElement::ElementInfo *
158c8b306f5221658c7e4b5516be8917dc8c9288e7eIan RogersRSExportElement::GetElementInfo(const llvm::StringRef &Name) {
159c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  if (!Initialized)
160c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    Init();
161996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
162c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
163c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  if (I == ElementInfoMap.end())
164c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    return NULL;
165c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  else
166996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    return I->getValue();
167c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers}
168c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
169c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers}  // namespace slang
170c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers