slang_rs_export_type.cpp revision 474655a402e70cb329e1bcd4ebbe00bdc5be4206
1/* 2 * Copyright 2010-2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "slang_rs_export_type.h" 18 19#include <list> 20#include <vector> 21 22#include "clang/AST/ASTContext.h" 23#include "clang/AST/Attr.h" 24#include "clang/AST/RecordLayout.h" 25 26#include "llvm/ADT/StringExtras.h" 27#include "llvm/IR/DataLayout.h" 28#include "llvm/IR/DerivedTypes.h" 29#include "llvm/IR/Type.h" 30 31#include "slang_assert.h" 32#include "slang_rs_context.h" 33#include "slang_rs_export_element.h" 34#include "slang_rs_type_spec.h" 35#include "slang_version.h" 36 37#define CHECK_PARENT_EQUALITY(ParentClass, E) \ 38 if (!ParentClass::equals(E)) \ 39 return false; 40 41namespace slang { 42 43namespace { 44 45/* For the data types we support, their category, names, and size (in bits). 46 * 47 * IMPORTANT: The data types in this table should be at the same index 48 * as specified by the corresponding DataType enum. 49 */ 50static RSReflectionType gReflectionTypes[] = { 51 {PrimitiveDataType, "FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false}, 52 {PrimitiveDataType, "FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false}, 53 {PrimitiveDataType, "FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false}, 54 {PrimitiveDataType, "SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false}, 55 {PrimitiveDataType, "SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false}, 56 {PrimitiveDataType, "SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false}, 57 {PrimitiveDataType, "SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false}, 58 {PrimitiveDataType, "UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true}, 59 {PrimitiveDataType, "UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true}, 60 {PrimitiveDataType, "UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true}, 61 {PrimitiveDataType, "UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false}, 62 63 {PrimitiveDataType, "BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false}, 64 65 {PrimitiveDataType, "UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false}, 66 {PrimitiveDataType, "UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false}, 67 {PrimitiveDataType, "UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false}, 68 69 {MatrixDataType, "MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false}, 70 {MatrixDataType, "MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false}, 71 {MatrixDataType, "MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false}, 72 73 // TODO: For 64 bit, what will be the size of the objects?? 74 {ObjectDataType, "RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false}, 75 {ObjectDataType, "RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false}, 76 {ObjectDataType, "RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false}, 77 {ObjectDataType, "RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false}, 78 {ObjectDataType, "RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false}, 79 {ObjectDataType, "RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false}, 80 {ObjectDataType, "RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false}, 81 82 {ObjectDataType, "RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false}, 83 {ObjectDataType, "RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false}, 84 {ObjectDataType, "RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false}, 85 {ObjectDataType, "RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false}, 86 {ObjectDataType, "RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false} 87}; 88 89const int kMaxVectorSize = 4; 90 91struct BuiltinInfo { 92 clang::BuiltinType::Kind builtinTypeKind; 93 RSExportPrimitiveType::DataType type; 94 /* TODO If we return std::string instead of llvm::StringRef, we could build 95 * the name instead of duplicating the entries. 96 */ 97 const char *cname[kMaxVectorSize]; 98}; 99 100BuiltinInfo BuiltinInfoTable[] = { 101 {clang::BuiltinType::Bool, RSExportPrimitiveType::DataTypeBoolean, 102 {"bool", "bool2", "bool3", "bool4"}}, 103 {clang::BuiltinType::Char_U, RSExportPrimitiveType::DataTypeUnsigned8, 104 {"uchar", "uchar2", "uchar3", "uchar4"}}, 105 {clang::BuiltinType::UChar, RSExportPrimitiveType::DataTypeUnsigned8, 106 {"uchar", "uchar2", "uchar3", "uchar4"}}, 107 {clang::BuiltinType::Char16, RSExportPrimitiveType::DataTypeSigned16, 108 {"short", "short2", "short3", "short4"}}, 109 {clang::BuiltinType::Char32, RSExportPrimitiveType::DataTypeSigned32, 110 {"int", "int2", "int3", "int4"}}, 111 {clang::BuiltinType::UShort, RSExportPrimitiveType::DataTypeUnsigned16, 112 {"ushort", "ushort2", "ushort3", "ushort4"}}, 113 {clang::BuiltinType::UInt, RSExportPrimitiveType::DataTypeUnsigned32, 114 {"uint", "uint2", "uint3", "uint4"}}, 115 {clang::BuiltinType::ULong, RSExportPrimitiveType::DataTypeUnsigned32, 116 {"uint", "uint2", "uint3", "uint4"}}, 117 {clang::BuiltinType::ULongLong, RSExportPrimitiveType::DataTypeUnsigned64, 118 {"ulong", "ulong2", "ulong3", "ulong4"}}, 119 120 {clang::BuiltinType::Char_S, RSExportPrimitiveType::DataTypeSigned8, 121 {"char", "char2", "char3", "char4"}}, 122 {clang::BuiltinType::SChar, RSExportPrimitiveType::DataTypeSigned8, 123 {"char", "char2", "char3", "char4"}}, 124 {clang::BuiltinType::Short, RSExportPrimitiveType::DataTypeSigned16, 125 {"short", "short2", "short3", "short4"}}, 126 {clang::BuiltinType::Int, RSExportPrimitiveType::DataTypeSigned32, 127 {"int", "int2", "int3", "int4"}}, 128 {clang::BuiltinType::Long, RSExportPrimitiveType::DataTypeSigned64, 129 {"long", "long2", "long3", "long4"}}, 130 {clang::BuiltinType::LongLong, RSExportPrimitiveType::DataTypeSigned64, 131 {"long", "long2", "long3", "long4"}}, 132 {clang::BuiltinType::Float, RSExportPrimitiveType::DataTypeFloat32, 133 {"float", "float2", "float3", "float4"}}, 134 {clang::BuiltinType::Double, RSExportPrimitiveType::DataTypeFloat64, 135 {"double", "double2", "double3", "double4"}}, 136}; 137const int BuiltinInfoTableCount = sizeof(BuiltinInfoTable) / sizeof(BuiltinInfoTable[0]); 138 139struct NameAndPrimitiveType { 140 const char *name; 141 RSExportPrimitiveType::DataType dataType; 142}; 143 144static NameAndPrimitiveType MatrixAndObjectDataTypes[] = { 145 {"rs_matrix2x2", RSExportPrimitiveType::DataTypeRSMatrix2x2}, 146 {"rs_matrix3x3", RSExportPrimitiveType::DataTypeRSMatrix3x3}, 147 {"rs_matrix4x4", RSExportPrimitiveType::DataTypeRSMatrix4x4}, 148 {"rs_element", RSExportPrimitiveType::DataTypeRSElement}, 149 {"rs_type", RSExportPrimitiveType::DataTypeRSType}, 150 {"rs_allocation", RSExportPrimitiveType::DataTypeRSAllocation}, 151 {"rs_sampler", RSExportPrimitiveType::DataTypeRSSampler}, 152 {"rs_script", RSExportPrimitiveType::DataTypeRSScript}, 153 {"rs_mesh", RSExportPrimitiveType::DataTypeRSMesh}, 154 {"rs_path", RSExportPrimitiveType::DataTypeRSPath}, 155 {"rs_program_fragment", RSExportPrimitiveType::DataTypeRSProgramFragment}, 156 {"rs_program_vertex", RSExportPrimitiveType::DataTypeRSProgramVertex}, 157 {"rs_program_raster", RSExportPrimitiveType::DataTypeRSProgramRaster}, 158 {"rs_program_store", RSExportPrimitiveType::DataTypeRSProgramStore}, 159 {"rs_font", RSExportPrimitiveType::DataTypeRSFont}, 160}; 161 162const int MatrixAndObjectDataTypesCount = 163 sizeof(MatrixAndObjectDataTypes) / sizeof(MatrixAndObjectDataTypes[0]); 164 165static const clang::Type *TypeExportableHelper( 166 const clang::Type *T, 167 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 168 slang::RSContext *Context, 169 const clang::VarDecl *VD, 170 const clang::RecordDecl *TopLevelRecord); 171 172template <unsigned N> 173static void ReportTypeError(slang::RSContext *Context, 174 const clang::NamedDecl *ND, 175 const clang::RecordDecl *TopLevelRecord, 176 const char (&Message)[N], 177 unsigned int TargetAPI = 0) { 178 // Attempt to use the type declaration first (if we have one). 179 // Fall back to the variable definition, if we are looking at something 180 // like an array declaration that can't be exported. 181 if (TopLevelRecord) { 182 Context->ReportError(TopLevelRecord->getLocation(), Message) 183 << TopLevelRecord->getName() << TargetAPI; 184 } else if (ND) { 185 Context->ReportError(ND->getLocation(), Message) << ND->getName() 186 << TargetAPI; 187 } else { 188 slangAssert(false && "Variables should be validated before exporting"); 189 } 190} 191 192static const clang::Type *ConstantArrayTypeExportableHelper( 193 const clang::ConstantArrayType *CAT, 194 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 195 slang::RSContext *Context, 196 const clang::VarDecl *VD, 197 const clang::RecordDecl *TopLevelRecord) { 198 // Check element type 199 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 200 if (ElementType->isArrayType()) { 201 ReportTypeError(Context, VD, TopLevelRecord, 202 "multidimensional arrays cannot be exported: '%0'"); 203 return NULL; 204 } else if (ElementType->isExtVectorType()) { 205 const clang::ExtVectorType *EVT = 206 static_cast<const clang::ExtVectorType*>(ElementType); 207 unsigned numElements = EVT->getNumElements(); 208 209 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 210 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) { 211 ReportTypeError(Context, VD, TopLevelRecord, 212 "vectors of non-primitive types cannot be exported: '%0'"); 213 return NULL; 214 } 215 216 if (numElements == 3 && CAT->getSize() != 1) { 217 ReportTypeError(Context, VD, TopLevelRecord, 218 "arrays of width 3 vector types cannot be exported: '%0'"); 219 return NULL; 220 } 221 } 222 223 if (TypeExportableHelper(ElementType, SPS, Context, VD, 224 TopLevelRecord) == NULL) { 225 return NULL; 226 } else { 227 return CAT; 228 } 229} 230 231BuiltinInfo *FindBuiltinType(clang::BuiltinType::Kind builtinTypeKind) { 232 for (int i = 0; i < BuiltinInfoTableCount; i++) { 233 if (builtinTypeKind == BuiltinInfoTable[i].builtinTypeKind) { 234 return &BuiltinInfoTable[i]; 235 } 236 } 237 return NULL; 238} 239 240static const clang::Type *TypeExportableHelper( 241 clang::Type const *T, 242 llvm::SmallPtrSet<clang::Type const *, 8> &SPS, 243 slang::RSContext *Context, 244 clang::VarDecl const *VD, 245 clang::RecordDecl const *TopLevelRecord) { 246 // Normalize first 247 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 248 return NULL; 249 250 if (SPS.count(T)) 251 return T; 252 253 switch (T->getTypeClass()) { 254 case clang::Type::Builtin: { 255 const clang::BuiltinType *BT = 256 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 257 return FindBuiltinType(BT->getKind()) == NULL ? NULL : T; 258 } 259 case clang::Type::Record: { 260 if (RSExportPrimitiveType::GetRSSpecificType(T) != 261 RSExportPrimitiveType::DataTypeUnknown) { 262 return T; // RS object type, no further checks are needed 263 } 264 265 // Check internal struct 266 if (T->isUnionType()) { 267 ReportTypeError(Context, VD, T->getAsUnionType()->getDecl(), 268 "unions cannot be exported: '%0'"); 269 return NULL; 270 } else if (!T->isStructureType()) { 271 slangAssert(false && "Unknown type cannot be exported"); 272 return NULL; 273 } 274 275 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 276 if (RD != NULL) { 277 RD = RD->getDefinition(); 278 if (RD == NULL) { 279 ReportTypeError(Context, NULL, T->getAsStructureType()->getDecl(), 280 "struct is not defined in this module"); 281 return NULL; 282 } 283 } 284 285 if (!TopLevelRecord) { 286 TopLevelRecord = RD; 287 } 288 if (RD->getName().empty()) { 289 ReportTypeError(Context, NULL, RD, 290 "anonymous structures cannot be exported"); 291 return NULL; 292 } 293 294 // Fast check 295 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 296 return NULL; 297 298 // Insert myself into checking set 299 SPS.insert(T); 300 301 // Check all element 302 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 303 FE = RD->field_end(); 304 FI != FE; 305 FI++) { 306 const clang::FieldDecl *FD = *FI; 307 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 308 FT = GET_CANONICAL_TYPE(FT); 309 310 if (!TypeExportableHelper(FT, SPS, Context, VD, TopLevelRecord)) { 311 return NULL; 312 } 313 314 // We don't support bit fields yet 315 // 316 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32 317 if (FD->isBitField()) { 318 Context->ReportError( 319 FD->getLocation(), 320 "bit fields are not able to be exported: '%0.%1'") 321 << RD->getName() << FD->getName(); 322 return NULL; 323 } 324 } 325 326 return T; 327 } 328 case clang::Type::Pointer: { 329 if (TopLevelRecord) { 330 ReportTypeError(Context, VD, TopLevelRecord, 331 "structures containing pointers cannot be exported: '%0'"); 332 return NULL; 333 } 334 335 const clang::PointerType *PT = 336 UNSAFE_CAST_TYPE(const clang::PointerType, T); 337 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 338 339 if (PointeeType->getTypeClass() == clang::Type::Pointer) { 340 ReportTypeError(Context, VD, TopLevelRecord, 341 "multiple levels of pointers cannot be exported: '%0'"); 342 return NULL; 343 } 344 // We don't support pointer with array-type pointee or unsupported pointee 345 // type 346 if (PointeeType->isArrayType() || 347 (TypeExportableHelper(PointeeType, SPS, Context, VD, 348 TopLevelRecord) == NULL)) 349 return NULL; 350 else 351 return T; 352 } 353 case clang::Type::ExtVector: { 354 const clang::ExtVectorType *EVT = 355 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 356 // Only vector with size 2, 3 and 4 are supported. 357 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4) 358 return NULL; 359 360 // Check base element type 361 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 362 363 if ((ElementType->getTypeClass() != clang::Type::Builtin) || 364 (TypeExportableHelper(ElementType, SPS, Context, VD, 365 TopLevelRecord) == NULL)) 366 return NULL; 367 else 368 return T; 369 } 370 case clang::Type::ConstantArray: { 371 const clang::ConstantArrayType *CAT = 372 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 373 374 return ConstantArrayTypeExportableHelper(CAT, SPS, Context, VD, 375 TopLevelRecord); 376 } 377 case clang::Type::Enum: { 378 // FIXME: We currently convert enums to integers, rather than reflecting 379 // a more complete (and nicer type-safe Java version). 380 return Context->getASTContext().IntTy.getTypePtr(); 381 } 382 default: { 383 slangAssert(false && "Unknown type cannot be validated"); 384 return NULL; 385 } 386 } 387} 388 389// Return the type that can be used to create RSExportType, will always return 390// the canonical type 391// If the Type T is not exportable, this function returns NULL. DiagEngine is 392// used to generate proper Clang diagnostic messages when a 393// non-exportable type is detected. TopLevelRecord is used to capture the 394// highest struct (in the case of a nested hierarchy) for detecting other 395// types that cannot be exported (mostly pointers within a struct). 396static const clang::Type *TypeExportable(const clang::Type *T, 397 slang::RSContext *Context, 398 const clang::VarDecl *VD) { 399 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 400 llvm::SmallPtrSet<const clang::Type*, 8>(); 401 402 return TypeExportableHelper(T, SPS, Context, VD, NULL); 403} 404 405static bool ValidateRSObjectInVarDecl(slang::RSContext *Context, 406 clang::VarDecl *VD, bool InCompositeType, 407 unsigned int TargetAPI) { 408 if (TargetAPI < SLANG_JB_TARGET_API) { 409 // Only if we are already in a composite type (like an array or structure). 410 if (InCompositeType) { 411 // Only if we are actually exported (i.e. non-static). 412 if (VD->hasLinkage() && 413 (VD->getFormalLinkage() == clang::ExternalLinkage)) { 414 // Only if we are not a pointer to an object. 415 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr()); 416 if (T->getTypeClass() != clang::Type::Pointer) { 417 ReportTypeError(Context, VD, NULL, 418 "arrays/structures containing RS object types " 419 "cannot be exported in target API < %1: '%0'", 420 SLANG_JB_TARGET_API); 421 return false; 422 } 423 } 424 } 425 } 426 427 return true; 428} 429 430// Helper function for ValidateType(). We do a recursive descent on the 431// type hierarchy to ensure that we can properly export/handle the 432// declaration. 433// \return true if the variable declaration is valid, 434// false if it is invalid (along with proper diagnostics). 435// 436// C - ASTContext (for diagnostics + builtin types). 437// T - sub-type that we are validating. 438// ND - (optional) top-level named declaration that we are validating. 439// SPS - set of types we have already seen/validated. 440// InCompositeType - true if we are within an outer composite type. 441// UnionDecl - set if we are in a sub-type of a union. 442// TargetAPI - target SDK API level. 443// IsFilterscript - whether or not we are compiling for Filterscript 444static bool ValidateTypeHelper( 445 slang::RSContext *Context, 446 clang::ASTContext &C, 447 const clang::Type *&T, 448 clang::NamedDecl *ND, 449 clang::SourceLocation Loc, 450 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 451 bool InCompositeType, 452 clang::RecordDecl *UnionDecl, 453 unsigned int TargetAPI, 454 bool IsFilterscript) { 455 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 456 return true; 457 458 if (SPS.count(T)) 459 return true; 460 461 switch (T->getTypeClass()) { 462 case clang::Type::Record: { 463 if (RSExportPrimitiveType::IsRSObjectType(T)) { 464 clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL); 465 if (VD && !ValidateRSObjectInVarDecl(Context, VD, InCompositeType, 466 TargetAPI)) { 467 return false; 468 } 469 } 470 471 if (RSExportPrimitiveType::GetRSSpecificType(T) != 472 RSExportPrimitiveType::DataTypeUnknown) { 473 if (!UnionDecl) { 474 return true; 475 } else if (RSExportPrimitiveType::IsRSObjectType(T)) { 476 ReportTypeError(Context, NULL, UnionDecl, 477 "unions containing RS object types are not allowed"); 478 return false; 479 } 480 } 481 482 clang::RecordDecl *RD = NULL; 483 484 // Check internal struct 485 if (T->isUnionType()) { 486 RD = T->getAsUnionType()->getDecl(); 487 UnionDecl = RD; 488 } else if (T->isStructureType()) { 489 RD = T->getAsStructureType()->getDecl(); 490 } else { 491 slangAssert(false && "Unknown type cannot be exported"); 492 return false; 493 } 494 495 if (RD != NULL) { 496 RD = RD->getDefinition(); 497 if (RD == NULL) { 498 // FIXME 499 return true; 500 } 501 } 502 503 // Fast check 504 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 505 return false; 506 507 // Insert myself into checking set 508 SPS.insert(T); 509 510 // Check all elements 511 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 512 FE = RD->field_end(); 513 FI != FE; 514 FI++) { 515 const clang::FieldDecl *FD = *FI; 516 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 517 FT = GET_CANONICAL_TYPE(FT); 518 519 if (!ValidateTypeHelper(Context, C, FT, ND, Loc, SPS, true, UnionDecl, 520 TargetAPI, IsFilterscript)) { 521 return false; 522 } 523 } 524 525 return true; 526 } 527 528 case clang::Type::Builtin: { 529 if (IsFilterscript) { 530 clang::QualType QT = T->getCanonicalTypeInternal(); 531 if (QT == C.DoubleTy || 532 QT == C.LongDoubleTy || 533 QT == C.LongTy || 534 QT == C.LongLongTy) { 535 if (ND) { 536 Context->ReportError( 537 Loc, 538 "Builtin types > 32 bits in size are forbidden in " 539 "Filterscript: '%0'") 540 << ND->getName(); 541 } else { 542 Context->ReportError( 543 Loc, 544 "Builtin types > 32 bits in size are forbidden in " 545 "Filterscript"); 546 } 547 return false; 548 } 549 } 550 break; 551 } 552 553 case clang::Type::Pointer: { 554 if (IsFilterscript) { 555 if (ND) { 556 Context->ReportError(Loc, 557 "Pointers are forbidden in Filterscript: '%0'") 558 << ND->getName(); 559 return false; 560 } else { 561 // TODO(srhines): Find a better way to handle expressions (i.e. no 562 // NamedDecl) involving pointers in FS that should be allowed. 563 // An example would be calls to library functions like 564 // rsMatrixMultiply() that take rs_matrixNxN * types. 565 } 566 } 567 568 const clang::PointerType *PT = 569 UNSAFE_CAST_TYPE(const clang::PointerType, T); 570 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 571 572 return ValidateTypeHelper(Context, C, PointeeType, ND, Loc, SPS, 573 InCompositeType, UnionDecl, TargetAPI, 574 IsFilterscript); 575 } 576 577 case clang::Type::ExtVector: { 578 const clang::ExtVectorType *EVT = 579 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 580 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 581 if (TargetAPI < SLANG_ICS_TARGET_API && 582 InCompositeType && 583 EVT->getNumElements() == 3 && 584 ND && 585 ND->getFormalLinkage() == clang::ExternalLinkage) { 586 ReportTypeError(Context, ND, NULL, 587 "structs containing vectors of dimension 3 cannot " 588 "be exported at this API level: '%0'"); 589 return false; 590 } 591 return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true, 592 UnionDecl, TargetAPI, IsFilterscript); 593 } 594 595 case clang::Type::ConstantArray: { 596 const clang::ConstantArrayType *CAT = 597 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 598 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 599 return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true, 600 UnionDecl, TargetAPI, IsFilterscript); 601 } 602 603 default: { 604 break; 605 } 606 } 607 608 return true; 609} 610 611} // namespace 612 613/****************************** RSExportType ******************************/ 614bool RSExportType::NormalizeType(const clang::Type *&T, 615 llvm::StringRef &TypeName, 616 RSContext *Context, 617 const clang::VarDecl *VD) { 618 if ((T = TypeExportable(T, Context, VD)) == NULL) { 619 return false; 620 } 621 // Get type name 622 TypeName = RSExportType::GetTypeName(T); 623 if (Context && TypeName.empty()) { 624 if (VD) { 625 Context->ReportError(VD->getLocation(), 626 "anonymous types cannot be exported"); 627 } else { 628 Context->ReportError("anonymous types cannot be exported"); 629 } 630 return false; 631 } 632 633 return true; 634} 635 636bool RSExportType::ValidateType(slang::RSContext *Context, clang::ASTContext &C, 637 clang::QualType QT, clang::NamedDecl *ND, 638 clang::SourceLocation Loc, 639 unsigned int TargetAPI, bool IsFilterscript) { 640 const clang::Type *T = QT.getTypePtr(); 641 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 642 llvm::SmallPtrSet<const clang::Type*, 8>(); 643 644 return ValidateTypeHelper(Context, C, T, ND, Loc, SPS, false, NULL, TargetAPI, 645 IsFilterscript); 646 return true; 647} 648 649bool RSExportType::ValidateVarDecl(slang::RSContext *Context, 650 clang::VarDecl *VD, unsigned int TargetAPI, 651 bool IsFilterscript) { 652 return ValidateType(Context, VD->getASTContext(), VD->getType(), VD, 653 VD->getLocation(), TargetAPI, IsFilterscript); 654} 655 656const clang::Type 657*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 658 if (DD) { 659 clang::QualType T = DD->getType(); 660 661 if (T.isNull()) 662 return NULL; 663 else 664 return T.getTypePtr(); 665 } 666 return NULL; 667} 668 669llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 670 T = GET_CANONICAL_TYPE(T); 671 if (T == NULL) 672 return llvm::StringRef(); 673 674 switch (T->getTypeClass()) { 675 case clang::Type::Builtin: { 676 const clang::BuiltinType *BT = 677 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 678 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 679 if (info != NULL) { 680 return info->cname[0]; 681 } 682 slangAssert(false && "Unknown data type of the builtin"); 683 break; 684 } 685 case clang::Type::Record: { 686 clang::RecordDecl *RD; 687 if (T->isStructureType()) { 688 RD = T->getAsStructureType()->getDecl(); 689 } else { 690 break; 691 } 692 693 llvm::StringRef Name = RD->getName(); 694 if (Name.empty()) { 695 if (RD->getTypedefNameForAnonDecl() != NULL) { 696 Name = RD->getTypedefNameForAnonDecl()->getName(); 697 } 698 699 if (Name.empty()) { 700 // Try to find a name from redeclaration (i.e. typedef) 701 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 702 RE = RD->redecls_end(); 703 RI != RE; 704 RI++) { 705 slangAssert(*RI != NULL && "cannot be NULL object"); 706 707 Name = (*RI)->getName(); 708 if (!Name.empty()) 709 break; 710 } 711 } 712 } 713 return Name; 714 } 715 case clang::Type::Pointer: { 716 // "*" plus pointee name 717 const clang::Type *PT = GET_POINTEE_TYPE(T); 718 llvm::StringRef PointeeName; 719 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 720 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 721 Name[0] = '*'; 722 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 723 Name[PointeeName.size() + 1] = '\0'; 724 return Name; 725 } 726 break; 727 } 728 case clang::Type::ExtVector: { 729 const clang::ExtVectorType *EVT = 730 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 731 return RSExportVectorType::GetTypeName(EVT); 732 break; 733 } 734 case clang::Type::ConstantArray : { 735 // Construct name for a constant array is too complicated. 736 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 737 } 738 default: { 739 break; 740 } 741 } 742 743 return llvm::StringRef(); 744} 745 746 747RSExportType *RSExportType::Create(RSContext *Context, 748 const clang::Type *T, 749 const llvm::StringRef &TypeName) { 750 // Lookup the context to see whether the type was processed before. 751 // Newly created RSExportType will insert into context 752 // in RSExportType::RSExportType() 753 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 754 755 if (ETI != Context->export_types_end()) 756 return ETI->second; 757 758 RSExportType *ET = NULL; 759 switch (T->getTypeClass()) { 760 case clang::Type::Record: { 761 RSExportPrimitiveType::DataType dt = 762 RSExportPrimitiveType::GetRSSpecificType(TypeName); 763 switch (dt) { 764 case RSExportPrimitiveType::DataTypeUnknown: { 765 // User-defined types 766 ET = RSExportRecordType::Create(Context, 767 T->getAsStructureType(), 768 TypeName); 769 break; 770 } 771 case RSExportPrimitiveType::DataTypeRSMatrix2x2: { 772 // 2 x 2 Matrix type 773 ET = RSExportMatrixType::Create(Context, 774 T->getAsStructureType(), 775 TypeName, 776 2); 777 break; 778 } 779 case RSExportPrimitiveType::DataTypeRSMatrix3x3: { 780 // 3 x 3 Matrix type 781 ET = RSExportMatrixType::Create(Context, 782 T->getAsStructureType(), 783 TypeName, 784 3); 785 break; 786 } 787 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 788 // 4 x 4 Matrix type 789 ET = RSExportMatrixType::Create(Context, 790 T->getAsStructureType(), 791 TypeName, 792 4); 793 break; 794 } 795 default: { 796 // Others are primitive types 797 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 798 break; 799 } 800 } 801 break; 802 } 803 case clang::Type::Builtin: { 804 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 805 break; 806 } 807 case clang::Type::Pointer: { 808 ET = RSExportPointerType::Create(Context, 809 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName); 810 // FIXME: free the name (allocated in RSExportType::GetTypeName) 811 delete [] TypeName.data(); 812 break; 813 } 814 case clang::Type::ExtVector: { 815 ET = RSExportVectorType::Create(Context, 816 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName); 817 break; 818 } 819 case clang::Type::ConstantArray: { 820 ET = RSExportConstantArrayType::Create( 821 Context, 822 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T)); 823 break; 824 } 825 default: { 826 Context->ReportError("unknown type cannot be exported: '%0'") 827 << T->getTypeClassName(); 828 break; 829 } 830 } 831 832 return ET; 833} 834 835RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 836 llvm::StringRef TypeName; 837 if (NormalizeType(T, TypeName, Context, NULL)) { 838 return Create(Context, T, TypeName); 839 } else { 840 return NULL; 841 } 842} 843 844RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 845 const clang::VarDecl *VD) { 846 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 847} 848 849size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 850 return ET->getRSContext()->getDataLayout()->getTypeStoreSize( 851 ET->getLLVMType()); 852} 853 854size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 855 if (ET->getClass() == RSExportType::ExportClassRecord) 856 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 857 else 858 return ET->getRSContext()->getDataLayout()->getTypeAllocSize( 859 ET->getLLVMType()); 860} 861 862RSExportType::RSExportType(RSContext *Context, 863 ExportClass Class, 864 const llvm::StringRef &Name) 865 : RSExportable(Context, RSExportable::EX_TYPE), 866 mClass(Class), 867 // Make a copy on Name since memory stored @Name is either allocated in 868 // ASTContext or allocated in GetTypeName which will be destroyed later. 869 mName(Name.data(), Name.size()), 870 mLLVMType(NULL), 871 mSpecType(NULL) { 872 // Don't cache the type whose name start with '<'. Those type failed to 873 // get their name since constructing their name in GetTypeName() requiring 874 // complicated work. 875 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 876 // TODO(zonr): Need to check whether the insertion is successful or not. 877 Context->insertExportType(llvm::StringRef(Name), this); 878 return; 879} 880 881bool RSExportType::keep() { 882 if (!RSExportable::keep()) 883 return false; 884 // Invalidate converted LLVM type. 885 mLLVMType = NULL; 886 return true; 887} 888 889bool RSExportType::equals(const RSExportable *E) const { 890 CHECK_PARENT_EQUALITY(RSExportable, E); 891 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 892} 893 894RSExportType::~RSExportType() { 895 delete mSpecType; 896} 897 898/************************** RSExportPrimitiveType **************************/ 899llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 900RSExportPrimitiveType::RSSpecificTypeMap; 901 902llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 903 904bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 905 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 906 return true; 907 else 908 return false; 909} 910 911RSExportPrimitiveType::DataType 912RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 913 if (TypeName.empty()) 914 return DataTypeUnknown; 915 916 if (RSSpecificTypeMap->empty()) { 917 for (int i = 0; i < MatrixAndObjectDataTypesCount; i++) { 918 RSSpecificTypeMap->GetOrCreateValue(MatrixAndObjectDataTypes[i].name, 919 MatrixAndObjectDataTypes[i].dataType); 920 } 921 } 922 923 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 924 if (I == RSSpecificTypeMap->end()) 925 return DataTypeUnknown; 926 else 927 return I->getValue(); 928} 929 930RSExportPrimitiveType::DataType 931RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 932 T = GET_CANONICAL_TYPE(T); 933 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 934 return DataTypeUnknown; 935 936 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 937} 938 939bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 940 if (DT < 0 || DT >= DataTypeMax) { 941 return false; 942 } 943 return gReflectionTypes[DT].category == MatrixDataType; 944} 945 946bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 947 if (DT < 0 || DT >= DataTypeMax) { 948 return false; 949 } 950 return gReflectionTypes[DT].category == ObjectDataType; 951} 952 953bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 954 bool RSObjectTypeSeen = false; 955 while (T && T->isArrayType()) { 956 T = T->getArrayElementTypeNoTypeQual(); 957 } 958 959 const clang::RecordType *RT = T->getAsStructureType(); 960 if (!RT) { 961 return false; 962 } 963 964 const clang::RecordDecl *RD = RT->getDecl(); 965 if (RD) { 966 RD = RD->getDefinition(); 967 } 968 if (!RD) { 969 return false; 970 } 971 972 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 973 FE = RD->field_end(); 974 FI != FE; 975 FI++) { 976 // We just look through all field declarations to see if we find a 977 // declaration for an RS object type (or an array of one). 978 const clang::FieldDecl *FD = *FI; 979 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 980 while (FT && FT->isArrayType()) { 981 FT = FT->getArrayElementTypeNoTypeQual(); 982 } 983 984 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT); 985 if (IsRSObjectType(DT)) { 986 // RS object types definitely need to be zero-initialized 987 RSObjectTypeSeen = true; 988 } else { 989 switch (DT) { 990 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 991 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 992 case RSExportPrimitiveType::DataTypeRSMatrix4x4: 993 // Matrix types should get zero-initialized as well 994 RSObjectTypeSeen = true; 995 break; 996 default: 997 // Ignore all other primitive types 998 break; 999 } 1000 while (FT && FT->isArrayType()) { 1001 FT = FT->getArrayElementTypeNoTypeQual(); 1002 } 1003 if (FT->isStructureType()) { 1004 // Recursively handle structs of structs (even though these can't 1005 // be exported, it is possible for a user to have them internally). 1006 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 1007 } 1008 } 1009 } 1010 1011 return RSObjectTypeSeen; 1012} 1013 1014size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 1015 int type = EPT->getType(); 1016 slangAssert((type > DataTypeUnknown && type < DataTypeMax) && 1017 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 1018 return gReflectionTypes[type].size_in_bits; 1019} 1020 1021RSExportPrimitiveType::DataType 1022RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 1023 if (T == NULL) 1024 return DataTypeUnknown; 1025 1026 switch (T->getTypeClass()) { 1027 case clang::Type::Builtin: { 1028 const clang::BuiltinType *BT = 1029 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 1030 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1031 if (info != NULL) { 1032 return info->type; 1033 } 1034 // The size of type WChar depend on platform so we abandon the support 1035 // to them. 1036 Context->ReportError("built-in type cannot be exported: '%0'") 1037 << T->getTypeClassName(); 1038 break; 1039 } 1040 case clang::Type::Record: { 1041 // must be RS object type 1042 return RSExportPrimitiveType::GetRSSpecificType(T); 1043 } 1044 default: { 1045 Context->ReportError("primitive type cannot be exported: '%0'") 1046 << T->getTypeClassName(); 1047 break; 1048 } 1049 } 1050 1051 return DataTypeUnknown; 1052} 1053 1054RSExportPrimitiveType 1055*RSExportPrimitiveType::Create(RSContext *Context, 1056 const clang::Type *T, 1057 const llvm::StringRef &TypeName, 1058 bool Normalized) { 1059 DataType DT = GetDataType(Context, T); 1060 1061 if ((DT == DataTypeUnknown) || TypeName.empty()) 1062 return NULL; 1063 else 1064 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 1065 DT, Normalized); 1066} 1067 1068RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 1069 const clang::Type *T) { 1070 llvm::StringRef TypeName; 1071 if (RSExportType::NormalizeType(T, TypeName, Context, NULL) 1072 && IsPrimitiveType(T)) { 1073 return Create(Context, T, TypeName); 1074 } else { 1075 return NULL; 1076 } 1077} 1078 1079llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 1080 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1081 1082 if (isRSObjectType()) { 1083 // struct { 1084 // int *p; 1085 // } __attribute__((packed, aligned(pointer_size))) 1086 // 1087 // which is 1088 // 1089 // <{ [1 x i32] }> in LLVM 1090 // 1091 if (RSObjectLLVMType == NULL) { 1092 std::vector<llvm::Type *> Elements; 1093 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 1094 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 1095 } 1096 return RSObjectLLVMType; 1097 } 1098 1099 switch (mType) { 1100 case DataTypeFloat32: { 1101 return llvm::Type::getFloatTy(C); 1102 break; 1103 } 1104 case DataTypeFloat64: { 1105 return llvm::Type::getDoubleTy(C); 1106 break; 1107 } 1108 case DataTypeBoolean: { 1109 return llvm::Type::getInt1Ty(C); 1110 break; 1111 } 1112 case DataTypeSigned8: 1113 case DataTypeUnsigned8: { 1114 return llvm::Type::getInt8Ty(C); 1115 break; 1116 } 1117 case DataTypeSigned16: 1118 case DataTypeUnsigned16: 1119 case DataTypeUnsigned565: 1120 case DataTypeUnsigned5551: 1121 case DataTypeUnsigned4444: { 1122 return llvm::Type::getInt16Ty(C); 1123 break; 1124 } 1125 case DataTypeSigned32: 1126 case DataTypeUnsigned32: { 1127 return llvm::Type::getInt32Ty(C); 1128 break; 1129 } 1130 case DataTypeSigned64: 1131 case DataTypeUnsigned64: { 1132 return llvm::Type::getInt64Ty(C); 1133 break; 1134 } 1135 default: { 1136 slangAssert(false && "Unknown data type"); 1137 } 1138 } 1139 1140 return NULL; 1141} 1142 1143union RSType *RSExportPrimitiveType::convertToSpecType() const { 1144 llvm::OwningPtr<union RSType> ST(new union RSType); 1145 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive); 1146 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in 1147 // slang_rs_type_spec.h 1148 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType()); 1149 return ST.take(); 1150} 1151 1152bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1153 CHECK_PARENT_EQUALITY(RSExportType, E); 1154 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1155} 1156 1157RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1158 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1159 return &gReflectionTypes[DT]; 1160 } else { 1161 return NULL; 1162 } 1163} 1164 1165/**************************** RSExportPointerType ****************************/ 1166 1167RSExportPointerType 1168*RSExportPointerType::Create(RSContext *Context, 1169 const clang::PointerType *PT, 1170 const llvm::StringRef &TypeName) { 1171 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 1172 const RSExportType *PointeeET; 1173 1174 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1175 PointeeET = RSExportType::Create(Context, PointeeType); 1176 } else { 1177 // Double or higher dimension of pointer, export as int* 1178 PointeeET = RSExportPrimitiveType::Create(Context, 1179 Context->getASTContext().IntTy.getTypePtr()); 1180 } 1181 1182 if (PointeeET == NULL) { 1183 // Error diagnostic is emitted for corresponding pointee type 1184 return NULL; 1185 } 1186 1187 return new RSExportPointerType(Context, TypeName, PointeeET); 1188} 1189 1190llvm::Type *RSExportPointerType::convertToLLVMType() const { 1191 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1192 return llvm::PointerType::getUnqual(PointeeType); 1193} 1194 1195union RSType *RSExportPointerType::convertToSpecType() const { 1196 llvm::OwningPtr<union RSType> ST(new union RSType); 1197 1198 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer); 1199 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType()); 1200 1201 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL) 1202 return ST.take(); 1203 else 1204 return NULL; 1205} 1206 1207bool RSExportPointerType::keep() { 1208 if (!RSExportType::keep()) 1209 return false; 1210 const_cast<RSExportType*>(mPointeeType)->keep(); 1211 return true; 1212} 1213 1214bool RSExportPointerType::equals(const RSExportable *E) const { 1215 CHECK_PARENT_EQUALITY(RSExportType, E); 1216 return (static_cast<const RSExportPointerType*>(E) 1217 ->getPointeeType()->equals(getPointeeType())); 1218} 1219 1220/***************************** RSExportVectorType *****************************/ 1221llvm::StringRef 1222RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1223 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1224 llvm::StringRef name; 1225 1226 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1227 return name; 1228 1229 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType, 1230 ElementType); 1231 if ((EVT->getNumElements() < 1) || 1232 (EVT->getNumElements() > 4)) 1233 return name; 1234 1235 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1236 if (info != NULL) { 1237 // Compiler is smart enough to optimize following *big if branches* since 1238 // they all become "constant comparison" after macro expansion 1239 int I = EVT->getNumElements() - 1; 1240 if (I < kMaxVectorSize) { 1241 name = info->cname[I]; 1242 } else { 1243 slangAssert(false && "Max vector is 4"); 1244 } 1245 } 1246 return name; 1247} 1248 1249RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1250 const clang::ExtVectorType *EVT, 1251 const llvm::StringRef &TypeName, 1252 bool Normalized) { 1253 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1254 1255 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