slang_rs_export_type.cpp revision cec9b65aa890dea58e39951900ae13efb8d11703
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_version.h" 35 36#define CHECK_PARENT_EQUALITY(ParentClass, E) \ 37 if (!ParentClass::equals(E)) \ 38 return false; 39 40namespace slang { 41 42namespace { 43 44/* For the data types we support, their category, names, and size (in bits). 45 * 46 * IMPORTANT: The data types in this table should be at the same index 47 * as specified by the corresponding DataType enum. 48 */ 49static RSReflectionType gReflectionTypes[] = { 50 {PrimitiveDataType, "FLOAT_16", "F16", 16, "half", "half", "Half", "Half", false}, 51 {PrimitiveDataType, "FLOAT_32", "F32", 32, "float", "float", "Float", "Float", false}, 52 {PrimitiveDataType, "FLOAT_64", "F64", 64, "double", "double", "Double", "Double",false}, 53 {PrimitiveDataType, "SIGNED_8", "I8", 8, "int8_t", "byte", "Byte", "Byte", false}, 54 {PrimitiveDataType, "SIGNED_16", "I16", 16, "int16_t", "short", "Short", "Short", false}, 55 {PrimitiveDataType, "SIGNED_32", "I32", 32, "int32_t", "int", "Int", "Int", false}, 56 {PrimitiveDataType, "SIGNED_64", "I64", 64, "int64_t", "long", "Long", "Long", false}, 57 {PrimitiveDataType, "UNSIGNED_8", "U8", 8, "uint8_t", "short", "UByte", "Short", true}, 58 {PrimitiveDataType, "UNSIGNED_16", "U16", 16, "uint16_t", "int", "UShort", "Int", true}, 59 {PrimitiveDataType, "UNSIGNED_32", "U32", 32, "uint32_t", "long", "UInt", "Long", true}, 60 {PrimitiveDataType, "UNSIGNED_64", "U64", 64, "uint64_t", "long", "ULong", "Long", false}, 61 62 {PrimitiveDataType, "BOOLEAN", "BOOLEAN", 8, "bool", "boolean", NULL, NULL, false}, 63 64 {PrimitiveDataType, "UNSIGNED_5_6_5", NULL, 16, NULL, NULL, NULL, NULL, false}, 65 {PrimitiveDataType, "UNSIGNED_5_5_5_1", NULL, 16, NULL, NULL, NULL, NULL, false}, 66 {PrimitiveDataType, "UNSIGNED_4_4_4_4", NULL, 16, NULL, NULL, NULL, NULL, false}, 67 68 {MatrixDataType, "MATRIX_2X2", NULL, 4*32, "rsMatrix_2x2", "Matrix2f", NULL, NULL, false}, 69 {MatrixDataType, "MATRIX_3X3", NULL, 9*32, "rsMatrix_3x3", "Matrix3f", NULL, NULL, false}, 70 {MatrixDataType, "MATRIX_4X4", NULL, 16*32, "rsMatrix_4x4", "Matrix4f", NULL, NULL, false}, 71 72 // TODO: For 64 bit, what will be the size of the objects?? 73 {ObjectDataType, "RS_ELEMENT", "ELEMENT", 32, "Element", "Element", NULL, NULL, false}, 74 {ObjectDataType, "RS_TYPE", "TYPE", 32, "Type", "Type", NULL, NULL, false}, 75 {ObjectDataType, "RS_ALLOCATION", "ALLOCATION", 32, "Allocation", "Allocation", NULL, NULL, false}, 76 {ObjectDataType, "RS_SAMPLER", "SAMPLER", 32, "Sampler", "Sampler", NULL, NULL, false}, 77 {ObjectDataType, "RS_SCRIPT", "SCRIPT", 32, "Script", "Script", NULL, NULL, false}, 78 {ObjectDataType, "RS_MESH", "MESH", 32, "Mesh", "Mesh", NULL, NULL, false}, 79 {ObjectDataType, "RS_PATH", "PATH", 32, "Path", "Path", NULL, NULL, false}, 80 81 {ObjectDataType, "RS_PROGRAM_FRAGMENT", "PROGRAM_FRAGMENT", 32, "ProgramFragment", "ProgramFragment", NULL, NULL, false}, 82 {ObjectDataType, "RS_PROGRAM_VERTEX", "PROGRAM_VERTEX", 32, "ProgramVertex", "ProgramVertex", NULL, NULL, false}, 83 {ObjectDataType, "RS_PROGRAM_RASTER", "PROGRAM_RASTER", 32, "ProgramRaster", "ProgramRaster", NULL, NULL, false}, 84 {ObjectDataType, "RS_PROGRAM_STORE", "PROGRAM_STORE", 32, "ProgramStore", "ProgramStore", NULL, NULL, false}, 85 {ObjectDataType, "RS_FONT", "FONT", 32, "Font", "Font", NULL, NULL, false} 86}; 87 88const int kMaxVectorSize = 4; 89 90struct BuiltinInfo { 91 clang::BuiltinType::Kind builtinTypeKind; 92 DataType type; 93 /* TODO If we return std::string instead of llvm::StringRef, we could build 94 * the name instead of duplicating the entries. 95 */ 96 const char *cname[kMaxVectorSize]; 97}; 98 99 100BuiltinInfo BuiltinInfoTable[] = { 101 {clang::BuiltinType::Bool, DataTypeBoolean, 102 {"bool", "bool2", "bool3", "bool4"}}, 103 {clang::BuiltinType::Char_U, DataTypeUnsigned8, 104 {"uchar", "uchar2", "uchar3", "uchar4"}}, 105 {clang::BuiltinType::UChar, DataTypeUnsigned8, 106 {"uchar", "uchar2", "uchar3", "uchar4"}}, 107 {clang::BuiltinType::Char16, DataTypeSigned16, 108 {"short", "short2", "short3", "short4"}}, 109 {clang::BuiltinType::Char32, DataTypeSigned32, 110 {"int", "int2", "int3", "int4"}}, 111 {clang::BuiltinType::UShort, DataTypeUnsigned16, 112 {"ushort", "ushort2", "ushort3", "ushort4"}}, 113 {clang::BuiltinType::UInt, DataTypeUnsigned32, 114 {"uint", "uint2", "uint3", "uint4"}}, 115 {clang::BuiltinType::ULong, DataTypeUnsigned32, 116 {"uint", "uint2", "uint3", "uint4"}}, 117 {clang::BuiltinType::ULongLong, DataTypeUnsigned64, 118 {"ulong", "ulong2", "ulong3", "ulong4"}}, 119 120 {clang::BuiltinType::Char_S, DataTypeSigned8, 121 {"char", "char2", "char3", "char4"}}, 122 {clang::BuiltinType::SChar, DataTypeSigned8, 123 {"char", "char2", "char3", "char4"}}, 124 {clang::BuiltinType::Short, DataTypeSigned16, 125 {"short", "short2", "short3", "short4"}}, 126 {clang::BuiltinType::Int, DataTypeSigned32, 127 {"int", "int2", "int3", "int4"}}, 128 {clang::BuiltinType::Long, DataTypeSigned64, 129 {"long", "long2", "long3", "long4"}}, 130 {clang::BuiltinType::LongLong, DataTypeSigned64, 131 {"long", "long2", "long3", "long4"}}, 132 {clang::BuiltinType::Float, DataTypeFloat32, 133 {"float", "float2", "float3", "float4"}}, 134 {clang::BuiltinType::Double, DataTypeFloat64, 135 {"double", "double2", "double3", "double4"}}, 136}; 137const int BuiltinInfoTableCount = sizeof(BuiltinInfoTable) / sizeof(BuiltinInfoTable[0]); 138 139struct NameAndPrimitiveType { 140 const char *name; 141 DataType dataType; 142}; 143 144static NameAndPrimitiveType MatrixAndObjectDataTypes[] = { 145 {"rs_matrix2x2", DataTypeRSMatrix2x2}, 146 {"rs_matrix3x3", DataTypeRSMatrix3x3}, 147 {"rs_matrix4x4", DataTypeRSMatrix4x4}, 148 {"rs_element", DataTypeRSElement}, 149 {"rs_type", DataTypeRSType}, 150 {"rs_allocation", DataTypeRSAllocation}, 151 {"rs_sampler", DataTypeRSSampler}, 152 {"rs_script", DataTypeRSScript}, 153 {"rs_mesh", DataTypeRSMesh}, 154 {"rs_path", DataTypeRSPath}, 155 {"rs_program_fragment", DataTypeRSProgramFragment}, 156 {"rs_program_vertex", DataTypeRSProgramVertex}, 157 {"rs_program_raster", DataTypeRSProgramRaster}, 158 {"rs_program_store", DataTypeRSProgramStore}, 159 {"rs_font", 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) != DataTypeUnknown) { 261 return T; // RS object type, no further checks are needed 262 } 263 264 // Check internal struct 265 if (T->isUnionType()) { 266 ReportTypeError(Context, VD, T->getAsUnionType()->getDecl(), 267 "unions cannot be exported: '%0'"); 268 return NULL; 269 } else if (!T->isStructureType()) { 270 slangAssert(false && "Unknown type cannot be exported"); 271 return NULL; 272 } 273 274 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 275 if (RD != NULL) { 276 RD = RD->getDefinition(); 277 if (RD == NULL) { 278 ReportTypeError(Context, NULL, T->getAsStructureType()->getDecl(), 279 "struct is not defined in this module"); 280 return NULL; 281 } 282 } 283 284 if (!TopLevelRecord) { 285 TopLevelRecord = RD; 286 } 287 if (RD->getName().empty()) { 288 ReportTypeError(Context, NULL, RD, 289 "anonymous structures cannot be exported"); 290 return NULL; 291 } 292 293 // Fast check 294 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 295 return NULL; 296 297 // Insert myself into checking set 298 SPS.insert(T); 299 300 // Check all element 301 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 302 FE = RD->field_end(); 303 FI != FE; 304 FI++) { 305 const clang::FieldDecl *FD = *FI; 306 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 307 FT = GET_CANONICAL_TYPE(FT); 308 309 if (!TypeExportableHelper(FT, SPS, Context, VD, TopLevelRecord)) { 310 return NULL; 311 } 312 313 // We don't support bit fields yet 314 // 315 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32 316 if (FD->isBitField()) { 317 Context->ReportError( 318 FD->getLocation(), 319 "bit fields are not able to be exported: '%0.%1'") 320 << RD->getName() << FD->getName(); 321 return NULL; 322 } 323 } 324 325 return T; 326 } 327 case clang::Type::Pointer: { 328 if (TopLevelRecord) { 329 ReportTypeError(Context, VD, TopLevelRecord, 330 "structures containing pointers cannot be exported: '%0'"); 331 return NULL; 332 } 333 334 const clang::PointerType *PT = 335 UNSAFE_CAST_TYPE(const clang::PointerType, T); 336 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 337 338 if (PointeeType->getTypeClass() == clang::Type::Pointer) { 339 ReportTypeError(Context, VD, TopLevelRecord, 340 "multiple levels of pointers cannot be exported: '%0'"); 341 return NULL; 342 } 343 // We don't support pointer with array-type pointee or unsupported pointee 344 // type 345 if (PointeeType->isArrayType() || 346 (TypeExportableHelper(PointeeType, SPS, Context, VD, 347 TopLevelRecord) == NULL)) 348 return NULL; 349 else 350 return T; 351 } 352 case clang::Type::ExtVector: { 353 const clang::ExtVectorType *EVT = 354 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 355 // Only vector with size 2, 3 and 4 are supported. 356 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4) 357 return NULL; 358 359 // Check base element type 360 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 361 362 if ((ElementType->getTypeClass() != clang::Type::Builtin) || 363 (TypeExportableHelper(ElementType, SPS, Context, VD, 364 TopLevelRecord) == NULL)) 365 return NULL; 366 else 367 return T; 368 } 369 case clang::Type::ConstantArray: { 370 const clang::ConstantArrayType *CAT = 371 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 372 373 return ConstantArrayTypeExportableHelper(CAT, SPS, Context, VD, 374 TopLevelRecord); 375 } 376 case clang::Type::Enum: { 377 // FIXME: We currently convert enums to integers, rather than reflecting 378 // a more complete (and nicer type-safe Java version). 379 return Context->getASTContext().IntTy.getTypePtr(); 380 } 381 default: { 382 slangAssert(false && "Unknown type cannot be validated"); 383 return NULL; 384 } 385 } 386} 387 388// Return the type that can be used to create RSExportType, will always return 389// the canonical type 390// If the Type T is not exportable, this function returns NULL. DiagEngine is 391// used to generate proper Clang diagnostic messages when a 392// non-exportable type is detected. TopLevelRecord is used to capture the 393// highest struct (in the case of a nested hierarchy) for detecting other 394// types that cannot be exported (mostly pointers within a struct). 395static const clang::Type *TypeExportable(const clang::Type *T, 396 slang::RSContext *Context, 397 const clang::VarDecl *VD) { 398 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 399 llvm::SmallPtrSet<const clang::Type*, 8>(); 400 401 return TypeExportableHelper(T, SPS, Context, VD, NULL); 402} 403 404static bool ValidateRSObjectInVarDecl(slang::RSContext *Context, 405 clang::VarDecl *VD, bool InCompositeType, 406 unsigned int TargetAPI) { 407 if (TargetAPI < SLANG_JB_TARGET_API) { 408 // Only if we are already in a composite type (like an array or structure). 409 if (InCompositeType) { 410 // Only if we are actually exported (i.e. non-static). 411 if (VD->hasLinkage() && 412 (VD->getFormalLinkage() == clang::ExternalLinkage)) { 413 // Only if we are not a pointer to an object. 414 const clang::Type *T = GET_CANONICAL_TYPE(VD->getType().getTypePtr()); 415 if (T->getTypeClass() != clang::Type::Pointer) { 416 ReportTypeError(Context, VD, NULL, 417 "arrays/structures containing RS object types " 418 "cannot be exported in target API < %1: '%0'", 419 SLANG_JB_TARGET_API); 420 return false; 421 } 422 } 423 } 424 } 425 426 return true; 427} 428 429// Helper function for ValidateType(). We do a recursive descent on the 430// type hierarchy to ensure that we can properly export/handle the 431// declaration. 432// \return true if the variable declaration is valid, 433// false if it is invalid (along with proper diagnostics). 434// 435// C - ASTContext (for diagnostics + builtin types). 436// T - sub-type that we are validating. 437// ND - (optional) top-level named declaration that we are validating. 438// SPS - set of types we have already seen/validated. 439// InCompositeType - true if we are within an outer composite type. 440// UnionDecl - set if we are in a sub-type of a union. 441// TargetAPI - target SDK API level. 442// IsFilterscript - whether or not we are compiling for Filterscript 443static bool ValidateTypeHelper( 444 slang::RSContext *Context, 445 clang::ASTContext &C, 446 const clang::Type *&T, 447 clang::NamedDecl *ND, 448 clang::SourceLocation Loc, 449 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 450 bool InCompositeType, 451 clang::RecordDecl *UnionDecl, 452 unsigned int TargetAPI, 453 bool IsFilterscript) { 454 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 455 return true; 456 457 if (SPS.count(T)) 458 return true; 459 460 switch (T->getTypeClass()) { 461 case clang::Type::Record: { 462 if (RSExportPrimitiveType::IsRSObjectType(T)) { 463 clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL); 464 if (VD && !ValidateRSObjectInVarDecl(Context, VD, InCompositeType, 465 TargetAPI)) { 466 return false; 467 } 468 } 469 470 if (RSExportPrimitiveType::GetRSSpecificType(T) != DataTypeUnknown) { 471 if (!UnionDecl) { 472 return true; 473 } else if (RSExportPrimitiveType::IsRSObjectType(T)) { 474 ReportTypeError(Context, NULL, UnionDecl, 475 "unions containing RS object types are not allowed"); 476 return false; 477 } 478 } 479 480 clang::RecordDecl *RD = NULL; 481 482 // Check internal struct 483 if (T->isUnionType()) { 484 RD = T->getAsUnionType()->getDecl(); 485 UnionDecl = RD; 486 } else if (T->isStructureType()) { 487 RD = T->getAsStructureType()->getDecl(); 488 } else { 489 slangAssert(false && "Unknown type cannot be exported"); 490 return false; 491 } 492 493 if (RD != NULL) { 494 RD = RD->getDefinition(); 495 if (RD == NULL) { 496 // FIXME 497 return true; 498 } 499 } 500 501 // Fast check 502 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 503 return false; 504 505 // Insert myself into checking set 506 SPS.insert(T); 507 508 // Check all elements 509 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 510 FE = RD->field_end(); 511 FI != FE; 512 FI++) { 513 const clang::FieldDecl *FD = *FI; 514 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 515 FT = GET_CANONICAL_TYPE(FT); 516 517 if (!ValidateTypeHelper(Context, C, FT, ND, Loc, SPS, true, UnionDecl, 518 TargetAPI, IsFilterscript)) { 519 return false; 520 } 521 } 522 523 return true; 524 } 525 526 case clang::Type::Builtin: { 527 if (IsFilterscript) { 528 clang::QualType QT = T->getCanonicalTypeInternal(); 529 if (QT == C.DoubleTy || 530 QT == C.LongDoubleTy || 531 QT == C.LongTy || 532 QT == C.LongLongTy) { 533 if (ND) { 534 Context->ReportError( 535 Loc, 536 "Builtin types > 32 bits in size are forbidden in " 537 "Filterscript: '%0'") 538 << ND->getName(); 539 } else { 540 Context->ReportError( 541 Loc, 542 "Builtin types > 32 bits in size are forbidden in " 543 "Filterscript"); 544 } 545 return false; 546 } 547 } 548 break; 549 } 550 551 case clang::Type::Pointer: { 552 if (IsFilterscript) { 553 if (ND) { 554 Context->ReportError(Loc, 555 "Pointers are forbidden in Filterscript: '%0'") 556 << ND->getName(); 557 return false; 558 } else { 559 // TODO(srhines): Find a better way to handle expressions (i.e. no 560 // NamedDecl) involving pointers in FS that should be allowed. 561 // An example would be calls to library functions like 562 // rsMatrixMultiply() that take rs_matrixNxN * types. 563 } 564 } 565 566 const clang::PointerType *PT = 567 UNSAFE_CAST_TYPE(const clang::PointerType, T); 568 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 569 570 return ValidateTypeHelper(Context, C, PointeeType, ND, Loc, SPS, 571 InCompositeType, UnionDecl, TargetAPI, 572 IsFilterscript); 573 } 574 575 case clang::Type::ExtVector: { 576 const clang::ExtVectorType *EVT = 577 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 578 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 579 if (TargetAPI < SLANG_ICS_TARGET_API && 580 InCompositeType && 581 EVT->getNumElements() == 3 && 582 ND && 583 ND->getFormalLinkage() == clang::ExternalLinkage) { 584 ReportTypeError(Context, ND, NULL, 585 "structs containing vectors of dimension 3 cannot " 586 "be exported at this API level: '%0'"); 587 return false; 588 } 589 return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true, 590 UnionDecl, TargetAPI, IsFilterscript); 591 } 592 593 case clang::Type::ConstantArray: { 594 const clang::ConstantArrayType *CAT = 595 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 596 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 597 return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true, 598 UnionDecl, TargetAPI, IsFilterscript); 599 } 600 601 default: { 602 break; 603 } 604 } 605 606 return true; 607} 608 609} // namespace 610 611/****************************** RSExportType ******************************/ 612bool RSExportType::NormalizeType(const clang::Type *&T, 613 llvm::StringRef &TypeName, 614 RSContext *Context, 615 const clang::VarDecl *VD) { 616 if ((T = TypeExportable(T, Context, VD)) == NULL) { 617 return false; 618 } 619 // Get type name 620 TypeName = RSExportType::GetTypeName(T); 621 if (Context && TypeName.empty()) { 622 if (VD) { 623 Context->ReportError(VD->getLocation(), 624 "anonymous types cannot be exported"); 625 } else { 626 Context->ReportError("anonymous types cannot be exported"); 627 } 628 return false; 629 } 630 631 return true; 632} 633 634bool RSExportType::ValidateType(slang::RSContext *Context, clang::ASTContext &C, 635 clang::QualType QT, clang::NamedDecl *ND, 636 clang::SourceLocation Loc, 637 unsigned int TargetAPI, bool IsFilterscript) { 638 const clang::Type *T = QT.getTypePtr(); 639 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 640 llvm::SmallPtrSet<const clang::Type*, 8>(); 641 642 return ValidateTypeHelper(Context, C, T, ND, Loc, SPS, false, NULL, TargetAPI, 643 IsFilterscript); 644 return true; 645} 646 647bool RSExportType::ValidateVarDecl(slang::RSContext *Context, 648 clang::VarDecl *VD, unsigned int TargetAPI, 649 bool IsFilterscript) { 650 return ValidateType(Context, VD->getASTContext(), VD->getType(), VD, 651 VD->getLocation(), TargetAPI, IsFilterscript); 652} 653 654const clang::Type 655*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 656 if (DD) { 657 clang::QualType T = DD->getType(); 658 659 if (T.isNull()) 660 return NULL; 661 else 662 return T.getTypePtr(); 663 } 664 return NULL; 665} 666 667llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 668 T = GET_CANONICAL_TYPE(T); 669 if (T == NULL) 670 return llvm::StringRef(); 671 672 switch (T->getTypeClass()) { 673 case clang::Type::Builtin: { 674 const clang::BuiltinType *BT = 675 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 676 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 677 if (info != NULL) { 678 return info->cname[0]; 679 } 680 slangAssert(false && "Unknown data type of the builtin"); 681 break; 682 } 683 case clang::Type::Record: { 684 clang::RecordDecl *RD; 685 if (T->isStructureType()) { 686 RD = T->getAsStructureType()->getDecl(); 687 } else { 688 break; 689 } 690 691 llvm::StringRef Name = RD->getName(); 692 if (Name.empty()) { 693 if (RD->getTypedefNameForAnonDecl() != NULL) { 694 Name = RD->getTypedefNameForAnonDecl()->getName(); 695 } 696 697 if (Name.empty()) { 698 // Try to find a name from redeclaration (i.e. typedef) 699 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 700 RE = RD->redecls_end(); 701 RI != RE; 702 RI++) { 703 slangAssert(*RI != NULL && "cannot be NULL object"); 704 705 Name = (*RI)->getName(); 706 if (!Name.empty()) 707 break; 708 } 709 } 710 } 711 return Name; 712 } 713 case clang::Type::Pointer: { 714 // "*" plus pointee name 715 const clang::Type *PT = GET_POINTEE_TYPE(T); 716 llvm::StringRef PointeeName; 717 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 718 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 719 Name[0] = '*'; 720 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 721 Name[PointeeName.size() + 1] = '\0'; 722 return Name; 723 } 724 break; 725 } 726 case clang::Type::ExtVector: { 727 const clang::ExtVectorType *EVT = 728 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 729 return RSExportVectorType::GetTypeName(EVT); 730 break; 731 } 732 case clang::Type::ConstantArray : { 733 // Construct name for a constant array is too complicated. 734 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 735 } 736 default: { 737 break; 738 } 739 } 740 741 return llvm::StringRef(); 742} 743 744 745RSExportType *RSExportType::Create(RSContext *Context, 746 const clang::Type *T, 747 const llvm::StringRef &TypeName) { 748 // Lookup the context to see whether the type was processed before. 749 // Newly created RSExportType will insert into context 750 // in RSExportType::RSExportType() 751 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 752 753 if (ETI != Context->export_types_end()) 754 return ETI->second; 755 756 RSExportType *ET = NULL; 757 switch (T->getTypeClass()) { 758 case clang::Type::Record: { 759 DataType dt = RSExportPrimitiveType::GetRSSpecificType(TypeName); 760 switch (dt) { 761 case DataTypeUnknown: { 762 // User-defined types 763 ET = RSExportRecordType::Create(Context, 764 T->getAsStructureType(), 765 TypeName); 766 break; 767 } 768 case DataTypeRSMatrix2x2: { 769 // 2 x 2 Matrix type 770 ET = RSExportMatrixType::Create(Context, 771 T->getAsStructureType(), 772 TypeName, 773 2); 774 break; 775 } 776 case DataTypeRSMatrix3x3: { 777 // 3 x 3 Matrix type 778 ET = RSExportMatrixType::Create(Context, 779 T->getAsStructureType(), 780 TypeName, 781 3); 782 break; 783 } 784 case DataTypeRSMatrix4x4: { 785 // 4 x 4 Matrix type 786 ET = RSExportMatrixType::Create(Context, 787 T->getAsStructureType(), 788 TypeName, 789 4); 790 break; 791 } 792 default: { 793 // Others are primitive types 794 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 795 break; 796 } 797 } 798 break; 799 } 800 case clang::Type::Builtin: { 801 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 802 break; 803 } 804 case clang::Type::Pointer: { 805 ET = RSExportPointerType::Create(Context, 806 UNSAFE_CAST_TYPE(const clang::PointerType, T), TypeName); 807 // FIXME: free the name (allocated in RSExportType::GetTypeName) 808 delete [] TypeName.data(); 809 break; 810 } 811 case clang::Type::ExtVector: { 812 ET = RSExportVectorType::Create(Context, 813 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), TypeName); 814 break; 815 } 816 case clang::Type::ConstantArray: { 817 ET = RSExportConstantArrayType::Create( 818 Context, 819 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T)); 820 break; 821 } 822 default: { 823 Context->ReportError("unknown type cannot be exported: '%0'") 824 << T->getTypeClassName(); 825 break; 826 } 827 } 828 829 return ET; 830} 831 832RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 833 llvm::StringRef TypeName; 834 if (NormalizeType(T, TypeName, Context, NULL)) { 835 return Create(Context, T, TypeName); 836 } else { 837 return NULL; 838 } 839} 840 841RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 842 const clang::VarDecl *VD) { 843 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 844} 845 846size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 847 return ET->getRSContext()->getDataLayout()->getTypeStoreSize( 848 ET->getLLVMType()); 849} 850 851size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 852 if (ET->getClass() == RSExportType::ExportClassRecord) 853 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 854 else 855 return ET->getRSContext()->getDataLayout()->getTypeAllocSize( 856 ET->getLLVMType()); 857} 858 859RSExportType::RSExportType(RSContext *Context, 860 ExportClass Class, 861 const llvm::StringRef &Name) 862 : RSExportable(Context, RSExportable::EX_TYPE), 863 mClass(Class), 864 // Make a copy on Name since memory stored @Name is either allocated in 865 // ASTContext or allocated in GetTypeName which will be destroyed later. 866 mName(Name.data(), Name.size()), 867 mLLVMType(NULL) { 868 // Don't cache the type whose name start with '<'. Those type failed to 869 // get their name since constructing their name in GetTypeName() requiring 870 // complicated work. 871 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 872 // TODO(zonr): Need to check whether the insertion is successful or not. 873 Context->insertExportType(llvm::StringRef(Name), this); 874 return; 875} 876 877bool RSExportType::keep() { 878 if (!RSExportable::keep()) 879 return false; 880 // Invalidate converted LLVM type. 881 mLLVMType = NULL; 882 return true; 883} 884 885bool RSExportType::equals(const RSExportable *E) const { 886 CHECK_PARENT_EQUALITY(RSExportable, E); 887 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 888} 889 890RSExportType::~RSExportType() { 891} 892 893/************************** RSExportPrimitiveType **************************/ 894llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 895RSExportPrimitiveType::RSSpecificTypeMap; 896 897llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 898 899bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 900 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 901 return true; 902 else 903 return false; 904} 905 906DataType 907RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 908 if (TypeName.empty()) 909 return DataTypeUnknown; 910 911 if (RSSpecificTypeMap->empty()) { 912 for (int i = 0; i < MatrixAndObjectDataTypesCount; i++) { 913 RSSpecificTypeMap->GetOrCreateValue(MatrixAndObjectDataTypes[i].name, 914 MatrixAndObjectDataTypes[i].dataType); 915 } 916 } 917 918 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 919 if (I == RSSpecificTypeMap->end()) 920 return DataTypeUnknown; 921 else 922 return I->getValue(); 923} 924 925DataType RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 926 T = GET_CANONICAL_TYPE(T); 927 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 928 return DataTypeUnknown; 929 930 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 931} 932 933bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 934 if (DT < 0 || DT >= DataTypeMax) { 935 return false; 936 } 937 return gReflectionTypes[DT].category == MatrixDataType; 938} 939 940bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 941 if (DT < 0 || DT >= DataTypeMax) { 942 return false; 943 } 944 return gReflectionTypes[DT].category == ObjectDataType; 945} 946 947bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 948 bool RSObjectTypeSeen = false; 949 while (T && T->isArrayType()) { 950 T = T->getArrayElementTypeNoTypeQual(); 951 } 952 953 const clang::RecordType *RT = T->getAsStructureType(); 954 if (!RT) { 955 return false; 956 } 957 958 const clang::RecordDecl *RD = RT->getDecl(); 959 if (RD) { 960 RD = RD->getDefinition(); 961 } 962 if (!RD) { 963 return false; 964 } 965 966 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 967 FE = RD->field_end(); 968 FI != FE; 969 FI++) { 970 // We just look through all field declarations to see if we find a 971 // declaration for an RS object type (or an array of one). 972 const clang::FieldDecl *FD = *FI; 973 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 974 while (FT && FT->isArrayType()) { 975 FT = FT->getArrayElementTypeNoTypeQual(); 976 } 977 978 DataType DT = GetRSSpecificType(FT); 979 if (IsRSObjectType(DT)) { 980 // RS object types definitely need to be zero-initialized 981 RSObjectTypeSeen = true; 982 } else { 983 switch (DT) { 984 case DataTypeRSMatrix2x2: 985 case DataTypeRSMatrix3x3: 986 case DataTypeRSMatrix4x4: 987 // Matrix types should get zero-initialized as well 988 RSObjectTypeSeen = true; 989 break; 990 default: 991 // Ignore all other primitive types 992 break; 993 } 994 while (FT && FT->isArrayType()) { 995 FT = FT->getArrayElementTypeNoTypeQual(); 996 } 997 if (FT->isStructureType()) { 998 // Recursively handle structs of structs (even though these can't 999 // be exported, it is possible for a user to have them internally). 1000 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 1001 } 1002 } 1003 } 1004 1005 return RSObjectTypeSeen; 1006} 1007 1008size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 1009 int type = EPT->getType(); 1010 slangAssert((type > DataTypeUnknown && type < DataTypeMax) && 1011 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 1012 return gReflectionTypes[type].size_in_bits; 1013} 1014 1015DataType 1016RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 1017 if (T == NULL) 1018 return DataTypeUnknown; 1019 1020 switch (T->getTypeClass()) { 1021 case clang::Type::Builtin: { 1022 const clang::BuiltinType *BT = 1023 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 1024 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1025 if (info != NULL) { 1026 return info->type; 1027 } 1028 // The size of type WChar depend on platform so we abandon the support 1029 // to them. 1030 Context->ReportError("built-in type cannot be exported: '%0'") 1031 << T->getTypeClassName(); 1032 break; 1033 } 1034 case clang::Type::Record: { 1035 // must be RS object type 1036 return RSExportPrimitiveType::GetRSSpecificType(T); 1037 } 1038 default: { 1039 Context->ReportError("primitive type cannot be exported: '%0'") 1040 << T->getTypeClassName(); 1041 break; 1042 } 1043 } 1044 1045 return DataTypeUnknown; 1046} 1047 1048RSExportPrimitiveType 1049*RSExportPrimitiveType::Create(RSContext *Context, 1050 const clang::Type *T, 1051 const llvm::StringRef &TypeName, 1052 bool Normalized) { 1053 DataType DT = GetDataType(Context, T); 1054 1055 if ((DT == DataTypeUnknown) || TypeName.empty()) 1056 return NULL; 1057 else 1058 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 1059 DT, Normalized); 1060} 1061 1062RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 1063 const clang::Type *T) { 1064 llvm::StringRef TypeName; 1065 if (RSExportType::NormalizeType(T, TypeName, Context, NULL) 1066 && IsPrimitiveType(T)) { 1067 return Create(Context, T, TypeName); 1068 } else { 1069 return NULL; 1070 } 1071} 1072 1073llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 1074 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1075 1076 if (isRSObjectType()) { 1077 // struct { 1078 // int *p; 1079 // } __attribute__((packed, aligned(pointer_size))) 1080 // 1081 // which is 1082 // 1083 // <{ [1 x i32] }> in LLVM 1084 // 1085 if (RSObjectLLVMType == NULL) { 1086 std::vector<llvm::Type *> Elements; 1087 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 1088 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 1089 } 1090 return RSObjectLLVMType; 1091 } 1092 1093 switch (mType) { 1094 case DataTypeFloat32: { 1095 return llvm::Type::getFloatTy(C); 1096 break; 1097 } 1098 case DataTypeFloat64: { 1099 return llvm::Type::getDoubleTy(C); 1100 break; 1101 } 1102 case DataTypeBoolean: { 1103 return llvm::Type::getInt1Ty(C); 1104 break; 1105 } 1106 case DataTypeSigned8: 1107 case DataTypeUnsigned8: { 1108 return llvm::Type::getInt8Ty(C); 1109 break; 1110 } 1111 case DataTypeSigned16: 1112 case DataTypeUnsigned16: 1113 case DataTypeUnsigned565: 1114 case DataTypeUnsigned5551: 1115 case DataTypeUnsigned4444: { 1116 return llvm::Type::getInt16Ty(C); 1117 break; 1118 } 1119 case DataTypeSigned32: 1120 case DataTypeUnsigned32: { 1121 return llvm::Type::getInt32Ty(C); 1122 break; 1123 } 1124 case DataTypeSigned64: 1125 case DataTypeUnsigned64: { 1126 return llvm::Type::getInt64Ty(C); 1127 break; 1128 } 1129 default: { 1130 slangAssert(false && "Unknown data type"); 1131 } 1132 } 1133 1134 return NULL; 1135} 1136 1137bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1138 CHECK_PARENT_EQUALITY(RSExportType, E); 1139 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1140} 1141 1142RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1143 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1144 return &gReflectionTypes[DT]; 1145 } else { 1146 return NULL; 1147 } 1148} 1149 1150/**************************** RSExportPointerType ****************************/ 1151 1152RSExportPointerType 1153*RSExportPointerType::Create(RSContext *Context, 1154 const clang::PointerType *PT, 1155 const llvm::StringRef &TypeName) { 1156 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 1157 const RSExportType *PointeeET; 1158 1159 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1160 PointeeET = RSExportType::Create(Context, PointeeType); 1161 } else { 1162 // Double or higher dimension of pointer, export as int* 1163 PointeeET = RSExportPrimitiveType::Create(Context, 1164 Context->getASTContext().IntTy.getTypePtr()); 1165 } 1166 1167 if (PointeeET == NULL) { 1168 // Error diagnostic is emitted for corresponding pointee type 1169 return NULL; 1170 } 1171 1172 return new RSExportPointerType(Context, TypeName, PointeeET); 1173} 1174 1175llvm::Type *RSExportPointerType::convertToLLVMType() const { 1176 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1177 return llvm::PointerType::getUnqual(PointeeType); 1178} 1179 1180bool RSExportPointerType::keep() { 1181 if (!RSExportType::keep()) 1182 return false; 1183 const_cast<RSExportType*>(mPointeeType)->keep(); 1184 return true; 1185} 1186 1187bool RSExportPointerType::equals(const RSExportable *E) const { 1188 CHECK_PARENT_EQUALITY(RSExportType, E); 1189 return (static_cast<const RSExportPointerType*>(E) 1190 ->getPointeeType()->equals(getPointeeType())); 1191} 1192 1193/***************************** RSExportVectorType *****************************/ 1194llvm::StringRef 1195RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1196 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1197 llvm::StringRef name; 1198 1199 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1200 return name; 1201 1202 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType, 1203 ElementType); 1204 if ((EVT->getNumElements() < 1) || 1205 (EVT->getNumElements() > 4)) 1206 return name; 1207 1208 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1209 if (info != NULL) { 1210 // Compiler is smart enough to optimize following *big if branches* since 1211 // they all become "constant comparison" after macro expansion 1212 int I = EVT->getNumElements() - 1; 1213 if (I < kMaxVectorSize) { 1214 name = info->cname[I]; 1215 } else { 1216 slangAssert(false && "Max vector is 4"); 1217 } 1218 } 1219 return name; 1220} 1221 1222RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1223 const clang::ExtVectorType *EVT, 1224 const llvm::StringRef &TypeName, 1225 bool Normalized) { 1226 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1227 1228 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 1229 DataType DT = RSExportPrimitiveType::GetDataType(Context, ElementType); 1230 1231 if (DT != DataTypeUnknown) 1232 return new RSExportVectorType(Context, 1233 TypeName, 1234 DT, 1235 Normalized, 1236 EVT->getNumElements()); 1237 else 1238 return NULL; 1239} 1240 1241llvm::Type *RSExportVectorType::convertToLLVMType() const { 1242 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 1243 return llvm::VectorType::get(ElementType, getNumElement()); 1244} 1245 1246bool RSExportVectorType::equals(const RSExportable *E) const { 1247 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 1248 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 1249 == getNumElement()); 1250} 1251 1252/***************************** RSExportMatrixType *****************************/ 1253RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 1254 const clang::RecordType *RT, 1255 const llvm::StringRef &TypeName, 1256 unsigned Dim) { 1257 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 1258 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 1259 1260 // Check whether the struct rs_matrix is in our expected form (but assume it's 1261 // correct if we're not sure whether it's correct or not) 1262 const clang::RecordDecl* RD = RT->getDecl(); 1263 RD = RD->getDefinition(); 1264 if (RD != NULL) { 1265 // Find definition, perform further examination 1266 if (RD->field_empty()) { 1267 Context->ReportError( 1268 RD->getLocation(), 1269 "invalid matrix struct: must have 1 field for saving values: '%0'") 1270 << RD->getName(); 1271 return NULL; 1272 } 1273 1274 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 1275 const clang::FieldDecl *FD = *FIT; 1276 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1277 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 1278 Context->ReportError(RD->getLocation(), 1279 "invalid matrix struct: first field should" 1280 " be an array with constant size: '%0'") 1281 << RD->getName(); 1282 return NULL; 1283 } 1284 const clang::ConstantArrayType *CAT = 1285 static_cast<const clang::ConstantArrayType *>(FT); 1286 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1287 if ((ElementType == NULL) || 1288 (ElementType->getTypeClass() != clang::Type::Builtin) || 1289 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() != 1290 clang::BuiltinType::Float)) { 1291 Context->ReportError(RD->getLocation(), 1292 "invalid matrix struct: first field " 1293 "should be a float array: '%0'") 1294 << RD->getName(); 1295 return NULL; 1296 } 1297 1298 if (CAT->getSize() != Dim * Dim) { 1299 Context->ReportError(RD->getLocation(), 1300 "invalid matrix struct: first field " 1301 "should be an array with size %0: '%1'") 1302 << (Dim * Dim) << (RD->getName()); 1303 return NULL; 1304 } 1305 1306 FIT++; 1307 if (FIT != RD->field_end()) { 1308 Context->ReportError(RD->getLocation(), 1309 "invalid matrix struct: must have " 1310 "exactly 1 field: '%0'") 1311 << RD->getName(); 1312 return NULL; 1313 } 1314 } 1315 1316 return new RSExportMatrixType(Context, TypeName, Dim); 1317} 1318 1319llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1320 // Construct LLVM type: 1321 // struct { 1322 // float X[mDim * mDim]; 1323 // } 1324 1325 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1326 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1327 mDim * mDim); 1328 return llvm::StructType::get(C, X, false); 1329} 1330 1331bool RSExportMatrixType::equals(const RSExportable *E) const { 1332 CHECK_PARENT_EQUALITY(RSExportType, E); 1333 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1334} 1335 1336/************************* RSExportConstantArrayType *************************/ 1337RSExportConstantArrayType 1338*RSExportConstantArrayType::Create(RSContext *Context, 1339 const clang::ConstantArrayType *CAT) { 1340 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1341 1342 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1343 1344 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1345 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1346 1347 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1348 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1349 1350 if (ElementET == NULL) { 1351 return NULL; 1352 } 1353 1354 return new RSExportConstantArrayType(Context, 1355 ElementET, 1356 Size); 1357} 1358 1359llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1360 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1361} 1362 1363bool RSExportConstantArrayType::keep() { 1364 if (!RSExportType::keep()) 1365 return false; 1366 const_cast<RSExportType*>(mElementType)->keep(); 1367 return true; 1368} 1369 1370bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1371 CHECK_PARENT_EQUALITY(RSExportType, E); 1372 const RSExportConstantArrayType *RHS = 1373 static_cast<const RSExportConstantArrayType*>(E); 1374 return ((getSize() == RHS->getSize()) && 1375 (getElementType()->equals(RHS->getElementType()))); 1376} 1377 1378/**************************** RSExportRecordType ****************************/ 1379RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1380 const clang::RecordType *RT, 1381 const llvm::StringRef &TypeName, 1382 bool mIsArtificial) { 1383 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1384 1385 const clang::RecordDecl *RD = RT->getDecl(); 1386 slangAssert(RD->isStruct()); 1387 1388 RD = RD->getDefinition(); 1389 if (RD == NULL) { 1390 slangAssert(false && "struct is not defined in this module"); 1391 return NULL; 1392 } 1393 1394 // Struct layout construct by clang. We rely on this for obtaining the 1395 // alloc size of a struct and offset of every field in that struct. 1396 const clang::ASTRecordLayout *RL = 1397 &Context->getASTContext().getASTRecordLayout(RD); 1398 slangAssert((RL != NULL) && 1399 "Failed to retrieve the struct layout from Clang."); 1400 1401 RSExportRecordType *ERT = 1402 new RSExportRecordType(Context, 1403 TypeName, 1404 RD->hasAttr<clang::PackedAttr>(), 1405 mIsArtificial, 1406 RL->getSize().getQuantity()); 1407 unsigned int Index = 0; 1408 1409 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1410 FE = RD->field_end(); 1411 FI != FE; 1412 FI++, Index++) { 1413 1414 // FIXME: All fields should be primitive type 1415 slangAssert(FI->getKind() == clang::Decl::Field); 1416 clang::FieldDecl *FD = *FI; 1417 1418 if (FD->isBitField()) { 1419 return NULL; 1420 } 1421 1422 // Type 1423 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1424 1425 if (ET != NULL) { 1426 ERT->mFields.push_back( 1427 new Field(ET, FD->getName(), ERT, 1428 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1429 } else { 1430 Context->ReportError(RD->getLocation(), 1431 "field type cannot be exported: '%0.%1'") 1432 << RD->getName() << FD->getName(); 1433 return NULL; 1434 } 1435 } 1436 1437 return ERT; 1438} 1439 1440llvm::Type *RSExportRecordType::convertToLLVMType() const { 1441 // Create an opaque type since struct may reference itself recursively. 1442 1443 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to? 1444 std::vector<llvm::Type*> FieldTypes; 1445 1446 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1447 FI != FE; 1448 FI++) { 1449 const Field *F = *FI; 1450 const RSExportType *FET = F->getType(); 1451 1452 FieldTypes.push_back(FET->getLLVMType()); 1453 } 1454 1455 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1456 FieldTypes, 1457 mIsPacked); 1458 if (ST != NULL) { 1459 return ST; 1460 } else { 1461 return NULL; 1462 } 1463} 1464 1465bool RSExportRecordType::keep() { 1466 if (!RSExportType::keep()) 1467 return false; 1468 for (std::list<const Field*>::iterator I = mFields.begin(), 1469 E = mFields.end(); 1470 I != E; 1471 I++) { 1472 const_cast<RSExportType*>((*I)->getType())->keep(); 1473 } 1474 return true; 1475} 1476 1477bool RSExportRecordType::equals(const RSExportable *E) const { 1478 CHECK_PARENT_EQUALITY(RSExportType, E); 1479 1480 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1481 1482 if (ERT->getFields().size() != getFields().size()) 1483 return false; 1484 1485 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1486 1487 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1488 if (!(*AI)->getType()->equals((*BI)->getType())) 1489 return false; 1490 AI++; 1491 BI++; 1492 } 1493 1494 return true; 1495} 1496 1497void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const { 1498 memset(rtd, 0, sizeof(*rtd)); 1499 rtd->vecSize = 1; 1500 1501 switch(getClass()) { 1502 case RSExportType::ExportClassPrimitive: { 1503 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this); 1504 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT); 1505 return; 1506 } 1507 case RSExportType::ExportClassPointer: { 1508 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this); 1509 const RSExportType *PointeeType = EPT->getPointeeType(); 1510 PointeeType->convertToRTD(rtd); 1511 rtd->isPointer = true; 1512 return; 1513 } 1514 case RSExportType::ExportClassVector: { 1515 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this); 1516 rtd->type = EVT->getRSReflectionType(EVT); 1517 rtd->vecSize = EVT->getNumElement(); 1518 return; 1519 } 1520 case RSExportType::ExportClassMatrix: { 1521 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this); 1522 unsigned Dim = EMT->getDim(); 1523 slangAssert((Dim >= 2) && (Dim <= 4)); 1524 rtd->type = &gReflectionTypes[15 + Dim-2]; 1525 return; 1526 } 1527 case RSExportType::ExportClassConstantArray: { 1528 const RSExportConstantArrayType* CAT = 1529 static_cast<const RSExportConstantArrayType*>(this); 1530 CAT->getElementType()->convertToRTD(rtd); 1531 rtd->arraySize = CAT->getSize(); 1532 return; 1533 } 1534 case RSExportType::ExportClassRecord: { 1535 slangAssert(!"RSExportType::ExportClassRecord not implemented"); 1536 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item"; 1537 } 1538 default: { 1539 slangAssert(false && "Unknown class of type"); 1540 } 1541 } 1542} 1543 1544 1545} // namespace slang 1546