1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
|
//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the main TableGen data structures, including the TableGen
// types, values, and high-level data structures.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TABLEGEN_RECORD_H
#define LLVM_TABLEGEN_RECORD_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
class ListRecTy;
struct MultiClass;
class Record;
class RecordKeeper;
class RecordVal;
class Resolver;
class StringInit;
class TypedInit;
//===----------------------------------------------------------------------===//
// Type Classes
//===----------------------------------------------------------------------===//
class RecTy {
public:
/// Subclass discriminator (for dyn_cast<> et al.)
enum RecTyKind {
BitRecTyKind,
BitsRecTyKind,
CodeRecTyKind,
IntRecTyKind,
StringRecTyKind,
ListRecTyKind,
DagRecTyKind,
RecordRecTyKind
};
private:
RecTyKind Kind;
ListRecTy *ListTy = nullptr;
public:
RecTy(RecTyKind K) : Kind(K) {}
virtual ~RecTy() = default;
RecTyKind getRecTyKind() const { return Kind; }
virtual std::string getAsString() const = 0;
void print(raw_ostream &OS) const { OS << getAsString(); }
void dump() const;
/// Return true if all values of 'this' type can be converted to the specified
/// type.
virtual bool typeIsConvertibleTo(const RecTy *RHS) const;
/// Return true if 'this' type is equal to or a subtype of RHS. For example,
/// a bit set is not an int, but they are convertible.
virtual bool typeIsA(const RecTy *RHS) const;
/// Returns the type representing list<this>.
ListRecTy *getListTy();
};
inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
Ty.print(OS);
return OS;
}
/// 'bit' - Represent a single bit
class BitRecTy : public RecTy {
static BitRecTy Shared;
BitRecTy() : RecTy(BitRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == BitRecTyKind;
}
static BitRecTy *get() { return &Shared; }
std::string getAsString() const override { return "bit"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'bits<n>' - Represent a fixed number of bits
class BitsRecTy : public RecTy {
unsigned Size;
explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == BitsRecTyKind;
}
static BitsRecTy *get(unsigned Sz);
unsigned getNumBits() const { return Size; }
std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
bool typeIsA(const RecTy *RHS) const override;
};
/// 'code' - Represent a code fragment
class CodeRecTy : public RecTy {
static CodeRecTy Shared;
CodeRecTy() : RecTy(CodeRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == CodeRecTyKind;
}
static CodeRecTy *get() { return &Shared; }
std::string getAsString() const override { return "code"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'int' - Represent an integer value of no particular size
class IntRecTy : public RecTy {
static IntRecTy Shared;
IntRecTy() : RecTy(IntRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == IntRecTyKind;
}
static IntRecTy *get() { return &Shared; }
std::string getAsString() const override { return "int"; }
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'string' - Represent an string value
class StringRecTy : public RecTy {
static StringRecTy Shared;
StringRecTy() : RecTy(StringRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == StringRecTyKind;
}
static StringRecTy *get() { return &Shared; }
std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
};
/// 'list<Ty>' - Represent a list of values, all of which must be of
/// the specified type.
class ListRecTy : public RecTy {
friend ListRecTy *RecTy::getListTy();
RecTy *Ty;
explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == ListRecTyKind;
}
static ListRecTy *get(RecTy *T) { return T->getListTy(); }
RecTy *getElementType() const { return Ty; }
std::string getAsString() const override;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
bool typeIsA(const RecTy *RHS) const override;
};
/// 'dag' - Represent a dag fragment
class DagRecTy : public RecTy {
static DagRecTy Shared;
DagRecTy() : RecTy(DagRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == DagRecTyKind;
}
static DagRecTy *get() { return &Shared; }
std::string getAsString() const override;
};
/// '[classname]' - Type of record values that have zero or more superclasses.
///
/// The list of superclasses is non-redundant, i.e. only contains classes that
/// are not the superclass of some other listed class.
class RecordRecTy final : public RecTy, public FoldingSetNode,
public TrailingObjects<RecordRecTy, Record *> {
friend class Record;
unsigned NumClasses;
explicit RecordRecTy(unsigned Num)
: RecTy(RecordRecTyKind), NumClasses(Num) {}
public:
RecordRecTy(const RecordRecTy &) = delete;
RecordRecTy &operator=(const RecordRecTy &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == RecordRecTyKind;
}
/// Get the record type with the given non-redundant list of superclasses.
static RecordRecTy *get(ArrayRef<Record *> Classes);
void Profile(FoldingSetNodeID &ID) const;
ArrayRef<Record *> getClasses() const {
return makeArrayRef(getTrailingObjects<Record *>(), NumClasses);
}
using const_record_iterator = Record * const *;
const_record_iterator classes_begin() const { return getClasses().begin(); }
const_record_iterator classes_end() const { return getClasses().end(); }
std::string getAsString() const override;
bool isSubClassOf(Record *Class) const;
bool typeIsConvertibleTo(const RecTy *RHS) const override;
bool typeIsA(const RecTy *RHS) const override;
};
/// Find a common type that T1 and T2 convert to.
/// Return 0 if no such type exists.
RecTy *resolveTypes(RecTy *T1, RecTy *T2);
//===----------------------------------------------------------------------===//
// Initializer Classes
//===----------------------------------------------------------------------===//
class Init {
protected:
/// Discriminator enum (for isa<>, dyn_cast<>, et al.)
///
/// This enum is laid out by a preorder traversal of the inheritance
/// hierarchy, and does not contain an entry for abstract classes, as per
/// the recommendation in docs/HowToSetUpLLVMStyleRTTI.rst.
///
/// We also explicitly include "first" and "last" values for each
/// interior node of the inheritance tree, to make it easier to read the
/// corresponding classof().
///
/// We could pack these a bit tighter by not having the IK_FirstXXXInit
/// and IK_LastXXXInit be their own values, but that would degrade
/// readability for really no benefit.
enum InitKind : uint8_t {
IK_First, // unused; silence a spurious warning
IK_FirstTypedInit,
IK_BitInit,
IK_BitsInit,
IK_CodeInit,
IK_DagInit,
IK_DefInit,
IK_FieldInit,
IK_IntInit,
IK_ListInit,
IK_FirstOpInit,
IK_BinOpInit,
IK_TernOpInit,
IK_UnOpInit,
IK_LastOpInit,
IK_FoldOpInit,
IK_IsAOpInit,
IK_StringInit,
IK_VarInit,
IK_VarListElementInit,
IK_VarBitInit,
IK_VarDefInit,
IK_LastTypedInit,
IK_UnsetInit
};
private:
const InitKind Kind;
protected:
uint8_t Opc; // Used by UnOpInit, BinOpInit, and TernOpInit
private:
virtual void anchor();
public:
InitKind getKind() const { return Kind; }
protected:
explicit Init(InitKind K, uint8_t Opc = 0) : Kind(K), Opc(Opc) {}
public:
Init(const Init &) = delete;
Init &operator=(const Init &) = delete;
virtual ~Init() = default;
/// This virtual method should be overridden by values that may
/// not be completely specified yet.
virtual bool isComplete() const { return true; }
/// Is this a concrete and fully resolved value without any references or
/// stuck operations? Unset values are concrete.
virtual bool isConcrete() const { return false; }
/// Print out this value.
void print(raw_ostream &OS) const { OS << getAsString(); }
/// Convert this value to a string form.
virtual std::string getAsString() const = 0;
/// Convert this value to a string form,
/// without adding quote markers. This primaruly affects
/// StringInits where we will not surround the string value with
/// quotes.
virtual std::string getAsUnquotedString() const { return getAsString(); }
/// Debugging method that may be called through a debugger, just
/// invokes print on stderr.
void dump() const;
/// If this initializer is convertible to Ty, return an initializer whose
/// type is-a Ty, generating a !cast operation if required. Otherwise, return
/// nullptr.
virtual Init *getCastTo(RecTy *Ty) const = 0;
/// Convert to an initializer whose type is-a Ty, or return nullptr if this
/// is not possible (this can happen if the initializer's type is convertible
/// to Ty, but there are unresolved references).
virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
/// This method is used to implement the bitrange
/// selection operator. Given an initializer, it selects the specified bits
/// out, returning them as a new init of bits type. If it is not legal to use
/// the bit subscript operator on this initializer, return null.
virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
return nullptr;
}
/// This method is used to implement the list slice
/// selection operator. Given an initializer, it selects the specified list
/// elements, returning them as a new init of list type. If it is not legal
/// to take a slice of this, return null.
virtual Init *convertInitListSlice(ArrayRef<unsigned> Elements) const {
return nullptr;
}
/// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
/// they are of record type.
virtual RecTy *getFieldType(StringInit *FieldName) const {
return nullptr;
}
/// This method is used by classes that refer to other
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
virtual Init *resolveReferences(Resolver &R) const {
return const_cast<Init *>(this);
}
/// This method is used to return the initializer for the specified
/// bit.
virtual Init *getBit(unsigned Bit) const = 0;
};
inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
I.print(OS); return OS;
}
/// This is the common super-class of types that have a specific,
/// explicit, type.
class TypedInit : public Init {
RecTy *Ty;
protected:
explicit TypedInit(InitKind K, RecTy *T, uint8_t Opc = 0)
: Init(K, Opc), Ty(T) {}
public:
TypedInit(const TypedInit &) = delete;
TypedInit &operator=(const TypedInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() >= IK_FirstTypedInit &&
I->getKind() <= IK_LastTypedInit;
}
RecTy *getType() const { return Ty; }
Init *getCastTo(RecTy *Ty) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
Init *convertInitListSlice(ArrayRef<unsigned> Elements) const override;
/// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
/// they are of record type.
///
RecTy *getFieldType(StringInit *FieldName) const override;
};
/// '?' - Represents an uninitialized value
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
public:
UnsetInit(const UnsetInit &) = delete;
UnsetInit &operator=(const UnsetInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_UnsetInit;
}
static UnsetInit *get();
Init *getCastTo(RecTy *Ty) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
Init *getBit(unsigned Bit) const override {
return const_cast<UnsetInit*>(this);
}
bool isComplete() const override { return false; }
bool isConcrete() const override { return true; }
std::string getAsString() const override { return "?"; }
};
/// 'true'/'false' - Represent a concrete initializer for a bit.
class BitInit final : public TypedInit {
bool Value;
explicit BitInit(bool V) : TypedInit(IK_BitInit, BitRecTy::get()), Value(V) {}
public:
BitInit(const BitInit &) = delete;
BitInit &operator=(BitInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_BitInit;
}
static BitInit *get(bool V);
bool getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override;
Init *getBit(unsigned Bit) const override {
assert(Bit < 1 && "Bit index out of range!");
return const_cast<BitInit*>(this);
}
bool isConcrete() const override { return true; }
std::string getAsString() const override { return Value ? "1" : "0"; }
};
/// '{ a, b, c }' - Represents an initializer for a BitsRecTy value.
/// It contains a vector of bits, whose size is determined by the type.
class BitsInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<BitsInit, Init *> {
unsigned NumBits;
BitsInit(unsigned N)
: TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {}
public:
BitsInit(const BitsInit &) = delete;
BitsInit &operator=(const BitsInit &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
static bool classof(const Init *I) {
return I->getKind() == IK_BitsInit;
}
static BitsInit *get(ArrayRef<Init *> Range);
void Profile(FoldingSetNodeID &ID) const;
unsigned getNumBits() const { return NumBits; }
Init *convertInitializerTo(RecTy *Ty) const override;
Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
bool isComplete() const override {
for (unsigned i = 0; i != getNumBits(); ++i)
if (!getBit(i)->isComplete()) return false;
return true;
}
bool allInComplete() const {
for (unsigned i = 0; i != getNumBits(); ++i)
if (getBit(i)->isComplete()) return false;
return true;
}
bool isConcrete() const override;
std::string getAsString() const override;
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override {
assert(Bit < NumBits && "Bit index out of range!");
return getTrailingObjects<Init *>()[Bit];
}
};
/// '7' - Represent an initialization by a literal integer value.
class IntInit : public TypedInit {
int64_t Value;
explicit IntInit(int64_t V)
: TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
public:
IntInit(const IntInit &) = delete;
IntInit &operator=(const IntInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_IntInit;
}
static IntInit *get(int64_t V);
int64_t getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override;
Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override;
bool isConcrete() const override { return true; }
std::string getAsString() const override;
Init *getBit(unsigned Bit) const override {
return BitInit::get((Value & (1ULL << Bit)) != 0);
}
};
/// "foo" - Represent an initialization by a string value.
class StringInit : public TypedInit {
StringRef Value;
explicit StringInit(StringRef V)
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
public:
StringInit(const StringInit &) = delete;
StringInit &operator=(const StringInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_StringInit;
}
static StringInit *get(StringRef);
StringRef getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override;
bool isConcrete() const override { return true; }
std::string getAsString() const override { return "\"" + Value.str() + "\""; }
std::string getAsUnquotedString() const override { return Value; }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
}
};
class CodeInit : public TypedInit {
StringRef Value;
explicit CodeInit(StringRef V)
: TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())),
Value(V) {}
public:
CodeInit(const StringInit &) = delete;
CodeInit &operator=(const StringInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_CodeInit;
}
static CodeInit *get(StringRef);
StringRef getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override;
bool isConcrete() const override { return true; }
std::string getAsString() const override {
return "[{" + Value.str() + "}]";
}
std::string getAsUnquotedString() const override { return Value; }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
}
};
/// [AL, AH, CL] - Represent a list of defs
///
class ListInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<ListInit, Init *> {
unsigned NumValues;
public:
using const_iterator = Init *const *;
private:
explicit ListInit(unsigned N, RecTy *EltTy)
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
public:
ListInit(const ListInit &) = delete;
ListInit &operator=(const ListInit &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
static bool classof(const Init *I) {
return I->getKind() == IK_ListInit;
}
static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy);
void Profile(FoldingSetNodeID &ID) const;
Init *getElement(unsigned i) const {
assert(i < NumValues && "List element index out of range!");
return getTrailingObjects<Init *>()[i];
}
RecTy *getElementType() const {
return cast<ListRecTy>(getType())->getElementType();
}
Record *getElementAsRecord(unsigned i) const;
Init *convertInitListSlice(ArrayRef<unsigned> Elements) const override;
Init *convertInitializerTo(RecTy *Ty) const override;
/// This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
Init *resolveReferences(Resolver &R) const override;
bool isConcrete() const override;
std::string getAsString() const override;
ArrayRef<Init*> getValues() const {
return makeArrayRef(getTrailingObjects<Init *>(), NumValues);
}
const_iterator begin() const { return getTrailingObjects<Init *>(); }
const_iterator end () const { return begin() + NumValues; }
size_t size () const { return NumValues; }
bool empty() const { return NumValues == 0; }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off list");
}
};
/// Base class for operators
///
class OpInit : public TypedInit {
protected:
explicit OpInit(InitKind K, RecTy *Type, uint8_t Opc)
: TypedInit(K, Type, Opc) {}
public:
OpInit(const OpInit &) = delete;
OpInit &operator=(OpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() >= IK_FirstOpInit &&
I->getKind() <= IK_LastOpInit;
}
// Clone - Clone this operator, replacing arguments with the new list
virtual OpInit *clone(ArrayRef<Init *> Operands) const = 0;
virtual unsigned getNumOperands() const = 0;
virtual Init *getOperand(unsigned i) const = 0;
Init *getBit(unsigned Bit) const override;
};
/// !op (X) - Transform an init.
///
class UnOpInit : public OpInit, public FoldingSetNode {
public:
enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY };
private:
Init *LHS;
UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
: OpInit(IK_UnOpInit, Type, opc), LHS(lhs) {}
public:
UnOpInit(const UnOpInit &) = delete;
UnOpInit &operator=(const UnOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_UnOpInit;
}
static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
void Profile(FoldingSetNodeID &ID) const;
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(ArrayRef<Init *> Operands) const override {
assert(Operands.size() == 1 &&
"Wrong number of operands for unary operation");
return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
}
unsigned getNumOperands() const override { return 1; }
Init *getOperand(unsigned i) const override {
assert(i == 0 && "Invalid operand id for unary operator");
return getOperand();
}
UnaryOp getOpcode() const { return (UnaryOp)Opc; }
Init *getOperand() const { return LHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec, bool IsFinal = false) const;
Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
/// !op (X, Y) - Combine two inits.
class BinOpInit : public OpInit, public FoldingSetNode {
public:
enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT,
STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT };
private:
Init *LHS, *RHS;
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
OpInit(IK_BinOpInit, Type, opc), LHS(lhs), RHS(rhs) {}
public:
BinOpInit(const BinOpInit &) = delete;
BinOpInit &operator=(const BinOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_BinOpInit;
}
static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
RecTy *Type);
static Init *getStrConcat(Init *lhs, Init *rhs);
void Profile(FoldingSetNodeID &ID) const;
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(ArrayRef<Init *> Operands) const override {
assert(Operands.size() == 2 &&
"Wrong number of operands for binary operation");
return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
}
unsigned getNumOperands() const override { return 2; }
Init *getOperand(unsigned i) const override {
switch (i) {
default: llvm_unreachable("Invalid operand id for binary operator");
case 0: return getLHS();
case 1: return getRHS();
}
}
BinaryOp getOpcode() const { return (BinaryOp)Opc; }
Init *getLHS() const { return LHS; }
Init *getRHS() const { return RHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec) const;
Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
/// !op (X, Y, Z) - Combine two inits.
class TernOpInit : public OpInit, public FoldingSetNode {
public:
enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG };
private:
Init *LHS, *MHS, *RHS;
TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs,
RecTy *Type) :
OpInit(IK_TernOpInit, Type, opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
public:
TernOpInit(const TernOpInit &) = delete;
TernOpInit &operator=(const TernOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_TernOpInit;
}
static TernOpInit *get(TernaryOp opc, Init *lhs,
Init *mhs, Init *rhs,
RecTy *Type);
void Profile(FoldingSetNodeID &ID) const;
// Clone - Clone this operator, replacing arguments with the new list
OpInit *clone(ArrayRef<Init *> Operands) const override {
assert(Operands.size() == 3 &&
"Wrong number of operands for ternary operation");
return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2],
getType());
}
unsigned getNumOperands() const override { return 3; }
Init *getOperand(unsigned i) const override {
switch (i) {
default: llvm_unreachable("Invalid operand id for ternary operator");
case 0: return getLHS();
case 1: return getMHS();
case 2: return getRHS();
}
}
TernaryOp getOpcode() const { return (TernaryOp)Opc; }
Init *getLHS() const { return LHS; }
Init *getMHS() const { return MHS; }
Init *getRHS() const { return RHS; }
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec) const;
bool isComplete() const override {
return LHS->isComplete() && MHS->isComplete() && RHS->isComplete();
}
Init *resolveReferences(Resolver &R) const override;
std::string getAsString() const override;
};
/// !foldl (a, b, expr, start, lst) - Fold over a list.
class FoldOpInit : public TypedInit, public FoldingSetNode {
private:
Init *Start;
Init *List;
Init *A;
Init *B;
Init *Expr;
FoldOpInit(Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type)
: TypedInit(IK_FoldOpInit, Type), Start(Start), List(List), A(A), B(B),
Expr(Expr) {}
public:
FoldOpInit(const FoldOpInit &) = delete;
FoldOpInit &operator=(const FoldOpInit &) = delete;
static bool classof(const Init *I) { return I->getKind() == IK_FoldOpInit; }
static FoldOpInit *get(Init *Start, Init *List, Init *A, Init *B, Init *Expr,
RecTy *Type);
void Profile(FoldingSetNodeID &ID) const;
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold(Record *CurRec) const;
bool isComplete() const override { return false; }
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
std::string getAsString() const override;
};
/// !isa<type>(expr) - Dynamically determine the type of an expression.
class IsAOpInit : public TypedInit, public FoldingSetNode {
private:
RecTy *CheckType;
Init *Expr;
IsAOpInit(RecTy *CheckType, Init *Expr)
: TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType),
Expr(Expr) {}
public:
IsAOpInit(const IsAOpInit &) = delete;
IsAOpInit &operator=(const IsAOpInit &) = delete;
static bool classof(const Init *I) { return I->getKind() == IK_IsAOpInit; }
static IsAOpInit *get(RecTy *CheckType, Init *Expr);
void Profile(FoldingSetNodeID &ID) const;
// Fold - If possible, fold this to a simpler init. Return this if not
// possible to fold.
Init *Fold() const;
bool isComplete() const override { return false; }
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
std::string getAsString() const override;
};
/// 'Opcode' - Represent a reference to an entire variable object.
class VarInit : public TypedInit {
Init *VarName;
explicit VarInit(Init *VN, RecTy *T)
: TypedInit(IK_VarInit, T), VarName(VN) {}
public:
VarInit(const VarInit &) = delete;
VarInit &operator=(const VarInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarInit;
}
static VarInit *get(StringRef VN, RecTy *T);
static VarInit *get(Init *VN, RecTy *T);
StringRef getName() const;
Init *getNameInit() const { return VarName; }
std::string getNameInitAsString() const {
return getNameInit()->getAsUnquotedString();
}
/// This method is used by classes that refer to other
/// variables which may not be defined at the time they expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
///
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
std::string getAsString() const override { return getName(); }
};
/// Opcode{0} - Represent access to one bit of a variable or field.
class VarBitInit final : public TypedInit {
TypedInit *TI;
unsigned Bit;
VarBitInit(TypedInit *T, unsigned B)
: TypedInit(IK_VarBitInit, BitRecTy::get()), TI(T), Bit(B) {
assert(T->getType() &&
(isa<IntRecTy>(T->getType()) ||
(isa<BitsRecTy>(T->getType()) &&
cast<BitsRecTy>(T->getType())->getNumBits() > B)) &&
"Illegal VarBitInit expression!");
}
public:
VarBitInit(const VarBitInit &) = delete;
VarBitInit &operator=(const VarBitInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarBitInit;
}
static VarBitInit *get(TypedInit *T, unsigned B);
Init *getBitVar() const { return TI; }
unsigned getBitNum() const { return Bit; }
std::string getAsString() const override;
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned B) const override {
assert(B < 1 && "Bit index out of range!");
return const_cast<VarBitInit*>(this);
}
};
/// List[4] - Represent access to one element of a var or
/// field.
class VarListElementInit : public TypedInit {
TypedInit *TI;
unsigned Element;
VarListElementInit(TypedInit *T, unsigned E)
: TypedInit(IK_VarListElementInit,
cast<ListRecTy>(T->getType())->getElementType()),
TI(T), Element(E) {
assert(T->getType() && isa<ListRecTy>(T->getType()) &&
"Illegal VarBitInit expression!");
}
public:
VarListElementInit(const VarListElementInit &) = delete;
VarListElementInit &operator=(const VarListElementInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarListElementInit;
}
static VarListElementInit *get(TypedInit *T, unsigned E);
TypedInit *getVariable() const { return TI; }
unsigned getElementNum() const { return Element; }
std::string getAsString() const override;
Init *resolveReferences(Resolver &R) const override;
Init *getBit(unsigned Bit) const override;
};
/// AL - Represent a reference to a 'def' in the description
class DefInit : public TypedInit {
friend class Record;
Record *Def;
explicit DefInit(Record *D);
public:
DefInit(const DefInit &) = delete;
DefInit &operator=(const DefInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_DefInit;
}
static DefInit *get(Record*);
Init *convertInitializerTo(RecTy *Ty) const override;
Record *getDef() const { return Def; }
//virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits);
RecTy *getFieldType(StringInit *FieldName) const override;
bool isConcrete() const override { return true; }
std::string getAsString() const override;
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off def");
}
};
/// classname<targs...> - Represent an uninstantiated anonymous class
/// instantiation.
class VarDefInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<VarDefInit, Init *> {
Record *Class;
DefInit *Def = nullptr; // after instantiation
unsigned NumArgs;
explicit VarDefInit(Record *Class, unsigned N)
: TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {}
DefInit *instantiate();
public:
VarDefInit(const VarDefInit &) = delete;
VarDefInit &operator=(const VarDefInit &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
static bool classof(const Init *I) {
return I->getKind() == IK_VarDefInit;
}
static VarDefInit *get(Record *Class, ArrayRef<Init *> Args);
void Profile(FoldingSetNodeID &ID) const;
Init *resolveReferences(Resolver &R) const override;
Init *Fold() const;
std::string getAsString() const override;
Init *getArg(unsigned i) const {
assert(i < NumArgs && "Argument index out of range!");
return getTrailingObjects<Init *>()[i];
}
using const_iterator = Init *const *;
const_iterator args_begin() const { return getTrailingObjects<Init *>(); }
const_iterator args_end () const { return args_begin() + NumArgs; }
size_t args_size () const { return NumArgs; }
bool args_empty() const { return NumArgs == 0; }
ArrayRef<Init *> args() const { return makeArrayRef(args_begin(), NumArgs); }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off anonymous def");
}
};
/// X.Y - Represent a reference to a subfield of a variable
class FieldInit : public TypedInit {
Init *Rec; // Record we are referring to
StringInit *FieldName; // Field we are accessing
FieldInit(Init *R, StringInit *FN)
: TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) {
assert(getType() && "FieldInit with non-record type!");
}
public:
FieldInit(const FieldInit &) = delete;
FieldInit &operator=(const FieldInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_FieldInit;
}
static FieldInit *get(Init *R, StringInit *FN);
Init *getRecord() const { return Rec; }
StringInit *getFieldName() const { return FieldName; }
Init *getBit(unsigned Bit) const override;
Init *resolveReferences(Resolver &R) const override;
Init *Fold(Record *CurRec) const;
std::string getAsString() const override {
return Rec->getAsString() + "." + FieldName->getValue().str();
}
};
/// (v a, b) - Represent a DAG tree value. DAG inits are required
/// to have at least one value then a (possibly empty) list of arguments. Each
/// argument can have a name associated with it.
class DagInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<DagInit, Init *, StringInit *> {
friend TrailingObjects;
Init *Val;
StringInit *ValName;
unsigned NumArgs;
unsigned NumArgNames;
DagInit(Init *V, StringInit *VN, unsigned NumArgs, unsigned NumArgNames)
: TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
NumArgs(NumArgs), NumArgNames(NumArgNames) {}
size_t numTrailingObjects(OverloadToken<Init *>) const { return NumArgs; }
public:
DagInit(const DagInit &) = delete;
DagInit &operator=(const DagInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_DagInit;
}
static DagInit *get(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange,
ArrayRef<StringInit*> NameRange);
static DagInit *get(Init *V, StringInit *VN,
ArrayRef<std::pair<Init*, StringInit*>> Args);
void Profile(FoldingSetNodeID &ID) const;
Init *getOperator() const { return Val; }
StringInit *getName() const { return ValName; }
StringRef getNameStr() const {
return ValName ? ValName->getValue() : StringRef();
}
unsigned getNumArgs() const { return NumArgs; }
Init *getArg(unsigned Num) const {
assert(Num < NumArgs && "Arg number out of range!");
return getTrailingObjects<Init *>()[Num];
}
StringInit *getArgName(unsigned Num) const {
assert(Num < NumArgNames && "Arg number out of range!");
return getTrailingObjects<StringInit *>()[Num];
}
StringRef getArgNameStr(unsigned Num) const {
StringInit *Init = getArgName(Num);
return Init ? Init->getValue() : StringRef();
}
ArrayRef<Init *> getArgs() const {
return makeArrayRef(getTrailingObjects<Init *>(), NumArgs);
}
ArrayRef<StringInit *> getArgNames() const {
return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
}
Init *resolveReferences(Resolver &R) const override;
bool isConcrete() const override;
std::string getAsString() const override;
using const_arg_iterator = SmallVectorImpl<Init*>::const_iterator;
using const_name_iterator = SmallVectorImpl<StringInit*>::const_iterator;
inline const_arg_iterator arg_begin() const { return getArgs().begin(); }
inline const_arg_iterator arg_end () const { return getArgs().end(); }
inline size_t arg_size () const { return NumArgs; }
inline bool arg_empty() const { return NumArgs == 0; }
inline const_name_iterator name_begin() const { return getArgNames().begin();}
inline const_name_iterator name_end () const { return getArgNames().end(); }
inline size_t name_size () const { return NumArgNames; }
inline bool name_empty() const { return NumArgNames == 0; }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off dag");
}
};
//===----------------------------------------------------------------------===//
// High-Level Classes
//===----------------------------------------------------------------------===//
class RecordVal {
friend class Record;
Init *Name;
PointerIntPair<RecTy *, 1, bool> TyAndPrefix;
Init *Value;
public:
RecordVal(Init *N, RecTy *T, bool P);
StringRef getName() const;
Init *getNameInit() const { return Name; }
std::string getNameInitAsString() const {
return getNameInit()->getAsUnquotedString();
}
bool getPrefix() const { return TyAndPrefix.getInt(); }
RecTy *getType() const { return TyAndPrefix.getPointer(); }
Init *getValue() const { return Value; }
bool setValue(Init *V);
void dump() const;
void print(raw_ostream &OS, bool PrintSem = true) const;
};
inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
RV.print(OS << " ");
return OS;
}
class Record {
static unsigned LastID;
Init *Name;
// Location where record was instantiated, followed by the location of
// multiclass prototypes used.
SmallVector<SMLoc, 4> Locs;
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
// All superclasses in the inheritance forest in reverse preorder (yes, it
// must be a forest; diamond-shaped inheritance is not allowed).
SmallVector<std::pair<Record *, SMRange>, 0> SuperClasses;
// Tracks Record instances. Not owned by Record.
RecordKeeper &TrackedRecords;
DefInit *TheInit = nullptr;
// Unique record ID.
unsigned ID;
bool IsAnonymous;
bool IsClass;
void checkName();
public:
// Constructs a record.
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Anonymous = false, bool Class = false)
: Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
ID(LastID++), IsAnonymous(Anonymous), IsClass(Class) {
checkName();
}
explicit Record(StringRef N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Class = false)
: Record(StringInit::get(N), locs, records, false, Class) {}
// When copy-constructing a Record, we must still guarantee a globally unique
// ID number. Don't copy TheInit either since it's owned by the original
// record. All other fields can be copied normally.
Record(const Record &O)
: Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs),
Values(O.Values), SuperClasses(O.SuperClasses),
TrackedRecords(O.TrackedRecords), ID(LastID++),
IsAnonymous(O.IsAnonymous), IsClass(O.IsClass) { }
static unsigned getNewUID() { return LastID++; }
unsigned getID() const { return ID; }
StringRef getName() const { return cast<StringInit>(Name)->getValue(); }
Init *getNameInit() const {
return Name;
}
const std::string getNameInitAsString() const {
return getNameInit()->getAsUnquotedString();
}
void setName(Init *Name); // Also updates RecordKeeper.
ArrayRef<SMLoc> getLoc() const { return Locs; }
void appendLoc(SMLoc Loc) { Locs.push_back(Loc); }
// Make the type that this record should have based on its superclasses.
RecordRecTy *getType();
/// get the corresponding DefInit.
DefInit *getDefInit();
bool isClass() const { return IsClass; }
ArrayRef<Init *> getTemplateArgs() const {
return TemplateArgs;
}
ArrayRef<RecordVal> getValues() const { return Values; }
ArrayRef<std::pair<Record *, SMRange>> getSuperClasses() const {
return SuperClasses;
}
/// Append the direct super classes of this record to Classes.
void getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const;
bool isTemplateArg(Init *Name) const {
for (Init *TA : TemplateArgs)
if (TA == Name) return true;
return false;
}
const RecordVal *getValue(const Init *Name) const {
for (const RecordVal &Val : Values)
if (Val.Name == Name) return &Val;
return nullptr;
}
const RecordVal *getValue(StringRef Name) const {
return getValue(StringInit::get(Name));
}
RecordVal *getValue(const Init *Name) {
return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
RecordVal *getValue(StringRef Name) {
return const_cast<RecordVal *>(static_cast<const Record *>(this)->getValue(Name));
}
void addTemplateArg(Init *Name) {
assert(!isTemplateArg(Name) && "Template arg already defined!");
TemplateArgs.push_back(Name);
}
void addValue(const RecordVal &RV) {
assert(getValue(RV.getNameInit()) == nullptr && "Value already added!");
Values.push_back(RV);
}
void removeValue(Init *Name) {
for (unsigned i = 0, e = Values.size(); i != e; ++i)
if (Values[i].getNameInit() == Name) {
Values.erase(Values.begin()+i);
return;
}
llvm_unreachable("Cannot remove an entry that does not exist!");
}
void removeValue(StringRef Name) {
removeValue(StringInit::get(Name));
}
bool isSubClassOf(const Record *R) const {
for (const auto &SCPair : SuperClasses)
if (SCPair.first == R)
return true;
return false;
}
bool isSubClassOf(StringRef Name) const {
for (const auto &SCPair : SuperClasses) {
if (const auto *SI = dyn_cast<StringInit>(SCPair.first->getNameInit())) {
if (SI->getValue() == Name)
return true;
} else if (SCPair.first->getNameInitAsString() == Name) {
return true;
}
}
return false;
}
void addSuperClass(Record *R, SMRange Range) {
assert(!TheInit && "changing type of record after it has been referenced");
assert(!isSubClassOf(R) && "Already subclassing record!");
SuperClasses.push_back(std::make_pair(R, Range));
}
/// If there are any field references that refer to fields
/// that have been filled in, we can propagate the values now.
///
/// This is a final resolve: any error messages, e.g. due to undefined
/// !cast references, are generated now.
void resolveReferences();
/// Apply the resolver to the name of the record as well as to the
/// initializers of all fields of the record except SkipVal.
///
/// The resolver should not resolve any of the fields itself, to avoid
/// recursion / infinite loops.
void resolveReferences(Resolver &R, const RecordVal *SkipVal = nullptr);
/// If anything in this record refers to RV, replace the
/// reference to RV with the RHS of RV. If RV is null, we resolve all
/// possible references.
void resolveReferencesTo(const RecordVal *RV);
RecordKeeper &getRecords() const {
return TrackedRecords;
}
bool isAnonymous() const {
return IsAnonymous;
}
void print(raw_ostream &OS) const;
void dump() const;
//===--------------------------------------------------------------------===//
// High-level methods useful to tablegen back-ends
//
/// Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
Init *getValueInit(StringRef FieldName) const;
/// Return true if the named field is unset.
bool isValueUnset(StringRef FieldName) const {
return isa<UnsetInit>(getValueInit(FieldName));
}
/// This method looks up the specified field and returns
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
StringRef getValueAsString(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
BitsInit *getValueAsBitsInit(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a ListInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
ListInit *getValueAsListInit(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of records, throwing an exception if the
/// field does not exist or if the value is not the right type.
std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of integers, throwing an exception if the
/// field does not exist or if the value is not the right type.
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of strings, throwing an exception if the
/// field does not exist or if the value is not the right type.
std::vector<StringRef> getValueAsListOfStrings(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
Record *getValueAsDef(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
bool getValueAsBit(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a bit. If the field is unset, sets Unset to true and
/// returns false.
bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const;
/// This method looks up the specified field and returns its
/// value as an int64_t, throwing an exception if the field does not exist or
/// if the value is not the right type.
int64_t getValueAsInt(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as an Dag, throwing an exception if the field does not exist or if
/// the value is not the right type.
DagInit *getValueAsDag(StringRef FieldName) const;
};
raw_ostream &operator<<(raw_ostream &OS, const Record &R);
class RecordKeeper {
friend class RecordRecTy;
using RecordMap = std::map<std::string, std::unique_ptr<Record>>;
RecordMap Classes, Defs;
FoldingSet<RecordRecTy> RecordTypePool;
std::map<std::string, Init *> ExtraGlobals;
unsigned AnonCounter = 0;
public:
const RecordMap &getClasses() const { return Classes; }
const RecordMap &getDefs() const { return Defs; }
Record *getClass(StringRef Name) const {
auto I = Classes.find(Name);
return I == Classes.end() ? nullptr : I->second.get();
}
Record *getDef(StringRef Name) const {
auto I = Defs.find(Name);
return I == Defs.end() ? nullptr : I->second.get();
}
Init *getGlobal(StringRef Name) const {
if (Record *R = getDef(Name))
return R->getDefInit();
auto It = ExtraGlobals.find(Name);
return It == ExtraGlobals.end() ? nullptr : It->second;
}
void addClass(std::unique_ptr<Record> R) {
bool Ins = Classes.insert(std::make_pair(R->getName(),
std::move(R))).second;
(void)Ins;
assert(Ins && "Class already exists");
}
void addDef(std::unique_ptr<Record> R) {
bool Ins = Defs.insert(std::make_pair(R->getName(),
std::move(R))).second;
(void)Ins;
assert(Ins && "Record already exists");
}
void addExtraGlobal(StringRef Name, Init *I) {
bool Ins = ExtraGlobals.insert(std::make_pair(Name, I)).second;
(void)Ins;
assert(!getDef(Name));
assert(Ins && "Global already exists");
}
Init *getNewAnonymousName();
//===--------------------------------------------------------------------===//
// High-level helper methods, useful for tablegen backends...
/// This method returns all concrete definitions
/// that derive from the specified class name. A class with the specified
/// name must exist.
std::vector<Record *> getAllDerivedDefinitions(StringRef ClassName) const;
void dump() const;
};
/// Sorting predicate to sort record pointers by name.
struct LessRecord {
bool operator()(const Record *Rec1, const Record *Rec2) const {
return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
}
};
/// Sorting predicate to sort record pointers by their
/// unique ID. If you just need a deterministic order, use this, since it
/// just compares two `unsigned`; the other sorting predicates require
/// string manipulation.
struct LessRecordByID {
bool operator()(const Record *LHS, const Record *RHS) const {
return LHS->getID() < RHS->getID();
}
};
/// Sorting predicate to sort record pointers by their
/// name field.
struct LessRecordFieldName {
bool operator()(const Record *Rec1, const Record *Rec2) const {
return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
}
};
struct LessRecordRegister {
static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; }
struct RecordParts {
SmallVector<std::pair< bool, StringRef>, 4> Parts;
RecordParts(StringRef Rec) {
if (Rec.empty())
return;
size_t Len = 0;
const char *Start = Rec.data();
const char *Curr = Start;
bool isDigitPart = ascii_isdigit(Curr[0]);
for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) {
bool isDigit = ascii_isdigit(Curr[I]);
if (isDigit != isDigitPart) {
Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
Len = 0;
Start = &Curr[I];
isDigitPart = ascii_isdigit(Curr[I]);
}
}
// Push the last part.
Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
}
size_t size() { return Parts.size(); }
std::pair<bool, StringRef> getPart(size_t i) {
assert (i < Parts.size() && "Invalid idx!");
return Parts[i];
}
};
bool operator()(const Record *Rec1, const Record *Rec2) const {
RecordParts LHSParts(StringRef(Rec1->getName()));
RecordParts RHSParts(StringRef(Rec2->getName()));
size_t LHSNumParts = LHSParts.size();
size_t RHSNumParts = RHSParts.size();
assert (LHSNumParts && RHSNumParts && "Expected at least one part!");
if (LHSNumParts != RHSNumParts)
return LHSNumParts < RHSNumParts;
// We expect the registers to be of the form [_a-zA-Z]+([0-9]*[_a-zA-Z]*)*.
for (size_t I = 0, E = LHSNumParts; I < E; I+=2) {
std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I);
std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I);
// Expect even part to always be alpha.
assert (LHSPart.first == false && RHSPart.first == false &&
"Expected both parts to be alpha.");
if (int Res = LHSPart.second.compare(RHSPart.second))
return Res < 0;
}
for (size_t I = 1, E = LHSNumParts; I < E; I+=2) {
std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I);
std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I);
// Expect odd part to always be numeric.
assert (LHSPart.first == true && RHSPart.first == true &&
"Expected both parts to be numeric.");
if (LHSPart.second.size() != RHSPart.second.size())
return LHSPart.second.size() < RHSPart.second.size();
unsigned LHSVal, RHSVal;
bool LHSFailed = LHSPart.second.getAsInteger(10, LHSVal); (void)LHSFailed;
assert(!LHSFailed && "Unable to convert LHS to integer.");
bool RHSFailed = RHSPart.second.getAsInteger(10, RHSVal); (void)RHSFailed;
assert(!RHSFailed && "Unable to convert RHS to integer.");
if (LHSVal != RHSVal)
return LHSVal < RHSVal;
}
return LHSNumParts < RHSNumParts;
}
};
raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
//===----------------------------------------------------------------------===//
// Resolvers
//===----------------------------------------------------------------------===//
/// Interface for looking up the initializer for a variable name, used by
/// Init::resolveReferences.
class Resolver {
Record *CurRec;
bool IsFinal = false;
public:
explicit Resolver(Record *CurRec) : CurRec(CurRec) {}
virtual ~Resolver() {}
Record *getCurrentRecord() const { return CurRec; }
/// Return the initializer for the given variable name (should normally be a
/// StringInit), or nullptr if the name could not be resolved.
virtual Init *resolve(Init *VarName) = 0;
// Whether bits in a BitsInit should stay unresolved if resolving them would
// result in a ? (UnsetInit). This behavior is used to represent instruction
// encodings by keeping references to unset variables within a record.
virtual bool keepUnsetBits() const { return false; }
// Whether this is the final resolve step before adding a record to the
// RecordKeeper. Error reporting during resolve and related constant folding
// should only happen when this is true.
bool isFinal() const { return IsFinal; }
void setFinal(bool Final) { IsFinal = Final; }
};
/// Resolve arbitrary mappings.
class MapResolver final : public Resolver {
struct MappedValue {
Init *V;
bool Resolved;
MappedValue() : V(nullptr), Resolved(false) {}
MappedValue(Init *V, bool Resolved) : V(V), Resolved(Resolved) {}
};
DenseMap<Init *, MappedValue> Map;
public:
explicit MapResolver(Record *CurRec = nullptr) : Resolver(CurRec) {}
void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; }
Init *resolve(Init *VarName) override;
};
/// Resolve all variables from a record except for unset variables.
class RecordResolver final : public Resolver {
DenseMap<Init *, Init *> Cache;
SmallVector<Init *, 4> Stack;
public:
explicit RecordResolver(Record &R) : Resolver(&R) {}
Init *resolve(Init *VarName) override;
bool keepUnsetBits() const override { return true; }
};
/// Resolve all references to a specific RecordVal.
//
// TODO: This is used for resolving references to template arguments, in a
// rather inefficient way. Change those uses to resolve all template
// arguments simultaneously and get rid of this class.
class RecordValResolver final : public Resolver {
const RecordVal *RV;
public:
explicit RecordValResolver(Record &R, const RecordVal *RV)
: Resolver(&R), RV(RV) {}
Init *resolve(Init *VarName) override {
if (VarName == RV->getNameInit())
return RV->getValue();
return nullptr;
}
};
/// Delegate resolving to a sub-resolver, but shadow some variable names.
class ShadowResolver final : public Resolver {
Resolver &R;
DenseSet<Init *> Shadowed;
public:
explicit ShadowResolver(Resolver &R)
: Resolver(R.getCurrentRecord()), R(R) {
setFinal(R.isFinal());
}
void addShadow(Init *Key) { Shadowed.insert(Key); }
Init *resolve(Init *VarName) override {
if (Shadowed.count(VarName))
return nullptr;
return R.resolve(VarName);
}
};
/// (Optionally) delegate resolving to a sub-resolver, and keep track whether
/// there were unresolved references.
class TrackUnresolvedResolver final : public Resolver {
Resolver *R;
bool FoundUnresolved = false;
public:
explicit TrackUnresolvedResolver(Resolver *R = nullptr)
: Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {}
bool foundUnresolved() const { return FoundUnresolved; }
Init *resolve(Init *VarName) override;
};
/// Do not resolve anything, but keep track of whether a given variable was
/// referenced.
class HasReferenceResolver final : public Resolver {
Init *VarNameToTrack;
bool Found = false;
public:
explicit HasReferenceResolver(Init *VarNameToTrack)
: Resolver(nullptr), VarNameToTrack(VarNameToTrack) {}
bool found() const { return Found; }
Init *resolve(Init *VarName) override;
};
void EmitJSON(RecordKeeper &RK, raw_ostream &OS);
} // end namespace llvm
#endif // LLVM_TABLEGEN_RECORD_H
|