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