slang_rs_export_type.cpp revision 474655a402e70cb329e1bcd4ebbe00bdc5be4206
1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Copyright 2010-2012, The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *     http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "slang_rs_export_type.h"
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include <list>
20d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn#include <vector>
21a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh#include "clang/AST/ASTContext.h"
23a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "clang/AST/Attr.h"
24a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "clang/AST/RecordLayout.h"
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
266bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius#include "llvm/ADT/StringExtras.h"
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "llvm/IR/DataLayout.h"
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "llvm/IR/DerivedTypes.h"
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "llvm/IR/Type.h"
30db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
316bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius#include "slang_assert.h"
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "slang_rs_context.h"
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "slang_rs_export_element.h"
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#include "slang_rs_type_spec.h"
352e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn#include "slang_version.h"
36eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
37a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville#define CHECK_PARENT_EQUALITY(ParentClass, E) \
38286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  if (!ParentClass::equals(E))                \
39286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    return false;
402999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn
417fa8ac39602ee9841dfcb0fb5c5f4d401925f8b5Tyler Gunnnamespace slang {
42db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
43a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillenamespace {
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/* For the data types we support, their category, names, and size (in bits).
46a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * IMPORTANT: The data types in this table should be at the same index
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * as specified by the corresponding DataType enum.
4921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar */
5021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkarstatic RSReflectionType gReflectionTypes[] = {
51a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false},
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false},
53a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false},
54db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    {PrimitiveDataType, "SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false},
55db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    {PrimitiveDataType, "SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false},
56db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    {PrimitiveDataType, "SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false},
57a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false},
58a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true},
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true},
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true},
61a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false},
62a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false},
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    {PrimitiveDataType, "UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false},
66a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false},
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {PrimitiveDataType, "UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false},
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {MatrixDataType, "MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false},
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {MatrixDataType, "MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false},
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {MatrixDataType, "MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false},
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // TODO: For 64 bit, what will be the size of the objects??
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false},
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false},
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false},
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false},
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false},
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false},
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false},
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false},
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false},
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {ObjectDataType, "RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false},
85fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    {ObjectDataType, "RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false},
86fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    {ObjectDataType, "RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false}
87fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn};
886bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
896bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusconst int kMaxVectorSize = 4;
906bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
918bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajanstruct BuiltinInfo {
928bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan  clang::BuiltinType::Kind builtinTypeKind;
932e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn  RSExportPrimitiveType::DataType type;
94db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  /* TODO If we return std::string instead of llvm::StringRef, we could build
95db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn   * the name instead of duplicating the entries.
96db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn   */
97db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  const char *cname[kMaxVectorSize];
98db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn};
99db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
100db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler GunnBuiltinInfo BuiltinInfoTable[] = {
101db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    {clang::BuiltinType::Bool, RSExportPrimitiveType::DataTypeBoolean,
102359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     {"bool", "bool2", "bool3", "bool4"}},
103359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    {clang::BuiltinType::Char_U, RSExportPrimitiveType::DataTypeUnsigned8,
104222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C     {"uchar", "uchar2", "uchar3", "uchar4"}},
105222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    {clang::BuiltinType::UChar, RSExportPrimitiveType::DataTypeUnsigned8,
106fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     {"uchar", "uchar2", "uchar3", "uchar4"}},
107fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    {clang::BuiltinType::Char16, RSExportPrimitiveType::DataTypeSigned16,
108fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     {"short", "short2", "short3", "short4"}},
109286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    {clang::BuiltinType::Char32, RSExportPrimitiveType::DataTypeSigned32,
110286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     {"int", "int2", "int3", "int4"}},
111286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    {clang::BuiltinType::UShort, RSExportPrimitiveType::DataTypeUnsigned16,
112286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     {"ushort", "ushort2", "ushort3", "ushort4"}},
113286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    {clang::BuiltinType::UInt, RSExportPrimitiveType::DataTypeUnsigned32,
11463fa599fef0383b41f85e1fc3a38d33c4434e24aTyler Gunn     {"uint", "uint2", "uint3", "uint4"}},
1157a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    {clang::BuiltinType::ULong, RSExportPrimitiveType::DataTypeUnsigned32,
1167a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     {"uint", "uint2", "uint3", "uint4"}},
1177a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    {clang::BuiltinType::ULongLong, RSExportPrimitiveType::DataTypeUnsigned64,
1187a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     {"ulong", "ulong2", "ulong3", "ulong4"}},
1197a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
1207a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    {clang::BuiltinType::Char_S, RSExportPrimitiveType::DataTypeSigned8,
1217a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     {"char", "char2", "char3", "char4"}},
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::SChar, RSExportPrimitiveType::DataTypeSigned8,
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"char", "char2", "char3", "char4"}},
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::Short, RSExportPrimitiveType::DataTypeSigned16,
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"short", "short2", "short3", "short4"}},
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::Int, RSExportPrimitiveType::DataTypeSigned32,
1276bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius     {"int", "int2", "int3", "int4"}},
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::Long, RSExportPrimitiveType::DataTypeSigned64,
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"long", "long2", "long3", "long4"}},
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::LongLong, RSExportPrimitiveType::DataTypeSigned64,
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"long", "long2", "long3", "long4"}},
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::Float, RSExportPrimitiveType::DataTypeFloat32,
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"float", "float2", "float3", "float4"}},
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {clang::BuiltinType::Double, RSExportPrimitiveType::DataTypeFloat64,
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     {"double", "double2", "double3", "double4"}},
136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville};
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleconst int BuiltinInfoTableCount = sizeof(BuiltinInfoTable) / sizeof(BuiltinInfoTable[0]);
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillestruct NameAndPrimitiveType {
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  const char *name;
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  RSExportPrimitiveType::DataType dataType;
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville};
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1446bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusstatic NameAndPrimitiveType MatrixAndObjectDataTypes[] = {
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_matrix2x2", RSExportPrimitiveType::DataTypeRSMatrix2x2},
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_matrix3x3", RSExportPrimitiveType::DataTypeRSMatrix3x3},
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_matrix4x4", RSExportPrimitiveType::DataTypeRSMatrix4x4},
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_element", RSExportPrimitiveType::DataTypeRSElement},
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_type", RSExportPrimitiveType::DataTypeRSType},
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_allocation", RSExportPrimitiveType::DataTypeRSAllocation},
1516bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_sampler", RSExportPrimitiveType::DataTypeRSSampler},
1526bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_script", RSExportPrimitiveType::DataTypeRSScript},
1536bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_mesh", RSExportPrimitiveType::DataTypeRSMesh},
1546bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_path", RSExportPrimitiveType::DataTypeRSPath},
1556bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_program_fragment", RSExportPrimitiveType::DataTypeRSProgramFragment},
1566bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    {"rs_program_vertex", RSExportPrimitiveType::DataTypeRSProgramVertex},
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_program_raster", RSExportPrimitiveType::DataTypeRSProgramRaster},
158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_program_store", RSExportPrimitiveType::DataTypeRSProgramStore},
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    {"rs_font", RSExportPrimitiveType::DataTypeRSFont},
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville};
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleconst int MatrixAndObjectDataTypesCount =
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    sizeof(MatrixAndObjectDataTypes) / sizeof(MatrixAndObjectDataTypes[0]);
164f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu
16508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshstatic const clang::Type *TypeExportableHelper(
166c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    const clang::Type *T,
1676bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    slang::RSContext *Context,
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    const clang::VarDecl *VD,
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    const clang::RecordDecl *TopLevelRecord);
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilletemplate <unsigned N>
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillestatic void ReportTypeError(slang::RSContext *Context,
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            const clang::NamedDecl *ND,
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            const clang::RecordDecl *TopLevelRecord,
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            const char (&Message)[N],
177d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao                            unsigned int TargetAPI = 0) {
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  // Attempt to use the type declaration first (if we have one).
179d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao  // Fall back to the variable definition, if we are looking at something
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  // like an array declaration that can't be exported.
1816a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if (TopLevelRecord) {
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    Context->ReportError(TopLevelRecord->getLocation(), Message)
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        << TopLevelRecord->getName() << TargetAPI;
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  } else if (ND) {
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    Context->ReportError(ND->getLocation(), Message) << ND->getName()
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                                     << TargetAPI;
18708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh  } else {
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    slangAssert(false && "Variables should be validated before exporting");
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
191553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
192553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunnstatic const clang::Type *ConstantArrayTypeExportableHelper(
193553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn    const clang::ConstantArrayType *CAT,
194553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
195553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn    slang::RSContext *Context,
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    const clang::VarDecl *VD,
19708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh    const clang::RecordDecl *TopLevelRecord) {
19808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh  // Check element type
1996bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius  const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
2006bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius  if (ElementType->isArrayType()) {
201c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu    ReportTypeError(Context, VD, TopLevelRecord,
202c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                    "multidimensional arrays cannot be exported: '%0'");
203c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu    return NULL;
204c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu  } else if (ElementType->isExtVectorType()) {
205c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu    const clang::ExtVectorType *EVT =
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        static_cast<const clang::ExtVectorType*>(ElementType);
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    unsigned numElements = EVT->getNumElements();
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
209f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
2108bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) {
211c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan      ReportTypeError(Context, VD, TopLevelRecord,
2126bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        "vectors of non-primitive types cannot be exported: '%0'");
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return NULL;
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    if (numElements == 3 && CAT->getSize() != 1) {
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      ReportTypeError(Context, VD, TopLevelRecord,
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        "arrays of width 3 vector types cannot be exported: '%0'");
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return NULL;
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if (TypeExportableHelper(ElementType, SPS, Context, VD,
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                           TopLevelRecord) == NULL) {
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return NULL;
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  } else {
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return CAT;
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink SavilleBuiltinInfo *FindBuiltinType(clang::BuiltinType::Kind builtinTypeKind) {
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  for (int i = 0; i < BuiltinInfoTableCount; i++) {
2336bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    if (builtinTypeKind == BuiltinInfoTable[i].builtinTypeKind) {
2348bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan      return &BuiltinInfoTable[i];
2358bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
2366bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius  }
237c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu  return NULL;
238c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu}
239c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
240c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wustatic const clang::Type *TypeExportableHelper(
241c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu    clang::Type const *T,
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    llvm::SmallPtrSet<clang::Type const *, 8> &SPS,
243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    slang::RSContext *Context,
244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::VarDecl const *VD,
245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::RecordDecl const *TopLevelRecord) {
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  // Normalize first
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if ((T = GET_CANONICAL_TYPE(T)) == NULL)
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return NULL;
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if (SPS.count(T))
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return T;
25274c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi
25374c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi  switch (T->getTypeClass()) {
25474c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    case clang::Type::Builtin: {
25574c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi      const clang::BuiltinType *BT =
25674c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
2577a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn      return FindBuiltinType(BT->getKind()) == NULL ? NULL : T;
2587a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    }
259f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    case clang::Type::Record: {
2602e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn      if (RSExportPrimitiveType::GetRSSpecificType(T) !=
261f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn          RSExportPrimitiveType::DataTypeUnknown) {
2627a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        return T;  // RS object type, no further checks are needed
2637a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn      }
2647a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
2657a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn      // Check internal struct
266f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      if (T->isUnionType()) {
267f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        ReportTypeError(Context, VD, T->getAsUnionType()->getDecl(),
2682e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        "unions cannot be exported: '%0'");
269f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return NULL;
270f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      } else if (!T->isStructureType()) {
2712e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        slangAssert(false && "Unknown type cannot be exported");
272f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return NULL;
273f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      }
274f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
275f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
276f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      if (RD != NULL) {
277f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        RD = RD->getDefinition();
2782e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        if (RD == NULL) {
279f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn          ReportTypeError(Context, NULL, T->getAsStructureType()->getDecl(),
2802e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                          "struct is not defined in this module");
281f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn          return NULL;
282f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
283f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      }
2842e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
285f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      if (!TopLevelRecord) {
286f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        TopLevelRecord = RD;
2872e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn      }
288f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      if (RD->getName().empty()) {
289f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        ReportTypeError(Context, NULL, RD,
290f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                        "anonymous structures cannot be exported");
291f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return NULL;
292f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn      }
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Fast check
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Insert myself into checking set
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      SPS.insert(T);
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Check all element
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville               FE = RD->field_end();
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville           FI != FE;
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville           FI++) {
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        const clang::FieldDecl *FD = *FI;
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        FT = GET_CANONICAL_TYPE(FT);
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!TypeExportableHelper(FT, SPS, Context, VD, TopLevelRecord)) {
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return NULL;
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // We don't support bit fields yet
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // TODO(zonr/srhines): allow bit fields of size 8, 16, 32
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (FD->isBitField()) {
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          Context->ReportError(
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              FD->getLocation(),
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              "bit fields are not able to be exported: '%0.%1'")
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              << RD->getName() << FD->getName();
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return NULL;
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return T;
32733cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
32833cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    case clang::Type::Pointer: {
32933cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      if (TopLevelRecord) {
33033cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu        ReportTypeError(Context, VD, TopLevelRecord,
33133cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu            "structures containing pointers cannot be exported: '%0'");
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::PointerType *PT =
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        UNSAFE_CAST_TYPE(const clang::PointerType, T);
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (PointeeType->getTypeClass() == clang::Type::Pointer) {
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ReportTypeError(Context, VD, TopLevelRecord,
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            "multiple levels of pointers cannot be exported: '%0'");
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // We don't support pointer with array-type pointee or unsupported pointee
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // type
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (PointeeType->isArrayType() ||
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          (TypeExportableHelper(PointeeType, SPS, Context, VD,
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                TopLevelRecord) == NULL))
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      else
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return T;
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::ExtVector: {
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::ExtVectorType *EVT =
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Only vector with size 2, 3 and 4 are supported.
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Check base element type
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          (TypeExportableHelper(ElementType, SPS, Context, VD,
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                TopLevelRecord) == NULL))
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return NULL;
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      else
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return T;
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::ConstantArray: {
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::ConstantArrayType *CAT =
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return ConstantArrayTypeExportableHelper(CAT, SPS, Context, VD,
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                               TopLevelRecord);
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::Enum: {
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // FIXME: We currently convert enums to integers, rather than reflecting
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // a more complete (and nicer type-safe Java version).
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return Context->getASTContext().IntTy.getTypePtr();
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    default: {
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      slangAssert(false && "Unknown type cannot be validated");
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return NULL;
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// Return the type that can be used to create RSExportType, will always return
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// the canonical type
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// If the Type T is not exportable, this function returns NULL. DiagEngine is
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// used to generate proper Clang diagnostic messages when a
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// non-exportable type is detected. TopLevelRecord is used to capture the
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// highest struct (in the case of a nested hierarchy) for detecting other
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// types that cannot be exported (mostly pointers within a struct).
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillestatic const clang::Type *TypeExportable(const clang::Type *T,
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                         slang::RSContext *Context,
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                         const clang::VarDecl *VD) {
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  llvm::SmallPtrSet<const clang::Type*, 8> SPS =
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      llvm::SmallPtrSet<const clang::Type*, 8>();
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  return TypeExportableHelper(T, SPS, Context, VD, NULL);
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillestatic bool ValidateRSObjectInVarDecl(slang::RSContext *Context,
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                      clang::VarDecl *VD, bool InCompositeType,
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                      unsigned int TargetAPI) {
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if (TargetAPI < SLANG_JB_TARGET_API) {
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    // Only if we are already in a composite type (like an array or structure).
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    if (InCompositeType) {
411c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan      // Only if we are actually exported (i.e. non-static).
412c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan      if (VD->hasLinkage() &&
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          (VD->getFormalLinkage() == clang::ExternalLinkage)) {
4141999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        // Only if we are not a pointer to an object.
4151999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr());
4161999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (T->getTypeClass() != clang::Type::Pointer) {
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          ReportTypeError(Context, VD, NULL,
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                          "arrays/structures containing RS object types "
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                          "cannot be exported in target API < %1: '%0'",
420f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu                          SLANG_JB_TARGET_API);
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return false;
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  return true;
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// Helper function for ValidateType(). We do a recursive descent on the
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// type hierarchy to ensure that we can properly export/handle the
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// declaration.
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// \return true if the variable declaration is valid,
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//         false if it is invalid (along with proper diagnostics).
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville//
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// C - ASTContext (for diagnostics + builtin types).
43734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu// T - sub-type that we are validating.
43834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu// ND - (optional) top-level named declaration that we are validating.
43934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu// SPS - set of types we have already seen/validated.
44034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu// InCompositeType - true if we are within an outer composite type.
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// UnionDecl - set if we are in a sub-type of a union.
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// TargetAPI - target SDK API level.
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville// IsFilterscript - whether or not we are compiling for Filterscript
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillestatic bool ValidateTypeHelper(
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    slang::RSContext *Context,
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::ASTContext &C,
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    const clang::Type *&T,
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::NamedDecl *ND,
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::SourceLocation Loc,
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    llvm::SmallPtrSet<const clang::Type*, 8>& SPS,
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    bool InCompositeType,
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clang::RecordDecl *UnionDecl,
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    unsigned int TargetAPI,
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    bool IsFilterscript) {
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if ((T = GET_CANONICAL_TYPE(T)) == NULL)
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return true;
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if (SPS.count(T))
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return true;
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  switch (T->getTypeClass()) {
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::Record: {
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (RSExportPrimitiveType::IsRSObjectType(T)) {
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL);
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (VD && !ValidateRSObjectInVarDecl(Context, VD, InCompositeType,
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                             TargetAPI)) {
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return false;
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (RSExportPrimitiveType::GetRSSpecificType(T) !=
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          RSExportPrimitiveType::DataTypeUnknown) {
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!UnionDecl) {
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return true;
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (RSExportPrimitiveType::IsRSObjectType(T)) {
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          ReportTypeError(Context, NULL, UnionDecl,
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              "unions containing RS object types are not allowed");
478d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee          return false;
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      clang::RecordDecl *RD = NULL;
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Check internal struct
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (T->isUnionType()) {
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        RD = T->getAsUnionType()->getDecl();
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        UnionDecl = RD;
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      } else if (T->isStructureType()) {
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        RD = T->getAsStructureType()->getDecl();
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      } else {
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        slangAssert(false && "Unknown type cannot be exported");
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return false;
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (RD != NULL) {
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        RD = RD->getDefinition();
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (RD == NULL) {
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          // FIXME
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return true;
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Fast check
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return false;
506032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Insert myself into checking set
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      SPS.insert(T);
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      // Check all elements
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville               FE = RD->field_end();
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville           FI != FE;
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville           FI++) {
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        const clang::FieldDecl *FD = *FI;
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        FT = GET_CANONICAL_TYPE(FT);
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!ValidateTypeHelper(Context, C, FT, ND, Loc, SPS, true, UnionDecl,
520d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee                                TargetAPI, IsFilterscript)) {
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return false;
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return true;
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::Builtin: {
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (IsFilterscript) {
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clang::QualType QT = T->getCanonicalTypeInternal();
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (QT == C.DoubleTy ||
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            QT == C.LongDoubleTy ||
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            QT == C.LongTy ||
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            QT == C.LongLongTy) {
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          if (ND) {
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Context->ReportError(
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Loc,
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                "Builtin types > 32 bits in size are forbidden in "
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                "Filterscript: '%0'")
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                << ND->getName();
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          } else {
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Context->ReportError(
5434567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen                Loc,
5444567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen                "Builtin types > 32 bits in size are forbidden in "
5454567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen                "Filterscript");
54693c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan          }
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return false;
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      break;
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::Pointer: {
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (IsFilterscript) {
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (ND) {
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          Context->ReportError(Loc,
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                               "Pointers are forbidden in Filterscript: '%0'")
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              << ND->getName();
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          return false;
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
561d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati          // TODO(srhines): Find a better way to handle expressions (i.e. no
562d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati          // NamedDecl) involving pointers in FS that should be allowed.
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          // An example would be calls to library functions like
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          // rsMatrixMultiply() that take rs_matrixNxN * types.
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::PointerType *PT =
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        UNSAFE_CAST_TYPE(const clang::PointerType, T);
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return ValidateTypeHelper(Context, C, PointeeType, ND, Loc, SPS,
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                InCompositeType, UnionDecl, TargetAPI,
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                IsFilterscript);
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::ExtVector: {
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::ExtVectorType *EVT =
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (TargetAPI < SLANG_ICS_TARGET_API &&
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          InCompositeType &&
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          EVT->getNumElements() == 3 &&
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          ND &&
585d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee          ND->getFormalLinkage() == clang::ExternalLinkage) {
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ReportTypeError(Context, ND, NULL,
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        "structs containing vectors of dimension 3 cannot "
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        "be exported at this API level: '%0'");
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return false;
590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true,
592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                UnionDecl, TargetAPI, IsFilterscript);
593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    case clang::Type::ConstantArray: {
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::ConstantArrayType *CAT =
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T);
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true,
60097fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com                                UnionDecl, TargetAPI, IsFilterscript);
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
60237800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan
60337800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan    default: {
60437800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan      break;
60537800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan    }
60637800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan  }
60737800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  return true;
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}  // namespace
612c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
6136bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius/****************************** RSExportType ******************************/
6146bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusbool RSExportType::NormalizeType(const clang::Type *&T,
6156bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                                 llvm::StringRef &TypeName,
6166bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                                 RSContext *Context,
6176bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                                 const clang::VarDecl *VD) {
6186bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius  if ((T = TypeExportable(T, Context, VD)) == NULL) {
6196bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    return false;
6206bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius  }
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  // Get type name
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  TypeName = RSExportType::GetTypeName(T);
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  if (Context && TypeName.empty()) {
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    if (VD) {
625a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      Context->ReportError(VD->getLocation(),
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                           "anonymous types cannot be exported");
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    } else {
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      Context->ReportError("anonymous types cannot be exported");
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    return false;
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  return true;
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillebool RSExportType::ValidateType(slang::RSContext *Context, clang::ASTContext &C,
63734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                                clang::QualType QT, clang::NamedDecl *ND,
638541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn                                clang::SourceLocation Loc,
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                                unsigned int TargetAPI, bool IsFilterscript) {
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  const clang::Type *T = QT.getTypePtr();
641ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn  llvm::SmallPtrSet<const clang::Type*, 8> SPS =
642ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn      llvm::SmallPtrSet<const clang::Type*, 8>();
643ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
644ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn  return ValidateTypeHelper(Context, C, T, ND, Loc, SPS, false, NULL, TargetAPI,
645ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                            IsFilterscript);
646ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn  return true;
647ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn}
648ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
649c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajanbool RSExportType::ValidateVarDecl(slang::RSContext *Context,
65034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                                   clang::VarDecl *VD, unsigned int TargetAPI,
65134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                                   bool IsFilterscript) {
652ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn  return ValidateType(Context, VD->getASTContext(), VD->getType(), VD,
653ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                      VD->getLocation(), TargetAPI, IsFilterscript);
654c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan}
655c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
656c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajanconst clang::Type
657c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
658c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan  if (DD) {
65934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    clang::QualType T = DD->getType();
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    if (T.isNull())
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return NULL;
66334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    else
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      return T.getTypePtr();
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  }
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  return NULL;
667f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu}
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillellvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  T = GET_CANONICAL_TYPE(T);
6716a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if (T == NULL)
6726a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    return llvm::StringRef();
6736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
6746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  switch (T->getTypeClass()) {
675f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    case clang::Type::Builtin: {
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      const clang::BuiltinType *BT =
677707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
678707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn      BuiltinInfo *info = FindBuiltinType(BT->getKind());
679707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn      if (info != NULL) {
680707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        return info->cname[0];
681707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn      }
682707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn      slangAssert(false && "Unknown data type of the builtin");
683707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn      break;
684707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    }
685707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    case clang::Type::Record: {
6866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee      clang::RecordDecl *RD;
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (T->isStructureType()) {
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        RD = T->getAsStructureType()->getDecl();
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      } else {
6906a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        break;
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      llvm::StringRef Name = RD->getName();
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      if (Name.empty()) {
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (RD->getTypedefNameForAnonDecl() != NULL) {
696a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          Name = RD->getTypedefNameForAnonDecl()->getName();
697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Name.empty()) {
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          // Try to find a name from redeclaration (i.e. typedef)
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                   RE = RD->redecls_end();
703549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen               RI != RE;
704eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh               RI++) {
70521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            slangAssert(*RI != NULL && "cannot be NULL object");
70621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
707ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            Name = (*RI)->getName();
70875f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger            if (!Name.empty())
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville              break;
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville          }
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      }
713222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C      return Name;
714222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
715222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    case clang::Type::Pointer: {
716222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C      // "*" plus pointee name
717222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C      const clang::Type *PT = GET_POINTEE_TYPE(T);
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville      llvm::StringRef PointeeName;
719d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      if (NormalizeType(PT, PointeeName, NULL, NULL)) {
720d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
721d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        Name[0] = '*';
722d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        memcpy(Name + 1, PointeeName.data(), PointeeName.size());
723d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        Name[PointeeName.size() + 1] = '\0';
724d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        return Name;
725d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      }
726d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      break;
727d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
728d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    case clang::Type::ExtVector: {
729d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      const clang::ExtVectorType *EVT =
730d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn          UNSAFE_CAST_TYPE(const clang::ExtVectorType, T);
731d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      return RSExportVectorType::GetTypeName(EVT);
732d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      break;
733d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
734d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    case clang::Type::ConstantArray : {
735d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      // Construct name for a constant array is too complicated.
736d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE;
737d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
738d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    default: {
739d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn      break;
740541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
741541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn  }
742fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
743fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  return llvm::StringRef();
744fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn}
745fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
746fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
747fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler GunnRSExportType *RSExportType::Create(RSContext *Context,
748fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn                                   const clang::Type *T,
749fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn                                   const llvm::StringRef &TypeName) {
750fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  // Lookup the context to see whether the type was processed before.
751fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  // Newly created RSExportType will insert into context
752fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  // in RSExportType::RSExportType()
753fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
754fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
755fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  if (ETI != Context->export_types_end())
756fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    return ETI->second;
757fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
758fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn  RSExportType *ET = NULL;
759eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh  switch (T->getTypeClass()) {
760eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    case clang::Type::Record: {
761eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh      RSExportPrimitiveType::DataType dt =
762eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          RSExportPrimitiveType::GetRSSpecificType(TypeName);
763eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh      switch (dt) {
764eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        case RSExportPrimitiveType::DataTypeUnknown: {
76527e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati          // User-defined types
766eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          ET = RSExportRecordType::Create(Context,
767eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                                          T->getAsStructureType(),
768eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                                          TypeName);
769eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          break;
770eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
771eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        case RSExportPrimitiveType::DataTypeRSMatrix2x2: {
772eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn          // 2 x 2 Matrix type
773eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn          ET = RSExportMatrixType::Create(Context,
774eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn                                          T->getAsStructureType(),
775eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn                                          TypeName,
776eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                                          2);
777eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          break;
778eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
779eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        case RSExportPrimitiveType::DataTypeRSMatrix3x3: {
780eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          // 3 x 3 Matrix type
781eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh          ET = RSExportMatrixType::Create(Context,
782eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                                          T->getAsStructureType(),
783eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn                                          TypeName,
784c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng                                          3);
785c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng          break;
786eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
787286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
788286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          // 4 x 4 Matrix type
789286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          ET = RSExportMatrixType::Create(Context,
790286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                                          T->getAsStructureType(),
791286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                                          TypeName,
792286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                                          4);
793286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          break;
794286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        }
795286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        default: {
796286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          // Others are primitive types
797286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          ET = RSExportPrimitiveType::Create(Context, T, TypeName);
798286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn          break;
799286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        }
800286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      }
801286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      break;
802286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
803286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    case clang::Type::Builtin: {
804286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      ET = RSExportPrimitiveType::Create(Context, T, TypeName);
805286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      break;
806286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
807286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    case clang::Type::Pointer: {
808286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      ET = RSExportPointerType::Create(Context,
809286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn               UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName);
810286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      // FIXME: free the name (allocated in RSExportType::GetTypeName)
811286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      delete [] TypeName.data();
812286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn      break;
813286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
814286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    case clang::Type::ExtVector: {
815eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh      ET = RSExportVectorType::Create(Context,
816eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh               UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName);
817eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh      break;
818eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
819eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    case clang::Type::ConstantArray: {
820eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh      ET = RSExportConstantArrayType::Create(
821eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh              Context,
822eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh              UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T));
8236a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee      break;
8246a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
8256a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    default: {
8266a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee      Context->ReportError("unknown type cannot be exported: '%0'")
8276a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee          << T->getTypeClassName();
8286a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee      break;
829d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    }
8306a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  }
8316a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8326a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  return ET;
8336a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee}
8346a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8356a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew LeeRSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
8366a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  llvm::StringRef TypeName;
837e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn  if (NormalizeType(T, TypeName, Context, NULL)) {
838e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn    return Create(Context, T, TypeName);
8396a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  } else {
840e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn    return NULL;
841288268d5528e0df03f348e303954813cb188c55bRekha Kumar  }
842288268d5528e0df03f348e303954813cb188c55bRekha Kumar}
843288268d5528e0df03f348e303954813cb188c55bRekha Kumar
844e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler GunnRSExportType *RSExportType::CreateFromDecl(RSContext *Context,
845288268d5528e0df03f348e303954813cb188c55bRekha Kumar                                           const clang::VarDecl *VD) {
846db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  return RSExportType::Create(Context, GetTypeOfDecl(VD));
847db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
848db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
849db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnsize_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
850db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  return ET->getRSContext()->getDataLayout()->getTypeStoreSize(
851db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      ET->getLLVMType());
852db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
853db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
854db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnsize_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
855db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  if (ET->getClass() == RSExportType::ExportClassRecord)
856db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
857db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  else
858db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    return ET->getRSContext()->getDataLayout()->getTypeAllocSize(
859db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        ET->getLLVMType());
860db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
86144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
862db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler GunnRSExportType::RSExportType(RSContext *Context,
863db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                           ExportClass Class,
864db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                           const llvm::StringRef &Name)
865db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    : RSExportable(Context, RSExportable::EX_TYPE),
866db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      mClass(Class),
867db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      // Make a copy on Name since memory stored @Name is either allocated in
868db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      // ASTContext or allocated in GetTypeName which will be destroyed later.
869db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      mName(Name.data(), Name.size()),
870db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      mLLVMType(NULL),
871db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      mSpecType(NULL) {
872db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  // Don't cache the type whose name start with '<'. Those type failed to
873db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  // get their name since constructing their name in GetTypeName() requiring
874db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  // complicated work.
875e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn  if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX))
876e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn    // TODO(zonr): Need to check whether the insertion is successful or not.
877e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn    Context->insertExportType(llvm::StringRef(Name), this);
878f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn  return;
879f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn}
880f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
8812e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunnbool RSExportType::keep() {
8822e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  if (!RSExportable::keep())
8832e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    return false;
8842e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  // Invalidate converted LLVM type.
8852e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  mLLVMType = NULL;
8862e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  return true;
8872e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn}
8882e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
8892e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunnbool RSExportType::equals(const RSExportable *E) const {
8902e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  CHECK_PARENT_EQUALITY(RSExportable, E);
8912e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn  return (static_cast<const RSExportType*>(E)->getClass() == getClass());
8922e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn}
893f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
894f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler GunnRSExportType::~RSExportType() {
895f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn  delete mSpecType;
8966a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee}
897f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
8986a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee/************************** RSExportPrimitiveType **************************/
8996a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Leellvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy>
900f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler GunnRSExportPrimitiveType::RSSpecificTypeMap;
901f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
902f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunnllvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
903288268d5528e0df03f348e303954813cb188c55bRekha Kumar
904f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunnbool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
905f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn  if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
906f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    return true;
907f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn  else
908f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    return false;
909288268d5528e0df03f348e303954813cb188c55bRekha Kumar}
910288268d5528e0df03f348e303954813cb188c55bRekha Kumar
9116a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew LeeRSExportPrimitiveType::DataType
9126a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew LeeRSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) {
9136a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if (TypeName.empty())
9146a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    return DataTypeUnknown;
9156a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9166a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if (RSSpecificTypeMap->empty()) {
9176a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    for (int i = 0; i < MatrixAndObjectDataTypesCount; i++) {
9186a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee      RSSpecificTypeMap->GetOrCreateValue(MatrixAndObjectDataTypes[i].name,
9196a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                                          MatrixAndObjectDataTypes[i].dataType);
9206a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9216a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  }
9226a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9236a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName);
92444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  if (I == RSSpecificTypeMap->end())
92544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    return DataTypeUnknown;
92644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  else
92744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    return I->getValue();
92844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn}
92944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
93044b58c8044c5fc0b271432429fc97707c4c773e1Tyler GunnRSExportPrimitiveType::DataType
931fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall LiuRSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) {
932fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  T = GET_CANONICAL_TYPE(T);
933fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
934fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    return DataTypeUnknown;
935fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
936fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  return GetRSSpecificType( RSExportType::GetTypeName(T) );
937fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu}
938fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
939fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liubool RSExportPrimitiveType::IsRSMatrixType(DataType DT) {
940fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    if (DT < 0 || DT >= DataTypeMax) {
941fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        return false;
942fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
943fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    return gReflectionTypes[DT].category == MatrixDataType;
944fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu}
945fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
946fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liubool RSExportPrimitiveType::IsRSObjectType(DataType DT) {
947fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    if (DT < 0 || DT >= DataTypeMax) {
948fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        return false;
949fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
950fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    return gReflectionTypes[DT].category == ObjectDataType;
951fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu}
952fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
953fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liubool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) {
954fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  bool RSObjectTypeSeen = false;
955fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  while (T && T->isArrayType()) {
956fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    T = T->getArrayElementTypeNoTypeQual();
957fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  }
958fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
959fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  const clang::RecordType *RT = T->getAsStructureType();
960fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  if (!RT) {
961fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    return false;
962fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  }
963fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
964fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  const clang::RecordDecl *RD = RT->getDecl();
965fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  if (RD) {
966fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    RD = RD->getDefinition();
967fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  }
968fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  if (!RD) {
969fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    return false;
970fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  }
971fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
972fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
973fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu         FE = RD->field_end();
974fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu       FI != FE;
975fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu       FI++) {
9766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    // We just look through all field declarations to see if we find a
9772e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    // declaration for an RS object type (or an array of one).
9782e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    const clang::FieldDecl *FD = *FI;
9792e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
9802e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    while (FT && FT->isArrayType()) {
9812e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn      FT = FT->getArrayElementTypeNoTypeQual();
9822e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
9832e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
984d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger    RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT);
985d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger    if (IsRSObjectType(DT)) {
9862e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn      // RS object types definitely need to be zero-initialized
987d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger      RSObjectTypeSeen = true;
988d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger    } else {
989d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger      switch (DT) {
990d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        case RSExportPrimitiveType::DataTypeRSMatrix2x2:
991d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        case RSExportPrimitiveType::DataTypeRSMatrix3x3:
9922e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        case RSExportPrimitiveType::DataTypeRSMatrix4x4:
9932e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn          // Matrix types should get zero-initialized as well
9942e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn          RSObjectTypeSeen = true;
9952e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn          break;
9962e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        default:
9972e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn          // Ignore all other primitive types
9982e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn          break;
9992e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn      }
10002e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn      while (FT && FT->isArrayType()) {
100121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        FT = FT->getArrayElementTypeNoTypeQual();
100221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      }
100321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      if (FT->isStructureType()) {
100421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        // Recursively handle structs of structs (even though these can't
100521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        // be exported, it is possible for a user to have them internally).
100621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT);
100721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      }
100821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
100921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  }
101021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  return RSObjectTypeSeen;
101221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar}
101321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkarsize_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
101521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  int type = EPT->getType();
101621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  slangAssert((type > DataTypeUnknown && type < DataTypeMax) &&
101721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar              "RSExportPrimitiveType::GetSizeInBits : unknown data type");
101821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  return gReflectionTypes[type].size_in_bits;
101921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar}
10202e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
10212e66c6325d321e41b8851da9a4596f7a745c7b1eTyler GunnRSExportPrimitiveType::DataType
102221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita SarkarRSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) {
102321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  if (T == NULL)
102421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    return DataTypeUnknown;
102521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
102621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  switch (T->getTypeClass()) {
102721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    case clang::Type::Builtin: {
102821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      const clang::BuiltinType *BT =
102921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        UNSAFE_CAST_TYPE(const clang::BuiltinType, T);
103021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      BuiltinInfo *info = FindBuiltinType(BT->getKind());
103121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      if (info != NULL) {
103221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return info->type;
103321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      }
103421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      // The size of type WChar depend on platform so we abandon the support
103521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      // to them.
103621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      Context->ReportError("built-in type cannot be exported: '%0'")
103721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar          << T->getTypeClassName();
103821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      break;
103921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
104021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    case clang::Type::Record: {
104121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      // must be RS object type
104221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      return RSExportPrimitiveType::GetRSSpecificType(T);
104321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
104421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    default: {
104521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      Context->ReportError("primitive type cannot be exported: '%0'")
104621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar          << T->getTypeClassName();
104721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar      break;
104821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
104921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar  }
105021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
10516a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  return DataTypeUnknown;
1052363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty}
1053363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
1054363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj ShettyRSExportPrimitiveType
10556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee*RSExportPrimitiveType::Create(RSContext *Context,
10566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                               const clang::Type *T,
10576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                               const llvm::StringRef &TypeName,
10586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                               bool Normalized) {
10596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  DataType DT = GetDataType(Context, T);
10606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
10616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if ((DT == DataTypeUnknown) || TypeName.empty())
10626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    return NULL;
10636a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  else
10646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName,
10656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                                     DT, Normalized);
10666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee}
1067363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
1068363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj ShettyRSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
1069363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                                                     const clang::Type *T) {
1070363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty  llvm::StringRef TypeName;
1071363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty  if (RSExportType::NormalizeType(T, TypeName, Context, NULL)
1072363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty      && IsPrimitiveType(T)) {
1073363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty    return Create(Context, T, TypeName);
1074363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty  } else {
10756a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    return NULL;
10766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  }
1077363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty}
1078363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
10796a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Leellvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
10806a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
10816a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
10826a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee  if (isRSObjectType()) {
10836a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    // struct {
1084541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    //   int *p;
1085541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    // } __attribute__((packed, aligned(pointer_size)))
1086541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    //
1087541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    // which is
1088541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    //
1089541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    // <{ [1 x i32] }> in LLVM
1090541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    //
1091541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    if (RSObjectLLVMType == NULL) {
1092541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn      std::vector<llvm::Type *> Elements;
1093541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn      Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
10941a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu      RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
10951a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    }
10961a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu    return RSObjectLLVMType;
109777a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu  }
10981a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu
109934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu  switch (mType) {
110034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    case DataTypeFloat32: {
110134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu      return llvm::Type::getFloatTy(C);
110234310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu      break;
110334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    }
110434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    case DataTypeFloat64: {
1105541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn      return llvm::Type::getDoubleTy(C);
1106541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn      break;
1107541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
1108541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    case DataTypeBoolean: {
11098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan      return llvm::Type::getInt1Ty(C);
1110359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn      break;
1111359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1112359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    case DataTypeSigned8:
1113359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    case DataTypeUnsigned8: {
1114359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn      return llvm::Type::getInt8Ty(C);
1115359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn      break;
1116359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1117359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    case DataTypeSigned16:
1118359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    case DataTypeUnsigned16:
11198bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    case DataTypeUnsigned565:
11208bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    case DataTypeUnsigned5551:
11218bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    case DataTypeUnsigned4444: {
11228bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan      return llvm::Type::getInt16Ty(C);
11238bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan      break;
11248bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
11258bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    case DataTypeSigned32:
1126db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    case DataTypeUnsigned32: {
1127db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      return llvm::Type::getInt32Ty(C);
1128db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      break;
1129db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1130db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    case DataTypeSigned64:
1131db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    case DataTypeUnsigned64: {
1132db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      return llvm::Type::getInt64Ty(C);
1133db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      break;
1134db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1135db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    default: {
1136db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn      slangAssert(false && "Unknown data type");
1137db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1138db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  }
1139db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1140db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  return NULL;
1141db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
1142db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1143db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnunion RSType *RSExportPrimitiveType::convertToSpecType() const {
1144db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  llvm::OwningPtr<union RSType> ST(new union RSType);
1145db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  RS_TYPE_SET_CLASS(ST, RS_TC_Primitive);
1146db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in
1147db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  // slang_rs_type_spec.h
1148db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType());
1149db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  return ST.take();
1150db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
1151db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1152db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnbool RSExportPrimitiveType::equals(const RSExportable *E) const {
1153db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  CHECK_PARENT_EQUALITY(RSExportType, E);
1154db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
1155db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
1156db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1157db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler GunnRSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) {
1158db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  if (DT > DataTypeUnknown && DT < DataTypeMax) {
1159db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    return &gReflectionTypes[DT];
1160db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  } else {
1161db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    return NULL;
1162db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn  }
1163db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn}
1164db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1165db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn/**************************** RSExportPointerType ****************************/
1166db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1167db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler GunnRSExportPointerType
1168db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn*RSExportPointerType::Create(RSContext *Context,
1169db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                             const clang::PointerType *PT,
1170359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn                             const llvm::StringRef &TypeName) {
1171359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
1172359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  const RSExportType *PointeeET;
1173359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1174359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  if (PointeeType->getTypeClass() != clang::Type::Pointer) {
1175359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    PointeeET = RSExportType::Create(Context, PointeeType);
1176359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  } else {
1177359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    // Double or higher dimension of pointer, export as int*
1178359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    PointeeET = RSExportPrimitiveType::Create(Context,
1179359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn                    Context->getASTContext().IntTy.getTypePtr());
1180359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  }
1181359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1182359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  if (PointeeET == NULL) {
1183359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    // Error diagnostic is emitted for corresponding pointee type
1184359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    return NULL;
1185359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  }
1186359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1187359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  return new RSExportPointerType(Context, TypeName, PointeeET);
1188359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn}
1189359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1190359c182111879b821c0b7eba6d5fa52194293212Tyler Gunnllvm::Type *RSExportPointerType::convertToLLVMType() const {
1191359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  llvm::Type *PointeeType = mPointeeType->getLLVMType();
1192359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  return llvm::PointerType::getUnqual(PointeeType);
1193359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn}
1194359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1195359c182111879b821c0b7eba6d5fa52194293212Tyler Gunnunion RSType *RSExportPointerType::convertToSpecType() const {
1196359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  llvm::OwningPtr<union RSType> ST(new union RSType);
1197359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1198359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  RS_TYPE_SET_CLASS(ST, RS_TC_Pointer);
1199359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType());
1200359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1201359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL)
1202359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    return ST.take();
1203359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  else
1204359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    return NULL;
1205359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn}
1206359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1207359c182111879b821c0b7eba6d5fa52194293212Tyler Gunnbool RSExportPointerType::keep() {
1208359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  if (!RSExportType::keep())
1209359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    return false;
1210359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  const_cast<RSExportType*>(mPointeeType)->keep();
1211359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn  return true;
1212286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn}
1213286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1214286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunnbool RSExportPointerType::equals(const RSExportable *E) const {
1215286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  CHECK_PARENT_EQUALITY(RSExportType, E);
1216286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  return (static_cast<const RSExportPointerType*>(E)
1217286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn              ->getPointeeType()->equals(getPointeeType()));
1218286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn}
1219286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1220286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn/***************************** RSExportVectorType *****************************/
1221286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunnllvm::StringRef
1222286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler GunnRSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
1223286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1224286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  llvm::StringRef name;
1225286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1226286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn  if ((ElementType->getTypeClass() != clang::Type::Builtin))
1227286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    return name;
122844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
122944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType,
123044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                                                  ElementType);
123144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  if ((EVT->getNumElements() < 1) ||
123244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn      (EVT->getNumElements() > 4))
123344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    return name;
12346dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn
123544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  BuiltinInfo *info = FindBuiltinType(BT->getKind());
123644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn  if (info != NULL) {
123744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    // Compiler is smart enough to optimize following *big if branches* since
123844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    // they all become "constant comparison" after macro expansion
123944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    int I = EVT->getNumElements() - 1;
124044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    if (I < kMaxVectorSize) {
124144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn      name = info->cname[I];
12426dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn    } else {
124344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn      slangAssert(false && "Max vector is 4");
12447a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    }
12457a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn  }
12467a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn  return name;
12477a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn}
12487a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
12497a411d4797fb60914f5f6230bde24fc25b12f920Tyler GunnRSExportVectorType *RSExportVectorType::Create(RSContext *Context,
12507a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                                               const clang::ExtVectorType *EVT,
12517a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                                               const llvm::StringRef &TypeName,
12527a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                                               bool Normalized) {
12537a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn  slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector);
125465cd15597c5e611184a3f4c8ead5f42644fc00d6Tyler Gunn
1255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
1256  RSExportPrimitiveType::DataType DT =
1257      RSExportPrimitiveType::GetDataType(Context, ElementType);
1258
1259  if (DT != RSExportPrimitiveType::DataTypeUnknown)
1260    return new RSExportVectorType(Context,
1261                                  TypeName,
1262                                  DT,
1263                                  Normalized,
1264                                  EVT->getNumElements());
1265  else
1266    return NULL;
1267}
1268
1269llvm::Type *RSExportVectorType::convertToLLVMType() const {
1270  llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
1271  return llvm::VectorType::get(ElementType, getNumElement());
1272}
1273
1274union RSType *RSExportVectorType::convertToSpecType() const {
1275  llvm::OwningPtr<union RSType> ST(new union RSType);
1276
1277  RS_TYPE_SET_CLASS(ST, RS_TC_Vector);
1278  RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType());
1279  RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement());
1280
1281  return ST.take();
1282}
1283
1284bool RSExportVectorType::equals(const RSExportable *E) const {
1285  CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
1286  return (static_cast<const RSExportVectorType*>(E)->getNumElement()
1287              == getNumElement());
1288}
1289
1290/***************************** RSExportMatrixType *****************************/
1291RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
1292                                               const clang::RecordType *RT,
1293                                               const llvm::StringRef &TypeName,
1294                                               unsigned Dim) {
1295  slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record));
1296  slangAssert((Dim > 1) && "Invalid dimension of matrix");
1297
1298  // Check whether the struct rs_matrix is in our expected form (but assume it's
1299  // correct if we're not sure whether it's correct or not)
1300  const clang::RecordDecl* RD = RT->getDecl();
1301  RD = RD->getDefinition();
1302  if (RD != NULL) {
1303    // Find definition, perform further examination
1304    if (RD->field_empty()) {
1305      Context->ReportError(
1306          RD->getLocation(),
1307          "invalid matrix struct: must have 1 field for saving values: '%0'")
1308          << RD->getName();
1309      return NULL;
1310    }
1311
1312    clang::RecordDecl::field_iterator FIT = RD->field_begin();
1313    const clang::FieldDecl *FD = *FIT;
1314    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1315    if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) {
1316      Context->ReportError(RD->getLocation(),
1317                           "invalid matrix struct: first field should"
1318                           " be an array with constant size: '%0'")
1319          << RD->getName();
1320      return NULL;
1321    }
1322    const clang::ConstantArrayType *CAT =
1323      static_cast<const clang::ConstantArrayType *>(FT);
1324    const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1325    if ((ElementType == NULL) ||
1326        (ElementType->getTypeClass() != clang::Type::Builtin) ||
1327        (static_cast<const clang::BuiltinType *>(ElementType)->getKind() !=
1328         clang::BuiltinType::Float)) {
1329      Context->ReportError(RD->getLocation(),
1330                           "invalid matrix struct: first field "
1331                           "should be a float array: '%0'")
1332          << RD->getName();
1333      return NULL;
1334    }
1335
1336    if (CAT->getSize() != Dim * Dim) {
1337      Context->ReportError(RD->getLocation(),
1338                           "invalid matrix struct: first field "
1339                           "should be an array with size %0: '%1'")
1340          << (Dim * Dim) << (RD->getName());
1341      return NULL;
1342    }
1343
1344    FIT++;
1345    if (FIT != RD->field_end()) {
1346      Context->ReportError(RD->getLocation(),
1347                           "invalid matrix struct: must have "
1348                           "exactly 1 field: '%0'")
1349          << RD->getName();
1350      return NULL;
1351    }
1352  }
1353
1354  return new RSExportMatrixType(Context, TypeName, Dim);
1355}
1356
1357llvm::Type *RSExportMatrixType::convertToLLVMType() const {
1358  // Construct LLVM type:
1359  // struct {
1360  //  float X[mDim * mDim];
1361  // }
1362
1363  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
1364  llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C),
1365                                            mDim * mDim);
1366  return llvm::StructType::get(C, X, false);
1367}
1368
1369union RSType *RSExportMatrixType::convertToSpecType() const {
1370  llvm::OwningPtr<union RSType> ST(new union RSType);
1371  RS_TYPE_SET_CLASS(ST, RS_TC_Matrix);
1372  switch (getDim()) {
1373    case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break;
1374    case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break;
1375    case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break;
1376    default: slangAssert(false && "Matrix type with unsupported dimension.");
1377  }
1378  return ST.take();
1379}
1380
1381bool RSExportMatrixType::equals(const RSExportable *E) const {
1382  CHECK_PARENT_EQUALITY(RSExportType, E);
1383  return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
1384}
1385
1386/************************* RSExportConstantArrayType *************************/
1387RSExportConstantArrayType
1388*RSExportConstantArrayType::Create(RSContext *Context,
1389                                   const clang::ConstantArrayType *CAT) {
1390  slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray);
1391
1392  slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large");
1393
1394  unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue());
1395  slangAssert((Size > 0) && "Constant array should have size greater than 0");
1396
1397  const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT);
1398  RSExportType *ElementET = RSExportType::Create(Context, ElementType);
1399
1400  if (ElementET == NULL) {
1401    return NULL;
1402  }
1403
1404  return new RSExportConstantArrayType(Context,
1405                                       ElementET,
1406                                       Size);
1407}
1408
1409llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
1410  return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
1411}
1412
1413union RSType *RSExportConstantArrayType::convertToSpecType() const {
1414  llvm::OwningPtr<union RSType> ST(new union RSType);
1415
1416  RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray);
1417  RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE(
1418      ST, getElementType()->getSpecType());
1419  RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize());
1420
1421  if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL)
1422    return ST.take();
1423  else
1424    return NULL;
1425}
1426
1427bool RSExportConstantArrayType::keep() {
1428  if (!RSExportType::keep())
1429    return false;
1430  const_cast<RSExportType*>(mElementType)->keep();
1431  return true;
1432}
1433
1434bool RSExportConstantArrayType::equals(const RSExportable *E) const {
1435  CHECK_PARENT_EQUALITY(RSExportType, E);
1436  const RSExportConstantArrayType *RHS =
1437      static_cast<const RSExportConstantArrayType*>(E);
1438  return ((getSize() == RHS->getSize()) &&
1439          (getElementType()->equals(RHS->getElementType())));
1440}
1441
1442/**************************** RSExportRecordType ****************************/
1443RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
1444                                               const clang::RecordType *RT,
1445                                               const llvm::StringRef &TypeName,
1446                                               bool mIsArtificial) {
1447  slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record);
1448
1449  const clang::RecordDecl *RD = RT->getDecl();
1450  slangAssert(RD->isStruct());
1451
1452  RD = RD->getDefinition();
1453  if (RD == NULL) {
1454    slangAssert(false && "struct is not defined in this module");
1455    return NULL;
1456  }
1457
1458  // Struct layout construct by clang. We rely on this for obtaining the
1459  // alloc size of a struct and offset of every field in that struct.
1460  const clang::ASTRecordLayout *RL =
1461      &Context->getASTContext().getASTRecordLayout(RD);
1462  slangAssert((RL != NULL) &&
1463      "Failed to retrieve the struct layout from Clang.");
1464
1465  RSExportRecordType *ERT =
1466      new RSExportRecordType(Context,
1467                             TypeName,
1468                             RD->hasAttr<clang::PackedAttr>(),
1469                             mIsArtificial,
1470                             RL->getSize().getQuantity());
1471  unsigned int Index = 0;
1472
1473  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1474           FE = RD->field_end();
1475       FI != FE;
1476       FI++, Index++) {
1477
1478    // FIXME: All fields should be primitive type
1479    slangAssert(FI->getKind() == clang::Decl::Field);
1480    clang::FieldDecl *FD = *FI;
1481
1482    if (FD->isBitField()) {
1483      return NULL;
1484    }
1485
1486    // Type
1487    RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
1488
1489    if (ET != NULL) {
1490      ERT->mFields.push_back(
1491          new Field(ET, FD->getName(), ERT,
1492                    static_cast<size_t>(RL->getFieldOffset(Index) >> 3)));
1493    } else {
1494      Context->ReportError(RD->getLocation(),
1495                           "field type cannot be exported: '%0.%1'")
1496          << RD->getName() << FD->getName();
1497      return NULL;
1498    }
1499  }
1500
1501  return ERT;
1502}
1503
1504llvm::Type *RSExportRecordType::convertToLLVMType() const {
1505  // Create an opaque type since struct may reference itself recursively.
1506
1507  // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to?
1508  std::vector<llvm::Type*> FieldTypes;
1509
1510  for (const_field_iterator FI = fields_begin(), FE = fields_end();
1511       FI != FE;
1512       FI++) {
1513    const Field *F = *FI;
1514    const RSExportType *FET = F->getType();
1515
1516    FieldTypes.push_back(FET->getLLVMType());
1517  }
1518
1519  llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
1520                                               FieldTypes,
1521                                               mIsPacked);
1522  if (ST != NULL) {
1523    return ST;
1524  } else {
1525    return NULL;
1526  }
1527}
1528
1529union RSType *RSExportRecordType::convertToSpecType() const {
1530  unsigned NumFields = getFields().size();
1531  unsigned AllocSize = sizeof(union RSType) +
1532                       sizeof(struct RSRecordField) * NumFields;
1533  llvm::OwningPtr<union RSType> ST(
1534      reinterpret_cast<union RSType*>(operator new(AllocSize)));
1535
1536  ::memset(ST.get(), 0, AllocSize);
1537
1538  RS_TYPE_SET_CLASS(ST, RS_TC_Record);
1539  RS_RECORD_TYPE_SET_NAME(ST, getName().c_str());
1540  RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields);
1541
1542  setSpecTypeTemporarily(ST.get());
1543
1544  unsigned FieldIdx = 0;
1545  for (const_field_iterator FI = fields_begin(), FE = fields_end();
1546       FI != FE;
1547       FI++, FieldIdx++) {
1548    const Field *F = *FI;
1549
1550    RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str());
1551    RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType());
1552  }
1553
1554  // TODO(slang): Check whether all fields were created normally.
1555
1556  return ST.take();
1557}
1558
1559bool RSExportRecordType::keep() {
1560  if (!RSExportType::keep())
1561    return false;
1562  for (std::list<const Field*>::iterator I = mFields.begin(),
1563          E = mFields.end();
1564       I != E;
1565       I++) {
1566    const_cast<RSExportType*>((*I)->getType())->keep();
1567  }
1568  return true;
1569}
1570
1571bool RSExportRecordType::equals(const RSExportable *E) const {
1572  CHECK_PARENT_EQUALITY(RSExportType, E);
1573
1574  const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
1575
1576  if (ERT->getFields().size() != getFields().size())
1577    return false;
1578
1579  const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
1580
1581  for (unsigned i = 0, e = getFields().size(); i != e; i++) {
1582    if (!(*AI)->getType()->equals((*BI)->getType()))
1583      return false;
1584    AI++;
1585    BI++;
1586  }
1587
1588  return true;
1589}
1590
1591void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const {
1592    memset(rtd, 0, sizeof(*rtd));
1593    rtd->vecSize = 1;
1594
1595    switch(getClass()) {
1596    case RSExportType::ExportClassPrimitive: {
1597            const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this);
1598            rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT);
1599            return;
1600        }
1601    case RSExportType::ExportClassPointer: {
1602            const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this);
1603            const RSExportType *PointeeType = EPT->getPointeeType();
1604            PointeeType->convertToRTD(rtd);
1605            rtd->isPointer = true;
1606            return;
1607        }
1608    case RSExportType::ExportClassVector: {
1609            const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this);
1610            rtd->type = EVT->getRSReflectionType(EVT);
1611            rtd->vecSize = EVT->getNumElement();
1612            return;
1613        }
1614    case RSExportType::ExportClassMatrix: {
1615            const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this);
1616            unsigned Dim = EMT->getDim();
1617            slangAssert((Dim >= 2) && (Dim <= 4));
1618            rtd->type = &gReflectionTypes[15 + Dim-2];
1619            return;
1620        }
1621    case RSExportType::ExportClassConstantArray: {
1622            const RSExportConstantArrayType* CAT =
1623              static_cast<const RSExportConstantArrayType*>(this);
1624            CAT->getElementType()->convertToRTD(rtd);
1625            rtd->arraySize = CAT->getSize();
1626            return;
1627        }
1628    case RSExportType::ExportClassRecord: {
1629            slangAssert(!"RSExportType::ExportClassRecord not implemented");
1630            return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item";
1631        }
1632    default: {
1633            slangAssert(false && "Unknown class of type");
1634        }
1635    }
1636}
1637
1638
1639}  // namespace slang
1640