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