slang_rs_export_type.cpp revision 9ae18b2bbee0b08afd400542e863dd665ff76059
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 // 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 89const int kMaxVectorSize = 4; 90 91struct 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 101BuiltinInfo 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, DataTypeUnsigned32, 117 {"uint", "uint2", "uint3", "uint4"}}, 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}; 138const int BuiltinInfoTableCount = sizeof(BuiltinInfoTable) / sizeof(BuiltinInfoTable[0]); 139 140struct NameAndPrimitiveType { 141 const char *name; 142 DataType dataType; 143}; 144 145static 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 163const int MatrixAndObjectDataTypesCount = 164 sizeof(MatrixAndObjectDataTypes) / sizeof(MatrixAndObjectDataTypes[0]); 165 166static 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 173template <unsigned N> 174static 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 193static 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 232BuiltinInfo *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 241static 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). 396static const clang::Type *TypeExportable(const clang::Type *T, 397 slang::RSContext *Context, 398 const clang::VarDecl *VD) { 399 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 400 llvm::SmallPtrSet<const clang::Type*, 8>(); 401 402 return TypeExportableHelper(T, SPS, Context, VD, NULL); 403} 404 405static bool ValidateRSObjectInVarDecl(slang::RSContext *Context, 406 clang::VarDecl *VD, bool InCompositeType, 407 unsigned int TargetAPI) { 408 if (TargetAPI < SLANG_JB_TARGET_API) { 409 // Only if we are already in a composite type (like an array or structure). 410 if (InCompositeType) { 411 // Only if we are actually exported (i.e. non-static). 412 if (VD->hasLinkage() && 413 (VD->getFormalLinkage() == clang::ExternalLinkage)) { 414 // Only if we are not a pointer to an object. 415 const clang::Type *T = 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 444static bool ValidateTypeHelper( 445 slang::RSContext *Context, 446 clang::ASTContext &C, 447 const clang::Type *&T, 448 clang::NamedDecl *ND, 449 clang::SourceLocation Loc, 450 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 451 bool InCompositeType, 452 clang::RecordDecl *UnionDecl, 453 unsigned int TargetAPI, 454 bool IsFilterscript) { 455 if ((T = 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 612std::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 ******************************/ 623bool 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 645bool 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 658bool 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 665const 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 678llvm::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 CreateDummyName("ConstantArray", std::string()); 748 } 749 default: { 750 break; 751 } 752 } 753 754 return llvm::StringRef(); 755} 756 757 758RSExportType *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 849RSExportType *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 858RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 859 const clang::VarDecl *VD) { 860 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 861} 862 863size_t RSExportType::getStoreSize() const { 864 return getRSContext()->getDataLayout()->getTypeStoreSize(getLLVMType()); 865} 866 867size_t RSExportType::getAllocSize() const { 868 return getRSContext()->getDataLayout()->getTypeAllocSize(getLLVMType()); 869} 870 871RSExportType::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 890bool RSExportType::keep() { 891 if (!RSExportable::keep()) 892 return false; 893 // Invalidate converted LLVM type. 894 mLLVMType = NULL; 895 return true; 896} 897 898bool RSExportType::equals(const RSExportable *E) const { 899 CHECK_PARENT_EQUALITY(RSExportable, E); 900 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 901} 902 903RSExportType::~RSExportType() { 904} 905 906/************************** RSExportPrimitiveType **************************/ 907llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 908RSExportPrimitiveType::RSSpecificTypeMap; 909 910llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 911 912bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 913 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 914 return true; 915 else 916 return false; 917} 918 919DataType 920RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 921 if (TypeName.empty()) 922 return DataTypeUnknown; 923 924 if (RSSpecificTypeMap->empty()) { 925 for (int i = 0; i < MatrixAndObjectDataTypesCount; i++) { 926 RSSpecificTypeMap->GetOrCreateValue(MatrixAndObjectDataTypes[i].name, 927 MatrixAndObjectDataTypes[i].dataType); 928 } 929 } 930 931 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 932 if (I == RSSpecificTypeMap->end()) 933 return DataTypeUnknown; 934 else 935 return I->getValue(); 936} 937 938DataType RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 939 T = GetCanonicalType(T); 940 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 941 return DataTypeUnknown; 942 943 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 944} 945 946bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 947 if (DT < 0 || DT >= DataTypeMax) { 948 return false; 949 } 950 return gReflectionTypes[DT].category == MatrixDataType; 951} 952 953bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 954 if (DT < 0 || DT >= DataTypeMax) { 955 return false; 956 } 957 return gReflectionTypes[DT].category == ObjectDataType; 958} 959 960bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 961 bool RSObjectTypeSeen = false; 962 while (T && T->isArrayType()) { 963 T = T->getArrayElementTypeNoTypeQual(); 964 } 965 966 const clang::RecordType *RT = T->getAsStructureType(); 967 if (!RT) { 968 return false; 969 } 970 971 const clang::RecordDecl *RD = RT->getDecl(); 972 if (RD) { 973 RD = RD->getDefinition(); 974 } 975 if (!RD) { 976 return false; 977 } 978 979 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 980 FE = RD->field_end(); 981 FI != FE; 982 FI++) { 983 // We just look through all field declarations to see if we find a 984 // declaration for an RS object type (or an array of one). 985 const clang::FieldDecl *FD = *FI; 986 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 987 while (FT && FT->isArrayType()) { 988 FT = FT->getArrayElementTypeNoTypeQual(); 989 } 990 991 DataType DT = GetRSSpecificType(FT); 992 if (IsRSObjectType(DT)) { 993 // RS object types definitely need to be zero-initialized 994 RSObjectTypeSeen = true; 995 } else { 996 switch (DT) { 997 case DataTypeRSMatrix2x2: 998 case DataTypeRSMatrix3x3: 999 case DataTypeRSMatrix4x4: 1000 // Matrix types should get zero-initialized as well 1001 RSObjectTypeSeen = true; 1002 break; 1003 default: 1004 // Ignore all other primitive types 1005 break; 1006 } 1007 while (FT && FT->isArrayType()) { 1008 FT = FT->getArrayElementTypeNoTypeQual(); 1009 } 1010 if (FT->isStructureType()) { 1011 // Recursively handle structs of structs (even though these can't 1012 // be exported, it is possible for a user to have them internally). 1013 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 1014 } 1015 } 1016 } 1017 1018 return RSObjectTypeSeen; 1019} 1020 1021size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 1022 int type = EPT->getType(); 1023 slangAssert((type > DataTypeUnknown && type < DataTypeMax) && 1024 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 1025 // All RS object types are 256 bits in 64-bit RS. 1026 if (EPT->isRSObjectType() && EPT->getRSContext()->is64Bit()) { 1027 return 256; 1028 } 1029 return gReflectionTypes[type].size_in_bits; 1030} 1031 1032DataType 1033RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 1034 if (T == NULL) 1035 return DataTypeUnknown; 1036 1037 switch (T->getTypeClass()) { 1038 case clang::Type::Builtin: { 1039 const clang::BuiltinType *BT = 1040 static_cast<const clang::BuiltinType*>(T->getCanonicalTypeInternal().getTypePtr()); 1041 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1042 if (info != NULL) { 1043 return info->type; 1044 } 1045 // The size of type WChar depend on platform so we abandon the support 1046 // to them. 1047 Context->ReportError("built-in type cannot be exported: '%0'") 1048 << T->getTypeClassName(); 1049 break; 1050 } 1051 case clang::Type::Record: { 1052 // must be RS object type 1053 return RSExportPrimitiveType::GetRSSpecificType(T); 1054 } 1055 default: { 1056 Context->ReportError("primitive type cannot be exported: '%0'") 1057 << T->getTypeClassName(); 1058 break; 1059 } 1060 } 1061 1062 return DataTypeUnknown; 1063} 1064 1065RSExportPrimitiveType 1066*RSExportPrimitiveType::Create(RSContext *Context, 1067 const clang::Type *T, 1068 const llvm::StringRef &TypeName, 1069 bool Normalized) { 1070 DataType DT = GetDataType(Context, T); 1071 1072 if ((DT == DataTypeUnknown) || TypeName.empty()) 1073 return NULL; 1074 else 1075 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 1076 DT, Normalized); 1077} 1078 1079RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 1080 const clang::Type *T) { 1081 llvm::StringRef TypeName; 1082 if (RSExportType::NormalizeType(T, TypeName, Context, NULL) 1083 && IsPrimitiveType(T)) { 1084 return Create(Context, T, TypeName); 1085 } else { 1086 return NULL; 1087 } 1088} 1089 1090llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 1091 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1092 1093 if (isRSObjectType()) { 1094 // struct { 1095 // int *p; 1096 // } __attribute__((packed, aligned(pointer_size))) 1097 // 1098 // which is 1099 // 1100 // <{ [1 x i32] }> in LLVM 1101 // 1102 if (RSObjectLLVMType == NULL) { 1103 std::vector<llvm::Type *> Elements; 1104 if (getRSContext()->is64Bit()) { 1105 // 64-bit path 1106 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt64Ty(C), 4)); 1107 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 1108 } else { 1109 // 32-bit legacy path 1110 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 1111 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 1112 } 1113 } 1114 return RSObjectLLVMType; 1115 } 1116 1117 switch (mType) { 1118 case DataTypeFloat32: { 1119 return llvm::Type::getFloatTy(C); 1120 break; 1121 } 1122 case DataTypeFloat64: { 1123 return llvm::Type::getDoubleTy(C); 1124 break; 1125 } 1126 case DataTypeBoolean: { 1127 return llvm::Type::getInt1Ty(C); 1128 break; 1129 } 1130 case DataTypeSigned8: 1131 case DataTypeUnsigned8: { 1132 return llvm::Type::getInt8Ty(C); 1133 break; 1134 } 1135 case DataTypeSigned16: 1136 case DataTypeUnsigned16: 1137 case DataTypeUnsigned565: 1138 case DataTypeUnsigned5551: 1139 case DataTypeUnsigned4444: { 1140 return llvm::Type::getInt16Ty(C); 1141 break; 1142 } 1143 case DataTypeSigned32: 1144 case DataTypeUnsigned32: { 1145 return llvm::Type::getInt32Ty(C); 1146 break; 1147 } 1148 case DataTypeSigned64: 1149 case DataTypeUnsigned64: { 1150 return llvm::Type::getInt64Ty(C); 1151 break; 1152 } 1153 default: { 1154 slangAssert(false && "Unknown data type"); 1155 } 1156 } 1157 1158 return NULL; 1159} 1160 1161bool RSExportPrimitiveType::equals(const RSExportable *E) const { 1162 CHECK_PARENT_EQUALITY(RSExportType, E); 1163 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 1164} 1165 1166RSReflectionType *RSExportPrimitiveType::getRSReflectionType(DataType DT) { 1167 if (DT > DataTypeUnknown && DT < DataTypeMax) { 1168 return &gReflectionTypes[DT]; 1169 } else { 1170 return NULL; 1171 } 1172} 1173 1174/**************************** RSExportPointerType ****************************/ 1175 1176RSExportPointerType 1177*RSExportPointerType::Create(RSContext *Context, 1178 const clang::PointerType *PT, 1179 const llvm::StringRef &TypeName) { 1180 const clang::Type *PointeeType = GetPointeeType(PT); 1181 const RSExportType *PointeeET; 1182 1183 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 1184 PointeeET = RSExportType::Create(Context, PointeeType); 1185 } else { 1186 // Double or higher dimension of pointer, export as int* 1187 PointeeET = RSExportPrimitiveType::Create(Context, 1188 Context->getASTContext().IntTy.getTypePtr()); 1189 } 1190 1191 if (PointeeET == NULL) { 1192 // Error diagnostic is emitted for corresponding pointee type 1193 return NULL; 1194 } 1195 1196 return new RSExportPointerType(Context, TypeName, PointeeET); 1197} 1198 1199llvm::Type *RSExportPointerType::convertToLLVMType() const { 1200 llvm::Type *PointeeType = mPointeeType->getLLVMType(); 1201 return llvm::PointerType::getUnqual(PointeeType); 1202} 1203 1204bool RSExportPointerType::keep() { 1205 if (!RSExportType::keep()) 1206 return false; 1207 const_cast<RSExportType*>(mPointeeType)->keep(); 1208 return true; 1209} 1210 1211bool RSExportPointerType::equals(const RSExportable *E) const { 1212 CHECK_PARENT_EQUALITY(RSExportType, E); 1213 return (static_cast<const RSExportPointerType*>(E) 1214 ->getPointeeType()->equals(getPointeeType())); 1215} 1216 1217/***************************** RSExportVectorType *****************************/ 1218llvm::StringRef 1219RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 1220 const clang::Type *ElementType = GetExtVectorElementType(EVT); 1221 llvm::StringRef name; 1222 1223 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 1224 return name; 1225 1226 const clang::BuiltinType *BT = 1227 static_cast<const clang::BuiltinType*>( 1228 ElementType->getCanonicalTypeInternal().getTypePtr()); 1229 1230 if ((EVT->getNumElements() < 1) || 1231 (EVT->getNumElements() > 4)) 1232 return name; 1233 1234 BuiltinInfo *info = FindBuiltinType(BT->getKind()); 1235 if (info != NULL) { 1236 int I = EVT->getNumElements() - 1; 1237 if (I < kMaxVectorSize) { 1238 name = info->cname[I]; 1239 } else { 1240 slangAssert(false && "Max vector is 4"); 1241 } 1242 } 1243 return name; 1244} 1245 1246RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 1247 const clang::ExtVectorType *EVT, 1248 const llvm::StringRef &TypeName, 1249 bool Normalized) { 1250 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 1251 1252 const clang::Type *ElementType = GetExtVectorElementType(EVT); 1253 DataType DT = RSExportPrimitiveType::GetDataType(Context, ElementType); 1254 1255 if (DT != DataTypeUnknown) 1256 return new RSExportVectorType(Context, 1257 TypeName, 1258 DT, 1259 Normalized, 1260 EVT->getNumElements()); 1261 else 1262 return NULL; 1263} 1264 1265llvm::Type *RSExportVectorType::convertToLLVMType() const { 1266 llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 1267 return llvm::VectorType::get(ElementType, getNumElement()); 1268} 1269 1270bool RSExportVectorType::equals(const RSExportable *E) const { 1271 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 1272 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 1273 == getNumElement()); 1274} 1275 1276/***************************** RSExportMatrixType *****************************/ 1277RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 1278 const clang::RecordType *RT, 1279 const llvm::StringRef &TypeName, 1280 unsigned Dim) { 1281 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 1282 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 1283 1284 // Check whether the struct rs_matrix is in our expected form (but assume it's 1285 // correct if we're not sure whether it's correct or not) 1286 const clang::RecordDecl* RD = RT->getDecl(); 1287 RD = RD->getDefinition(); 1288 if (RD != NULL) { 1289 // Find definition, perform further examination 1290 if (RD->field_empty()) { 1291 Context->ReportError( 1292 RD->getLocation(), 1293 "invalid matrix struct: must have 1 field for saving values: '%0'") 1294 << RD->getName(); 1295 return NULL; 1296 } 1297 1298 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 1299 const clang::FieldDecl *FD = *FIT; 1300 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1301 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 1302 Context->ReportError(RD->getLocation(), 1303 "invalid matrix struct: first field should" 1304 " be an array with constant size: '%0'") 1305 << RD->getName(); 1306 return NULL; 1307 } 1308 const clang::ConstantArrayType *CAT = 1309 static_cast<const clang::ConstantArrayType *>(FT); 1310 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 1311 if ((ElementType == NULL) || 1312 (ElementType->getTypeClass() != clang::Type::Builtin) || 1313 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() != 1314 clang::BuiltinType::Float)) { 1315 Context->ReportError(RD->getLocation(), 1316 "invalid matrix struct: first field " 1317 "should be a float array: '%0'") 1318 << RD->getName(); 1319 return NULL; 1320 } 1321 1322 if (CAT->getSize() != Dim * Dim) { 1323 Context->ReportError(RD->getLocation(), 1324 "invalid matrix struct: first field " 1325 "should be an array with size %0: '%1'") 1326 << (Dim * Dim) << (RD->getName()); 1327 return NULL; 1328 } 1329 1330 FIT++; 1331 if (FIT != RD->field_end()) { 1332 Context->ReportError(RD->getLocation(), 1333 "invalid matrix struct: must have " 1334 "exactly 1 field: '%0'") 1335 << RD->getName(); 1336 return NULL; 1337 } 1338 } 1339 1340 return new RSExportMatrixType(Context, TypeName, Dim); 1341} 1342 1343llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1344 // Construct LLVM type: 1345 // struct { 1346 // float X[mDim * mDim]; 1347 // } 1348 1349 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1350 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1351 mDim * mDim); 1352 return llvm::StructType::get(C, X, false); 1353} 1354 1355bool RSExportMatrixType::equals(const RSExportable *E) const { 1356 CHECK_PARENT_EQUALITY(RSExportType, E); 1357 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1358} 1359 1360/************************* RSExportConstantArrayType *************************/ 1361RSExportConstantArrayType 1362*RSExportConstantArrayType::Create(RSContext *Context, 1363 const clang::ConstantArrayType *CAT) { 1364 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1365 1366 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1367 1368 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1369 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1370 1371 const clang::Type *ElementType = GetConstantArrayElementType(CAT); 1372 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1373 1374 if (ElementET == NULL) { 1375 return NULL; 1376 } 1377 1378 return new RSExportConstantArrayType(Context, 1379 ElementET, 1380 Size); 1381} 1382 1383llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1384 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1385} 1386 1387bool RSExportConstantArrayType::keep() { 1388 if (!RSExportType::keep()) 1389 return false; 1390 const_cast<RSExportType*>(mElementType)->keep(); 1391 return true; 1392} 1393 1394bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1395 CHECK_PARENT_EQUALITY(RSExportType, E); 1396 const RSExportConstantArrayType *RHS = 1397 static_cast<const RSExportConstantArrayType*>(E); 1398 return ((getSize() == RHS->getSize()) && 1399 (getElementType()->equals(RHS->getElementType()))); 1400} 1401 1402/**************************** RSExportRecordType ****************************/ 1403RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1404 const clang::RecordType *RT, 1405 const llvm::StringRef &TypeName, 1406 bool mIsArtificial) { 1407 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1408 1409 const clang::RecordDecl *RD = RT->getDecl(); 1410 slangAssert(RD->isStruct()); 1411 1412 RD = RD->getDefinition(); 1413 if (RD == NULL) { 1414 slangAssert(false && "struct is not defined in this module"); 1415 return NULL; 1416 } 1417 1418 // Struct layout construct by clang. We rely on this for obtaining the 1419 // alloc size of a struct and offset of every field in that struct. 1420 const clang::ASTRecordLayout *RL = 1421 &Context->getASTContext().getASTRecordLayout(RD); 1422 slangAssert((RL != NULL) && 1423 "Failed to retrieve the struct layout from Clang."); 1424 1425 RSExportRecordType *ERT = 1426 new RSExportRecordType(Context, 1427 TypeName, 1428 RD->hasAttr<clang::PackedAttr>(), 1429 mIsArtificial, 1430 RL->getDataSize().getQuantity(), 1431 RL->getSize().getQuantity()); 1432 unsigned int Index = 0; 1433 1434 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1435 FE = RD->field_end(); 1436 FI != FE; 1437 FI++, Index++) { 1438 1439 // FIXME: All fields should be primitive type 1440 slangAssert(FI->getKind() == clang::Decl::Field); 1441 clang::FieldDecl *FD = *FI; 1442 1443 if (FD->isBitField()) { 1444 return NULL; 1445 } 1446 1447 // Type 1448 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1449 1450 if (ET != NULL) { 1451 ERT->mFields.push_back( 1452 new Field(ET, FD->getName(), ERT, 1453 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1454 } else { 1455 Context->ReportError(RD->getLocation(), 1456 "field type cannot be exported: '%0.%1'") 1457 << RD->getName() << FD->getName(); 1458 return NULL; 1459 } 1460 } 1461 1462 return ERT; 1463} 1464 1465llvm::Type *RSExportRecordType::convertToLLVMType() const { 1466 // Create an opaque type since struct may reference itself recursively. 1467 1468 // TODO(sliao): LLVM took out the OpaqueType. Any other to migrate to? 1469 std::vector<llvm::Type*> FieldTypes; 1470 1471 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1472 FI != FE; 1473 FI++) { 1474 const Field *F = *FI; 1475 const RSExportType *FET = F->getType(); 1476 1477 FieldTypes.push_back(FET->getLLVMType()); 1478 } 1479 1480 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1481 FieldTypes, 1482 mIsPacked); 1483 if (ST != NULL) { 1484 return ST; 1485 } else { 1486 return NULL; 1487 } 1488} 1489 1490bool RSExportRecordType::keep() { 1491 if (!RSExportType::keep()) 1492 return false; 1493 for (std::list<const Field*>::iterator I = mFields.begin(), 1494 E = mFields.end(); 1495 I != E; 1496 I++) { 1497 const_cast<RSExportType*>((*I)->getType())->keep(); 1498 } 1499 return true; 1500} 1501 1502bool RSExportRecordType::equals(const RSExportable *E) const { 1503 CHECK_PARENT_EQUALITY(RSExportType, E); 1504 1505 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1506 1507 if (ERT->getFields().size() != getFields().size()) 1508 return false; 1509 1510 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1511 1512 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1513 if (!(*AI)->getType()->equals((*BI)->getType())) 1514 return false; 1515 AI++; 1516 BI++; 1517 } 1518 1519 return true; 1520} 1521 1522void RSExportType::convertToRTD(RSReflectionTypeData *rtd) const { 1523 memset(rtd, 0, sizeof(*rtd)); 1524 rtd->vecSize = 1; 1525 1526 switch(getClass()) { 1527 case RSExportType::ExportClassPrimitive: { 1528 const RSExportPrimitiveType *EPT = static_cast<const RSExportPrimitiveType*>(this); 1529 rtd->type = RSExportPrimitiveType::getRSReflectionType(EPT); 1530 return; 1531 } 1532 case RSExportType::ExportClassPointer: { 1533 const RSExportPointerType *EPT = static_cast<const RSExportPointerType*>(this); 1534 const RSExportType *PointeeType = EPT->getPointeeType(); 1535 PointeeType->convertToRTD(rtd); 1536 rtd->isPointer = true; 1537 return; 1538 } 1539 case RSExportType::ExportClassVector: { 1540 const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(this); 1541 rtd->type = EVT->getRSReflectionType(EVT); 1542 rtd->vecSize = EVT->getNumElement(); 1543 return; 1544 } 1545 case RSExportType::ExportClassMatrix: { 1546 const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType*>(this); 1547 unsigned Dim = EMT->getDim(); 1548 slangAssert((Dim >= 2) && (Dim <= 4)); 1549 rtd->type = &gReflectionTypes[15 + Dim-2]; 1550 return; 1551 } 1552 case RSExportType::ExportClassConstantArray: { 1553 const RSExportConstantArrayType* CAT = 1554 static_cast<const RSExportConstantArrayType*>(this); 1555 CAT->getElementType()->convertToRTD(rtd); 1556 rtd->arraySize = CAT->getSize(); 1557 return; 1558 } 1559 case RSExportType::ExportClassRecord: { 1560 slangAssert(!"RSExportType::ExportClassRecord not implemented"); 1561 return;// RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + ".Item"; 1562 } 1563 default: { 1564 slangAssert(false && "Unknown class of type"); 1565 } 1566 } 1567} 1568 1569 1570} // namespace slang 1571