17#include "mlir/IR/DialectImplementation.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/TypeSwitch.h"
23using namespace firrtl;
25using mlir::OptionalParseResult;
26using mlir::TypeStorageAllocator;
33#define GET_TYPEDEF_CLASSES
34#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
49 auto printWidthQualifier = [&](std::optional<int32_t> width) {
51 os <<
'<' << *width <<
'>';
53 bool anyFailed =
false;
54 TypeSwitch<Type>(type)
55 .Case<ClockType>([&](
auto) { os <<
"clock"; })
56 .Case<ResetType>([&](
auto) { os <<
"reset"; })
57 .Case<AsyncResetType>([&](
auto) { os <<
"asyncreset"; })
58 .Case<SIntType>([&](
auto sIntType) {
60 printWidthQualifier(sIntType.getWidth());
62 .Case<UIntType>([&](
auto uIntType) {
64 printWidthQualifier(uIntType.getWidth());
66 .Case<AnalogType>([&](
auto analogType) {
68 printWidthQualifier(analogType.getWidth());
70 .Case<BundleType, OpenBundleType>([&](
auto bundleType) {
71 if (firrtl::type_isa<OpenBundleType>(bundleType))
74 llvm::interleaveComma(bundleType, os, [&](
auto element) {
75 StringRef fieldName = element.name.getValue();
76 bool isLiteralIdentifier =
77 !fieldName.empty() && llvm::isDigit(fieldName.front());
78 if (isLiteralIdentifier)
80 os << element.name.getValue();
81 if (isLiteralIdentifier)
90 .Case<FEnumType>([&](
auto fenumType) {
92 std::optional<APInt> previous;
93 llvm::interleaveComma(
94 fenumType, os, [&](FEnumType::EnumElement element) {
96 os << element.name.getValue();
99 auto value = element.value.getValue();
104 if (value != previous) {
106 os.printAttributeWithoutType(element.value);
108 }
else if (!element.value.getValue().isZero()) {
110 os.printAttributeWithoutType(element.value);
115 bool skipType =
false;
116 if (
auto type = dyn_cast<UIntType>(element.type))
117 if (type.getWidth() == 0)
126 .Case<FVectorType, OpenVectorType>([&](
auto vectorType) {
127 if (firrtl::type_isa<OpenVectorType>(vectorType))
131 os <<
", " << vectorType.getNumElements() <<
'>';
133 .Case<RefType>([&](RefType refType) {
134 if (refType.getForceable())
138 if (
auto layer = refType.getLayer())
142 .Case<LHSType>([&](LHSType lhstype) {
147 .Case<StringType>([&](
auto stringType) { os <<
"string"; })
148 .Case<FIntegerType>([&](
auto integerType) { os <<
"integer"; })
149 .Case<BoolType>([&](
auto boolType) { os <<
"bool"; })
150 .Case<DoubleType>([&](
auto doubleType) { os <<
"double"; })
151 .Case<ListType>([&](
auto listType) {
156 .Case<RegistryType>([&](
auto registryType) {
161 .Case<PathType>([&](
auto pathType) { os <<
"path"; })
162 .Case<BaseTypeAliasType>([&](BaseTypeAliasType alias) {
163 os <<
"alias<" << alias.getName().getValue() <<
", ";
167 .Case<ClassType>([&](ClassType type) {
169 type.printInterface(os);
172 .Case<AnyRefType>([&](AnyRefType type) { os <<
"anyref"; })
173 .Case<FStringType>([&](
auto) { os <<
"fstring"; })
174 .Case<DomainType>([&](DomainType type) {
176 os.printSymbolName(type.getName().getValue());
178 llvm::interleaveComma(type.getFields(), os, [&](Attribute attr) {
179 auto field = cast<DomainFieldAttr>(attr);
180 os << field.getName().getValue() <<
": ";
181 os.printType(field.getType());
186 .Default([&](
auto) { anyFailed =
true; });
187 return failure(anyFailed);
198 assert(
false &&
"type to print unknown to FIRRTL dialect");
233 const char constPrefix[] =
"const.";
234 if (name.starts_with(constPrefix)) {
236 name = name.drop_front(std::size(constPrefix) - 1);
239 auto *
context = parser.getContext();
244 if (name ==
"asyncreset")
247 if (name ==
"sint" || name ==
"uint" || name ==
"analog") {
250 if (!parser.parseOptionalLess()) {
251 if (parser.parseInteger(width) || parser.parseGreater())
255 return parser.emitError(parser.getNameLoc(),
"unknown width"),
261 else if (name ==
"uint")
270 if (name ==
"bundle") {
271 SmallVector<BundleType::BundleElement, 4> elements;
273 auto parseBundleElement = [&]() -> ParseResult {
278 if (failed(parser.parseKeywordOrString(&nameStr)))
282 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
286 elements.push_back({StringAttr::get(
context, name), isFlip, type});
290 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
294 result = parser.getChecked<BundleType>(
context, elements,
isConst);
295 return failure(!result);
297 if (name ==
"openbundle") {
298 SmallVector<OpenBundleType::BundleElement, 4> elements;
300 auto parseBundleElement = [&]() -> ParseResult {
305 if (failed(parser.parseKeywordOrString(&nameStr)))
309 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
313 elements.push_back({StringAttr::get(
context, name), isFlip, type});
317 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
321 result = parser.getChecked<OpenBundleType>(
context, elements,
isConst);
322 return failure(!result);
325 if (name ==
"enum") {
326 SmallVector<StringAttr> names;
327 SmallVector<APInt> values;
328 SmallVector<FIRRTLBaseType> types;
329 auto parseEnumElement = [&]() -> ParseResult {
332 if (failed(parser.parseKeywordOrString(&nameStr)))
334 names.push_back(StringAttr::get(
context, nameStr));
340 if (succeeded(parser.parseOptionalEqual())) {
341 if (parser.parseInteger(value))
343 }
else if (values.empty()) {
349 auto &prev = values.back();
350 if (prev.isMaxValue())
351 value = prev.zext(prev.getBitWidth() + 1);
356 values.push_back(std::move(value));
360 if (succeeded(parser.parseOptionalColon())) {
364 type = UIntType::get(parser.getContext(), 0);
366 types.push_back(type);
371 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
376 unsigned bitwidth = 0;
377 for (
auto &value : values)
378 bitwidth = std::max(bitwidth, value.getActiveBits());
379 auto tagType = IntegerType::get(
context, bitwidth, IntegerType::Unsigned);
381 SmallVector<FEnumType::EnumElement, 4> elements;
382 for (
auto [name, value, type] : llvm::zip(names, values, types)) {
383 auto tagValue = value.zextOrTrunc(bitwidth);
384 elements.push_back({name, IntegerAttr::get(tagType, tagValue), type});
387 if (failed(FEnumType::verify(
388 [&]() {
return parser.emitError(parser.getNameLoc()); }, elements,
392 result = parser.getChecked<FEnumType>(
context, elements,
isConst);
393 return failure(!result);
396 if (name ==
"vector") {
401 parser.parseComma() || parser.parseInteger(width) ||
402 parser.parseGreater())
407 if (name ==
"openvector") {
412 parser.parseComma() || parser.parseInteger(width) ||
413 parser.parseGreater())
418 return failure(!result);
422 if (name ==
"ref" || name ==
"probe") {
429 if (parser.parseOptionalComma().succeeded())
430 if (parser.parseOptionalAttribute(layer).value())
431 return parser.emitError(parser.getNameLoc(),
432 "expected symbol reference");
433 if (parser.parseGreater())
436 if (failed(RefType::verify(
437 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
441 return result = RefType::get(type,
false, layer), success();
446 parser.parseGreater())
448 if (!isa<FIRRTLBaseType>(type))
449 return parser.emitError(parser.getNameLoc(),
"expected base type");
450 result = parser.getChecked<LHSType>(
context, cast<FIRRTLBaseType>(type));
451 return failure(!result);
453 if (name ==
"rwprobe") {
458 if (parser.parseOptionalComma().succeeded())
459 if (parser.parseOptionalAttribute(layer).value())
460 return parser.emitError(parser.getNameLoc(),
461 "expected symbol reference");
462 if (parser.parseGreater())
465 if (failed(RefType::verify(
466 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
true,
470 return result = RefType::get(type,
true, layer), success();
472 if (name ==
"class") {
474 return parser.emitError(parser.getNameLoc(),
"classes cannot be const");
476 if (parser.parseLess() || ClassType::parseInterface(parser, classType) ||
477 parser.parseGreater())
482 if (name ==
"anyref") {
484 return parser.emitError(parser.getNameLoc(),
"any refs cannot be const");
486 result = AnyRefType::get(parser.getContext());
489 if (name ==
"string") {
491 parser.emitError(parser.getNameLoc(),
"strings cannot be const");
494 result = StringType::get(parser.getContext());
497 if (name ==
"integer") {
499 parser.emitError(parser.getNameLoc(),
"bigints cannot be const");
502 result = FIntegerType::get(parser.getContext());
505 if (name ==
"bool") {
507 parser.emitError(parser.getNameLoc(),
"bools cannot be const");
510 result = BoolType::get(parser.getContext());
513 if (name ==
"double") {
515 parser.emitError(parser.getNameLoc(),
"doubles cannot be const");
518 result = DoubleType::get(parser.getContext());
521 if (name ==
"list") {
523 parser.emitError(parser.getNameLoc(),
"lists cannot be const");
528 parser.parseGreater())
535 if (name ==
"registry") {
537 parser.emitError(parser.getNameLoc(),
"registries cannot be const");
542 parser.parseGreater())
549 if (name ==
"path") {
551 parser.emitError(parser.getNameLoc(),
"path cannot be const");
554 result = PathType::get(parser.getContext());
557 if (name ==
"alias") {
560 if (parser.parseLess() || parser.parseKeyword(&name) ||
562 parser.parseGreater())
566 BaseTypeAliasType::get(StringAttr::get(
context, name), type),
569 if (name ==
"fstring") {
570 return result = FStringType::get(
context), success();
572 if (name ==
"domain") {
575 DomainType domainType;
576 if (parser.parseLess() || DomainType::parseInterface(parser, domainType) ||
577 parser.parseGreater())
592static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
595 if (parseResult.has_value())
596 return parseResult.value();
599 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL dialect type: \"")
611 if (failed(
parseType(type, name, parser)))
613 result = type_dyn_cast<FIRRTLType>(type);
616 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL type: \"")
626 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type)) {
630 parser.emitError(parser.getNameLoc(),
"expected base type, found ") << type;
639 if (
auto prop = type_dyn_cast<PropertyType>(type)) {
643 parser.emitError(parser.getNameLoc(),
"expected property type, found ")
656 if (parser.parseKeyword(&name))
666 if (parser.parseKeyword(&name))
676 if (parser.parseKeyword(&name))
687void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os)
const {
692Type FIRRTLDialect::parseType(DialectAsmParser &parser)
const {
695 if (parser.parseKeyword(&name) ||
::parseType(result, name, parser))
738bool FIRRTLType::isGround() {
739 return TypeSwitch<FIRRTLType, bool>(*
this)
740 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
741 AnalogType>([](Type) {
return true; })
742 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType>(
743 [](Type) {
return false; })
744 .Case<BaseTypeAliasType>([](BaseTypeAliasType alias) {
745 return alias.getAnonymousType().isGround();
748 .Case<PropertyType, RefType>([](Type) {
return false; })
750 llvm_unreachable(
"unknown FIRRTL type");
756 return TypeSwitch<FIRRTLType, bool>(*
this)
758 [](
auto type) {
return type.isConst(); })
765 return TypeSwitch<FIRRTLType, RecursiveTypeProperties>(*
this)
766 .Case<ClockType, ResetType, AsyncResetType>([](
FIRRTLBaseType type) {
773 firrtl::type_isa<ResetType>(type)};
775 .Case<SIntType, UIntType>([](
auto type) {
777 true,
false,
false, type.isConst(),
false, !type.hasWidth(),
false};
779 .Case<AnalogType>([](
auto type) {
781 true,
false,
true, type.isConst(),
false, !type.hasWidth(),
false};
783 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType,
784 RefType, BaseTypeAliasType>(
785 [](
auto type) {
return type.getRecursiveTypeProperties(); })
786 .Case<PropertyType>([](
auto type) {
788 false,
false,
false};
791 [](
auto type) {
return type.getType().getRecursiveTypeProperties(); })
792 .Case<FStringType>([](
auto type) {
794 false,
false,
false};
796 .Case<DomainType>([](
auto type) {
798 false,
false,
false};
801 llvm_unreachable(
"unknown FIRRTL type");
808 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
809 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
810 AnalogType>([&](Type) {
return *
this; })
811 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
812 [](
auto type) {
return type.getAnonymousType(); })
814 llvm_unreachable(
"unknown FIRRTL type");
821 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
822 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
823 AnalogType, FEnumType>([&](Type) {
return *
this; })
824 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
825 [](
auto type) {
return type.getPassiveType(); })
827 llvm_unreachable(
"unknown FIRRTL type");
834 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
835 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
836 UIntType, BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
837 [&](
auto type) {
return type.getConstType(
isConst); })
839 llvm_unreachable(
"unknown FIRRTL type");
846 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
847 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
848 UIntType>([&](
auto type) {
return type.getConstType(
false); })
849 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
850 [&](
auto type) {
return type.getAllConstDroppedType(); })
852 llvm_unreachable(
"unknown FIRRTL type");
860 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
861 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
862 AnalogType, FEnumType>([&](Type) {
863 return UIntType::get(this->getContext(), 1, this->
isConst());
865 .Case<BundleType>([&](BundleType bundleType) {
866 SmallVector<BundleType::BundleElement, 4> newElements;
867 newElements.reserve(bundleType.getElements().size());
868 for (
auto elt : bundleType)
869 newElements.push_back(
870 {elt.name,
false , elt.type.getMaskType()});
871 return BundleType::get(this->getContext(), newElements,
872 bundleType.isConst());
874 .Case<FVectorType>([](FVectorType vectorType) {
875 return FVectorType::get(vectorType.getElementType().getMaskType(),
876 vectorType.getNumElements(),
877 vectorType.isConst());
879 .Case<BaseTypeAliasType>([](BaseTypeAliasType base) {
880 return base.getModifiedType(base.getInnerType().getMaskType());
883 llvm_unreachable(
"unknown FIRRTL type");
891 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
892 .Case<ClockType, ResetType, AsyncResetType>([](
auto a) {
return a; })
893 .Case<UIntType, SIntType, AnalogType>(
894 [&](
auto a) {
return a.get(this->getContext(), -1, a.isConst()); })
895 .Case<BundleType>([&](
auto a) {
896 SmallVector<BundleType::BundleElement, 4> newElements;
897 newElements.reserve(a.getElements().size());
899 newElements.push_back(
900 {elt.name, elt.isFlip, elt.type.getWidthlessType()});
901 return BundleType::get(this->getContext(), newElements, a.isConst());
903 .Case<FVectorType>([](
auto a) {
904 return FVectorType::get(a.getElementType().getWidthlessType(),
905 a.getNumElements(), a.isConst());
907 .Case<FEnumType>([&](FEnumType a) {
908 SmallVector<FEnumType::EnumElement, 4> newElements;
909 newElements.reserve(a.getNumElements());
911 newElements.push_back(
912 {elt.name, elt.value, elt.type.getWidthlessType()});
913 return FEnumType::get(this->getContext(), newElements, a.isConst());
915 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
916 return type.getModifiedType(type.getInnerType().getWidthlessType());
919 llvm_unreachable(
"unknown FIRRTL type");
929 return TypeSwitch<FIRRTLBaseType, int32_t>(*
this)
930 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
931 .Case<SIntType, UIntType>(
934 [](AnalogType analogType) {
return analogType.getWidthOrSentinel(); })
935 .Case<FEnumType>([&](FEnumType fenum) {
return fenum.getBitWidth(); })
936 .Case<BundleType, FVectorType>([](Type) {
return -2; })
937 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
939 return type.getAnonymousType().getBitWidthOrSentinel();
942 llvm_unreachable(
"unknown FIRRTL type");
951 return TypeSwitch<FIRRTLType, bool>(*
this)
952 .Case<ResetType, AsyncResetType>([](Type) {
return true; })
954 [](UIntType a) {
return !a.hasWidth() || a.getWidth() == 1; })
955 .Case<BaseTypeAliasType>(
956 [](
auto type) {
return type.getInnerType().isResetType(); })
957 .Default([](Type) {
return false; });
961 return TypeSwitch<Type, bool>(type)
963 [](
auto base) {
return base.isConst(); })
968 return TypeSwitch<Type, bool>(type)
970 [](
auto base) {
return base.containsConst(); })
977 .
Case<BundleType>([&](
auto bundle) {
978 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
979 auto elt = bundle.getElement(i);
983 return bundle.getNumElements() == 0;
985 .Case<FVectorType>([&](
auto vector) {
986 if (vector.getNumElements() == 0)
990 .Case<FIRRTLBaseType>([](
auto groundType) {
993 .Case<RefType>([](
auto ref) {
return hasZeroBitWidth(ref.getType()); })
994 .Default([](
auto) {
return false; });
1004 BundleType::BundleElement srcElement,
1005 bool destOuterTypeIsConst,
1006 bool srcOuterTypeIsConst,
1007 bool requiresSameWidth) {
1008 if (destElement.name != srcElement.name)
1010 if (destElement.isFlip != srcElement.isFlip)
1013 if (destElement.isFlip) {
1014 std::swap(destElement, srcElement);
1015 std::swap(destOuterTypeIsConst, srcOuterTypeIsConst);
1019 destOuterTypeIsConst, srcOuterTypeIsConst,
1028 bool destOuterTypeIsConst,
1029 bool srcOuterTypeIsConst,
1030 bool requireSameWidths) {
1031 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1032 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1035 if (!destType || !srcType)
1036 return destFType == srcFType;
1038 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
1039 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
1042 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1043 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1044 if (destVectorType && srcVectorType)
1045 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1047 srcVectorType.getElementType(), destIsConst,
1048 srcIsConst, requireSameWidths);
1052 auto destBundleType = type_dyn_cast<BundleType>(destType);
1053 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1054 if (destBundleType && srcBundleType) {
1055 auto destElements = destBundleType.getElements();
1056 auto srcElements = srcBundleType.getElements();
1057 size_t numDestElements = destElements.size();
1058 if (numDestElements != srcElements.size())
1061 for (
size_t i = 0; i < numDestElements; ++i) {
1062 auto destElement = destElements[i];
1063 auto srcElement = srcElements[i];
1065 srcIsConst, requireSameWidths))
1073 auto dstEnumType = type_dyn_cast<FEnumType>(destType);
1074 auto srcEnumType = type_dyn_cast<FEnumType>(srcType);
1076 if (dstEnumType && srcEnumType) {
1077 if (dstEnumType.getNumElements() != srcEnumType.getNumElements())
1080 for (
const auto &[dst, src] : llvm::zip(dstEnumType, srcEnumType)) {
1082 if (dst.name != src.name)
1094 if (destIsConst && !srcIsConst)
1098 if (firrtl::type_isa<ResetType>(destType))
1099 return srcType.isResetType();
1102 if (firrtl::type_isa<ResetType>(srcType))
1103 return destType.isResetType();
1107 if (!requireSameWidths || destType.getBitWidthOrSentinel() == -1)
1108 srcType = srcType.getWidthlessType();
1109 if (!requireSameWidths || srcType.getBitWidthOrSentinel() == -1)
1110 destType = destType.getWidthlessType();
1113 return destType.getConstType(
false) == srcType.getConstType(
false);
1118 bool srcOuterTypeIsConst) {
1120 if (destFType == srcFType)
1123 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1124 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1127 if (!destType || !srcType)
1131 if (!destType.isPassive() || !srcType.isPassive())
1134 bool srcIsConst = srcType.isConst() || srcOuterTypeIsConst;
1137 if (destType.isConst() && !srcIsConst)
1142 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1143 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1144 if (destVectorType && srcVectorType)
1145 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1147 srcVectorType.getElementType(), srcIsConst);
1148 if (destVectorType != srcVectorType)
1153 auto destBundleType = type_dyn_cast<BundleType>(destType);
1154 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1155 if (destBundleType && srcBundleType) {
1156 auto destElements = destBundleType.getElements();
1157 auto srcElements = srcBundleType.getElements();
1158 size_t numDestElements = destElements.size();
1159 if (numDestElements != srcElements.size())
1162 return llvm::all_of_zip(
1163 destElements, srcElements,
1164 [&](
const auto &destElement,
const auto &srcElement) {
1165 return destElement.name == srcElement.name &&
1170 if (destBundleType != srcBundleType)
1175 return destType == srcType.getConstType(destType.isConst());
1179 auto dstRefType = type_dyn_cast<RefType>(dstType);
1180 auto srcRefType = type_dyn_cast<RefType>(srcType);
1181 if (!dstRefType || !srcRefType)
1183 if (dstRefType == srcRefType)
1185 if (dstRefType.getForceable() && !srcRefType.getForceable())
1197 bool srcOuterTypeIsConst) ->
bool {
1203 assert(dest.isPassive() && src.isPassive());
1205 bool srcIsConst = src.isConst() || srcOuterTypeIsConst;
1208 if (dest.isConst() && !srcIsConst)
1214 if (
auto destVectorType = type_dyn_cast<FVectorType>(dest)) {
1215 auto srcVectorType = type_dyn_cast<FVectorType>(src);
1216 return srcVectorType &&
1217 destVectorType.getNumElements() ==
1218 srcVectorType.getNumElements() &&
1219 f(f, destVectorType.getElementType(),
1220 srcVectorType.getElementType(), srcIsConst);
1223 if (
auto destBundleType = type_dyn_cast<BundleType>(dest)) {
1224 auto srcBundleType = type_dyn_cast<BundleType>(src);
1228 auto destElements = destBundleType.getElements();
1229 auto srcElements = srcBundleType.getElements();
1231 return destElements.size() == srcElements.size() &&
1233 destElements, srcElements,
1234 [&](
const auto &destElement,
const auto &srcElement) {
1235 return destElement.name == srcElement.name &&
1236 f(f, destElement.type, srcElement.type, srcIsConst);
1240 if (
auto destEnumType = type_dyn_cast<FEnumType>(dest)) {
1241 auto srcEnumType = type_dyn_cast<FEnumType>(src);
1244 auto destElements = destEnumType.getElements();
1245 auto srcElements = srcEnumType.getElements();
1247 return destElements.size() == srcElements.size() &&
1249 destElements, srcElements,
1250 [&](
const auto &destElement,
const auto &srcElement) {
1251 return destElement.name == srcElement.name &&
1252 f(f, destElement.type, srcElement.type, srcIsConst);
1257 if (type_isa<ResetType>(dest))
1258 return src.isResetType();
1262 src = src.getConstType(dest.isConst());
1265 if (dest.getBitWidthOrSentinel() == -1)
1266 src = src.getWidthlessType();
1271 return recurse(recurse, dstRefType.getType(), srcRefType.getType(),
false);
1278 return TypeSwitch<FIRRTLBaseType, bool>(dstType)
1279 .Case<BundleType>([&](
auto dstBundle) {
1280 auto srcBundle = type_cast<BundleType>(srcType);
1281 for (
size_t i = 0, n = dstBundle.getNumElements(); i < n; ++i) {
1282 auto srcElem = srcBundle.getElement(i);
1283 auto dstElem = dstBundle.getElement(i);
1284 if (dstElem.isFlip) {
1294 .Case<FVectorType>([&](
auto vector) {
1296 type_cast<FVectorType>(srcType).getElementType());
1298 .Default([&](
auto dstGround) {
1301 return destWidth <= -1 || srcWidth <= -1 || destWidth >= srcWidth;
1312 if (
auto destBaseType = type_dyn_cast<FIRRTLBaseType>(lhs))
1313 if (
auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(rhs))
1316 if (
auto destRefType = type_dyn_cast<RefType>(lhs))
1317 if (
auto srcRefType = type_dyn_cast<RefType>(rhs))
1319 srcRefType.getType());
1327 return type_cast<FIRRTLBaseType>(anyBaseFIRRTLType).getPassiveType();
1331 return llvm::TypeSwitch<Type, bool>(type)
1333 return !type.containsReference() &&
1334 (!type.isPassive() || type.containsAnalog());
1342 if (isa<FIRRTLBaseType>(type))
1345 if (
auto bundle = dyn_cast<OpenBundleType>(type))
1346 return llvm::any_of(bundle,
1348 if (
auto vector = dyn_cast<OpenVectorType>(type))
1361 int32_t widthOrSentinel,
bool isConst) {
1368 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1369 return sintType.getWidthOrSentinel();
1370 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1371 return uintType.getWidthOrSentinel();
1382 using KeyTy = std::tuple<int32_t, char>;
1399 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1408SIntType SIntType::get(MLIRContext *
context) {
return get(
context, -1,
false); }
1410SIntType SIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1415LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1416 int32_t widthOrSentinel,
bool isConst) {
1417 if (widthOrSentinel < -1)
1418 return emitError() <<
"invalid width";
1422int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1424SIntType SIntType::getConstType(
bool isConst)
const {
1427 return get(getContext(), getWidthOrSentinel(),
isConst);
1436UIntType UIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1441LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1442 int32_t widthOrSentinel,
bool isConst) {
1443 if (widthOrSentinel < -1)
1444 return emitError() <<
"invalid width";
1448int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1450UIntType UIntType::getConstType(
bool isConst)
const {
1453 return get(getContext(), getWidthOrSentinel(),
isConst);
1462 using KeyTy = std::tuple<ArrayRef<BundleType::BundleElement>,
char>;
1467 props{true, false, false,
isConst, false, false, false} {
1468 uint64_t fieldID = 0;
1471 auto type = element.type;
1472 auto eltInfo = type.getRecursiveTypeProperties();
1499 std::get<0>(key),
static_cast<bool>(std::get<1>(key)));
1513BundleType BundleType::get(MLIRContext *
context,
1514 ArrayRef<BundleElement> elements,
bool isConst) {
1518auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1519 return getImpl()->elements;
1524 return getImpl()->props;
1529 auto *impl = getImpl();
1532 if (impl->passiveType)
1533 return impl->passiveType;
1536 if (impl->props.isPassive) {
1537 impl->passiveType = *
this;
1542 SmallVector<BundleType::BundleElement, 16> newElements;
1543 newElements.reserve(impl->elements.size());
1544 for (
auto &elt : impl->elements) {
1545 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1548 auto passiveType = BundleType::get(getContext(), newElements,
isConst());
1549 impl->passiveType = passiveType;
1553BundleType BundleType::getConstType(
bool isConst)
const {
1556 return get(getContext(), getElements(),
isConst);
1559BundleType BundleType::getAllConstDroppedType() {
1563 SmallVector<BundleElement> constDroppedElements(
1564 llvm::map_range(getElements(), [](BundleElement element) {
1565 element.type = element.type.getAllConstDroppedType();
1568 return get(getContext(), constDroppedElements,
false);
1571std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1572 for (
const auto &it :
llvm::enumerate(getElements())) {
1573 auto element = it.value();
1574 if (element.name == name) {
1575 return unsigned(it.index());
1578 return std::nullopt;
1581std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1582 for (
const auto &it :
llvm::enumerate(getElements())) {
1583 auto element = it.value();
1584 if (element.name.getValue() == name) {
1585 return unsigned(it.index());
1588 return std::nullopt;
1591StringAttr BundleType::getElementNameAttr(
size_t index) {
1592 assert(index < getNumElements() &&
1593 "index must be less than number of fields in bundle");
1594 return getElements()[index].name;
1597StringRef BundleType::getElementName(
size_t index) {
1598 return getElementNameAttr(index).getValue();
1601std::optional<BundleType::BundleElement>
1602BundleType::getElement(StringAttr name) {
1603 if (
auto maybeIndex = getElementIndex(name))
1604 return getElements()[*maybeIndex];
1605 return std::nullopt;
1608std::optional<BundleType::BundleElement>
1609BundleType::getElement(StringRef name) {
1610 if (
auto maybeIndex = getElementIndex(name))
1611 return getElements()[*maybeIndex];
1612 return std::nullopt;
1616BundleType::BundleElement BundleType::getElement(
size_t index) {
1617 assert(index < getNumElements() &&
1618 "index must be less than number of fields in bundle");
1619 return getElements()[index];
1623 auto element = getElement(name);
1628 auto element = getElement(name);
1633 assert(index < getNumElements() &&
1634 "index must be less than number of fields in bundle");
1635 return getElements()[index].type;
1638uint64_t BundleType::getFieldID(uint64_t index)
const {
1639 return getImpl()->fieldIDs[index];
1642uint64_t BundleType::getIndexForFieldID(uint64_t fieldID)
const {
1643 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1644 auto fieldIDs = getImpl()->fieldIDs;
1645 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1646 return std::distance(fieldIDs.begin(), it);
1649std::pair<uint64_t, uint64_t>
1650BundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1653 return {index, fieldID - elementFieldID};
1656std::pair<Type, uint64_t>
1657BundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1661 auto subfieldType = getElementType(subfieldIndex);
1662 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1663 return {subfieldType, subfieldID};
1666uint64_t BundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1668std::pair<uint64_t, bool>
1669BundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1671 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1673 return std::make_pair(fieldID - childRoot,
1674 fieldID >= childRoot && fieldID <= rangeEnd);
1677bool BundleType::isConst()
const {
return getImpl()->isConst; }
1679BundleType::ElementType
1680BundleType::getElementTypePreservingConst(
size_t index) {
1681 auto type = getElementType(index);
1682 return type.getConstType(type.isConst() ||
isConst());
1687 auto *impl = getImpl();
1690 if (impl->anonymousType)
1691 return impl->anonymousType;
1694 if (!impl->props.containsTypeAlias) {
1695 impl->anonymousType = *
this;
1701 SmallVector<BundleType::BundleElement, 16> newElements;
1702 newElements.reserve(impl->elements.size());
1703 for (
auto &elt : impl->elements)
1704 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1706 auto anonymousType = BundleType::get(getContext(), newElements,
isConst());
1707 impl->anonymousType = anonymousType;
1708 return anonymousType;
1711LogicalResult BundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1712 ArrayRef<BundleElement> elements,
1714 SmallPtrSet<StringAttr, 4> nameSet;
1715 for (
auto &element : elements) {
1716 if (!nameSet.insert(element.name).second)
1717 return emitErrorFn() <<
"duplicate field name " << element.name
1729 using KeyTy = std::tuple<ArrayRef<OpenBundleType::BundleElement>,
char>;
1734 props{true, false, false,
isConst, false, false, false},
1736 uint64_t fieldID = 0;
1739 auto type = element.type;
1740 auto eltInfo = type.getRecursiveTypeProperties();
1769 static_cast<bool>(std::get<1>(key)));
1772 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1784OpenBundleType OpenBundleType::get(MLIRContext *
context,
1785 ArrayRef<BundleElement> elements,
1790auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1791 return getImpl()->elements;
1796 return getImpl()->props;
1799OpenBundleType OpenBundleType::getConstType(
bool isConst)
const {
1802 return get(getContext(), getElements(),
isConst);
1805std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1806 for (
const auto &it :
llvm::enumerate(getElements())) {
1807 auto element = it.value();
1808 if (element.name == name) {
1809 return unsigned(it.index());
1812 return std::nullopt;
1815std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1816 for (
const auto &it :
llvm::enumerate(getElements())) {
1817 auto element = it.value();
1818 if (element.name.getValue() == name) {
1819 return unsigned(it.index());
1822 return std::nullopt;
1825StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1826 assert(index < getNumElements() &&
1827 "index must be less than number of fields in bundle");
1828 return getElements()[index].name;
1831StringRef OpenBundleType::getElementName(
size_t index) {
1832 return getElementNameAttr(index).getValue();
1835std::optional<OpenBundleType::BundleElement>
1836OpenBundleType::getElement(StringAttr name) {
1837 if (
auto maybeIndex = getElementIndex(name))
1838 return getElements()[*maybeIndex];
1839 return std::nullopt;
1842std::optional<OpenBundleType::BundleElement>
1843OpenBundleType::getElement(StringRef name) {
1844 if (
auto maybeIndex = getElementIndex(name))
1845 return getElements()[*maybeIndex];
1846 return std::nullopt;
1850OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1851 assert(index < getNumElements() &&
1852 "index must be less than number of fields in bundle");
1853 return getElements()[index];
1856OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1857 auto element = getElement(name);
1861OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1862 auto element = getElement(name);
1866OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1867 assert(index < getNumElements() &&
1868 "index must be less than number of fields in bundle");
1869 return getElements()[index].type;
1872uint64_t OpenBundleType::getFieldID(uint64_t index)
const {
1873 return getImpl()->fieldIDs[index];
1876uint64_t OpenBundleType::getIndexForFieldID(uint64_t fieldID)
const {
1877 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1878 auto fieldIDs = getImpl()->fieldIDs;
1879 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1880 return std::distance(fieldIDs.begin(), it);
1883std::pair<uint64_t, uint64_t>
1884OpenBundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1887 return {index, fieldID - elementFieldID};
1890std::pair<Type, uint64_t>
1891OpenBundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1895 auto subfieldType = getElementType(subfieldIndex);
1896 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1897 return {subfieldType, subfieldID};
1900uint64_t OpenBundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1902std::pair<uint64_t, bool>
1903OpenBundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1905 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1907 return std::make_pair(fieldID - childRoot,
1908 fieldID >= childRoot && fieldID <= rangeEnd);
1911bool OpenBundleType::isConst()
const {
return getImpl()->isConst; }
1913OpenBundleType::ElementType
1914OpenBundleType::getElementTypePreservingConst(
size_t index) {
1915 auto type = getElementType(index);
1917 return TypeSwitch<FIRRTLType, ElementType>(type)
1918 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1919 return type.getConstType(type.isConst() ||
isConst());
1925OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1926 ArrayRef<BundleElement> elements,
bool isConst) {
1927 SmallPtrSet<StringAttr, 4> nameSet;
1928 for (
auto &element : elements) {
1929 if (!nameSet.insert(element.name).second)
1930 return emitErrorFn() <<
"duplicate field name " << element.name
1931 <<
" in openbundle";
1933 return emitErrorFn()
1934 <<
"'const' bundle cannot have references, but element "
1935 << element.name <<
" has type " << element.type;
1936 if (type_isa<LHSType>(element.type))
1937 return emitErrorFn() <<
"bundle element " << element.name
1938 <<
" cannot have a left-hand side type";
1950 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1968 static_cast<bool>(std::get<2>(key)));
1987 return getImpl()->elementType;
1990size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1994 return getImpl()->props;
1999 auto *impl = getImpl();
2002 if (impl->passiveType)
2003 return impl->passiveType;
2006 if (impl->elementType.getRecursiveTypeProperties().isPassive)
2007 return impl->passiveType = *
this;
2010 auto passiveType = FVectorType::get(getElementType().
getPassiveType(),
2012 impl->passiveType = passiveType;
2016FVectorType FVectorType::getConstType(
bool isConst)
const {
2019 return get(getElementType(), getNumElements(),
isConst);
2022FVectorType FVectorType::getAllConstDroppedType() {
2025 return get(getElementType().getAllConstDroppedType(), getNumElements(),
2031 auto *impl = getImpl();
2033 if (impl->anonymousType)
2034 return impl->anonymousType;
2037 if (!impl->props.containsTypeAlias)
2038 return impl->anonymousType = *
this;
2041 auto anonymousType = FVectorType::get(getElementType().getAnonymousType(),
2043 impl->anonymousType = anonymousType;
2044 return anonymousType;
2047uint64_t FVectorType::getFieldID(uint64_t index)
const {
2051uint64_t FVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2052 assert(fieldID &&
"fieldID must be at least 1");
2057std::pair<uint64_t, uint64_t>
2058FVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2061 return {index, fieldID - elementFieldID};
2064std::pair<Type, uint64_t>
2065FVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2071uint64_t FVectorType::getMaxFieldID()
const {
2072 return getNumElements() *
2076std::pair<uint64_t, bool>
2077FVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2081 return std::make_pair(fieldID - childRoot,
2082 fieldID >= childRoot && fieldID <= rangeEnd);
2085bool FVectorType::isConst()
const {
return getImpl()->isConst; }
2087FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
2088 auto type = getElementType();
2089 return type.getConstType(type.isConst() ||
isConst());
2097 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
2115 static_cast<bool>(std::get<2>(key)));
2130FIRRTLType OpenVectorType::getElementType()
const {
2131 return getImpl()->elementType;
2134size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
2138 return getImpl()->props;
2141OpenVectorType OpenVectorType::getConstType(
bool isConst)
const {
2144 return get(getElementType(), getNumElements(),
isConst);
2147uint64_t OpenVectorType::getFieldID(uint64_t index)
const {
2151uint64_t OpenVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2152 assert(fieldID &&
"fieldID must be at least 1");
2157std::pair<uint64_t, uint64_t>
2158OpenVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2161 return {index, fieldID - elementFieldID};
2164std::pair<Type, uint64_t>
2165OpenVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2171uint64_t OpenVectorType::getMaxFieldID()
const {
2173 return getNumElements() *
2177std::pair<uint64_t, bool>
2178OpenVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2182 return std::make_pair(fieldID - childRoot,
2183 fieldID >= childRoot && fieldID <= rangeEnd);
2186bool OpenVectorType::isConst()
const {
return getImpl()->isConst; }
2188OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2189 auto type = getElementType();
2191 return TypeSwitch<FIRRTLType, ElementType>(type)
2192 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2193 return type.getConstType(type.isConst() ||
isConst());
2199OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2203 return emitErrorFn() <<
"vector cannot be const with references";
2205 return emitErrorFn() <<
"vector cannot have a left-hand side type";
2214 using KeyTy = std::tuple<ArrayRef<FEnumType::EnumElement>,
char>;
2220 false,
false,
false};
2223 auto type = element.type;
2224 auto eltInfo = type.getRecursiveTypeProperties();
2226 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2253FEnumType FEnumType::get(::mlir::MLIRContext *
context,
2254 ArrayRef<EnumElement> elements,
bool isConst) {
2258ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2259 return getImpl()->elements;
2262FEnumType FEnumType::getConstType(
bool isConst)
const {
2263 return get(getContext(), getElements(),
isConst);
2266FEnumType FEnumType::getAllConstDroppedType() {
2270 SmallVector<EnumElement> constDroppedElements(
2271 llvm::map_range(getElements(), [](EnumElement element) {
2272 element.type = element.type.getAllConstDroppedType();
2275 return get(getContext(), constDroppedElements,
false);
2280 return getImpl()->recProps;
2283std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2284 for (
const auto &it :
llvm::enumerate(getElements())) {
2285 auto element = it.value();
2286 if (element.name == name) {
2287 return unsigned(it.index());
2290 return std::nullopt;
2293size_t FEnumType::getBitWidth() {
return getDataWidth() + getTagWidth(); }
2295size_t FEnumType::getDataWidth() {
return getImpl()->dataSize; }
2297size_t FEnumType::getTagWidth() {
2298 if (getElements().size() == 0)
2301 return cast<IntegerType>(getElements()[0].value.getType()).getWidth();
2304std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2305 for (
const auto &it :
llvm::enumerate(getElements())) {
2306 auto element = it.value();
2307 if (element.name.getValue() == name) {
2308 return unsigned(it.index());
2311 return std::nullopt;
2314StringAttr FEnumType::getElementNameAttr(
size_t index) {
2315 assert(index < getNumElements() &&
2316 "index must be less than number of fields in enum");
2317 return getElements()[index].name;
2320StringRef FEnumType::getElementName(
size_t index) {
2321 return getElementNameAttr(index).getValue();
2324IntegerAttr FEnumType::getElementValueAttr(
size_t index) {
2325 return getElements()[index].value;
2328APInt FEnumType::getElementValue(
size_t index) {
2329 return getElementValueAttr(index).getValue();
2333 return getElements()[index].type;
2336std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2337 if (
auto maybeIndex = getElementIndex(name))
2338 return getElements()[*maybeIndex];
2339 return std::nullopt;
2342std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2343 if (
auto maybeIndex = getElementIndex(name))
2344 return getElements()[*maybeIndex];
2345 return std::nullopt;
2349FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2350 assert(index < getNumElements() &&
2351 "index must be less than number of fields in enum");
2352 return getElements()[index];
2356 auto element = getElement(name);
2361 auto element = getElement(name);
2366 assert(index < getNumElements() &&
2367 "index must be less than number of fields in enum");
2368 return getElements()[index].type;
2371FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2372 auto type = getElementType(index);
2373 return type.getConstType(type.isConst() ||
isConst());
2376LogicalResult FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2377 ArrayRef<EnumElement> elements,
bool isConst) {
2379 IntegerAttr previous;
2380 SmallPtrSet<Attribute, 4> nameSet;
2382 for (
auto &elt : elements) {
2383 auto r = elt.type.getRecursiveTypeProperties();
2385 return emitErrorFn() <<
"enum field " << elt.name <<
" not passive";
2386 if (r.containsAnalog)
2387 return emitErrorFn() <<
"enum field " << elt.name <<
" contains analog";
2388 if (r.hasUninferredWidth)
2389 return emitErrorFn() <<
"enum field " << elt.name
2390 <<
" has uninferred width";
2391 if (r.hasUninferredReset)
2392 return emitErrorFn() <<
"enum field " << elt.name
2393 <<
" has uninferred reset";
2394 if (r.containsConst && !
isConst)
2395 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2397 if (!nameSet.insert(elt.name).second)
2398 return emitErrorFn() <<
"duplicate variant name " << elt.name
2402 previous = elt.value;
2405 auto current = elt.value;
2406 if (previous.getType() != current.getType())
2407 return emitErrorFn() <<
"enum variant " << elt.name <<
" has type"
2408 << current.getType()
2409 <<
" which is different than previous variant "
2410 << previous.getType();
2412 if (previous.getValue().getBitWidth() != current.getValue().getBitWidth())
2413 return emitErrorFn() <<
"enum variant " << elt.name <<
" has bitwidth"
2414 << current.getValue().getBitWidth()
2415 <<
" which is different than previous variant "
2416 << previous.getValue().getBitWidth();
2417 if (previous.getValue().uge(current.getValue()))
2418 return emitErrorFn()
2419 <<
"enum variant " << elt.name <<
" has value " << current
2420 <<
" which is not greater than previous variant " << previous;
2429 auto *impl = getImpl();
2431 if (impl->anonymousType)
2432 return impl->anonymousType;
2434 if (!impl->recProps.containsTypeAlias)
2435 return impl->anonymousType = *
this;
2437 SmallVector<FEnumType::EnumElement, 4> elements;
2439 for (
auto element : getElements())
2441 {element.name, element.value, element.type.getAnonymousType()});
2442 return impl->anonymousType = FEnumType::get(getContext(), elements);
2451 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2475auto BaseTypeAliasType::get(StringAttr name,
FIRRTLBaseType innerType)
2476 -> BaseTypeAliasType {
2477 return Base::get(name.getContext(), name, innerType);
2480auto BaseTypeAliasType::getName() const -> StringAttr {
2481 return getImpl()->name;
2485 return getImpl()->innerType;
2489 auto *impl = getImpl();
2490 if (impl->anonymousType)
2491 return impl->anonymousType;
2492 return impl->anonymousType = getInnerType().getAnonymousType();
2500 auto rtp = getInnerType().getRecursiveTypeProperties();
2508BaseTypeAliasType::getModifiedType(
FIRRTLBaseType newInnerType)
const {
2509 if (newInnerType == getInnerType())
2511 return newInnerType;
2516 return getModifiedType(getInnerType().getAllConstDroppedType());
2520 return getModifiedType(getInnerType().getConstType(
isConst));
2523std::pair<Type, uint64_t>
2524BaseTypeAliasType::getSubTypeByFieldID(uint64_t fieldID)
const {
2528uint64_t BaseTypeAliasType::getMaxFieldID()
const {
2532std::pair<uint64_t, bool>
2533BaseTypeAliasType::projectToChildFieldID(uint64_t fieldID,
2534 uint64_t index)
const {
2538uint64_t BaseTypeAliasType::getIndexForFieldID(uint64_t fieldID)
const {
2542uint64_t BaseTypeAliasType::getFieldID(uint64_t index)
const {
2546std::pair<uint64_t, uint64_t>
2547BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2556 return LHSType::get(type.getContext(), type);
2559LogicalResult LHSType::verify(function_ref<InFlightDiagnostic()> emitError,
2561 if (type.containsAnalog())
2562 return emitError() <<
"lhs type cannot contain an AnalogType";
2564 return emitError() <<
"lhs type cannot contain a non-passive type";
2565 if (type.containsReference())
2566 return emitError() <<
"lhs type cannot contain a reference";
2567 if (type_isa<LHSType>(type))
2568 return emitError() <<
"lhs type cannot contain a lhs type";
2577auto RefType::get(
FIRRTLBaseType type,
bool forceable, SymbolRefAttr layer)
2579 return Base::get(type.getContext(), type, forceable, layer);
2582auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2585 if (!base.isPassive())
2586 return emitErrorFn() <<
"reference base type must be passive";
2587 if (forceable && base.containsConst())
2588 return emitErrorFn()
2589 <<
"forceable reference base type cannot contain const";
2594 auto rtp = getType().getRecursiveTypeProperties();
2597 rtp.isPassive =
false;
2605AnalogType AnalogType::get(mlir::MLIRContext *
context) {
2606 return AnalogType::get(
context, -1,
false);
2609AnalogType AnalogType::get(mlir::MLIRContext *
context,
2610 std::optional<int32_t> width,
bool isConst) {
2614LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2615 int32_t widthOrSentinel,
bool isConst) {
2616 if (widthOrSentinel < -1)
2617 return emitError() <<
"invalid width";
2621int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2623AnalogType AnalogType::getConstType(
bool isConst)
const {
2626 return get(getContext(), getWidthOrSentinel(),
isConst);
2633ClockType ClockType::getConstType(
bool isConst)
const {
2643ResetType ResetType::getConstType(
bool isConst)
const {
2653AsyncResetType AsyncResetType::getConstType(
bool isConst)
const {
2664 using KeyTy = std::tuple<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2668 auto name = std::get<0>(key);
2669 auto elements = allocator.copyInto(std::get<1>(key));
2672 SmallVector<uint64_t, 4> ids;
2681 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2703ClassType ClassType::get(FlatSymbolRefAttr name,
2704 ArrayRef<ClassElement> elements) {
2705 return get(name.getContext(), name, elements);
2708StringRef ClassType::getName()
const {
2709 return getNameAttr().getAttr().getValue();
2712FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2714ArrayRef<ClassElement> ClassType::getElements()
const {
2715 return getImpl()->elements;
2718const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2719 return getElement(index.getValue().getZExtValue());
2722const ClassElement &ClassType::getElement(
size_t index)
const {
2723 return getElements()[index];
2726std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2727 for (
const auto [i, e] :
llvm::enumerate(getElements()))
2728 if (fieldName == e.name)
2733void ClassType::printInterface(AsmPrinter &p)
const {
2737 for (
const auto &element : getElements()) {
2741 p.printKeywordOrString(element.name);
2742 p <<
": " << element.type;
2748uint64_t ClassType::getFieldID(uint64_t index)
const {
2749 return getImpl()->fieldIDs[index];
2752uint64_t ClassType::getIndexForFieldID(uint64_t fieldID)
const {
2753 assert(!getElements().
empty() &&
"Class must have >0 fields");
2754 auto fieldIDs = getImpl()->fieldIDs;
2755 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2756 return std::distance(fieldIDs.begin(), it);
2759std::pair<uint64_t, uint64_t>
2760ClassType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2763 return {index, fieldID - elementFieldID};
2766std::pair<Type, uint64_t>
2767ClassType::getSubTypeByFieldID(uint64_t fieldID)
const {
2771 auto subfieldType = getElement(subfieldIndex).type;
2772 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2773 return {subfieldType, subfieldID};
2776uint64_t ClassType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2778std::pair<uint64_t, bool>
2779ClassType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2781 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2783 return std::make_pair(fieldID - childRoot,
2784 fieldID >= childRoot && fieldID <= rangeEnd);
2791struct InterfaceParser {
2794 InterfaceParser(AsmParser &parser) : parser(parser) {}
2797 template <
typename FieldContainer>
2799 function_ref<ParseResult(FieldContainer &, AsmParser &parser)> parseField,
2800 StringAttr &symbolName, FieldContainer &fields) {
2802 if (parser.parseSymbolName(symbolName))
2806 if (parser.parseLParen())
2810 if (failed(parser.parseOptionalRParen())) {
2811 auto parseElement = [&]() -> ParseResult {
2812 return parseField(fields, parser);
2815 if (parser.parseCommaSeparatedList(parseElement) || parser.parseRParen())
2824ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2825 InterfaceParser helper(parser);
2827 auto parseField = [](SmallVector<ClassElement> &elements,
2828 AsmParser &parser) -> ParseResult {
2831 if (succeeded(parser.parseOptionalKeyword(
"out")))
2833 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2839 std::string keyword;
2840 if (parser.parseKeywordOrString(&keyword))
2842 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2846 if (parser.parseColonType(type))
2849 elements.emplace_back(name, type, direction);
2853 StringAttr symbolName;
2854 SmallVector<ClassElement> elements;
2855 if (helper.parse<SmallVector<ClassElement>>(parseField, symbolName, elements))
2858 result = ClassType::get(FlatSymbolRefAttr::get(symbolName), elements);
2866ParseResult DomainType::parseInterface(AsmParser &parser, DomainType &result) {
2867 InterfaceParser helper(parser);
2869 auto parseField = [](SmallVector<Attribute> &fields,
2870 AsmParser &parser) -> ParseResult {
2871 std::string fieldNameStr;
2873 if (parser.parseKeywordOrString(&fieldNameStr) || parser.parseColon() ||
2874 parser.parseType(fieldTypeRaw))
2877 auto fieldType = dyn_cast<PropertyType>(fieldTypeRaw);
2879 return parser.emitError(parser.getCurrentLocation(),
2880 "expected property type");
2882 auto fieldName = StringAttr::get(parser.getContext(), fieldNameStr);
2884 DomainFieldAttr::get(parser.getContext(), fieldName, fieldType));
2888 StringAttr symbolName;
2889 SmallVector<Attribute> fields;
2890 if (helper.parse<SmallVector<Attribute>>(parseField, symbolName, fields))
2893 result = DomainType::get(FlatSymbolRefAttr::get(symbolName),
2894 ArrayAttr::get(parser.getContext(), fields));
2898DomainType DomainType::get(FlatSymbolRefAttr name, ArrayAttr fields) {
2899 return Base::get(name.getContext(), name, fields);
2902DomainType DomainType::getFromDomainOp(DomainOp domainOp) {
2903 auto name = FlatSymbolRefAttr::get(domainOp.getNameAttr());
2904 return DomainType::get(name, domainOp.getFieldsAttr());
2907DomainFieldAttr DomainType::getField(
size_t index)
const {
2908 assert(index < getNumFields() &&
"index out of bounds");
2909 return cast<DomainFieldAttr>(getFields()[index]);
2912std::optional<uint64_t> DomainType::getFieldIndex(StringRef fieldName)
const {
2913 for (
const auto [i, attr] :
llvm::enumerate(getFields())) {
2914 auto field = cast<DomainFieldAttr>(attr);
2915 if (fieldName == field.getName())
2921std::pair<Type, uint64_t>
2922DomainType::getSubTypeByFieldID(uint64_t fieldID)
const {
2928 if (fieldID > getNumFields())
2929 return {Type(), fieldID};
2931 return {getField(fieldID - 1).getType(), 0};
2934uint64_t DomainType::getMaxFieldID()
const {
2936 return getNumFields();
2939std::pair<uint64_t, bool>
2940DomainType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2942 if (index >= getNumFields())
2945 uint64_t childFieldID = index + 1;
2946 return {0, fieldID == childFieldID};
2949uint64_t DomainType::getFieldID(uint64_t index)
const {
2951 assert(index < getNumFields() &&
"index out of bounds");
2955uint64_t DomainType::getIndexForFieldID(uint64_t fieldID)
const {
2957 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2961std::pair<uint64_t, uint64_t>
2962DomainType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2964 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2965 return {fieldID - 1, 0};
2969DomainType::verifySymbolUses(Operation *op,
2970 SymbolTableCollection &symbolTable)
const {
2972 auto circuitOp = op->getParentOfType<CircuitOp>();
2974 return op->emitError() <<
"domain type used outside of a circuit";
2977 auto *symbol = symbolTable.lookupSymbolIn(circuitOp,
getName());
2979 return op->emitError() <<
"domain type references undefined symbol '"
2980 <<
getName().getValue() <<
"'";
2983 auto domainOp = dyn_cast<DomainOp>(symbol);
2985 return op->emitError() <<
"domain type references symbol '"
2986 <<
getName().getValue() <<
"' which is not a domain";
2989 auto expectedFields = domainOp.getFieldsAttr();
2990 auto actualFields = getFields();
2993 if (actualFields.size() != expectedFields.size())
2994 return op->emitError() <<
"domain type has " << actualFields.size()
2995 <<
" fields but domain definition has "
2996 << expectedFields.size() <<
" fields";
2999 for (
size_t i = 0; i < actualFields.size(); ++i) {
3000 auto actualField = cast<DomainFieldAttr>(actualFields[i]);
3001 auto expectedField = cast<DomainFieldAttr>(expectedFields[i]);
3004 if (actualField.getName() != expectedField.getName())
3005 return op->emitError() <<
"domain type field " << i <<
" has name '"
3006 << actualField.getName().getValue()
3007 <<
"' but domain definition expects '"
3008 << expectedField.getName().getValue() <<
"'";
3011 if (actualField.getType() != expectedField.getType())
3012 return op->emitError()
3013 <<
"domain type field '" << actualField.getName().getValue()
3014 <<
"' has type " << actualField.getType()
3015 <<
" but domain definition expects " << expectedField.getType();
3025void FIRRTLDialect::registerTypes() {
3027#define GET_TYPEDEF_LIST
3028#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
3042 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
3043 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
3045 for (
auto &elt : bundle) {
3046 if (elt.isFlip && !ignoreFlip)
3047 return std::nullopt;
3050 return std::nullopt;
3055 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
3057 for (
auto &elt : fenum) {
3060 return std::nullopt;
3061 width = std::max(width, *w);
3063 return width + fenum.getTagWidth();
3065 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
3068 return std::nullopt;
3069 return *w * vector.getNumElements();
3072 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
3073 .Default([&](
auto t) {
return std::nullopt; });
3075 return getWidth(type);
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
static std::unique_ptr< Context > context
static ParseResult parseFIRRTLBaseType(FIRRTLBaseType &result, StringRef name, AsmParser &parser)
static ParseResult parseFIRRTLPropertyType(PropertyType &result, StringRef name, AsmParser &parser)
static LogicalResult customTypePrinter(Type type, AsmPrinter &os)
Print a type with a custom printer implementation.
static OptionalParseResult customTypeParser(AsmParser &parser, StringRef name, Type &result)
Parse a type with a custom parser implementation.
static ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
static bool areBundleElementsEquivalent(BundleType::BundleElement destElement, BundleType::BundleElement srcElement, bool destOuterTypeIsConst, bool srcOuterTypeIsConst, bool requiresSameWidth)
Helper to implement the equivalence logic for a pair of bundle elements.
@ ContainsAnalogBitMask
Bit set if the type contains an analog type.
@ HasUninferredWidthBitMask
Bit set fi the type has any uninferred bit widths.
@ IsPassiveBitMask
Bit set if the type only contains passive elements.
static ParseResult parseFIRRTLType(FIRRTLType &result, StringRef name, AsmParser &parser)
Parse a FIRRTLType with a name that has already been parsed.
static unsigned getFieldID(BundleType type, unsigned index)
static unsigned getIndexForFieldID(BundleType type, unsigned fieldID)
static unsigned getMaxFieldID(FIRRTLBaseType type)
static InstancePath empty
FIRRTLBaseType getConstType(bool isConst) const
Return a 'const' or non-'const' version of this type.
FIRRTLBaseType getAnonymousType()
Return this type with any type alias types recursively removed from itself.
bool isResetType()
Return true if this is a valid "reset" type.
FIRRTLBaseType getMaskType()
Return this type with all ground types replaced with UInt<1>.
FIRRTLBaseType getPassiveType()
Return this type with any flip types recursively removed from itself.
int32_t getBitWidthOrSentinel()
If this is an IntType, AnalogType, or sugar type for a single bit (Clock, Reset, etc) then return the...
FIRRTLBaseType getAllConstDroppedType()
Return this type with a 'const' modifiers dropped.
bool isPassive() const
Return true if this is a "passive" type - one that contains no "flip" types recursively within itself...
FIRRTLBaseType getWidthlessType()
Return this type with widths of all ground types removed.
bool isConst() const
Returns true if this is a 'const' type that can only hold compile-time constant values.
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
bool containsReference()
Return true if this is or contains a Reference type.
RecursiveTypeProperties getRecursiveTypeProperties() const
Return the recursive properties of the type, containing the isPassive, containsAnalog,...
bool isConst() const
Returns true if this is a 'const' type that can only hold compile-time constant values.
This is the common base class between SIntType and UIntType.
IntType getConstType(bool isConst) const
Return a 'const' or non-'const' version of this type.
int32_t getWidthOrSentinel() const
Return the width of this type, or -1 if it has none specified.
static IntType get(MLIRContext *context, bool isSigned, int32_t widthOrSentinel=-1, bool isConst=false)
Return an SIntType or UIntType with the specified signedness, width, and constness.
std::optional< int32_t > getWidth() const
Return an optional containing the width, if the width is known (or empty if width is unknown).
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 ยง7....
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Direction
This represents the direction of a single port.
ParseResult parseNestedType(FIRRTLType &result, AsmParser &parser)
Parse a FIRRTLType.
bool areAnonymousTypesEquivalent(FIRRTLBaseType lhs, FIRRTLBaseType rhs)
Return true if anonymous types of given arguments are equivalent by pointer comparison.
ParseResult parseNestedBaseType(FIRRTLBaseType &result, AsmParser &parser)
bool isTypeInOut(mlir::Type type)
Returns true if the given type has some flipped (aka unaligned) dataflow.
bool areTypesRefCastable(Type dstType, Type srcType)
Return true if destination ref type can be cast from source ref type, per FIRRTL spec rules they must...
bool areTypesEquivalent(FIRRTLType destType, FIRRTLType srcType, bool destOuterTypeIsConst=false, bool srcOuterTypeIsConst=false, bool requireSameWidths=false)
Returns whether the two types are equivalent.
mlir::Type getPassiveType(mlir::Type anyBaseFIRRTLType)
bool isTypeLarger(FIRRTLBaseType dstType, FIRRTLBaseType srcType)
Returns true if the destination is at least as wide as a source.
bool containsConst(Type type)
Returns true if the type is or contains a 'const' type whose value is guaranteed to be unchanging at ...
bool hasZeroBitWidth(FIRRTLType type)
Return true if the type has zero bit width.
void printNestedType(Type type, AsmPrinter &os)
Print a type defined by this dialect.
bool isConst(Type type)
Returns true if this is a 'const' type whose value is guaranteed to be unchanging at circuit executio...
bool hasHardwareElements(FIRRTLType type)
Return true if the given type contains any elements of hardware types.
bool areTypesConstCastable(FIRRTLType destType, FIRRTLType srcType, bool srcOuterTypeIsConst=false)
Returns whether the srcType can be const-casted to the destType.
ParseResult parseNestedPropertyType(PropertyType &result, AsmParser &parser)
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
std::pair< uint64_t, uint64_t > getIndexAndSubfieldID(Type type, uint64_t fieldID)
uint64_t getFieldID(Type type, uint64_t index)
std::pair<::mlir::Type, uint64_t > getSubTypeByFieldID(Type, uint64_t fieldID)
std::pair< uint64_t, bool > projectToChildFieldID(Type, uint64_t fieldID, uint64_t index)
uint64_t getIndexForFieldID(Type type, uint64_t fieldID)
uint64_t getMaxFieldID(Type)
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
llvm::hash_code hash_value(const DenseSet< T > &set)
A collection of bits indicating the recursive properties of a type.
bool containsReference
Whether the type contains a reference type.
bool isPassive
Whether the type only contains passive elements.
bool containsAnalog
Whether the type contains an analog type.
bool hasUninferredReset
Whether the type has any uninferred reset.
bool containsTypeAlias
Whether the type contains a type alias.
bool containsConst
Whether the type contains a const type.
bool hasUninferredWidth
Whether the type has any uninferred bit widths.
bool operator==(const KeyTy &key) const
static BaseTypeAliasStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
BaseTypeAliasStorage(StringAttr name, FIRRTLBaseType innerType)
std::tuple< StringAttr, FIRRTLBaseType > KeyTy
static llvm::hash_code hashKey(const KeyTy &key)
FIRRTLBaseType anonymousType
static BundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
std::tuple< ArrayRef< BundleType::BundleElement >, char > KeyTy
SmallVector< BundleType::BundleElement, 4 > elements
static llvm::hash_code hashKey(const KeyTy &key)
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
BundleTypeStorage(ArrayRef< BundleType::BundleElement > elements, bool isConst)
bool operator==(const KeyTy &key) const
SmallVector< uint64_t, 4 > fieldIDs
bool operator==(const KeyTy &key) const
ArrayRef< uint64_t > fieldIDs
static ClassTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
std::tuple< FlatSymbolRefAttr, ArrayRef< ClassElement > > KeyTy
ArrayRef< ClassElement > elements
ClassTypeStorage(FlatSymbolRefAttr name, ArrayRef< ClassElement > elements, ArrayRef< uint64_t > fieldIDs, uint64_t maxFieldID)
SmallVector< FEnumType::EnumElement, 4 > elements
static llvm::hash_code hashKey(const KeyTy &key)
bool operator==(const KeyTy &key) const
static FEnumTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
FEnumTypeStorage(ArrayRef< FEnumType::EnumElement > elements, bool isConst)
RecursiveTypeProperties recProps
FIRRTLBaseType anonymousType
std::tuple< ArrayRef< FEnumType::EnumElement >, char > KeyTy
bool operator==(const KeyTy &key) const
FIRRTLBaseTypeStorage(bool isConst)
static FIRRTLBaseTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
bool operator==(const KeyTy &key) const
FIRRTLBaseType elementType
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
FIRRTLBaseType passiveType
static FVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
FIRRTLBaseType anonymousType
std::tuple< FIRRTLBaseType, size_t, char > KeyTy
FVectorTypeStorage(FIRRTLBaseType elementType, size_t numElements, bool isConst)
SmallVector< OpenBundleType::BundleElement, 4 > elements
bool operator==(const KeyTy &key) const
static OpenBundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
static llvm::hash_code hashKey(const KeyTy &key)
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
OpenBundleTypeStorage(ArrayRef< OpenBundleType::BundleElement > elements, bool isConst)
SmallVector< uint64_t, 4 > fieldIDs
std::tuple< ArrayRef< OpenBundleType::BundleElement >, char > KeyTy
std::tuple< FIRRTLType, size_t, char > KeyTy
bool operator==(const KeyTy &key) const
RecursiveTypeProperties props
static OpenVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
OpenVectorTypeStorage(FIRRTLType elementType, size_t numElements, bool isConst)
WidthTypeStorage(int32_t width, bool isConst)
std::tuple< int32_t, char > KeyTy
bool operator==(const KeyTy &key) const
static WidthTypeStorage * construct(TypeStorageAllocator &allocator, const KeyTy &key)