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 40 namespace slang { 41 42 namespace { 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 */ 49 static 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 // RS object types are 32 bits in 32-bit RS, but 256 bits in 64-bit RS. 73 // This is handled specially by the GetSizeInBits() method. 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 89 const int kMaxVectorSize = 4; 90 91 struct BuiltinInfo { 92 clang::BuiltinType::Kind builtinTypeKind; 93 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 100 101 BuiltinInfo BuiltinInfoTable[] = { 102 {clang::BuiltinType::Bool, DataTypeBoolean, 103 {"bool", "bool2", "bool3", "bool4"}}, 104 {clang::BuiltinType::Char_U, DataTypeUnsigned8, 105 {"uchar", "uchar2", "uchar3", "uchar4"}}, 106 {clang::BuiltinType::UChar, DataTypeUnsigned8, 107 {"uchar", "uchar2", "uchar3", "uchar4"}}, 108 {clang::BuiltinType::Char16, DataTypeSigned16, 109 {"short", "short2", "short3", "short4"}}, 110 {clang::BuiltinType::Char32, DataTypeSigned32, 111 {"int", "int2", "int3", "int4"}}, 112 {clang::BuiltinType::UShort, DataTypeUnsigned16, 113 {"ushort", "ushort2", "ushort3", "ushort4"}}, 114 {clang::BuiltinType::UInt, DataTypeUnsigned32, 115 {"uint", "uint2", "uint3", "uint4"}}, 116 {clang::BuiltinType::ULong, DataTypeUnsigned64, 117 {"ulong", "ulong2", "ulong3", "ulong4"}}, 118 {clang::BuiltinType::ULongLong, DataTypeUnsigned64, 119 {"ulong", "ulong2", "ulong3", "ulong4"}}, 120 121 {clang::BuiltinType::Char_S, DataTypeSigned8, 122 {"char", "char2", "char3", "char4"}}, 123 {clang::BuiltinType::SChar, DataTypeSigned8, 124 {"char", "char2", "char3", "char4"}}, 125 {clang::BuiltinType::Short, DataTypeSigned16, 126 {"short", "short2", "short3", "short4"}}, 127 {clang::BuiltinType::Int, DataTypeSigned32, 128 {"int", "int2", "int3", "int4"}}, 129 {clang::BuiltinType::Long, DataTypeSigned64, 130 {"long", "long2", "long3", "long4"}}, 131 {clang::BuiltinType::LongLong, DataTypeSigned64, 132 {"long", "long2", "long3", "long4"}}, 133 {clang::BuiltinType::Float, DataTypeFloat32, 134 {"float", "float2", "float3", "float4"}}, 135 {clang::BuiltinType::Double, DataTypeFloat64, 136 {"double", "double2", "double3", "double4"}}, 137 }; 138 const int BuiltinInfoTableCount = sizeof(BuiltinInfoTable) / sizeof(BuiltinInfoTable[0]); 139 140 struct NameAndPrimitiveType { 141 const char *name; 142 DataType dataType; 143 }; 144 145 static NameAndPrimitiveType MatrixAndObjectDataTypes[] = { 146 {"rs_matrix2x2", DataTypeRSMatrix2x2}, 147 {"rs_matrix3x3", DataTypeRSMatrix3x3}, 148 {"rs_matrix4x4", DataTypeRSMatrix4x4}, 149 {"rs_element", DataTypeRSElement}, 150 {"rs_type", DataTypeRSType}, 151 {"rs_allocation", DataTypeRSAllocation}, 152 {"rs_sampler", DataTypeRSSampler}, 153 {"rs_script", DataTypeRSScript}, 154 {"rs_mesh", DataTypeRSMesh}, 155 {"rs_path", DataTypeRSPath}, 156 {"rs_program_fragment", DataTypeRSProgramFragment}, 157 {"rs_program_vertex", DataTypeRSProgramVertex}, 158 {"rs_program_raster", DataTypeRSProgramRaster}, 159 {"rs_program_store", DataTypeRSProgramStore}, 160 {"rs_font", DataTypeRSFont}, 161 }; 162 163 const int MatrixAndObjectDataTypesCount = 164 sizeof(MatrixAndObjectDataTypes) / sizeof(MatrixAndObjectDataTypes[0]); 165 166 static const clang::Type *TypeExportableHelper( 167 const clang::Type *T, 168 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 169 slang::RSContext *Context, 170 const clang::VarDecl *VD, 171 const clang::RecordDecl *TopLevelRecord); 172 173 template <unsigned N> 174 static void ReportTypeError(slang::RSContext *Context, 175 const clang::NamedDecl *ND, 176 const clang::RecordDecl *TopLevelRecord, 177 const char (&Message)[N], 178 unsigned int TargetAPI = 0) { 179 // Attempt to use the type declaration first (if we have one). 180 // Fall back to the variable definition, if we are looking at something 181 // like an array declaration that can't be exported. 182 if (TopLevelRecord) { 183 Context->ReportError(TopLevelRecord->getLocation(), Message) 184 << TopLevelRecord->getName() << TargetAPI; 185 } else if (ND) { 186 Context->ReportError(ND->getLocation(), Message) << ND->getName() 187 << TargetAPI; 188 } else { 189 slangAssert(false && "Variables should be validated before exporting"); 190 } 191 } 192 193 static const clang::Type *ConstantArrayTypeExportableHelper( 194 const clang::ConstantArrayType *CAT, 195 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 196 slang::RSContext *Context, 197 const clang::VarDecl *VD, 198 const clang::RecordDecl *TopLevelRecord) { 199 // Check element type 200 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 201 if (ElementType->isArrayType()) { 202 ReportTypeError(Context, VD, TopLevelRecord, 203 "multidimensional arrays cannot be exported: '%0'"); 204 return NULL; 205 } else if (ElementType->isExtVectorType()) { 206 const clang::ExtVectorType *EVT = 207 static_cast<const clang::ExtVectorType*>(ElementType); 208 unsigned numElements = EVT->getNumElements(); 209 210 const clang::Type *BaseElementType = GetExtVectorElementType(EVT); 211 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) { 212 ReportTypeError(Context, VD, TopLevelRecord, 213 "vectors of non-primitive types cannot be exported: '%0'"); 214 return NULL; 215 } 216 217 if (numElements == 3 && CAT->getSize() != 1) { 218 ReportTypeError(Context, VD, TopLevelRecord, 219 "arrays of width 3 vector types cannot be exported: '%0'"); 220 return NULL; 221 } 222 } 223 224 if (TypeExportableHelper(ElementType, SPS, Context, VD, 225 TopLevelRecord) == NULL) { 226 return NULL; 227 } else { 228 return CAT; 229 } 230 } 231 232 BuiltinInfo *FindBuiltinType(clang::BuiltinType::Kind builtinTypeKind) { 233 for (int i = 0; i < BuiltinInfoTableCount; i++) { 234 if (builtinTypeKind == BuiltinInfoTable[i].builtinTypeKind) { 235 return &BuiltinInfoTable[i]; 236 } 237 } 238 return NULL; 239 } 240 241 static const clang::Type *TypeExportableHelper( 242 clang::Type const *T, 243 llvm::SmallPtrSet<clang::Type const *, 8> &SPS, 244 slang::RSContext *Context, 245 clang::VarDecl const *VD, 246 clang::RecordDecl const *TopLevelRecord) { 247 // Normalize first 248 if ((T = GetCanonicalType(T)) == NULL) 249 return NULL; 250 251 if (SPS.count(T)) 252 return T; 253 254 const clang::Type *CTI = T->getCanonicalTypeInternal().getTypePtr(); 255 256 switch (T->getTypeClass()) { 257 case clang::Type::Builtin: { 258 const clang::BuiltinType *BT = static_cast<const clang::BuiltinType*>(CTI); 259 return FindBuiltinType(BT->getKind()) == NULL ? NULL : T; 260 } 261 case clang::Type::Record: { 262 if (RSExportPrimitiveType::GetRSSpecificType(T) != DataTypeUnknown) { 263 return T; // RS object type, no further checks are needed 264 } 265 266 // Check internal struct 267 if (T->isUnionType()) { 268 ReportTypeError(Context, VD, T->getAsUnionType()->getDecl(), 269 "unions cannot be exported: '%0'"); 270 return NULL; 271 } else if (!T->isStructureType()) { 272 slangAssert(false && "Unknown type cannot be exported"); 273 return NULL; 274 } 275 276 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 277 if (RD != NULL) { 278 RD = RD->getDefinition(); 279 if (RD == NULL) { 280 ReportTypeError(Context, NULL, T->getAsStructureType()->getDecl(), 281 "struct is not defined in this module"); 282 return NULL; 283 } 284 } 285 286 if (!TopLevelRecord) { 287 TopLevelRecord = RD; 288 } 289 if (RD->getName().empty()) { 290 ReportTypeError(Context, NULL, RD, 291 "anonymous structures cannot be exported"); 292 return NULL; 293 } 294 295 // Fast check 296 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 297 return NULL; 298 299 // Insert myself into checking set 300 SPS.insert(T); 301 302 // Check all element 303 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 304 FE = RD->field_end(); 305 FI != FE; 306 FI++) { 307 const clang::FieldDecl *FD = *FI; 308 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 309 FT = GetCanonicalType(FT); 310 311 if (!TypeExportableHelper(FT, SPS, Context, VD, TopLevelRecord)) { 312 return NULL; 313 } 314 315 // We don't support bit fields yet 316 // 317 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32 318 if (FD->isBitField()) { 319 Context->ReportError( 320 FD->getLocation(), 321 "bit fields are not able to be exported: '%0.%1'") 322 << RD->getName() << FD->getName(); 323 return NULL; 324 } 325 } 326 327 return T; 328 } 329 case clang::Type::Pointer: { 330 if (TopLevelRecord) { 331 ReportTypeError(Context, VD, TopLevelRecord, 332 "structures containing pointers cannot be exported: '%0'"); 333 return NULL; 334 } 335 336 const clang::PointerType *PT = static_cast<const clang::PointerType*>(CTI); 337 const clang::Type *PointeeType = GetPointeeType(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 static_cast<const clang::ExtVectorType*>(CTI); 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 = GetExtVectorElementType(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 static_cast<const clang::ConstantArrayType*>(CTI); 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). 396 static 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 405 static 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 = GetCanonicalType(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 444 static 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 = GetCanonicalType(T)) == NULL) 456 return true; 457 458 if (SPS.count(T)) 459 return true; 460 461 const clang::Type *CTI = T->getCanonicalTypeInternal().getTypePtr(); 462 463 switch (T->getTypeClass()) { 464 case clang::Type::Record: { 465 if (RSExportPrimitiveType::IsRSObjectType(T)) { 466 clang::VarDecl *VD = (ND ? llvm::dyn_cast<clang::VarDecl>(ND) : NULL); 467 if (VD && !ValidateRSObjectInVarDecl(Context, VD, InCompositeType, 468 TargetAPI)) { 469 return false; 470 } 471 } 472 473 if (RSExportPrimitiveType::GetRSSpecificType(T) != DataTypeUnknown) { 474 if (!UnionDecl) { 475 return true; 476 } else if (RSExportPrimitiveType::IsRSObjectType(T)) { 477 ReportTypeError(Context, NULL, UnionDecl, 478 "unions containing RS object types are not allowed"); 479 return false; 480 } 481 } 482 483 clang::RecordDecl *RD = NULL; 484 485 // Check internal struct 486 if (T->isUnionType()) { 487 RD = T->getAsUnionType()->getDecl(); 488 UnionDecl = RD; 489 } else if (T->isStructureType()) { 490 RD = T->getAsStructureType()->getDecl(); 491 } else { 492 slangAssert(false && "Unknown type cannot be exported"); 493 return false; 494 } 495 496 if (RD != NULL) { 497 RD = RD->getDefinition(); 498 if (RD == NULL) { 499 // FIXME 500 return true; 501 } 502 } 503 504 // Fast check 505 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 506 return false; 507 508 // Insert myself into checking set 509 SPS.insert(T); 510 511 // Check all elements 512 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 513 FE = RD->field_end(); 514 FI != FE; 515 FI++) { 516 const clang::FieldDecl *FD = *FI; 517 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 518 FT = GetCanonicalType(FT); 519 520 if (!ValidateTypeHelper(Context, C, FT, ND, Loc, SPS, true, UnionDecl, 521 TargetAPI, IsFilterscript)) { 522 return false; 523 } 524 } 525 526 return true; 527 } 528 529 case clang::Type::Builtin: { 530 if (IsFilterscript) { 531 clang::QualType QT = T->getCanonicalTypeInternal(); 532 if (QT == C.DoubleTy || 533 QT == C.LongDoubleTy || 534 QT == C.LongTy || 535 QT == C.LongLongTy) { 536 if (ND) { 537 Context->ReportError( 538 Loc, 539 "Builtin types > 32 bits in size are forbidden in " 540 "Filterscript: '%0'") 541 << ND->getName(); 542 } else { 543 Context->ReportError( 544 Loc, 545 "Builtin types > 32 bits in size are forbidden in " 546 "Filterscript"); 547 } 548 return false; 549 } 550 } 551 break; 552 } 553 554 case clang::Type::Pointer: { 555 if (IsFilterscript) { 556 if (ND) { 557 Context->ReportError(Loc, 558 "Pointers are forbidden in Filterscript: '%0'") 559 << ND->getName(); 560 return false; 561 } else { 562 // TODO(srhines): Find a better way to handle expressions (i.e. no 563 // NamedDecl) involving pointers in FS that should be allowed. 564 // An example would be calls to library functions like 565 // rsMatrixMultiply() that take rs_matrixNxN * types. 566 } 567 } 568 569 const clang::PointerType *PT = static_cast<const clang::PointerType*>(CTI); 570 const clang::Type *PointeeType = GetPointeeType(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 static_cast<const clang::ExtVectorType*>(CTI); 580 const clang::Type *ElementType = GetExtVectorElementType(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 = static_cast<const clang::ConstantArrayType*>(CTI); 597 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 598 return ValidateTypeHelper(Context, C, ElementType, ND, Loc, SPS, true, 599 UnionDecl, TargetAPI, IsFilterscript); 600 } 601 602 default: { 603 break; 604 } 605 } 606 607 return true; 608 } 609 610 } // namespace 611 612 std::string CreateDummyName(const char *type, const std::string &name) { 613 std::stringstream S; 614 S << "<" << type; 615 if (!name.empty()) { 616 S << ":" << name; 617 } 618 S << ">"; 619 return S.str(); 620 } 621 622 /****************************** RSExportType ******************************/ 623 bool RSExportType::NormalizeType(const clang::Type *&T, 624 llvm::StringRef &TypeName, 625 RSContext *Context, 626 const clang::VarDecl *VD) { 627 if ((T = TypeExportable(T, Context, VD)) == NULL) { 628 return false; 629 } 630 // Get type name 631 TypeName = RSExportType::GetTypeName(T); 632 if (Context && TypeName.empty()) { 633 if (VD) { 634 Context->ReportError(VD->getLocation(), 635 "anonymous types cannot be exported"); 636 } else { 637 Context->ReportError("anonymous types cannot be exported"); 638 } 639 return false; 640 } 641 642 return true; 643 } 644 645 bool RSExportType::ValidateType(slang::RSContext *Context, clang::ASTContext &C, 646 clang::QualType QT, clang::NamedDecl *ND, 647 clang::SourceLocation Loc, 648 unsigned int TargetAPI, bool IsFilterscript) { 649 const clang::Type *T = QT.getTypePtr(); 650 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 651 llvm::SmallPtrSet<const clang::Type*, 8>(); 652 653 return ValidateTypeHelper(Context, C, T, ND, Loc, SPS, false, NULL, TargetAPI, 654 IsFilterscript); 655 return true; 656 } 657 658 bool RSExportType::ValidateVarDecl(slang::RSContext *Context, 659 clang::VarDecl *VD, unsigned int TargetAPI, 660 bool IsFilterscript) { 661 return ValidateType(Context, VD->getASTContext(), VD->getType(), VD, 662 VD->getLocation(), TargetAPI, IsFilterscript); 663 } 664 665 const clang::Type 666 *RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 667 if (DD) { 668 clang::QualType T = DD->getType(); 669 670 if (T.isNull()) 671 return NULL; 672 else 673 return T.getTypePtr(); 674 } 675 return NULL; 676 } 677 678 llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 679 T = GetCanonicalType(T); 680 if (T == NULL) 681 return llvm::StringRef(); 682 683 const clang::Type *CTI = T->getCanonicalTypeInternal().getTypePtr(); 684 685 switch (T->getTypeClass()) { 686 case clang::Type::Builtin: { 687 const clang::BuiltinType *BT = static_cast<const clang::BuiltinType*>(CTI); 688 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 689 if (info != NULL) { 690 return info->cname[0]; 691 } 692 slangAssert(false && "Unknown data type of the builtin"); 693 break; 694 } 695 case clang::Type::Record: { 696 clang::RecordDecl *RD; 697 if (T->isStructureType()) { 698 RD = T->getAsStructureType()->getDecl(); 699 } else { 700 break; 701 } 702 703 llvm::StringRef Name = RD->getName(); 704 if (Name.empty()) { 705 if (RD->getTypedefNameForAnonDecl() != NULL) { 706 Name = RD->getTypedefNameForAnonDecl()->getName(); 707 } 708 709 if (Name.empty()) { 710 // Try to find a name from redeclaration (i.e. typedef) 711 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 712 RE = RD->redecls_end(); 713 RI != RE; 714 RI++) { 715 slangAssert(*RI != NULL && "cannot be NULL object"); 716 717 Name = (*RI)->getName(); 718 if (!Name.empty()) 719 break; 720 } 721 } 722 } 723 return Name; 724 } 725 case clang::Type::Pointer: { 726 // "*" plus pointee name 727 const clang::PointerType *P = static_cast<const clang::PointerType*>(CTI); 728 const clang::Type *PT = GetPointeeType(P); 729 llvm::StringRef PointeeName; 730 if (NormalizeType(PT, PointeeName, NULL, NULL)) { 731 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 732 Name[0] = '*'; 733 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 734 Name[PointeeName.size() + 1] = '\0'; 735 return Name; 736 } 737 break; 738 } 739 case clang::Type::ExtVector: { 740 const clang::ExtVectorType *EVT = 741 static_cast<const clang::ExtVectorType*>(CTI); 742 return RSExportVectorType::GetTypeName(EVT); 743 break; 744 } 745 case clang::Type::ConstantArray : { 746 // Construct name for a constant array is too complicated. 747 return "<ConstantArray>"; 748 } 749 default: { 750 break; 751 } 752 } 753 754 return llvm::StringRef(); 755 } 756 757 758 RSExportType *RSExportType::Create(RSContext *Context, 759 const clang::Type *T, 760 const llvm::StringRef &TypeName) { 761 // Lookup the context to see whether the type was processed before. 762 // Newly created RSExportType will insert into context 763 // in RSExportType::RSExportType() 764 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 765 766 if (ETI != Context->export_types_end()) 767 return ETI->second; 768 769 const clang::Type *CTI = T->getCanonicalTypeInternal().getTypePtr(); 770 771 RSExportType *ET = NULL; 772 switch (T->getTypeClass()) { 773 case clang::Type::Record: { 774 DataType dt = RSExportPrimitiveType::GetRSSpecificType(TypeName); 775 switch (dt) { 776 case DataTypeUnknown: { 777 // User-defined types 778 ET = RSExportRecordType::Create(Context, 779 T->getAsStructureType(), 780 TypeName); 781 break; 782 } 783 case DataTypeRSMatrix2x2: { 784 // 2 x 2 Matrix type 785 ET = RSExportMatrixType::Create(Context, 786 T->getAsStructureType(), 787 TypeName, 788 2); 789 break; 790 } 791 case DataTypeRSMatrix3x3: { 792 // 3 x 3 Matrix type 793 ET = RSExportMatrixType::Create(Context, 794 T->getAsStructureType(), 795 TypeName, 796 3); 797 break; 798 } 799 case DataTypeRSMatrix4x4: { 800 // 4 x 4 Matrix type 801 ET = RSExportMatrixType::Create(Context, 802 T->getAsStructureType(), 803 TypeName, 804 4); 805 break; 806 } 807 default: { 808 // Others are primitive types 809 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 810 break; 811 } 812 } 813 break; 814 } 815 case clang::Type::Builtin: { 816 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 817 break; 818 } 819 case clang::Type::Pointer: { 820 ET = RSExportPointerType::Create(Context, 821 static_cast<const clang::PointerType*>(CTI), 822 TypeName); 823 // FIXME: free the name (allocated in RSExportType::GetTypeName) 824 delete [] TypeName.data(); 825 break; 826 } 827 case clang::Type::ExtVector: { 828 ET = RSExportVectorType::Create(Context, 829 static_cast<const clang::ExtVectorType*>(CTI), 830 TypeName); 831 break; 832 } 833 case clang::Type::ConstantArray: { 834 ET = RSExportConstantArrayType::Create( 835 Context, 836 static_cast<const clang::ConstantArrayType*>(CTI)); 837 break; 838 } 839 default: { 840 Context->ReportError("unknown type cannot be exported: '%0'") 841 << T->getTypeClassName(); 842 break; 843 } 844 } 845 846 return ET; 847 } 848 849 RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 850 llvm::StringRef TypeName; 851 if (NormalizeType(T, TypeName, Context, NULL)) { 852 return Create(Context, T, TypeName); 853 } else { 854 return NULL; 855 } 856 } 857 858 RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 859 const clang::VarDecl *VD) { 860 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 861 } 862 863 size_t RSExportType::getStoreSize() const { 864 return getRSContext()->getDataLayout()->getTypeStoreSize(getLLVMType()); 865 } 866 867 size_t RSExportType::getAllocSize() const { 868 return getRSContext()->getDataLayout()->getTypeAllocSize(getLLVMType()); 869 } 870 871 RSExportType::RSExportType(RSContext *Context, 872 ExportClass Class, 873 const llvm::StringRef &Name) 874 : RSExportable(Context, RSExportable::EX_TYPE), 875 mClass(Class), 876 // Make a copy on Name since memory stored @Name is either allocated in 877 // ASTContext or allocated in GetTypeName which will be destroyed later. 878 mName(Name.data(), Name.size()), 879 mLLVMType(NULL) { 880 // Don't cache the type whose name start with '<'. Those type failed to 881 // get their name since constructing their name in GetTypeName() requiring 882 // complicated work. 883 if (!IsDummyName(Name)) { 884 // TODO(zonr): Need to check whether the insertion is successful or not. 885 Context->insertExportType(llvm::StringRef(Name), this); 886 } 887 888 } 889 890 bool RSExportType::keep() { 891 if (!RSExportable::keep()) 892 return false; 893 // Invalidate converted LLVM type. 894 mLLVMType = NULL; 895 return true; 896 } 897 898 bool RSExportType::equals(const RSExportable *E) const { 899 CHECK_PARENT_EQUALITY(RSExportable, E); 900 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 901 } 902 903 RSExportType::~RSExportType() { 904 } 905 906 /************************** RSExportPrimitiveType **************************/ 907 llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 908 RSExportPrimitiveType::RSSpecificTypeMap; 909 910 bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 911 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 912 return true; 913 else 914 return false; 915 } 916 917 DataType 918 RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 919 if (TypeName.empty()) 920 return DataTypeUnknown; 921 922 if (RSSpecificTypeMap->empty()) { 923 for (int i = 0; i < MatrixAndObjectDataTypesCount; i++) { 924 RSSpecificTypeMap->GetOrCreateValue(MatrixAndObjectDataTypes[i].name, 925 MatrixAndObjectDataTypes[i].dataType); 926 } 927 } 928 929 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 930 if (I == RSSpecificTypeMap->end()) 931 return DataTypeUnknown; 932 else 933 return I->getValue(); 934 } 935 936 DataType RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 937 T = GetCanonicalType(T); 938 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 939 return DataTypeUnknown; 940 941 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 942 } 943 944 bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 945 if (DT < 0 || DT >= DataTypeMax) { 946 return false; 947 } 948 return gReflectionTypes[DT].category == MatrixDataType; 949 } 950 951 bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 952 if (DT < 0 || DT >= DataTypeMax) { 953 return false; 954 } 955 return gReflectionTypes[DT].category == ObjectDataType; 956 } 957 958 bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 959 bool RSObjectTypeSeen = false; 960 while (T && T->isArrayType()) { 961 T = T->getArrayElementTypeNoTypeQual(); 962 } 963 964 const clang::RecordType *RT = T->getAsStructureType(); 965 if (!RT) { 966 return false; 967 } 968 969 const clang::RecordDecl *RD = RT->getDecl(); 970 if (RD) { 971 RD = RD->getDefinition(); 972 } 973 if (!RD) { 974 return false; 975 } 976 977 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 978 FE = RD->field_end(); 979 FI != FE; 980 FI++) { 981 // We just look through all field declarations to see if we find a 982 // declaration for an RS object type (or an array of one). 983 const clang::FieldDecl *FD = *FI; 984 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 985 while (FT && FT->isArrayType()) { 986 FT = FT->getArrayElementTypeNoTypeQual(); 987 } 988 989 DataType DT = GetRSSpecificType(FT); 990 if (IsRSObjectType(DT)) { 991 // RS object types definitely need to be zero-initialized 992 RSObjectTypeSeen = true; 993 } else { 994 switch (DT) { 995 case DataTypeRSMatrix2x2: 996 case DataTypeRSMatrix3x3: 997 case DataTypeRSMatrix4x4: 998 // Matrix types should get zero-initialized as well 999 RSObjectTypeSeen = true; 1000 break; 1001 default: 1002 // Ignore all other primitive types 1003 break; 1004 } 1005 while (FT && FT->isArrayType()) { 1006 FT = FT->getArrayElementTypeNoTypeQual(); 1007 } 1008 if (FT->isStructureType()) { 1009 // Recursively handle structs of structs (even though these can't 1010 // be exported, it is possible for a user to have them internally). 1011 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 1012 } 1013 } 1014 } 1015 1016 return RSObjectTypeSeen; 1017 } 1018 1019 size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 1020 int type = EPT->getType(); 1021 slangAssert((type > DataTypeUnknown && type < DataTypeMax) && 1022 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 1023 // All RS object types are 256 bits in 64-bit RS. 1024 if (EPT->isRSObjectType() && EPT->getRSContext()->is64Bit()) { 1025 return 256; 1026 } 1027 return gReflectionTypes[type].size_in_bits; 1028 } 1029 1030 DataType 1031 RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 1032 if (T == NULL) 1033 return DataTypeUnknown; 1034 1035 switch (T->getTypeClass()) { 1036 case clang::Type::Builtin: { 1037 const clang::BuiltinType *BT = 1038 static_cast<const clang::BuiltinType*>(T->getCanonicalTypeInternal().getTypePtr()); 1039 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1040 if (info != NULL) { 1041 return info->type; 1042 } 1043 // The size of type WChar depend on platform so we abandon the support 1044 // to them. 1045 Context->ReportError("built-in type cannot be exported: '%0'") 1046 << T->getTypeClassName(); 1047 break; 1048 } 1049 case clang::Type::Record: { 1050 // must be RS object type 1051 return RSExportPrimitiveType::GetRSSpecificType(T); 1052 } 1053 default: { 1054 Context->ReportError("primitive type cannot be exported: '%0'") 1055 << T->getTypeClassName(); 1056 break; 1057 } 1058 } 1059 1060 return DataTypeUnknown; 1061 } 1062 1063 RSExportPrimitiveType 1064 *RSExportPrimitiveType::Create(RSContext *Context, 1065 const clang::Type *T, 1066 const llvm::StringRef &TypeName, 1067 bool Normalized) { 1068 DataType DT = GetDataType(Context, T); 1069 1070 if ((DT == DataTypeUnknown) || TypeName.empty()) 1071 return NULL; 1072 else 1073 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 1074 DT, Normalized); 1075 } 1076 1077 RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 1078 const clang::Type *T) { 1079 llvm::StringRef TypeName; 1080 if (RSExportType::NormalizeType(T, TypeName, Context, NULL) 1081 && IsPrimitiveType(T)) { 1082 return Create(Context, T, TypeName); 1083 } else { 1084 return NULL; 1085 } 1086 } 1087 1088 llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 1089 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1090 1091 if (isRSObjectType()) { 1092 // struct { 1093 // int *p; 1094 // } __attribute__((packed, aligned(pointer_size))) 1095 // 1096 // which is 1097 // 1098 // <{ [1 x i32] }> in LLVM 1099 // 1100 std::vector<llvm::Type *> Elements; 1101 if (getRSContext()->is64Bit()) { 1102 // 64-bit path 1103 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt64Ty(C), 4)); 1104 return llvm::StructType::get(C, Elements, true); 1105 } else { 1106 // 32-bit legacy path 1107 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 1108 return llvm::StructType::get(C, Elements, true); 1109 } 1110 } 1111 1112 switch (mType) { 1113 case DataTypeFloat32: { 1114 return llvm::Type::getFloatTy(C); 1115 break; 1116 } 1117 case DataTypeFloat64: { 1118 return llvm::Type::getDoubleTy(C); 1119 break; 1120 } 1121 case DataTypeBoolean: { 1122 return llvm::Type::getInt1Ty(C); 1123 break; 1124 } 1125 case DataTypeSigned8: 1126 case DataTypeUnsigned8: { 1127 return llvm::Type::getInt8Ty(C); 1128 break; 1129 } 1130 case DataTypeSigned16: 1131 case DataTypeUnsigned16: 1132 case DataTypeUnsigned565: 1133 case DataTypeUnsigned5551: 1134 case DataTypeUnsigned4444: { 1135 return llvm::Type::getInt16Ty(C); 1136 break; 1137 } 1138 case DataTypeSigned32: 1139 case DataTypeUnsigned32: { 1140 return llvm::Type::getInt32Ty(C); 1141 break; 1142 } 1143 case DataTypeSigned64: 1144 case DataTypeUnsigned64: { 1145 return llvm::Type::getInt64Ty(C); 1146 break; 1147 } 1148 default: { 1149 slangAssert(false && "Unknown data type"); 1150 } 1151 } 1152 1153 return NULL; 1154 } 1155 1156 bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1157 CHECK_PARENT_EQUALITY(RSExportType, E); 1158 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1159 } 1160 1161 RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1162 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1163 return &gReflectionTypes[DT]; 1164 } else { 1165 return NULL; 1166 } 1167 } 1168 1169 /**************************** RSExportPointerType ****************************/ 1170 1171 RSExportPointerType 1172 *RSExportPointerType::Create(RSContext *Context, 1173 const clang::PointerType *PT, 1174 const llvm::StringRef &TypeName) { 1175 const clang::Type *PointeeType = GetPointeeType(PT); 1176 const RSExportType *PointeeET; 1177 1178 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1179 PointeeET = RSExportType::Create(Context, PointeeType); 1180 } else { 1181 // Double or higher dimension of pointer, export as int* 1182 PointeeET = RSExportPrimitiveType::Create(Context, 1183 Context->getASTContext().IntTy.getTypePtr()); 1184 } 1185 1186 if (PointeeET == NULL) { 1187 // Error diagnostic is emitted for corresponding pointee type 1188 return NULL; 1189 } 1190 1191 return new RSExportPointerType(Context, TypeName, PointeeET); 1192 } 1193 1194 llvm::Type *RSExportPointerType::convertToLLVMType() const { 1195 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1196 return llvm::PointerType::getUnqual(PointeeType); 1197 } 1198 1199 bool RSExportPointerType::keep() { 1200 if (!RSExportType::keep()) 1201 return false; 1202 const_cast<RSExportType*>(mPointeeType)->keep(); 1203 return true; 1204 } 1205 1206 bool RSExportPointerType::equals(const RSExportable *E) const { 1207 CHECK_PARENT_EQUALITY(RSExportType, E); 1208 return (static_cast<const RSExportPointerType*>(E) 1209 ->getPointeeType()->equals(getPointeeType())); 1210 } 1211 1212 /***************************** RSExportVectorType *****************************/ 1213 llvm::StringRef 1214 RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1215 const clang::Type *ElementType = GetExtVectorElementType(EVT); 1216 llvm::StringRef name; 1217 1218 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1219 return name; 1220 1221 const clang::BuiltinType *BT = 1222 static_cast<const clang::BuiltinType*>( 1223 ElementType->getCanonicalTypeInternal().getTypePtr()); 1224 1225 if ((EVT->getNumElements() < 1) || 1226 (EVT->getNumElements() > 4)) 1227 return name; 1228 1229 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1230 if (info != NULL) { 1231 int I = EVT->getNumElements() - 1; 1232 if (I < kMaxVectorSize) { 1233 name = info->cname[I]; 1234 } else { 1235 slangAssert(false && "Max vector is 4"); 1236 } 1237 } 1238 return name; 1239 } 1240 1241 RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1242 const clang::ExtVectorType *EVT, 1243 const llvm::StringRef &TypeName, 1244 bool Normalized) { 1245 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1246 1247 const clang::Type *ElementType = GetExtVectorElementType(EVT); 1248 DataType DT = RSExportPrimitiveType::GetDataType(Context, ElementType); 1249 1250 if (DT != DataTypeUnknown) 1251 return new RSExportVectorType(Context, 1252 TypeName, 1253 DT, 1254 Normalized, 1255 EVT->getNumElements()); 1256 else 1257 return NULL; 1258 } 1259 1260 llvm::Type *RSExportVectorType::convertToLLVMType() const { 1261 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 1262 return llvm::VectorType::get(ElementType, getNumElement()); 1263 } 1264 1265 bool RSExportVectorType::equals(const RSExportable *E) const { 1266 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 1267 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 1268 == getNumElement()); 1269 } 1270 1271 /***************************** RSExportMatrixType *****************************/ 1272 RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 1273 const clang::RecordType *RT, 1274 const llvm::StringRef &TypeName, 1275 unsigned Dim) { 1276 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 1277 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 1278 1279 // Check whether the struct rs_matrix is in our expected form (but assume it's 1280 // correct if we're not sure whether it's correct or not) 1281 const clang::RecordDecl* RD = RT->getDecl(); 1282 RD = RD->getDefinition(); 1283 if (RD != NULL) { 1284 // Find definition, perform further examination 1285 if (RD->field_empty()) { 1286 Context->ReportError( 1287 RD->getLocation(), 1288 "invalid matrix struct: must have 1 field for saving values: '%0'") 1289 << RD->getName(); 1290 return NULL; 1291 } 1292 1293 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 1294 const clang::FieldDecl *FD = *FIT; 1295 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1296 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 1297 Context->ReportError(RD->getLocation(), 1298 "invalid matrix struct: first field should" 1299 " be an array with constant size: '%0'") 1300 << RD->getName(); 1301 return NULL; 1302 } 1303 const clang::ConstantArrayType *CAT = 1304 static_cast<const clang::ConstantArrayType *>(FT); 1305 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 1306 if ((ElementType == NULL) || 1307 (ElementType->getTypeClass() != clang::Type::Builtin) || 1308 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() != 1309 clang::BuiltinType::Float)) { 1310 Context->ReportError(RD->getLocation(), 1311 "invalid matrix struct: first field " 1312 "should be a float array: '%0'") 1313 << RD->getName(); 1314 return NULL; 1315 } 1316 1317 if (CAT->getSize() != Dim * Dim) { 1318 Context->ReportError(RD->getLocation(), 1319 "invalid matrix struct: first field " 1320 "should be an array with size %0: '%1'") 1321 << (Dim * Dim) << (RD->getName()); 1322 return NULL; 1323 } 1324 1325 FIT++; 1326 if (FIT != RD->field_end()) { 1327 Context->ReportError(RD->getLocation(), 1328 "invalid matrix struct: must have " 1329 "exactly 1 field: '%0'") 1330 << RD->getName(); 1331 return NULL; 1332 } 1333 } 1334 1335 return new RSExportMatrixType(Context, TypeName, Dim); 1336 } 1337 1338 llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1339 // Construct LLVM type: 1340 // struct { 1341 // float X[mDim * mDim]; 1342 // } 1343 1344 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1345 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1346 mDim * mDim); 1347 return llvm::StructType::get(C, X, false); 1348 } 1349 1350 bool RSExportMatrixType::equals(const RSExportable *E) const { 1351 CHECK_PARENT_EQUALITY(RSExportType, E); 1352 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1353 } 1354 1355 /************************* RSExportConstantArrayType *************************/ 1356 RSExportConstantArrayType 1357 *RSExportConstantArrayType::Create(RSContext *Context, 1358 const clang::ConstantArrayType *CAT) { 1359 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1360 1361 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1362 1363 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1364 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1365 1366 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 1367 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1368 1369 if (ElementET == NULL) { 1370 return NULL; 1371 } 1372 1373 return new RSExportConstantArrayType(Context, 1374 ElementET, 1375 Size); 1376 } 1377 1378 llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1379 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1380 } 1381 1382 bool RSExportConstantArrayType::keep() { 1383 if (!RSExportType::keep()) 1384 return false; 1385 const_cast<RSExportType*>(mElementType)->keep(); 1386 return true; 1387 } 1388 1389 bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1390 CHECK_PARENT_EQUALITY(RSExportType, E); 1391 const RSExportConstantArrayType *RHS = 1392 static_cast<const RSExportConstantArrayType*>(E); 1393 return ((getSize() == RHS->getSize()) && 1394 (getElementType()->equals(RHS->getElementType()))); 1395 } 1396 1397 /**************************** RSExportRecordType ****************************/ 1398 RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1399 const clang::RecordType *RT, 1400 const llvm::StringRef &TypeName, 1401 bool mIsArtificial) { 1402 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1403 1404 const clang::RecordDecl *RD = RT->getDecl(); 1405 slangAssert(RD->isStruct()); 1406 1407 RD = RD->getDefinition(); 1408 if (RD == NULL) { 1409 slangAssert(false && "struct is not defined in this module"); 1410 return NULL; 1411 } 1412 1413 // Struct layout construct by clang. We rely on this for obtaining the 1414 // alloc size of a struct and offset of every field in that struct. 1415 const clang::ASTRecordLayout *RL = 1416 &Context->getASTContext().getASTRecordLayout(RD); 1417 slangAssert((RL != NULL) && 1418 "Failed to retrieve the struct layout from Clang."); 1419 1420 RSExportRecordType *ERT = 1421 new RSExportRecordType(Context, 1422 TypeName, 1423 RD->hasAttr<clang::PackedAttr>(), 1424 mIsArtificial, 1425 RL->getDataSize().getQuantity(), 1426 RL->getSize().getQuantity()); 1427 unsigned int Index = 0; 1428 1429 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1430 FE = RD->field_end(); 1431 FI != FE; 1432 FI++, Index++) { 1433 1434 // FIXME: All fields should be primitive type 1435 slangAssert(FI->getKind() == clang::Decl::Field); 1436 clang::FieldDecl *FD = *FI; 1437 1438 if (FD->isBitField()) { 1439 return NULL; 1440 } 1441 1442 // Type 1443 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1444 1445 if (ET != NULL) { 1446 ERT->mFields.push_back( 1447 new Field(ET, FD->getName(), ERT, 1448 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1449 } else { 1450 Context->ReportError(RD->getLocation(), 1451 "field type cannot be exported: '%0.%1'") 1452 << RD->getName() << FD->getName(); 1453 return NULL; 1454 } 1455 } 1456 1457 return ERT; 1458 } 1459 1460 llvm::Type *RSExportRecordType::convertToLLVMType() const { 1461 // Create an opaque type since struct may reference itself recursively. 1462 1463 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to? 1464 std::vector<llvm::Type*> FieldTypes; 1465 1466 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1467 FI != FE; 1468 FI++) { 1469 const Field *F = *FI; 1470 const RSExportType *FET = F->getType(); 1471 1472 FieldTypes.push_back(FET->getLLVMType()); 1473 } 1474 1475 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1476 FieldTypes, 1477 mIsPacked); 1478 if (ST != NULL) { 1479 return ST; 1480 } else { 1481 return NULL; 1482 } 1483 } 1484 1485 bool RSExportRecordType::keep() { 1486 if (!RSExportType::keep()) 1487 return false; 1488 for (std::list<const Field*>::iterator I = mFields.begin(), 1489 E = mFields.end(); 1490 I != E; 1491 I++) { 1492 const_cast<RSExportType*>((*I)->getType())->keep(); 1493 } 1494 return true; 1495 } 1496 1497 bool RSExportRecordType::equals(const RSExportable *E) const { 1498 CHECK_PARENT_EQUALITY(RSExportType, E); 1499 1500 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1501 1502 if (ERT->getFields().size() != getFields().size()) 1503 return false; 1504 1505 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1506 1507 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1508 if (!(*AI)->getType()->equals((*BI)->getType())) 1509 return false; 1510 AI++; 1511 BI++; 1512 } 1513 1514 return true; 1515 } 1516 1517 void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const { 1518 memset(rtd, 0, sizeof(*rtd)); 1519 rtd->vecSize = 1; 1520 1521 switch(getClass()) { 1522 case RSExportType::ExportClassPrimitive: { 1523 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this); 1524 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT); 1525 return; 1526 } 1527 case RSExportType::ExportClassPointer: { 1528 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this); 1529 const RSExportType *PointeeType = EPT->getPointeeType(); 1530 PointeeType->convertToRTD(rtd); 1531 rtd->isPointer = true; 1532 return; 1533 } 1534 case RSExportType::ExportClassVector: { 1535 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this); 1536 rtd->type = EVT->getRSReflectionType(EVT); 1537 rtd->vecSize = EVT->getNumElement(); 1538 return; 1539 } 1540 case RSExportType::ExportClassMatrix: { 1541 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this); 1542 unsigned Dim = EMT->getDim(); 1543 slangAssert((Dim >= 2) && (Dim <= 4)); 1544 rtd->type = &gReflectionTypes[15 + Dim-2]; 1545 return; 1546 } 1547 case RSExportType::ExportClassConstantArray: { 1548 const RSExportConstantArrayType* CAT = 1549 static_cast<const RSExportConstantArrayType*>(this); 1550 CAT->getElementType()->convertToRTD(rtd); 1551 rtd->arraySize = CAT->getSize(); 1552 return; 1553 } 1554 case RSExportType::ExportClassRecord: { 1555 slangAssert(!"RSExportType::ExportClassRecord not implemented"); 1556 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item"; 1557 } 1558 default: { 1559 slangAssert(false && "Unknown class of type"); 1560 } 1561 } 1562 } 1563 1564 1565 } // namespace slang 1566