slang_rs_export_type.cpp revision 7207645766b118ef18081363bb58e39d3e715c2f
1/* 2 * Copyright 2010, 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/RecordLayout.h" 23 24#include "llvm/ADT/ArrayRef.h" 25#include "llvm/ADT/StringExtras.h" 26 27#include "llvm/DerivedTypes.h" 28 29#include "llvm/Target/TargetData.h" 30 31#include "llvm/Type.h" 32 33#include "slang_assert.h" 34#include "slang_rs_context.h" 35#include "slang_rs_export_element.h" 36#include "slang_rs_type_spec.h" 37 38#define CHECK_PARENT_EQUALITY(ParentClass, E) \ 39 if (!ParentClass::equals(E)) \ 40 return false; 41 42namespace slang { 43 44namespace { 45 46static const clang::Type *TypeExportableHelper( 47 const clang::Type *T, 48 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 49 clang::Diagnostic *Diags, 50 clang::SourceManager *SM, 51 const clang::VarDecl *VD, 52 const clang::RecordDecl *TopLevelRecord); 53 54static void ReportTypeError(clang::Diagnostic *Diags, 55 const clang::SourceManager *SM, 56 const clang::VarDecl *VD, 57 const clang::RecordDecl *TopLevelRecord, 58 const char *Message) { 59 if (!Diags || !SM) { 60 return; 61 } 62 63 // Attempt to use the type declaration first (if we have one). 64 // Fall back to the variable definition, if we are looking at something 65 // like an array declaration that can't be exported. 66 if (TopLevelRecord) { 67 Diags->Report(clang::FullSourceLoc(TopLevelRecord->getLocation(), *SM), 68 Diags->getCustomDiagID(clang::Diagnostic::Error, Message)) 69 << TopLevelRecord->getName(); 70 } else if (VD) { 71 Diags->Report(clang::FullSourceLoc(VD->getLocation(), *SM), 72 Diags->getCustomDiagID(clang::Diagnostic::Error, Message)) 73 << VD->getName(); 74 } else { 75 slangAssert(false && "Variables should be validated before exporting"); 76 } 77 78 return; 79} 80 81static const clang::Type *ConstantArrayTypeExportableHelper( 82 const clang::ConstantArrayType *CAT, 83 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 84 clang::Diagnostic *Diags, 85 clang::SourceManager *SM, 86 const clang::VarDecl *VD, 87 const clang::RecordDecl *TopLevelRecord) { 88 // Check element type 89 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 90 if (ElementType->isArrayType()) { 91 ReportTypeError(Diags, SM, VD, TopLevelRecord, 92 "multidimensional arrays cannot be exported: '%0'"); 93 return NULL; 94 } else if (ElementType->isExtVectorType()) { 95 const clang::ExtVectorType *EVT = 96 static_cast<const clang::ExtVectorType*>(ElementType); 97 unsigned numElements = EVT->getNumElements(); 98 99 const clang::Type *BaseElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 100 if (!RSExportPrimitiveType::IsPrimitiveType(BaseElementType)) { 101 ReportTypeError(Diags, SM, VD, TopLevelRecord, 102 "vectors of non-primitive types cannot be exported: '%0'"); 103 return NULL; 104 } 105 106 if (numElements == 3 && CAT->getSize() != 1) { 107 ReportTypeError(Diags, SM, VD, TopLevelRecord, 108 "arrays of width 3 vector types cannot be exported: '%0'"); 109 return NULL; 110 } 111 } 112 113 if (TypeExportableHelper(ElementType, SPS, Diags, SM, VD, 114 TopLevelRecord) == NULL) 115 return NULL; 116 else 117 return CAT; 118} 119 120static const clang::Type *TypeExportableHelper( 121 const clang::Type *T, 122 llvm::SmallPtrSet<const clang::Type*, 8>& SPS, 123 clang::Diagnostic *Diags, 124 clang::SourceManager *SM, 125 const clang::VarDecl *VD, 126 const clang::RecordDecl *TopLevelRecord) { 127 // Normalize first 128 if ((T = GET_CANONICAL_TYPE(T)) == NULL) 129 return NULL; 130 131 if (SPS.count(T)) 132 return T; 133 134 switch (T->getTypeClass()) { 135 case clang::Type::Builtin: { 136 const clang::BuiltinType *BT = 137 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 138 139 switch (BT->getKind()) { 140#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 141 case builtin_type: 142#include "RSClangBuiltinEnums.inc" 143 return T; 144 default: { 145 return NULL; 146 } 147 } 148 } 149 case clang::Type::Record: { 150 if (RSExportPrimitiveType::GetRSSpecificType(T) != 151 RSExportPrimitiveType::DataTypeUnknown) 152 return T; // RS object type, no further checks are needed 153 154 // Check internal struct 155 if (T->isUnionType()) { 156 ReportTypeError(Diags, SM, NULL, T->getAsUnionType()->getDecl(), 157 "unions cannot be exported: '%0'"); 158 return NULL; 159 } else if (!T->isStructureType()) { 160 slangAssert(false && "Unknown type cannot be exported"); 161 return NULL; 162 } 163 164 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 165 if (RD != NULL) { 166 RD = RD->getDefinition(); 167 if (RD == NULL) { 168 ReportTypeError(Diags, SM, NULL, T->getAsStructureType()->getDecl(), 169 "struct is not defined in this module"); 170 return NULL; 171 } 172 } 173 174 if (!TopLevelRecord) { 175 TopLevelRecord = RD; 176 } 177 if (RD->getName().empty()) { 178 ReportTypeError(Diags, SM, NULL, RD, 179 "anonymous structures cannot be exported"); 180 return NULL; 181 } 182 183 // Fast check 184 if (RD->hasFlexibleArrayMember() || RD->hasObjectMember()) 185 return NULL; 186 187 // Insert myself into checking set 188 SPS.insert(T); 189 190 // Check all element 191 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 192 FE = RD->field_end(); 193 FI != FE; 194 FI++) { 195 const clang::FieldDecl *FD = *FI; 196 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 197 FT = GET_CANONICAL_TYPE(FT); 198 199 if (!TypeExportableHelper(FT, SPS, Diags, SM, VD, TopLevelRecord)) { 200 return NULL; 201 } 202 203 // We don't support bit fields yet 204 // 205 // TODO(zonr/srhines): allow bit fields of size 8, 16, 32 206 if (FD->isBitField()) { 207 if (Diags && SM) { 208 Diags->Report(clang::FullSourceLoc(FD->getLocation(), *SM), 209 Diags->getCustomDiagID(clang::Diagnostic::Error, 210 "bit fields are not able to be exported: '%0.%1'")) 211 << RD->getName() 212 << FD->getName(); 213 } 214 return NULL; 215 } 216 } 217 218 return T; 219 } 220 case clang::Type::Pointer: { 221 if (TopLevelRecord) { 222 ReportTypeError(Diags, SM, NULL, TopLevelRecord, 223 "structures containing pointers cannot be exported: '%0'"); 224 return NULL; 225 } 226 227 const clang::PointerType *PT = 228 UNSAFE_CAST_TYPE(const clang::PointerType, T); 229 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 230 231 if (PointeeType->getTypeClass() == clang::Type::Pointer) 232 return T; 233 // We don't support pointer with array-type pointee or unsupported pointee 234 // type 235 if (PointeeType->isArrayType() || 236 (TypeExportableHelper(PointeeType, SPS, Diags, SM, VD, 237 TopLevelRecord) == NULL)) 238 return NULL; 239 else 240 return T; 241 } 242 case clang::Type::ExtVector: { 243 const clang::ExtVectorType *EVT = 244 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 245 // Only vector with size 2, 3 and 4 are supported. 246 if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4) 247 return NULL; 248 249 // Check base element type 250 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 251 252 if ((ElementType->getTypeClass() != clang::Type::Builtin) || 253 (TypeExportableHelper(ElementType, SPS, Diags, SM, VD, 254 TopLevelRecord) == NULL)) 255 return NULL; 256 else 257 return T; 258 } 259 case clang::Type::ConstantArray: { 260 const clang::ConstantArrayType *CAT = 261 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T); 262 263 return ConstantArrayTypeExportableHelper(CAT, SPS, Diags, SM, VD, 264 TopLevelRecord); 265 } 266 default: { 267 return NULL; 268 } 269 } 270} 271 272// Return the type that can be used to create RSExportType, will always return 273// the canonical type 274// If the Type T is not exportable, this function returns NULL. Diags and SM 275// are used to generate proper Clang diagnostic messages when a 276// non-exportable type is detected. TopLevelRecord is used to capture the 277// highest struct (in the case of a nested hierarchy) for detecting other 278// types that cannot be exported (mostly pointers within a struct). 279static const clang::Type *TypeExportable(const clang::Type *T, 280 clang::Diagnostic *Diags, 281 clang::SourceManager *SM, 282 const clang::VarDecl *VD) { 283 llvm::SmallPtrSet<const clang::Type*, 8> SPS = 284 llvm::SmallPtrSet<const clang::Type*, 8>(); 285 286 return TypeExportableHelper(T, SPS, Diags, SM, VD, NULL); 287} 288 289} // namespace 290 291/****************************** RSExportType ******************************/ 292bool RSExportType::NormalizeType(const clang::Type *&T, 293 llvm::StringRef &TypeName, 294 clang::Diagnostic *Diags, 295 clang::SourceManager *SM, 296 const clang::VarDecl *VD) { 297 if ((T = TypeExportable(T, Diags, SM, VD)) == NULL) { 298 return false; 299 } 300 // Get type name 301 TypeName = RSExportType::GetTypeName(T); 302 if (TypeName.empty()) { 303 if (Diags && SM) { 304 if (VD) { 305 Diags->Report(clang::FullSourceLoc(VD->getLocation(), *SM), 306 Diags->getCustomDiagID(clang::Diagnostic::Error, 307 "anonymous types cannot " 308 "be exported")); 309 } else { 310 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 311 "anonymous types cannot " 312 "be exported")); 313 } 314 } 315 return false; 316 } 317 318 return true; 319} 320 321const clang::Type 322*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) { 323 if (DD) { 324 clang::QualType T; 325 if (DD->getTypeSourceInfo()) 326 T = DD->getTypeSourceInfo()->getType(); 327 else 328 T = DD->getType(); 329 330 if (T.isNull()) 331 return NULL; 332 else 333 return T.getTypePtr(); 334 } 335 return NULL; 336} 337 338llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) { 339 T = GET_CANONICAL_TYPE(T); 340 if (T == NULL) 341 return llvm::StringRef(); 342 343 switch (T->getTypeClass()) { 344 case clang::Type::Builtin: { 345 const clang::BuiltinType *BT = 346 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 347 348 switch (BT->getKind()) { 349#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 350 case builtin_type: \ 351 return cname; \ 352 break; 353#include "RSClangBuiltinEnums.inc" 354 default: { 355 slangAssert(false && "Unknown data type of the builtin"); 356 break; 357 } 358 } 359 break; 360 } 361 case clang::Type::Record: { 362 clang::RecordDecl *RD; 363 if (T->isStructureType()) { 364 RD = T->getAsStructureType()->getDecl(); 365 } else { 366 break; 367 } 368 369 llvm::StringRef Name = RD->getName(); 370 if (Name.empty()) { 371 if (RD->getTypedefForAnonDecl() != NULL) 372 Name = RD->getTypedefForAnonDecl()->getName(); 373 374 if (Name.empty()) 375 // Try to find a name from redeclaration (i.e. typedef) 376 for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(), 377 RE = RD->redecls_end(); 378 RI != RE; 379 RI++) { 380 slangAssert(*RI != NULL && "cannot be NULL object"); 381 382 Name = (*RI)->getName(); 383 if (!Name.empty()) 384 break; 385 } 386 } 387 return Name; 388 } 389 case clang::Type::Pointer: { 390 // "*" plus pointee name 391 const clang::Type *PT = GET_POINTEE_TYPE(T); 392 llvm::StringRef PointeeName; 393 if (NormalizeType(PT, PointeeName, NULL, NULL, NULL)) { 394 char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ]; 395 Name[0] = '*'; 396 memcpy(Name + 1, PointeeName.data(), PointeeName.size()); 397 Name[PointeeName.size() + 1] = '\0'; 398 return Name; 399 } 400 break; 401 } 402 case clang::Type::ExtVector: { 403 const clang::ExtVectorType *EVT = 404 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T); 405 return RSExportVectorType::GetTypeName(EVT); 406 break; 407 } 408 case clang::Type::ConstantArray : { 409 // Construct name for a constant array is too complicated. 410 return DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE; 411 } 412 default: { 413 break; 414 } 415 } 416 417 return llvm::StringRef(); 418} 419 420 421RSExportType *RSExportType::Create(RSContext *Context, 422 const clang::Type *T, 423 const llvm::StringRef &TypeName) { 424 // Lookup the context to see whether the type was processed before. 425 // Newly created RSExportType will insert into context 426 // in RSExportType::RSExportType() 427 RSContext::export_type_iterator ETI = Context->findExportType(TypeName); 428 429 if (ETI != Context->export_types_end()) 430 return ETI->second; 431 432 RSExportType *ET = NULL; 433 switch (T->getTypeClass()) { 434 case clang::Type::Record: { 435 RSExportPrimitiveType::DataType dt = 436 RSExportPrimitiveType::GetRSSpecificType(TypeName); 437 switch (dt) { 438 case RSExportPrimitiveType::DataTypeUnknown: { 439 // User-defined types 440 ET = RSExportRecordType::Create(Context, 441 T->getAsStructureType(), 442 TypeName); 443 break; 444 } 445 case RSExportPrimitiveType::DataTypeRSMatrix2x2: { 446 // 2 x 2 Matrix type 447 ET = RSExportMatrixType::Create(Context, 448 T->getAsStructureType(), 449 TypeName, 450 2); 451 break; 452 } 453 case RSExportPrimitiveType::DataTypeRSMatrix3x3: { 454 // 3 x 3 Matrix type 455 ET = RSExportMatrixType::Create(Context, 456 T->getAsStructureType(), 457 TypeName, 458 3); 459 break; 460 } 461 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 462 // 4 x 4 Matrix type 463 ET = RSExportMatrixType::Create(Context, 464 T->getAsStructureType(), 465 TypeName, 466 4); 467 break; 468 } 469 default: { 470 // Others are primitive types 471 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 472 break; 473 } 474 } 475 break; 476 } 477 case clang::Type::Builtin: { 478 ET = RSExportPrimitiveType::Create(Context, T, TypeName); 479 break; 480 } 481 case clang::Type::Pointer: { 482 ET = RSExportPointerType::Create(Context, 483 UNSAFE_CAST_TYPE(const clang::PointerType, T), 484 TypeName); 485 // FIXME: free the name (allocated in RSExportType::GetTypeName) 486 delete [] TypeName.data(); 487 break; 488 } 489 case clang::Type::ExtVector: { 490 ET = RSExportVectorType::Create(Context, 491 UNSAFE_CAST_TYPE(const clang::ExtVectorType, T), 492 TypeName); 493 break; 494 } 495 case clang::Type::ConstantArray: { 496 ET = RSExportConstantArrayType::Create( 497 Context, 498 UNSAFE_CAST_TYPE(const clang::ConstantArrayType, T)); 499 break; 500 } 501 default: { 502 clang::Diagnostic *Diags = Context->getDiagnostics(); 503 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 504 "unknown type cannot be exported: '%0'")) 505 << T->getTypeClassName(); 506 break; 507 } 508 } 509 510 return ET; 511} 512 513RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) { 514 llvm::StringRef TypeName; 515 if (NormalizeType(T, TypeName, NULL, NULL, NULL)) 516 return Create(Context, T, TypeName); 517 else 518 return NULL; 519} 520 521RSExportType *RSExportType::CreateFromDecl(RSContext *Context, 522 const clang::VarDecl *VD) { 523 return RSExportType::Create(Context, GetTypeOfDecl(VD)); 524} 525 526size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) { 527 return ET->getRSContext()->getTargetData()->getTypeStoreSize( 528 ET->getLLVMType()); 529} 530 531size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) { 532 if (ET->getClass() == RSExportType::ExportClassRecord) 533 return static_cast<const RSExportRecordType*>(ET)->getAllocSize(); 534 else 535 return ET->getRSContext()->getTargetData()->getTypeAllocSize( 536 ET->getLLVMType()); 537} 538 539RSExportType::RSExportType(RSContext *Context, 540 ExportClass Class, 541 const llvm::StringRef &Name) 542 : RSExportable(Context, RSExportable::EX_TYPE), 543 mClass(Class), 544 // Make a copy on Name since memory stored @Name is either allocated in 545 // ASTContext or allocated in GetTypeName which will be destroyed later. 546 mName(Name.data(), Name.size()), 547 mLLVMType(NULL), 548 mSpecType(NULL) { 549 // Don't cache the type whose name start with '<'. Those type failed to 550 // get their name since constructing their name in GetTypeName() requiring 551 // complicated work. 552 if (!Name.startswith(DUMMY_RS_TYPE_NAME_PREFIX)) 553 // TODO(zonr): Need to check whether the insertion is successful or not. 554 Context->insertExportType(llvm::StringRef(Name), this); 555 return; 556} 557 558bool RSExportType::keep() { 559 if (!RSExportable::keep()) 560 return false; 561 // Invalidate converted LLVM type. 562 mLLVMType = NULL; 563 return true; 564} 565 566bool RSExportType::equals(const RSExportable *E) const { 567 CHECK_PARENT_EQUALITY(RSExportable, E); 568 return (static_cast<const RSExportType*>(E)->getClass() == getClass()); 569} 570 571RSExportType::~RSExportType() { 572 delete mSpecType; 573} 574 575/************************** RSExportPrimitiveType **************************/ 576llvm::ManagedStatic<RSExportPrimitiveType::RSSpecificTypeMapTy> 577RSExportPrimitiveType::RSSpecificTypeMap; 578 579llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL; 580 581bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) { 582 if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin)) 583 return true; 584 else 585 return false; 586} 587 588RSExportPrimitiveType::DataType 589RSExportPrimitiveType::GetRSSpecificType(const llvm::StringRef &TypeName) { 590 if (TypeName.empty()) 591 return DataTypeUnknown; 592 593 if (RSSpecificTypeMap->empty()) { 594#define ENUM_RS_MATRIX_TYPE(type, cname, dim) \ 595 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 596#include "RSMatrixTypeEnums.inc" 597#define ENUM_RS_OBJECT_TYPE(type, cname) \ 598 RSSpecificTypeMap->GetOrCreateValue(cname, DataType ## type); 599#include "RSObjectTypeEnums.inc" 600 } 601 602 RSSpecificTypeMapTy::const_iterator I = RSSpecificTypeMap->find(TypeName); 603 if (I == RSSpecificTypeMap->end()) 604 return DataTypeUnknown; 605 else 606 return I->getValue(); 607} 608 609RSExportPrimitiveType::DataType 610RSExportPrimitiveType::GetRSSpecificType(const clang::Type *T) { 611 T = GET_CANONICAL_TYPE(T); 612 if ((T == NULL) || (T->getTypeClass() != clang::Type::Record)) 613 return DataTypeUnknown; 614 615 return GetRSSpecificType( RSExportType::GetTypeName(T) ); 616} 617 618bool RSExportPrimitiveType::IsRSMatrixType(DataType DT) { 619 return ((DT >= FirstRSMatrixType) && (DT <= LastRSMatrixType)); 620} 621 622bool RSExportPrimitiveType::IsRSObjectType(DataType DT) { 623 return ((DT >= FirstRSObjectType) && (DT <= LastRSObjectType)); 624} 625 626bool RSExportPrimitiveType::IsStructureTypeWithRSObject(const clang::Type *T) { 627 bool RSObjectTypeSeen = false; 628 while (T && T->isArrayType()) { 629 T = T->getArrayElementTypeNoTypeQual(); 630 } 631 632 const clang::RecordType *RT = T->getAsStructureType(); 633 if (!RT) { 634 return false; 635 } 636 const clang::RecordDecl *RD = RT->getDecl(); 637 RD = RD->getDefinition(); 638 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 639 FE = RD->field_end(); 640 FI != FE; 641 FI++) { 642 // We just look through all field declarations to see if we find a 643 // declaration for an RS object type (or an array of one). 644 const clang::FieldDecl *FD = *FI; 645 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 646 while (FT && FT->isArrayType()) { 647 FT = FT->getArrayElementTypeNoTypeQual(); 648 } 649 650 RSExportPrimitiveType::DataType DT = GetRSSpecificType(FT); 651 if (IsRSObjectType(DT)) { 652 // RS object types definitely need to be zero-initialized 653 RSObjectTypeSeen = true; 654 } else { 655 switch (DT) { 656 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 657 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 658 case RSExportPrimitiveType::DataTypeRSMatrix4x4: 659 // Matrix types should get zero-initialized as well 660 RSObjectTypeSeen = true; 661 break; 662 default: 663 // Ignore all other primitive types 664 break; 665 } 666 while (FT && FT->isArrayType()) { 667 FT = FT->getArrayElementTypeNoTypeQual(); 668 } 669 if (FT->isStructureType()) { 670 // Recursively handle structs of structs (even though these can't 671 // be exported, it is possible for a user to have them internally). 672 RSObjectTypeSeen |= IsStructureTypeWithRSObject(FT); 673 } 674 } 675 } 676 677 return RSObjectTypeSeen; 678} 679 680const size_t RSExportPrimitiveType::SizeOfDataTypeInBits[] = { 681#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 682 bits, 683#include "RSDataTypeEnums.inc" 684 0 // DataTypeMax 685}; 686 687size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) { 688 slangAssert(((EPT->getType() > DataTypeUnknown) && 689 (EPT->getType() < DataTypeMax)) && 690 "RSExportPrimitiveType::GetSizeInBits : unknown data type"); 691 return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ]; 692} 693 694RSExportPrimitiveType::DataType 695RSExportPrimitiveType::GetDataType(RSContext *Context, const clang::Type *T) { 696 if (T == NULL) 697 return DataTypeUnknown; 698 699 switch (T->getTypeClass()) { 700 case clang::Type::Builtin: { 701 const clang::BuiltinType *BT = 702 UNSAFE_CAST_TYPE(const clang::BuiltinType, T); 703 switch (BT->getKind()) { 704#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 705 case builtin_type: { \ 706 return DataType ## type; \ 707 } 708#include "RSClangBuiltinEnums.inc" 709 // The size of type WChar depend on platform so we abandon the support 710 // to them. 711 default: { 712 clang::Diagnostic *Diags = Context->getDiagnostics(); 713 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 714 "built-in type cannot be exported: '%0'")) 715 << T->getTypeClassName(); 716 break; 717 } 718 } 719 break; 720 } 721 case clang::Type::Record: { 722 // must be RS object type 723 return RSExportPrimitiveType::GetRSSpecificType(T); 724 } 725 default: { 726 clang::Diagnostic *Diags = Context->getDiagnostics(); 727 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 728 "primitive type cannot be exported: '%0'")) 729 << T->getTypeClassName(); 730 break; 731 } 732 } 733 734 return DataTypeUnknown; 735} 736 737RSExportPrimitiveType 738*RSExportPrimitiveType::Create(RSContext *Context, 739 const clang::Type *T, 740 const llvm::StringRef &TypeName, 741 DataKind DK, 742 bool Normalized) { 743 DataType DT = GetDataType(Context, T); 744 745 if ((DT == DataTypeUnknown) || TypeName.empty()) 746 return NULL; 747 else 748 return new RSExportPrimitiveType(Context, ExportClassPrimitive, TypeName, 749 DT, DK, Normalized); 750} 751 752RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context, 753 const clang::Type *T, 754 DataKind DK) { 755 llvm::StringRef TypeName; 756 if (RSExportType::NormalizeType(T, TypeName, NULL, NULL, NULL) && 757 IsPrimitiveType(T)) { 758 return Create(Context, T, TypeName, DK); 759 } else { 760 return NULL; 761 } 762} 763 764const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const { 765 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 766 767 if (isRSObjectType()) { 768 // struct { 769 // int *p; 770 // } __attribute__((packed, aligned(pointer_size))) 771 // 772 // which is 773 // 774 // <{ [1 x i32] }> in LLVM 775 // 776 if (RSObjectLLVMType == NULL) { 777 std::vector<const llvm::Type *> Elements; 778 Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1)); 779 RSObjectLLVMType = llvm::StructType::get(C, Elements, true); 780 } 781 return RSObjectLLVMType; 782 } 783 784 switch (mType) { 785 case DataTypeFloat32: { 786 return llvm::Type::getFloatTy(C); 787 break; 788 } 789 case DataTypeFloat64: { 790 return llvm::Type::getDoubleTy(C); 791 break; 792 } 793 case DataTypeBoolean: { 794 return llvm::Type::getInt1Ty(C); 795 break; 796 } 797 case DataTypeSigned8: 798 case DataTypeUnsigned8: { 799 return llvm::Type::getInt8Ty(C); 800 break; 801 } 802 case DataTypeSigned16: 803 case DataTypeUnsigned16: 804 case DataTypeUnsigned565: 805 case DataTypeUnsigned5551: 806 case DataTypeUnsigned4444: { 807 return llvm::Type::getInt16Ty(C); 808 break; 809 } 810 case DataTypeSigned32: 811 case DataTypeUnsigned32: { 812 return llvm::Type::getInt32Ty(C); 813 break; 814 } 815 case DataTypeSigned64: 816 case DataTypeUnsigned64: { 817 return llvm::Type::getInt64Ty(C); 818 break; 819 } 820 default: { 821 slangAssert(false && "Unknown data type"); 822 } 823 } 824 825 return NULL; 826} 827 828union RSType *RSExportPrimitiveType::convertToSpecType() const { 829 llvm::OwningPtr<union RSType> ST(new union RSType); 830 RS_TYPE_SET_CLASS(ST, RS_TC_Primitive); 831 // enum RSExportPrimitiveType::DataType is synced with enum RSDataType in 832 // slang_rs_type_spec.h 833 RS_PRIMITIVE_TYPE_SET_DATA_TYPE(ST, getType()); 834 return ST.take(); 835} 836 837bool RSExportPrimitiveType::equals(const RSExportable *E) const { 838 CHECK_PARENT_EQUALITY(RSExportType, E); 839 return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType()); 840} 841 842/**************************** RSExportPointerType ****************************/ 843 844RSExportPointerType 845*RSExportPointerType::Create(RSContext *Context, 846 const clang::PointerType *PT, 847 const llvm::StringRef &TypeName) { 848 const clang::Type *PointeeType = GET_POINTEE_TYPE(PT); 849 const RSExportType *PointeeET; 850 851 if (PointeeType->getTypeClass() != clang::Type::Pointer) { 852 PointeeET = RSExportType::Create(Context, PointeeType); 853 } else { 854 // Double or higher dimension of pointer, export as int* 855 PointeeET = RSExportPrimitiveType::Create(Context, 856 Context->getASTContext().IntTy.getTypePtr()); 857 } 858 859 if (PointeeET == NULL) { 860 // Error diagnostic is emitted for corresponding pointee type 861 return NULL; 862 } 863 864 return new RSExportPointerType(Context, TypeName, PointeeET); 865} 866 867const llvm::Type *RSExportPointerType::convertToLLVMType() const { 868 const llvm::Type *PointeeType = mPointeeType->getLLVMType(); 869 return llvm::PointerType::getUnqual(PointeeType); 870} 871 872union RSType *RSExportPointerType::convertToSpecType() const { 873 llvm::OwningPtr<union RSType> ST(new union RSType); 874 875 RS_TYPE_SET_CLASS(ST, RS_TC_Pointer); 876 RS_POINTER_TYPE_SET_POINTEE_TYPE(ST, getPointeeType()->getSpecType()); 877 878 if (RS_POINTER_TYPE_GET_POINTEE_TYPE(ST) != NULL) 879 return ST.take(); 880 else 881 return NULL; 882} 883 884bool RSExportPointerType::keep() { 885 if (!RSExportType::keep()) 886 return false; 887 const_cast<RSExportType*>(mPointeeType)->keep(); 888 return true; 889} 890 891bool RSExportPointerType::equals(const RSExportable *E) const { 892 CHECK_PARENT_EQUALITY(RSExportType, E); 893 return (static_cast<const RSExportPointerType*>(E) 894 ->getPointeeType()->equals(getPointeeType())); 895} 896 897/***************************** RSExportVectorType *****************************/ 898llvm::StringRef 899RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) { 900 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 901 902 if ((ElementType->getTypeClass() != clang::Type::Builtin)) 903 return llvm::StringRef(); 904 905 const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(const clang::BuiltinType, 906 ElementType); 907 if ((EVT->getNumElements() < 1) || 908 (EVT->getNumElements() > 4)) 909 return llvm::StringRef(); 910 911 switch (BT->getKind()) { 912 // Compiler is smart enough to optimize following *big if branches* since 913 // they all become "constant comparison" after macro expansion 914#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \ 915 case builtin_type: { \ 916 const char *Name[] = { cname"2", cname"3", cname"4" }; \ 917 return Name[EVT->getNumElements() - 2]; \ 918 break; \ 919 } 920#include "RSClangBuiltinEnums.inc" 921 default: { 922 return llvm::StringRef(); 923 } 924 } 925} 926 927RSExportVectorType *RSExportVectorType::Create(RSContext *Context, 928 const clang::ExtVectorType *EVT, 929 const llvm::StringRef &TypeName, 930 DataKind DK, 931 bool Normalized) { 932 slangAssert(EVT != NULL && EVT->getTypeClass() == clang::Type::ExtVector); 933 934 const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT); 935 RSExportPrimitiveType::DataType DT = 936 RSExportPrimitiveType::GetDataType(Context, ElementType); 937 938 if (DT != RSExportPrimitiveType::DataTypeUnknown) 939 return new RSExportVectorType(Context, 940 TypeName, 941 DT, 942 DK, 943 Normalized, 944 EVT->getNumElements()); 945 else 946 return NULL; 947} 948 949const llvm::Type *RSExportVectorType::convertToLLVMType() const { 950 const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType(); 951 return llvm::VectorType::get(ElementType, getNumElement()); 952} 953 954union RSType *RSExportVectorType::convertToSpecType() const { 955 llvm::OwningPtr<union RSType> ST(new union RSType); 956 957 RS_TYPE_SET_CLASS(ST, RS_TC_Vector); 958 RS_VECTOR_TYPE_SET_ELEMENT_TYPE(ST, getType()); 959 RS_VECTOR_TYPE_SET_VECTOR_SIZE(ST, getNumElement()); 960 961 return ST.take(); 962} 963 964bool RSExportVectorType::equals(const RSExportable *E) const { 965 CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E); 966 return (static_cast<const RSExportVectorType*>(E)->getNumElement() 967 == getNumElement()); 968} 969 970/***************************** RSExportMatrixType *****************************/ 971RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context, 972 const clang::RecordType *RT, 973 const llvm::StringRef &TypeName, 974 unsigned Dim) { 975 slangAssert((RT != NULL) && (RT->getTypeClass() == clang::Type::Record)); 976 slangAssert((Dim > 1) && "Invalid dimension of matrix"); 977 978 // Check whether the struct rs_matrix is in our expected form (but assume it's 979 // correct if we're not sure whether it's correct or not) 980 const clang::RecordDecl* RD = RT->getDecl(); 981 RD = RD->getDefinition(); 982 if (RD != NULL) { 983 clang::Diagnostic *Diags = Context->getDiagnostics(); 984 const clang::SourceManager *SM = Context->getSourceManager(); 985 // Find definition, perform further examination 986 if (RD->field_empty()) { 987 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 988 Diags->getCustomDiagID(clang::Diagnostic::Error, 989 "invalid matrix struct: must have 1 field for saving " 990 "values: '%0'")) 991 << RD->getName(); 992 return NULL; 993 } 994 995 clang::RecordDecl::field_iterator FIT = RD->field_begin(); 996 const clang::FieldDecl *FD = *FIT; 997 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 998 if ((FT == NULL) || (FT->getTypeClass() != clang::Type::ConstantArray)) { 999 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 1000 Diags->getCustomDiagID(clang::Diagnostic::Error, 1001 "invalid matrix struct: first field should be an " 1002 "array with constant size: '%0'")) 1003 << RD->getName(); 1004 return NULL; 1005 } 1006 const clang::ConstantArrayType *CAT = 1007 static_cast<const clang::ConstantArrayType *>(FT); 1008 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1009 if ((ElementType == NULL) || 1010 (ElementType->getTypeClass() != clang::Type::Builtin) || 1011 (static_cast<const clang::BuiltinType *>(ElementType)->getKind() 1012 != clang::BuiltinType::Float)) { 1013 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 1014 Diags->getCustomDiagID(clang::Diagnostic::Error, 1015 "invalid matrix struct: first field should be a " 1016 "float array: '%0'")) 1017 << RD->getName(); 1018 return NULL; 1019 } 1020 1021 if (CAT->getSize() != Dim * Dim) { 1022 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 1023 Diags->getCustomDiagID(clang::Diagnostic::Error, 1024 "invalid matrix struct: first field should be an " 1025 "array with size %0: '%1'")) 1026 << Dim * Dim 1027 << RD->getName(); 1028 return NULL; 1029 } 1030 1031 FIT++; 1032 if (FIT != RD->field_end()) { 1033 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 1034 Diags->getCustomDiagID(clang::Diagnostic::Error, 1035 "invalid matrix struct: must have exactly 1 field: " 1036 "'%0'")) 1037 << RD->getName(); 1038 return NULL; 1039 } 1040 } 1041 1042 return new RSExportMatrixType(Context, TypeName, Dim); 1043} 1044 1045const llvm::Type *RSExportMatrixType::convertToLLVMType() const { 1046 // Construct LLVM type: 1047 // struct { 1048 // float X[mDim * mDim]; 1049 // } 1050 1051 llvm::LLVMContext &C = getRSContext()->getLLVMContext(); 1052 llvm::ArrayType *X = llvm::ArrayType::get(llvm::Type::getFloatTy(C), 1053 mDim * mDim); 1054 return llvm::StructType::get(C, llvm::ArrayRef<const llvm::Type*>(X), false); 1055} 1056 1057union RSType *RSExportMatrixType::convertToSpecType() const { 1058 llvm::OwningPtr<union RSType> ST(new union RSType); 1059 RS_TYPE_SET_CLASS(ST, RS_TC_Matrix); 1060 switch (getDim()) { 1061 case 2: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix2x2); break; 1062 case 3: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix3x3); break; 1063 case 4: RS_MATRIX_TYPE_SET_DATA_TYPE(ST, RS_DT_RSMatrix4x4); break; 1064 default: slangAssert(false && "Matrix type with unsupported dimension."); 1065 } 1066 return ST.take(); 1067} 1068 1069bool RSExportMatrixType::equals(const RSExportable *E) const { 1070 CHECK_PARENT_EQUALITY(RSExportType, E); 1071 return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim()); 1072} 1073 1074/************************* RSExportConstantArrayType *************************/ 1075RSExportConstantArrayType 1076*RSExportConstantArrayType::Create(RSContext *Context, 1077 const clang::ConstantArrayType *CAT) { 1078 slangAssert(CAT != NULL && CAT->getTypeClass() == clang::Type::ConstantArray); 1079 1080 slangAssert((CAT->getSize().getActiveBits() < 32) && "array too large"); 1081 1082 unsigned Size = static_cast<unsigned>(CAT->getSize().getZExtValue()); 1083 slangAssert((Size > 0) && "Constant array should have size greater than 0"); 1084 1085 const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(CAT); 1086 RSExportType *ElementET = RSExportType::Create(Context, ElementType); 1087 1088 if (ElementET == NULL) { 1089 return NULL; 1090 } 1091 1092 return new RSExportConstantArrayType(Context, 1093 ElementET, 1094 Size); 1095} 1096 1097const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const { 1098 return llvm::ArrayType::get(mElementType->getLLVMType(), getSize()); 1099} 1100 1101union RSType *RSExportConstantArrayType::convertToSpecType() const { 1102 llvm::OwningPtr<union RSType> ST(new union RSType); 1103 1104 RS_TYPE_SET_CLASS(ST, RS_TC_ConstantArray); 1105 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_TYPE( 1106 ST, getElementType()->getSpecType()); 1107 RS_CONSTANT_ARRAY_TYPE_SET_ELEMENT_SIZE(ST, getSize()); 1108 1109 if (RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(ST) != NULL) 1110 return ST.take(); 1111 else 1112 return NULL; 1113} 1114 1115bool RSExportConstantArrayType::keep() { 1116 if (!RSExportType::keep()) 1117 return false; 1118 const_cast<RSExportType*>(mElementType)->keep(); 1119 return true; 1120} 1121 1122bool RSExportConstantArrayType::equals(const RSExportable *E) const { 1123 CHECK_PARENT_EQUALITY(RSExportType, E); 1124 const RSExportConstantArrayType *RHS = 1125 static_cast<const RSExportConstantArrayType*>(E); 1126 return ((getSize() == RHS->getSize()) && 1127 (getElementType()->equals(RHS->getElementType()))); 1128} 1129 1130/**************************** RSExportRecordType ****************************/ 1131RSExportRecordType *RSExportRecordType::Create(RSContext *Context, 1132 const clang::RecordType *RT, 1133 const llvm::StringRef &TypeName, 1134 bool mIsArtificial) { 1135 slangAssert(RT != NULL && RT->getTypeClass() == clang::Type::Record); 1136 1137 const clang::RecordDecl *RD = RT->getDecl(); 1138 slangAssert(RD->isStruct()); 1139 1140 RD = RD->getDefinition(); 1141 if (RD == NULL) { 1142 slangAssert(false && "struct is not defined in this module"); 1143 return NULL; 1144 } 1145 1146 // Struct layout construct by clang. We rely on this for obtaining the 1147 // alloc size of a struct and offset of every field in that struct. 1148 const clang::ASTRecordLayout *RL = 1149 &Context->getASTContext().getASTRecordLayout(RD); 1150 slangAssert((RL != NULL) && 1151 "Failed to retrieve the struct layout from Clang."); 1152 1153 RSExportRecordType *ERT = 1154 new RSExportRecordType(Context, 1155 TypeName, 1156 RD->hasAttr<clang::PackedAttr>(), 1157 mIsArtificial, 1158 RL->getSize().getQuantity()); 1159 unsigned int Index = 0; 1160 1161 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1162 FE = RD->field_end(); 1163 FI != FE; 1164 FI++, Index++) { 1165 clang::Diagnostic *Diags = Context->getDiagnostics(); 1166 const clang::SourceManager *SM = Context->getSourceManager(); 1167 1168 // FIXME: All fields should be primitive type 1169 slangAssert((*FI)->getKind() == clang::Decl::Field); 1170 clang::FieldDecl *FD = *FI; 1171 1172 if (FD->isBitField()) { 1173 delete ERT; 1174 return NULL; 1175 } 1176 1177 // Type 1178 RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD); 1179 1180 if (ET != NULL) { 1181 ERT->mFields.push_back( 1182 new Field(ET, FD->getName(), ERT, 1183 static_cast<size_t>(RL->getFieldOffset(Index) >> 3))); 1184 } else { 1185 Diags->Report(clang::FullSourceLoc(RD->getLocation(), *SM), 1186 Diags->getCustomDiagID(clang::Diagnostic::Error, 1187 "field type cannot be exported: '%0.%1'")) 1188 << RD->getName() 1189 << FD->getName(); 1190 delete ERT; 1191 return NULL; 1192 } 1193 } 1194 1195 return ERT; 1196} 1197 1198const llvm::Type *RSExportRecordType::convertToLLVMType() const { 1199 // Create an opaque type since struct may reference itself recursively. 1200 llvm::PATypeHolder ResultHolder = 1201 llvm::OpaqueType::get(getRSContext()->getLLVMContext()); 1202 setAbstractLLVMType(ResultHolder.get()); 1203 1204 std::vector<const llvm::Type*> FieldTypes; 1205 1206 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1207 FI != FE; 1208 FI++) { 1209 const Field *F = *FI; 1210 const RSExportType *FET = F->getType(); 1211 1212 FieldTypes.push_back(FET->getLLVMType()); 1213 } 1214 1215 llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(), 1216 FieldTypes, 1217 mIsPacked); 1218 if (ST != NULL) 1219 static_cast<llvm::OpaqueType*>(ResultHolder.get()) 1220 ->refineAbstractTypeTo(ST); 1221 else 1222 return NULL; 1223 return ResultHolder.get(); 1224} 1225 1226union RSType *RSExportRecordType::convertToSpecType() const { 1227 unsigned NumFields = getFields().size(); 1228 unsigned AllocSize = sizeof(union RSType) + 1229 sizeof(struct RSRecordField) * NumFields; 1230 llvm::OwningPtr<union RSType> ST( 1231 reinterpret_cast<union RSType*>(operator new(AllocSize))); 1232 1233 ::memset(ST.get(), 0, AllocSize); 1234 1235 RS_TYPE_SET_CLASS(ST, RS_TC_Record); 1236 RS_RECORD_TYPE_SET_NAME(ST, getName().c_str()); 1237 RS_RECORD_TYPE_SET_NUM_FIELDS(ST, NumFields); 1238 1239 setSpecTypeTemporarily(ST.get()); 1240 1241 unsigned FieldIdx = 0; 1242 for (const_field_iterator FI = fields_begin(), FE = fields_end(); 1243 FI != FE; 1244 FI++, FieldIdx++) { 1245 const Field *F = *FI; 1246 1247 RS_RECORD_TYPE_SET_FIELD_NAME(ST, FieldIdx, F->getName().c_str()); 1248 RS_RECORD_TYPE_SET_FIELD_TYPE(ST, FieldIdx, F->getType()->getSpecType()); 1249 1250 enum RSDataKind DK = RS_DK_User; 1251 if ((F->getType()->getClass() == ExportClassPrimitive) || 1252 (F->getType()->getClass() == ExportClassVector)) { 1253 const RSExportPrimitiveType *EPT = 1254 static_cast<const RSExportPrimitiveType*>(F->getType()); 1255 // enum RSExportPrimitiveType::DataKind is synced with enum RSDataKind in 1256 // slang_rs_type_spec.h 1257 DK = static_cast<enum RSDataKind>(EPT->getKind()); 1258 } 1259 RS_RECORD_TYPE_SET_FIELD_DATA_KIND(ST, FieldIdx, DK); 1260 } 1261 1262 // TODO(slang): Check whether all fields were created normally. 1263 1264 return ST.take(); 1265} 1266 1267bool RSExportRecordType::keep() { 1268 if (!RSExportType::keep()) 1269 return false; 1270 for (std::list<const Field*>::iterator I = mFields.begin(), 1271 E = mFields.end(); 1272 I != E; 1273 I++) { 1274 const_cast<RSExportType*>((*I)->getType())->keep(); 1275 } 1276 return true; 1277} 1278 1279bool RSExportRecordType::equals(const RSExportable *E) const { 1280 CHECK_PARENT_EQUALITY(RSExportType, E); 1281 1282 const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E); 1283 1284 if (ERT->getFields().size() != getFields().size()) 1285 return false; 1286 1287 const_field_iterator AI = fields_begin(), BI = ERT->fields_begin(); 1288 1289 for (unsigned i = 0, e = getFields().size(); i != e; i++) { 1290 if (!(*AI)->getType()->equals((*BI)->getType())) 1291 return false; 1292 AI++; 1293 BI++; 1294 } 1295 1296 return true; 1297} 1298 1299} // namespace slang 1300