1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.semantic.Types; 5 6 import dil.semantic.Symbol, 7 dil.semantic.TypesEnum; 8 import dil.lexer.Identifier, 9 dil.lexer.IdTable, 10 dil.lexer.TokensEnum; 11 import dil.Enums, 12 dil.String; 13 import common; 14 15 /// The base type for all type structures. 16 abstract class Type/* : Symbol*/ 17 { 18 Type next; /// The next type in the type structure. 19 TYP tid; /// The ID of the type. 20 Symbol symbol; /// Not null if this type has a symbol. 21 cstring mangled; /// The mangled identifier of the type. 22 23 this(){} 24 25 /// Constructs a Type object. 26 /// Params: 27 /// next = The type's next type. 28 /// tid = The type's ID. 29 this(Type next, TYP tid) 30 { 31 // this.sid = SYM.Type; 32 33 this.next = next; 34 this.tid = tid; 35 } 36 37 /// Casts the type to Class. 38 Class to(Class)() 39 { 40 static if (Class.stringof == "TypeBasic") 41 assert(this.isBasic()); 42 else // [4..$] is there for slicing off "Type" from the class name. 43 assert(this.tid == mixin("TYP." ~ Class.stringof[4..$])); 44 return cast(Class)cast(void*)this; 45 } 46 47 /// Returns the mangled TypeInfo identifier for this type. 48 /// Params: 49 /// idtable = Inserts the returned id into this table. 50 final Identifier* mangledTypeInfoIdent(IdTable idtable) 51 { 52 auto m = toMangle(); 53 m = "_D" ~ itoa(m.length+9) ~ "TypeInfo_" ~ m ~ "6__initZ"; 54 return idtable.lookup(m); 55 } 56 57 /// Returns the base type if this is an enum or typedef, or itself otherwise. 58 Type baseType() 59 { 60 auto t = this; 61 for (; t.hasBaseType(); t = t.next) 62 assert(t !is null); 63 return t; 64 } 65 66 /// Returns true if this type has a base type (enum or typedef.) 67 final bool hasBaseType() 68 { 69 return tid == TYP.Enum || tid == TYP.Typedef; 70 } 71 72 alias opEquals = super.opEquals; 73 74 /// Returns true if this type equals the other one. 75 bool opEquals(Type other) 76 { 77 if (this.next is null && other.next is null) 78 return this.tid == other.tid; 79 // TODO: 80 return false; 81 } 82 83 /// Returns a pointer type to this type. 84 TypePointer ptrTo() 85 { 86 return new TypePointer(this); 87 } 88 89 /// Returns a dynamic array type using this type as its base. 90 TypeDArray arrayOf() 91 { 92 return new TypeDArray(this); 93 } 94 95 /// Returns an associative array type using this type as its base. 96 /// Params: 97 /// key = The key type. 98 TypeAArray arrayOf(Type key) 99 { 100 return new TypeAArray(this, key); 101 } 102 103 /// Returns a static array type using this type as its base. 104 /// Params: 105 /// size = The number of elements in the array. 106 TypeSArray arrayOf(size_t size) 107 { 108 return new TypeSArray(this, size); 109 } 110 111 /// Returns the byte size of this type. 112 /// Returns 0 if it could not be determined. 113 /// Params: 114 /// tti = Contains target-dependent info. 115 size_t sizeOf(TargetTInfo tti = null) 116 { 117 return MITable.getSize(this); 118 } 119 120 /// Returns the align size of this type. 121 /// Returns 0 if it could not be determined. 122 /// Params: 123 /// tti = Contains target-dependent info. 124 size_t alignSizeOf(TargetTInfo tti = null) 125 { 126 return MITable.getAlignSize(this); 127 } 128 129 /// Returns the flags of this type. 130 TypeFlags flagsOf() 131 { 132 return MITable.getFlags(this); 133 } 134 135 /// Returns true if this type has a boolean value. 136 final bool hasBoolVal() 137 { 138 return flagsOf().isBoolVal(); 139 } 140 141 /// Returns true if this type is initialized with zero(s). 142 final bool isZeroInit() 143 { 144 return flagsOf().isZeroInit(); 145 } 146 147 /// Returns true if this type has a symbol. 148 final bool hasSymbol() 149 { 150 return symbol !is null; 151 } 152 153 /// Returns the type as a human-readable string. 154 abstract cstring toText(); 155 156 /// Returns true if error type. 157 final bool isError() 158 { 159 return tid == TYP.Error; 160 } 161 162 /// Returns true if dynamic array type. 163 final bool isDArray() 164 { 165 return tid == TYP.DArray; 166 } 167 168 /// Returns true if static array type. 169 final bool isSArray() 170 { 171 return tid == TYP.SArray; 172 } 173 174 /// Returns true if associative array type. 175 final bool isAArray() 176 { 177 return tid == TYP.AArray; 178 } 179 180 /// Returns true if parameter type. 181 final bool isParameter() 182 { 183 return tid == TYP.Parameter; 184 } 185 186 /// Returns true if parameters type. 187 final bool isParameters() 188 { 189 return tid == TYP.Parameters; 190 } 191 192 /// Returns true if enum type. 193 final bool isEnum() 194 { 195 return tid == TYP.Enum; 196 } 197 198 /// Returns true if struct type. 199 final bool isStruct() 200 { 201 return tid == TYP.Struct; 202 } 203 204 /// Returns true if class type. 205 final bool isClass() 206 { 207 return tid == TYP.Struct; 208 } 209 210 /// Returns true if typedef type. 211 final bool isTypedef() 212 { 213 return tid == TYP.Typedef; 214 } 215 216 /// Returns true if function type. 217 final bool isFunction() 218 { 219 return tid == TYP.Function; 220 } 221 222 /// Returns true if Delegate type. 223 final bool isDelegate() 224 { 225 return tid == TYP.Delegate; 226 } 227 228 /// Returns true if pointer type. 229 final bool isPointer() 230 { 231 return tid == TYP.Pointer; 232 } 233 234 /// Returns true if reference type. 235 final bool isReference() 236 { 237 return tid == TYP.Reference; 238 } 239 240 /// Returns true if identifier type. 241 final bool isIdentifier() 242 { 243 return tid == TYP.Identifier; 244 } 245 246 /// Returns true if template instance type. 247 final bool isTInstance() 248 { 249 return tid == TYP.TInstance; 250 } 251 252 /// Returns true if tuple type. 253 final bool isTuple() 254 { 255 return tid == TYP.Tuple; 256 } 257 258 /// Returns true if const type. D2. 259 final bool isConst() 260 { 261 return tid == TYP.Const; 262 } 263 264 /// Returns true if immutable type. D2. 265 final bool isImmutable() 266 { 267 return tid == TYP.Immutable; 268 } 269 270 /// Returns true if dynamic or static array type. 271 final bool isDorSArray() 272 { 273 return tid == TYP.DArray || tid == TYP.SArray; 274 } 275 276 /// Returns true if bool type. 277 final bool isBool() 278 { 279 return tid == TYP.Bool; 280 } 281 282 /// Like isBool(). Also checks base types of typedef/enum. 283 final bool isBaseBool() 284 { 285 if (hasBaseType()) 286 return next.isBool(); // Check base type. 287 return isBool(); 288 } 289 290 /// Returns true if the type is signed. 291 final bool isSigned() 292 { 293 return MITable.getFlags(this).isSigned(); 294 } 295 296 /// Returns true if the type is unsigned. 297 final bool isUnsigned() 298 { 299 return MITable.getFlags(this).isUnsigned(); 300 } 301 302 /// Returns true if this is a basic type. 303 final bool isBasic() 304 { 305 return MITable.getFlags(this).isBasic(); 306 } 307 308 /// Returns true if this type is an integral number type. 309 final bool isIntegral() 310 { 311 return MITable.getFlags(this).isIntegral(); 312 } 313 314 /// Returns true if this type is a floating point number type. 315 final bool isFloating() 316 { 317 return MITable.getFlags(this).isFloating(); 318 } 319 320 /// Like isFloating(). Also checks base types of typedef/enum. 321 final bool isBaseFloating() 322 { 323 if (tid == TYP.Enum) 324 return false; // Base type of enum can't be floating. 325 if (tid == TYP.Typedef) 326 return next.isBaseFloating(); 327 return isFloating(); 328 } 329 330 /// Returns true if this type is a real number type. 331 final bool isReal() 332 { 333 return MITable.getFlags(this).isReal(); 334 } 335 336 /// Like isReal(). Also checks base types of typedef/enum. 337 final bool isBaseReal() 338 { 339 if (tid == TYP.Enum) 340 return false; // Base type of enum can't be real. 341 if (tid == TYP.Typedef) 342 return next.isBaseReal(); 343 return isReal(); 344 } 345 346 /// Returns true if this type is an imaginary number type. 347 final bool isImaginary() 348 { 349 return MITable.getFlags(this).isImaginary(); 350 } 351 352 /// Like isImaginary(). Also checks base types of typedef/enum. 353 final bool isBaseImaginary() 354 { 355 if (tid == TYP.Enum) 356 return false; // Base type of enum can't be imaginary. 357 if (tid == TYP.Typedef) 358 return next.isBaseImaginary(); 359 return isImaginary(); 360 } 361 362 /// Returns true if this type is a complex number type. 363 final bool isComplex() 364 { 365 return MITable.getFlags(this).isComplex(); 366 } 367 368 /// Like isComplex(). Also checks base types of typedef/enum. 369 final bool isBaseComplex() 370 { 371 if (tid == TYP.Enum) 372 return false; // Base type of enum can't be complex. 373 if (tid == TYP.Typedef) 374 return next.isBaseComplex(); 375 return isComplex(); 376 } 377 378 /// Returns true for scalar types. 379 final bool isScalar() 380 { 381 return MITable.getFlags(this).isScalar(); 382 } 383 384 /// Like isScalar(). Also checks base types of typedef/enum. 385 final bool isBaseScalar() 386 { 387 if (tid == TYP.Enum) 388 return true; // Base type of enum can only be scalar. 389 if (tid == TYP.Typedef) 390 return next.isScalar(); // Check base type. 391 return isScalar(); 392 } 393 394 /// Returns the mangle character for this type. 395 final char mangleChar() 396 { 397 return MITable.mangleChar(this); 398 } 399 400 /// Returns the mangled name of this type. 401 cstring toMangle() 402 { 403 if (mangled.length) 404 return mangled; 405 char[] m; 406 m ~= mangleChar(); 407 if (next) 408 m ~= next.toMangle(); 409 return m; 410 } 411 } 412 413 /// The error type. 414 class TypeError : Type 415 { 416 this() 417 { 418 super(null, TYP.Error); 419 } 420 421 override: 422 cstring toText() 423 { 424 return "{TypeError}"; 425 } 426 427 cstring toMangle() 428 { 429 return "{TypeError}"; 430 } 431 } 432 433 /// All basic types. E.g.: int, char, real etc. 434 class TypeBasic : Type 435 { 436 Identifier* ident; /// Keyword identifier. 437 438 this(Identifier* ident, TYP typ) 439 { 440 super(null, typ); 441 this.ident = ident; 442 } 443 444 override: 445 size_t alignSizeOf(TargetTInfo tti) 446 { // TODO: 447 return 0; 448 } 449 450 cstring toText() 451 { 452 return ident.str; 453 } 454 } 455 456 /// Dynamic array type. 457 class TypeDArray : Type 458 { 459 this(Type next) 460 { 461 super(next, TYP.DArray); 462 } 463 464 override: 465 size_t sizeOf(TargetTInfo tti) 466 { 467 return tti.ptrSize * 2; 468 } 469 470 size_t alignSizeOf(TargetTInfo tti) 471 { 472 return tti.ptrSize; 473 } 474 475 cstring toText() 476 { 477 return next.toText() ~ "[]"; 478 } 479 } 480 481 /// Associative array type. 482 class TypeAArray : Type 483 { 484 Type keyType; 485 this(Type next, Type keyType) 486 { 487 super(next, TYP.AArray); 488 this.keyType = keyType; 489 } 490 491 override: 492 size_t sizeOf(TargetTInfo tti) 493 { 494 return tti.ptrSize * 2; 495 } 496 497 cstring toText() 498 { 499 return next.toText() ~ "[" ~ keyType.toText() ~ "]"; 500 } 501 502 cstring toMangle() 503 { 504 if (mangled.length) 505 return mangled; 506 return mangleChar() ~ keyType.toMangle() ~ next.toMangle(); 507 } 508 } 509 510 /// Static array type. 511 class TypeSArray : Type 512 { 513 size_t dimension; 514 this(Type next, size_t dimension) 515 { 516 super(next, TYP.SArray); 517 this.dimension = dimension; 518 } 519 520 override: 521 size_t sizeOf(TargetTInfo tti) 522 { 523 return tti.ptrSize * 2; 524 } 525 526 size_t alignSizeOf(TargetTInfo tti) 527 { 528 return next.alignSizeOf(tti); 529 } 530 531 TypeFlags flagsOf() 532 { // TODO: 533 auto tf = next.flagsOf(); 534 //if (symbol.isZeroInit()) 535 //tf |= TypeFlags.ZeroInit; 536 return tf; 537 } 538 539 cstring toText() 540 { 541 return next.toText() ~ "[" ~ itoa(dimension) ~ "]"; 542 } 543 544 cstring toMangle() 545 { 546 if (mangled.length) 547 return mangled; 548 return mangleChar() ~ itoa(dimension) ~ next.toMangle(); 549 } 550 } 551 552 /// Pointer type. 553 class TypePointer : Type 554 { 555 this(Type next) 556 { 557 super(next, TYP.Pointer); 558 } 559 560 override: 561 size_t sizeOf(TargetTInfo tti) 562 { 563 return tti.ptrSize; 564 } 565 566 cstring toText() 567 { 568 return next.toText() ~ "*"; 569 } 570 } 571 572 /// Reference type. 573 class TypeReference : Type 574 { 575 this(Type next) 576 { 577 super(next, TYP.Reference); 578 } 579 580 override: 581 size_t sizeOf(TargetTInfo tti) 582 { 583 return tti.ptrSize; 584 } 585 586 cstring toText() 587 { // FIXME: this is probably wrong. 588 return next.toText() ~ "&"; 589 } 590 } 591 592 /// Enum type. 593 class TypeEnum : Type 594 { 595 this(Symbol symbol) 596 { 597 // FIXME: pass int as the base type for the time being. 598 // Use Types.DontKnowYet instead? 599 super(Types.Int32, TYP.Enum); 600 this.symbol = symbol; 601 } 602 603 /// Setter for the base type. 604 void baseType(Type type) 605 { 606 next = type; 607 } 608 609 override: 610 size_t sizeOf(TargetTInfo tti) 611 { // TODO: 612 return 0; 613 } 614 615 size_t alignSizeOf(TargetTInfo tti) 616 { 617 return next.sizeOf(tti); 618 } 619 620 TypeFlags flagsOf() 621 { // TODO: 622 auto tf = next.flagsOf(); 623 //if (symbol.isZeroInit()) 624 //tf |= TypeFlags.ZeroInit; 625 return tf; 626 } 627 628 cstring toText() 629 { 630 return symbol.name.str; 631 } 632 633 cstring toMangle() 634 { 635 if (mangled.length) 636 return mangled; 637 return mangleChar() ~ symbol.toMangle(); 638 } 639 } 640 641 /// Struct type. 642 class TypeStruct : Type 643 { 644 this(Symbol symbol) 645 { 646 super(null, TYP.Struct); 647 this.symbol = symbol; 648 } 649 650 override: 651 size_t sizeOf(TargetTInfo tti) 652 { // TODO: 653 return 0; 654 } 655 656 size_t alignSizeOf(TargetTInfo tti) 657 { // TODO: 658 return 0; 659 } 660 661 cstring toText() 662 { 663 return symbol.name.str; 664 } 665 666 cstring toMangle() 667 { 668 if (mangled.length) 669 return mangled; 670 return mangleChar() ~ symbol.toMangle(); 671 } 672 } 673 674 /// Class type. 675 class TypeClass : Type 676 { 677 this(Symbol symbol) 678 { 679 super(null, TYP.Class); 680 this.symbol = symbol; 681 } 682 683 override: 684 size_t sizeOf(TargetTInfo tti) 685 { 686 return tti.ptrSize; 687 } 688 689 cstring toText() 690 { 691 return symbol.name.str; 692 } 693 694 cstring toMangle() 695 { 696 if (mangled.length) 697 return mangled; 698 return mangleChar() ~ symbol.toMangle(); 699 } 700 } 701 702 /// Typedef type. 703 class TypeTypedef : Type 704 { 705 this(Type next) 706 { 707 super(next, TYP.Typedef); 708 } 709 710 override: 711 size_t sizeOf(TargetTInfo tti) 712 { 713 return next.sizeOf(tti); 714 } 715 716 size_t alignSizeOf(TargetTInfo tti) 717 { 718 return next.alignSizeOf(tti); 719 } 720 721 TypeFlags flagsOf() 722 { // TODO: 723 auto tf = next.flagsOf(); 724 //if (symbol.isZeroInit()) 725 //tf |= TypeFlags.ZeroInit; 726 return tf; 727 } 728 729 cstring toText() 730 { 731 return next.toText(); 732 } 733 734 cstring toMangle() 735 { 736 if (mangled.length) 737 return mangled; 738 return mangleChar() ~ symbol.toMangle(); 739 } 740 } 741 742 /// Parameter type. 743 class TypeParameter : Type 744 { 745 alias type = next; /// Parameter's type. 746 StorageClass stcs; /// Storage classes. 747 VariadicStyle variadic; /// Variadic style. 748 // TODO: add these? 749 // They have no relevance for mangling, 750 // because they don't affect the function signature, 751 // and they will be null after a Type.merge(). 752 // Identifier* name; 753 // Node defValue; 754 755 this(Type type, StorageClass stcs, VariadicStyle variadic=VariadicStyle.None) 756 { 757 super(type, TYP.Parameter); 758 this.stcs = stcs; 759 this.variadic = variadic; 760 } 761 762 /// NB: the parameter's name and the optional default value are not printed. 763 override: 764 cstring toText() 765 { // := StorageClasses? ParamType? "..."? 766 char[] s; 767 // TODO: exclude STC.In? 768 foreach (stc; EnumString.all(stcs/+ & ~StorageClass.In+/)) 769 s ~= stc ~ " "; 770 if (type) 771 s ~= type.toText(); 772 else if (variadic) 773 s ~= "..."; 774 assert(s.length, "empty parameter?"); 775 return s; 776 } 777 778 cstring toMangle() 779 { // := StorageClassMangleChar TypeMangle 780 if (mangled.length) 781 return mangled; 782 // 1. Mangle storage class. 783 char[] m; 784 char mc = 0; 785 // TODO: D2 can have more than one stc. What to do? 786 if (stcs & StorageClass.Out) 787 mc = 'J'; 788 //else if (stcs & StorageClass.In) 789 //mc = 0; 790 else if (stcs & StorageClass.Ref) 791 mc = 'K'; 792 else if (stcs & StorageClass.Lazy) 793 mc = 'L'; 794 if (mc) 795 m ~= mc; 796 // 2. Mangle parameter type. 797 if (type) 798 m ~= type.toMangle(); 799 else 800 assert(variadic == VariadicStyle.C); 801 return m; 802 } 803 } 804 805 /// A list of TypeParameter objects. 806 class TypeParameters : Type 807 { 808 TypeParameter[] params; /// The parameters. 809 810 this(TypeParameter[] params) 811 { 812 super(null, TYP.Parameters); 813 this.params = params; 814 } 815 816 /// Returns the variadic style of the last parameter. 817 VariadicStyle getVariadic() 818 { 819 return params.length ? params[$-1].variadic : VariadicStyle.None; 820 } 821 822 override: 823 cstring toText() 824 { // := "(" ParameterList ")" 825 char[] s; 826 s ~= "("; 827 foreach (i, p; params) { 828 if (i) s ~= ", "; // Append comma if more than one param. 829 s ~= p.toText(); 830 } 831 s ~= ")"; 832 return s; 833 } 834 835 cstring toMangle() 836 { 837 if (mangled.length) 838 return mangled; 839 char[] m; 840 foreach (p; params) 841 m ~= p.toMangle(); 842 return m; 843 } 844 } 845 846 /// A function type. 847 class TypeFunction : Type 848 { 849 alias retType = next; 850 TypeParameters params; /// The parameter list. 851 StorageClass stcs; /// The storage classes. 852 LinkageType linkage; /// The linkage type. 853 VariadicStyle variadic; /// Variadic style. 854 855 this(Type retType, TypeParameters params, StorageClass stcs, LinkageType linkage) 856 { 857 super(retType, TYP.Function); 858 this.params = params; 859 this.stcs = stcs; 860 this.linkage = linkage; 861 this.variadic = params.getVariadic(); 862 } 863 864 override cstring toText() 865 { // := ReturnType ParameterList 866 return retType.toText() ~ params.toText(); 867 } 868 869 override cstring toMangle() 870 { // := MangleChar LinkageChar ParamsMangle ReturnChar ReturnTypeMangle 871 if (mangled.length) 872 return mangled; 873 char[] m; 874 char mc = void; 875 version(D2) 876 m ~= modsToMangle(); 877 switch (linkage) 878 { 879 case LinkageType.C: mc = 'U'; break; 880 case LinkageType.D: mc = 'F'; break; 881 case LinkageType.Cpp: mc = 'R'; break; 882 case LinkageType.Windows: mc = 'W'; break; 883 case LinkageType.Pascal: mc = 'V'; break; 884 default: assert(0); 885 } 886 m ~= mc; 887 version(D2) 888 m ~= attrsToMangle(); 889 m ~= params.toMangle(); 890 mc = cast(char)('Z' - variadic); 891 assert(mc == 'X' || mc == 'Y' || mc == 'Z'); 892 m ~= mc; // Marks end of parameter list. 893 m ~= retType.toMangle(); 894 return m; 895 } 896 897 version(D2) 898 { 899 /// Mangles the modifiers of this function. 900 cstring modsToMangle() 901 out(m) { assert(m in ["O"[]:1, "Ox":1, "ONg":1, "x":1, "y":1, "Ng":1]); } 902 body 903 { 904 char[] m; 905 if (stcs & StorageClass.Shared) 906 m ~= "O"; 907 if (stcs & StorageClass.Const) 908 m ~= "x"; 909 if (stcs & StorageClass.Immutable) 910 m ~= "y"; 911 if (stcs & StorageClass.Inout) 912 m ~= "Ng"; 913 return m; 914 } 915 916 /// Mangles the attributes of this function. 917 cstring attrsToMangle() 918 { 919 char[] m; 920 if (stcs & StorageClass.Pure) 921 m ~= "Na"; 922 if (stcs & StorageClass.Nothrow) 923 m ~= "Nb"; 924 if (stcs & StorageClass.Ref) 925 m ~= "Nc"; 926 if (stcs & StorageClass.Property) 927 m ~= "Nd"; 928 if (stcs & StorageClass.Trusted) 929 m ~= "Ne"; 930 if (stcs & StorageClass.Safe) 931 m ~= "Nf"; 932 return m; 933 } 934 } // version(D2) 935 } 936 937 /// Pointer to function type. 938 class TypeFuncPtr : Type 939 { 940 this(TypeFunction func) 941 { 942 super(func, TYP.FuncPtr); 943 } 944 945 TypeFunction funcType() 946 { 947 return next.to!(TypeFunction); 948 } 949 950 override: 951 size_t sizeOf(TargetTInfo tti) 952 { 953 return tti.ptrSize; 954 } 955 956 cstring toText() 957 { 958 auto f = funcType(); 959 return f.retType.toText() ~ " function" ~ f.params.toText(); 960 } 961 962 cstring toMangle() 963 { 964 return mangleChar() ~ next.toMangle(); 965 } 966 } 967 968 /// Delegate type. 969 class TypeDelegate : Type 970 { 971 this(TypeFunction func) 972 { 973 super(func, TYP.Delegate); 974 } 975 976 TypeFunction funcType() 977 { 978 return next.to!(TypeFunction); 979 } 980 981 override: 982 size_t sizeOf(TargetTInfo tti) 983 { 984 return tti.ptrSize * 2; 985 } 986 987 size_t alignSizeOf(TargetTInfo tti) 988 { 989 return tti.ptrSize; 990 } 991 992 cstring toText() 993 { 994 auto f = funcType(); 995 return f.retType.toText() ~ " delegate" ~ f.params.toText(); 996 } 997 998 cstring toMangle() 999 { 1000 return mangleChar() ~ next.toMangle(); 1001 } 1002 } 1003 1004 /// Identifier type. 1005 class TypeIdentifier : Type 1006 { 1007 Identifier* ident; 1008 this(Identifier* ident) 1009 { 1010 super(null, TYP.Identifier); 1011 } 1012 1013 override: 1014 size_t sizeOf(TargetTInfo tti) 1015 { // TODO: 1016 return 0; 1017 } 1018 1019 cstring toText() 1020 { 1021 return ident.str; 1022 } 1023 1024 cstring toMangle() 1025 { // := MangleChar IDLength ID 1026 if (mangled.length) 1027 return mangled; 1028 auto id = ident.str; 1029 return mangleChar() ~ itoa(id.length) ~ id; 1030 } 1031 } 1032 1033 /// Template instantiation type. 1034 class TypeTemplInstance : Type 1035 { 1036 this() 1037 { 1038 super(null, TYP.TInstance); 1039 } 1040 1041 override: 1042 size_t sizeOf(TargetTInfo tti) 1043 { // TODO: 1044 return 0; 1045 } 1046 1047 cstring toText() 1048 { // TODO: 1049 return "tpl!()"; 1050 } 1051 } 1052 1053 /// Template tuple type. 1054 class TypeTuple : Type 1055 { 1056 Type[] types; /// The types inside this tuple. 1057 1058 this(Type[] types) 1059 { 1060 super(null, TYP.Tuple); 1061 this.types = types; 1062 } 1063 1064 override: 1065 size_t sizeOf(TargetTInfo tti) 1066 { // TODO: 1067 return 0; 1068 } 1069 1070 cstring toText() 1071 { // := "(" TypeList ")" 1072 char[] s; 1073 s ~= "("; 1074 foreach (i, t; types) { 1075 if (i) s ~= ", "; // Append comma if more than one type. 1076 s ~= t.toText(); 1077 } 1078 s ~= ")"; 1079 return s; 1080 } 1081 1082 cstring toMangle() 1083 { // := MangleChar TypesMangleLength TypesMangle 1084 if (mangled.length) 1085 return mangled; 1086 char[] tm; 1087 foreach (t; types) 1088 tm ~= t.toMangle(); 1089 return mangleChar() ~ itoa(tm.length) ~ tm; 1090 } 1091 } 1092 1093 /// Constant type. D2.0 1094 class TypeConst : Type 1095 { 1096 this(Type next) 1097 { 1098 super(next, TYP.Const); 1099 } 1100 1101 override: 1102 size_t sizeOf(TargetTInfo tti) 1103 { 1104 return next.sizeOf(tti); 1105 } 1106 1107 cstring toText() 1108 { 1109 return "const(" ~ next.toText() ~ ")"; 1110 } 1111 } 1112 1113 /// Immutable type. D2.0 1114 class TypeImmutable : Type 1115 { 1116 this(Type next) 1117 { 1118 super(next, TYP.Immutable); 1119 } 1120 1121 override: 1122 size_t sizeOf(TargetTInfo tti) 1123 { 1124 return next.sizeOf(tti); 1125 } 1126 1127 cstring toText() 1128 { 1129 return "immutable(" ~ next.toText() ~ ")"; 1130 } 1131 } 1132 1133 /// Maps mangled type identifiers to Type objects. 1134 class TypeTable 1135 { 1136 Type[hash_t] table; /// The table data structure. 1137 1138 /// Looks up a type by its mangled id. 1139 /// Returns: the symbol if there, otherwise null. 1140 Type lookup(cstring mangled) 1141 { 1142 assert(mangled.length); 1143 return lookup(hashOf(mangled)); 1144 } 1145 1146 /// Looks up a type by the hash of its mangled id. 1147 Type lookup(hash_t hash) 1148 { 1149 auto ptype = hash in table; 1150 return ptype ? *ptype : null; 1151 } 1152 1153 /// Inserts a type into the table. 1154 void insert(Type type) 1155 { 1156 assert(type.mangled.length); 1157 insert(type, hashOf(type.mangled)); 1158 } 1159 1160 /// Inserts a type into the table by its hash. 1161 void insert(Type type, hash_t hash) 1162 { 1163 assert(type.mangled.length && hash == hashOf(type.mangled)); 1164 table[hash] = type; 1165 } 1166 1167 /// Returns the unique version of a type 1168 /// by looking up its mangled name. 1169 /// The subtypes in the type chain are visited as well. 1170 /// The type is inserted into the table if not present. 1171 Type unique(Type t) 1172 { 1173 if (t.next) // Follow the type chain. 1174 t.next = unique(t.next); 1175 return unique2(t); 1176 } 1177 1178 /// Same as unique(Type) but doesn't follow the type chain. 1179 Type unique2(Type t) 1180 { // Get the mangled string and look it up. 1181 if (!t.mangled.length) 1182 t.mangled = t.toMangle(); 1183 auto m_hash = hashOf(t.mangled); // Only calculate once. 1184 if (auto t_intable = lookup(m_hash)) 1185 t = t_intable; // Found. 1186 else // Insert new type. 1187 insert(t, m_hash); 1188 return t; 1189 } 1190 1191 // TODO: change bool[string] to a different structure if necessary. 1192 /// Initializes the table and 1193 /// takes the target machine's properties into account. 1194 void init(bool[cstring] args) 1195 { 1196 synchronized Types.init(); 1197 1198 if("is64" in args) // Generate code for 64bit? 1199 { 1200 Size_t = Types.UInt64; 1201 Ptrdiff_t = Types.Int64; 1202 } 1203 else 1204 { 1205 Size_t = Types.UInt32; 1206 Ptrdiff_t = Types.Int32; 1207 } 1208 PtrSize = Ptrdiff_t.sizeOf(); 1209 1210 tti = new TargetTInfo; 1211 tti.ptrSize = PtrSize; 1212 tti.is64 = !!("is64" in args); 1213 } 1214 1215 TargetTInfo tti; /// An instance used to calculate type sizes. 1216 1217 TypeBasic Size_t; /// The size type. 1218 TypeBasic Ptrdiff_t; /// The pointer difference type. 1219 1220 size_t PtrSize; /// The size of a pointer (dependent on the architecture.) 1221 1222 /// Returns the byte size of t. 1223 size_t sizeOf(Type t) 1224 { 1225 return t.sizeOf(tti); 1226 } 1227 1228 /// Returns the align size of t. 1229 size_t alignOf(Type t) 1230 { 1231 return t.alignSizeOf(tti); 1232 } 1233 } 1234 1235 /// Represents a value related to a Type. 1236 union Value 1237 { 1238 void* pvoid; 1239 bool bool_; 1240 dchar dchar_; 1241 long long_; 1242 ulong ulong_; 1243 int int_; 1244 uint uint_; 1245 float float_; 1246 double double_; 1247 real real_; 1248 creal creal_; 1249 } 1250 1251 /// A list of flags for types. 1252 struct TypeFlags 1253 { 1254 /// The actual flags. 1255 immutable enum 1256 { 1257 None = 0, /// No flags are set. 1258 ZeroInit = 1 << 0, /// All bytes of the type can be initialized to 0. 1259 Signed = 1 << 1, /// Signed type. 1260 Unsigned = 1 << 2, /// Unsigned type. 1261 Integral = 1 << 3, /// Integral type. 1262 Floating = 1 << 4, /// Floating point type. 1263 Real = 1 << 5, /// Real part of a complex number. 1264 Imaginary = 1 << 6, /// Imaginary part of a complex number. 1265 Complex = 1 << 7, /// Complex number type. 1266 Pointer = 1 << 8, /// Pointer or function pointer type. 1267 BoolVal = 1 << 9, /// Non-scalar type can be in a boolean expression. 1268 Basic = Integral | Floating, /// Basic type. 1269 Scalar = Basic | Pointer, /// Scalar type. 1270 } 1271 alias Flags = typeof(None); /// Alias to enum member. 1272 1273 Flags flags; /// Holds a set of flags. 1274 1275 /// Returns true if any bit from fs is set in flags. 1276 bool has(Flags fs){ return (flags & fs) != 0; } 1277 /// Returns true if all bits from fs are set in flags. 1278 bool hasAll(Flags fs){ return (flags & fs) == fs; } 1279 /// Returns true if zero init. 1280 bool isZeroInit() { return has(ZeroInit); } 1281 /// Returns true if signed. 1282 bool isSigned() { return has(Signed); } 1283 /// Returns true if unsigned. 1284 bool isUnsigned() { return has(Unsigned); } 1285 /// Returns true if integral. 1286 bool isIntegral() { return has(Integral); } 1287 /// Returns true if floating. 1288 bool isFloating() { return has(Floating); } 1289 /// Returns true if real. 1290 bool isReal() { return has(Real); } 1291 /// Returns true if imaginary. 1292 bool isImaginary() { return has(Imaginary); } 1293 /// Returns true if complex. 1294 bool isComplex() { return has(Complex); } 1295 /// Returns true if pointer. 1296 bool isPointer() { return has(Pointer); } 1297 /// Returns true if boolean value. 1298 bool isBoolVal() { return has(BoolVal | Scalar); } 1299 /// Returns true if basic. 1300 bool isBasic() { return has(Basic); } 1301 /// Returns true if scalar. 1302 bool isScalar() { return has(Scalar); } 1303 1304 TypeFlags opOrAssign(TypeFlags tf) 1305 { 1306 flags |= tf.flags; 1307 return this; 1308 } 1309 1310 TypeFlags opOr(TypeFlags tf) 1311 { 1312 return this |= tf; 1313 } 1314 1315 TypeFlags opAndAssign(TypeFlags tf) 1316 { 1317 flags &= tf.flags; 1318 return this; 1319 } 1320 1321 TypeFlags opAnd(TypeFlags tf) 1322 { 1323 return this &= tf; 1324 } 1325 } 1326 1327 /// Target information for types. 1328 class TargetTInfo 1329 { 1330 size_t ptrSize; /// The size of a pointer. 1331 bool is64; /// Is it a 64bit CPU? 1332 bool isLE; /// Is it little-endian or big-endian? 1333 } 1334 1335 /// Information related to a Type. 1336 struct TypeMetaInfo 1337 { 1338 char mangle; /// Mangle character of the type. 1339 ushort size; /// Byte size of the type. 1340 ushort alignsize; /// Align size of the type. 1341 const Value* defaultInit; /// Default initialization value. 1342 TypeFlags.Flags flags; /// The flags of the type. 1343 } 1344 1345 /// Namespace for the meta info table. 1346 struct MITable 1347 { 1348 static: 1349 const ushort SIZE_NOT_AVAILABLE = 0; /// Size not available. 1350 const ushort ALIGN_NOT_AVAILABLE = 0; /// Align not available. 1351 const Value VZERO = {int_:0}; /// Value 0. 1352 const Value VNULL = {pvoid:null}; /// Value null. 1353 const Value V0xFF = {dchar_:0xFF}; /// Value 0xFF. 1354 const Value V0xFFFF = {dchar_:0xFFFF}; /// Value 0xFFFF. 1355 const Value VFALSE = {bool_:false}; /// Value false. 1356 const Value VNAN = {float_:float.nan}; /// Value NAN. 1357 const Value VCNAN = {creal_:creal.nan}; /// Value complex NAN. 1358 private 1359 { 1360 alias SNA = SIZE_NOT_AVAILABLE; 1361 alias ANA = ALIGN_NOT_AVAILABLE; 1362 const ushort PS = 0/+1?+/; // Used for documentation purposes below. 1363 alias TF = TypeFlags; /// Shortcuts. 1364 const Z = TF.ZeroInit; 1365 const U = TF.Unsigned;; /// ditto 1366 const S = TF.Signed;; /// ditto 1367 const I = TF.Integral;; /// ditto 1368 const F = TF.Floating;; /// ditto 1369 const Re = TF.Real;; /// ditto 1370 const Im = TF.Imaginary;; /// ditto 1371 const Cx = TF.Complex;; /// ditto 1372 const P = TF.Pointer;; /// ditto 1373 const BV = TF.BoolVal;; /// ditto 1374 } 1375 /// The meta info table. 1376 private const TypeMetaInfo table[] = [ 1377 {'?', SNA, ANA}, // Error 1378 1379 {'a', 1, ANA, &V0xFF, I|U}, // Char 1380 {'u', 2, ANA, &V0xFFFF, I|U}, // WChar 1381 {'w', 4, ANA, &V0xFFFF, I|U}, // DChar 1382 {'b', 1, ANA, &VFALSE, I|U|Z}, // Bool 1383 {'g', 1, ANA, &VZERO, I|S|Z}, // Int8 1384 {'h', 1, ANA, &VZERO, I|U|Z}, // UInt8 1385 {'s', 2, ANA, &VZERO, I|S|Z}, // Int16 1386 {'t', 2, ANA, &VZERO, I|U|Z}, // UInt16 1387 {'i', 4, ANA, &VZERO, I|S|Z}, // Int32 1388 {'k', 4, ANA, &VZERO, I|U|Z}, // UInt32 1389 {'l', 8, ANA, &VZERO, I|S|Z}, // Int64 1390 {'m', 8, ANA, &VZERO, I|U|Z}, // UInt64 1391 {'?', 16, ANA, &VZERO, I|S|Z}, // Int128 1392 {'?', 16, ANA, &VZERO, I|U|Z}, // UInt128 1393 {'f', 4, ANA, &VNAN, F|Re}, // Float32 1394 {'d', 8, ANA, &VNAN, F|Re}, // Float64 1395 {'e', 10, ANA, &VNAN, F|Re}, // Float80 1396 {'o', 4, ANA, &VNAN, F|Im}, // IFloat32 1397 {'p', 8, ANA, &VNAN, F|Im}, // IFloat64 1398 {'j', 10, ANA, &VNAN, F|Im}, // IFloat80 1399 {'q', 8, ANA, &VCNAN, F|Cx}, // CFloat32 1400 {'r', 16, ANA, &VCNAN, F|Cx}, // CFloat64 1401 {'c', 20, ANA, &VCNAN, F|Cx}, // CFloat80 1402 {'v', 1, 1}, // Void 1403 1404 {'n', SNA, ANA}, // None 1405 1406 {'?', SNA, ANA}, // Parameter 1407 {'?', SNA, ANA}, // Parameters 1408 1409 {'A', PS*2, ANA, &VNULL, Z|BV}, // Dynamic array 1410 {'G', PS*2, ANA}, // Static array 1411 {'H', PS*2, ANA, &VNULL, Z|BV}, // Associative array 1412 1413 {'E', SNA, ANA}, // Enum 1414 {'S', SNA, ANA}, // Struct 1415 {'C', PS, ANA, &VNULL, Z|BV}, // Class 1416 {'T', SNA, ANA}, // Typedef 1417 {'F', SNA, ANA}, // Function 1418 {'P', PS, ANA, &VNULL, Z|BV|P}, // FuncPtr 1419 {'D', PS*2, ANA, &VNULL, Z|BV}, // Delegate 1420 {'P', PS, ANA, &VNULL, Z|BV|P}, // Pointer 1421 {'R', PS, ANA, &VNULL, Z}, // Reference 1422 {'I', SNA, ANA}, // Identifier 1423 {'?', SNA, ANA}, // Template instance 1424 {'B', SNA, ANA}, // Tuple 1425 {'x', SNA, ANA}, // Const, D2 1426 {'y', SNA, ANA}, // Immutable, D2 1427 ]; 1428 static assert(table.length == TYP.max+1); 1429 1430 /// Returns the byte size of a type. 1431 size_t getSize(Type type) 1432 { 1433 return table[type.tid].size; 1434 } 1435 1436 /// Returns the align size of a type. 1437 size_t getAlignSize(Type type) 1438 { 1439 return table[type.tid].size; 1440 } 1441 1442 /// Returns the flags of a type. 1443 TypeFlags getFlags(Type type) 1444 { 1445 TypeFlags tf = {MITable.table[type.tid].flags}; 1446 return tf; 1447 } 1448 1449 /// Returns the mangle character of a type. 1450 char mangleChar(Type type) 1451 { 1452 return table[type.tid].mangle; 1453 } 1454 } 1455 1456 /// Namespace for a set of predefined types. 1457 struct Types 1458 { 1459 static: 1460 /// Predefined basic types. 1461 TypeBasic XChar, Char, WChar, DChar, Bool, 1462 Int8, UInt8, Int16, UInt16, 1463 Int32, UInt32, Int64, UInt64, 1464 Int128, UInt128, 1465 Float32, Float64, Float80, 1466 IFloat32, IFloat64, IFloat80, 1467 CFloat32, CFloat64, CFloat80, Void; 1468 1469 TypePointer Void_ptr; /// The void pointer type. 1470 TypeError Error; /// The error type. 1471 TypeError Undefined; /// The undefined type. 1472 TypeError DontKnowYet; /// The symbol is undefined but might be resolved. 1473 1474 TypeFunction Void_0Args_DFunc; /// Type: extern(D) void X() 1475 1476 // A table mapping the kind of a token to its corresponding semantic Type. 1477 TypeBasic[TOK] TOK2Type; 1478 1479 /// Returns the corresponding Type instance for tok, 1480 /// or null if it does not apply. 1481 Type fromTOK(TOK tok) 1482 { 1483 auto ptype = tok in TOK2Type; 1484 return ptype ? *ptype : null; 1485 } 1486 1487 /// Creates a list of statements for creating and initializing types. 1488 /// --- 1489 /// Int8 = new TypeBasic(Keyword.Byte, TYP.Int8); 1490 /// --- 1491 char[] createTypes(string[2][] typeNames) 1492 { 1493 char[] result; 1494 foreach (n; typeNames) 1495 result ~= n[0]~" = new TypeBasic(Keyword."~n[1]~", TYP."~n[0]~");"; 1496 return result; 1497 } 1498 1499 /// Initializes global, predefined types. 1500 /// NB: Not thread-safe. 1501 auto init = &init_; 1502 /// ditto 1503 void init_() 1504 { 1505 init = {}; // Disable with empty function after first call. 1506 1507 mixin(createTypes([ // Pass tuples: (TypeName, KeywordName) 1508 ["Char", "Char"], ["WChar", "Wchar"], ["DChar", "Dchar"], 1509 ["Bool", "Bool"], 1510 ["Int8", "Byte"], ["UInt8", "Ubyte"], 1511 ["Int16", "Short"], ["UInt16", "Ushort"], 1512 ["Int32", "Int"], ["UInt32", "Uint"], 1513 ["Int64", "Long"], ["UInt64", "Ulong"], 1514 ["Int128", "Cent"], ["UInt128", "Ucent"], 1515 ["Float32", "Float"], ["Float64", "Double"], ["Float80", "Real"], 1516 ["IFloat32", "Ifloat"], ["IFloat64", "Idouble"], ["IFloat80", "Ireal"], 1517 ["CFloat32", "Cfloat"], ["CFloat64", "Cdouble"], 1518 ["CFloat80", "Creal"], ["Void", "Void"] 1519 ])); 1520 1521 /// Polysemous character type. 1522 XChar = new TypeBasic(Char.ident, Char.tid); 1523 1524 TOK2Type = [ 1525 // Number literal TOKs: 1526 TOK.Int32 : Types.Int32, TOK.UInt32 : Types.UInt32, 1527 TOK.Int64 : Types.Int64, TOK.UInt64 : Types.UInt64, 1528 TOK.Float32 : Types.Float32, TOK.Float64 : Types.Float64, 1529 TOK.Float80 : Types.Float80, TOK.IFloat32 : Types.IFloat32, 1530 TOK.IFloat64 : Types.IFloat64, TOK.IFloat80 : Types.IFloat80, 1531 // Keyword TOKs: 1532 TOK.Char : Types.Char, TOK.Wchar : Types.WChar, TOK.Dchar : Types.DChar, 1533 TOK.Bool : Types.Bool, 1534 TOK.Byte : Types.Int8, TOK.Ubyte : Types.UInt8, 1535 TOK.Short : Types.Int16, TOK.Ushort : Types.UInt16, 1536 TOK.Int : Types.Int32, TOK.Uint : Types.UInt32, 1537 TOK.Long : Types.Int64, TOK.Ulong : Types.UInt64, 1538 TOK.Cent : Types.Int128, TOK.Ucent : Types.UInt128, 1539 TOK.Float : Types.Float32, TOK.Double : Types.Float64, 1540 TOK.Real : Types.Float80, 1541 TOK.Ifloat : Types.IFloat32, TOK.Idouble : Types.IFloat64, 1542 TOK.Ireal : Types.IFloat80, 1543 TOK.Cfloat : Types.CFloat32, TOK.Cdouble : Types.CFloat64, 1544 TOK.Creal : Types.CFloat80, TOK.Void : Types.Void 1545 ]; 1546 1547 Void_ptr = Void.ptrTo(); 1548 Error = new TypeError(); 1549 Undefined = new TypeError(); 1550 DontKnowYet = new TypeError(); 1551 1552 // A function type that's frequently used. 1553 auto params = new TypeParameters(null); 1554 Void_0Args_DFunc = new TypeFunction(Types.Void, params, 1555 StorageClass.None, LinkageType.D); 1556 } 1557 }