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<PathType>([&](
auto pathType) { os <<
"path"; })
157 .Case<BaseTypeAliasType>([&](BaseTypeAliasType alias) {
158 os <<
"alias<" << alias.getName().getValue() <<
", ";
162 .Case<ClassType>([&](ClassType type) {
164 type.printInterface(os);
167 .Case<AnyRefType>([&](AnyRefType type) { os <<
"anyref"; })
168 .Case<FStringType>([&](
auto) { os <<
"fstring"; })
169 .Case<DomainType>([&](DomainType type) {
171 os.printSymbolName(type.getName().getValue());
173 llvm::interleaveComma(type.getFields(), os, [&](Attribute attr) {
174 auto field = cast<DomainFieldAttr>(attr);
175 os << field.getName().getValue() <<
": ";
176 os.printType(field.getType());
181 .Default([&](
auto) { anyFailed =
true; });
182 return failure(anyFailed);
193 assert(
false &&
"type to print unknown to FIRRTL dialect");
228 const char constPrefix[] =
"const.";
229 if (name.starts_with(constPrefix)) {
231 name = name.drop_front(std::size(constPrefix) - 1);
234 auto *
context = parser.getContext();
239 if (name ==
"asyncreset")
242 if (name ==
"sint" || name ==
"uint" || name ==
"analog") {
245 if (!parser.parseOptionalLess()) {
246 if (parser.parseInteger(width) || parser.parseGreater())
250 return parser.emitError(parser.getNameLoc(),
"unknown width"),
256 else if (name ==
"uint")
265 if (name ==
"bundle") {
266 SmallVector<BundleType::BundleElement, 4> elements;
268 auto parseBundleElement = [&]() -> ParseResult {
273 if (failed(parser.parseKeywordOrString(&nameStr)))
277 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
281 elements.push_back({StringAttr::get(
context, name), isFlip, type});
285 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
289 result = parser.getChecked<BundleType>(
context, elements,
isConst);
290 return failure(!result);
292 if (name ==
"openbundle") {
293 SmallVector<OpenBundleType::BundleElement, 4> elements;
295 auto parseBundleElement = [&]() -> ParseResult {
300 if (failed(parser.parseKeywordOrString(&nameStr)))
304 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
308 elements.push_back({StringAttr::get(
context, name), isFlip, type});
312 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
316 result = parser.getChecked<OpenBundleType>(
context, elements,
isConst);
317 return failure(!result);
320 if (name ==
"enum") {
321 SmallVector<StringAttr> names;
322 SmallVector<APInt> values;
323 SmallVector<FIRRTLBaseType> types;
324 auto parseEnumElement = [&]() -> ParseResult {
327 if (failed(parser.parseKeywordOrString(&nameStr)))
329 names.push_back(StringAttr::get(
context, nameStr));
335 if (succeeded(parser.parseOptionalEqual())) {
336 if (parser.parseInteger(value))
338 }
else if (values.empty()) {
344 auto &prev = values.back();
345 if (prev.isMaxValue())
346 value = prev.zext(prev.getBitWidth() + 1);
351 values.push_back(std::move(value));
355 if (succeeded(parser.parseOptionalColon())) {
359 type = UIntType::get(parser.getContext(), 0);
361 types.push_back(type);
366 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
371 unsigned bitwidth = 0;
372 for (
auto &value : values)
373 bitwidth = std::max(bitwidth, value.getActiveBits());
374 auto tagType = IntegerType::get(
context, bitwidth, IntegerType::Unsigned);
376 SmallVector<FEnumType::EnumElement, 4> elements;
377 for (
auto [name, value, type] : llvm::zip(names, values, types)) {
378 auto tagValue = value.zextOrTrunc(bitwidth);
379 elements.push_back({name, IntegerAttr::get(tagType, tagValue), type});
382 if (failed(FEnumType::verify(
383 [&]() {
return parser.emitError(parser.getNameLoc()); }, elements,
387 result = parser.getChecked<FEnumType>(
context, elements,
isConst);
388 return failure(!result);
391 if (name ==
"vector") {
396 parser.parseComma() || parser.parseInteger(width) ||
397 parser.parseGreater())
402 if (name ==
"openvector") {
407 parser.parseComma() || parser.parseInteger(width) ||
408 parser.parseGreater())
413 return failure(!result);
417 if (name ==
"ref" || name ==
"probe") {
424 if (parser.parseOptionalComma().succeeded())
425 if (parser.parseOptionalAttribute(layer).value())
426 return parser.emitError(parser.getNameLoc(),
427 "expected symbol reference");
428 if (parser.parseGreater())
431 if (failed(RefType::verify(
432 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
436 return result = RefType::get(type,
false, layer), success();
441 parser.parseGreater())
443 if (!isa<FIRRTLBaseType>(type))
444 return parser.emitError(parser.getNameLoc(),
"expected base type");
445 result = parser.getChecked<LHSType>(
context, cast<FIRRTLBaseType>(type));
446 return failure(!result);
448 if (name ==
"rwprobe") {
453 if (parser.parseOptionalComma().succeeded())
454 if (parser.parseOptionalAttribute(layer).value())
455 return parser.emitError(parser.getNameLoc(),
456 "expected symbol reference");
457 if (parser.parseGreater())
460 if (failed(RefType::verify(
461 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
true,
465 return result = RefType::get(type,
true, layer), success();
467 if (name ==
"class") {
469 return parser.emitError(parser.getNameLoc(),
"classes cannot be const");
471 if (parser.parseLess() || ClassType::parseInterface(parser, classType) ||
472 parser.parseGreater())
477 if (name ==
"anyref") {
479 return parser.emitError(parser.getNameLoc(),
"any refs cannot be const");
481 result = AnyRefType::get(parser.getContext());
484 if (name ==
"string") {
486 parser.emitError(parser.getNameLoc(),
"strings cannot be const");
489 result = StringType::get(parser.getContext());
492 if (name ==
"integer") {
494 parser.emitError(parser.getNameLoc(),
"bigints cannot be const");
497 result = FIntegerType::get(parser.getContext());
500 if (name ==
"bool") {
502 parser.emitError(parser.getNameLoc(),
"bools cannot be const");
505 result = BoolType::get(parser.getContext());
508 if (name ==
"double") {
510 parser.emitError(parser.getNameLoc(),
"doubles cannot be const");
513 result = DoubleType::get(parser.getContext());
516 if (name ==
"list") {
518 parser.emitError(parser.getNameLoc(),
"lists cannot be const");
523 parser.parseGreater())
530 if (name ==
"path") {
532 parser.emitError(parser.getNameLoc(),
"path cannot be const");
535 result = PathType::get(parser.getContext());
538 if (name ==
"alias") {
541 if (parser.parseLess() || parser.parseKeyword(&name) ||
543 parser.parseGreater())
547 BaseTypeAliasType::get(StringAttr::get(
context, name), type),
550 if (name ==
"fstring") {
551 return result = FStringType::get(
context), success();
553 if (name ==
"domain") {
556 DomainType domainType;
557 if (parser.parseLess() || DomainType::parseInterface(parser, domainType) ||
558 parser.parseGreater())
573static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
576 if (parseResult.has_value())
577 return parseResult.value();
580 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL dialect type: \"")
592 if (failed(
parseType(type, name, parser)))
594 result = type_dyn_cast<FIRRTLType>(type);
597 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL type: \"")
607 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type)) {
611 parser.emitError(parser.getNameLoc(),
"expected base type, found ") << type;
620 if (
auto prop = type_dyn_cast<PropertyType>(type)) {
624 parser.emitError(parser.getNameLoc(),
"expected property type, found ")
637 if (parser.parseKeyword(&name))
647 if (parser.parseKeyword(&name))
657 if (parser.parseKeyword(&name))
668void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os)
const {
673Type FIRRTLDialect::parseType(DialectAsmParser &parser)
const {
676 if (parser.parseKeyword(&name) ||
::parseType(result, name, parser))
719bool FIRRTLType::isGround() {
720 return TypeSwitch<FIRRTLType, bool>(*
this)
721 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
722 AnalogType>([](Type) {
return true; })
723 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType>(
724 [](Type) {
return false; })
725 .Case<BaseTypeAliasType>([](BaseTypeAliasType alias) {
726 return alias.getAnonymousType().isGround();
729 .Case<PropertyType, RefType>([](Type) {
return false; })
731 llvm_unreachable(
"unknown FIRRTL type");
737 return TypeSwitch<FIRRTLType, bool>(*
this)
739 [](
auto type) {
return type.isConst(); })
746 return TypeSwitch<FIRRTLType, RecursiveTypeProperties>(*
this)
747 .Case<ClockType, ResetType, AsyncResetType>([](
FIRRTLBaseType type) {
754 firrtl::type_isa<ResetType>(type)};
756 .Case<SIntType, UIntType>([](
auto type) {
758 true,
false,
false, type.isConst(),
false, !type.hasWidth(),
false};
760 .Case<AnalogType>([](
auto type) {
762 true,
false,
true, type.isConst(),
false, !type.hasWidth(),
false};
764 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType,
765 RefType, BaseTypeAliasType>(
766 [](
auto type) {
return type.getRecursiveTypeProperties(); })
767 .Case<PropertyType>([](
auto type) {
769 false,
false,
false};
772 [](
auto type) {
return type.getType().getRecursiveTypeProperties(); })
773 .Case<FStringType>([](
auto type) {
775 false,
false,
false};
777 .Case<DomainType>([](
auto type) {
779 false,
false,
false};
782 llvm_unreachable(
"unknown FIRRTL type");
789 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
790 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
791 AnalogType>([&](Type) {
return *
this; })
792 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
793 [](
auto type) {
return type.getAnonymousType(); })
795 llvm_unreachable(
"unknown FIRRTL type");
802 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
803 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
804 AnalogType, FEnumType>([&](Type) {
return *
this; })
805 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
806 [](
auto type) {
return type.getPassiveType(); })
808 llvm_unreachable(
"unknown FIRRTL type");
815 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
816 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
817 UIntType, BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
818 [&](
auto type) {
return type.getConstType(
isConst); })
820 llvm_unreachable(
"unknown FIRRTL type");
827 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
828 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
829 UIntType>([&](
auto type) {
return type.getConstType(
false); })
830 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
831 [&](
auto type) {
return type.getAllConstDroppedType(); })
833 llvm_unreachable(
"unknown FIRRTL type");
841 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
842 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
843 AnalogType, FEnumType>([&](Type) {
844 return UIntType::get(this->getContext(), 1, this->
isConst());
846 .Case<BundleType>([&](BundleType bundleType) {
847 SmallVector<BundleType::BundleElement, 4> newElements;
848 newElements.reserve(bundleType.getElements().size());
849 for (
auto elt : bundleType)
850 newElements.push_back(
851 {elt.name,
false , elt.type.getMaskType()});
852 return BundleType::get(this->getContext(), newElements,
853 bundleType.isConst());
855 .Case<FVectorType>([](FVectorType vectorType) {
856 return FVectorType::get(vectorType.getElementType().getMaskType(),
857 vectorType.getNumElements(),
858 vectorType.isConst());
860 .Case<BaseTypeAliasType>([](BaseTypeAliasType base) {
861 return base.getModifiedType(base.getInnerType().getMaskType());
864 llvm_unreachable(
"unknown FIRRTL type");
872 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
873 .Case<ClockType, ResetType, AsyncResetType>([](
auto a) {
return a; })
874 .Case<UIntType, SIntType, AnalogType>(
875 [&](
auto a) {
return a.get(this->getContext(), -1, a.isConst()); })
876 .Case<BundleType>([&](
auto a) {
877 SmallVector<BundleType::BundleElement, 4> newElements;
878 newElements.reserve(a.getElements().size());
880 newElements.push_back(
881 {elt.name, elt.isFlip, elt.type.getWidthlessType()});
882 return BundleType::get(this->getContext(), newElements, a.isConst());
884 .Case<FVectorType>([](
auto a) {
885 return FVectorType::get(a.getElementType().getWidthlessType(),
886 a.getNumElements(), a.isConst());
888 .Case<FEnumType>([&](FEnumType a) {
889 SmallVector<FEnumType::EnumElement, 4> newElements;
890 newElements.reserve(a.getNumElements());
892 newElements.push_back(
893 {elt.name, elt.value, elt.type.getWidthlessType()});
894 return FEnumType::get(this->getContext(), newElements, a.isConst());
896 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
897 return type.getModifiedType(type.getInnerType().getWidthlessType());
900 llvm_unreachable(
"unknown FIRRTL type");
910 return TypeSwitch<FIRRTLBaseType, int32_t>(*
this)
911 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
912 .Case<SIntType, UIntType>(
915 [](AnalogType analogType) {
return analogType.getWidthOrSentinel(); })
916 .Case<FEnumType>([&](FEnumType fenum) {
return fenum.getBitWidth(); })
917 .Case<BundleType, FVectorType>([](Type) {
return -2; })
918 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
920 return type.getAnonymousType().getBitWidthOrSentinel();
923 llvm_unreachable(
"unknown FIRRTL type");
932 return TypeSwitch<FIRRTLType, bool>(*
this)
933 .Case<ResetType, AsyncResetType>([](Type) {
return true; })
935 [](UIntType a) {
return !a.hasWidth() || a.getWidth() == 1; })
936 .Case<BaseTypeAliasType>(
937 [](
auto type) {
return type.getInnerType().isResetType(); })
938 .Default([](Type) {
return false; });
942 return TypeSwitch<Type, bool>(type)
944 [](
auto base) {
return base.isConst(); })
949 return TypeSwitch<Type, bool>(type)
951 [](
auto base) {
return base.containsConst(); })
958 .
Case<BundleType>([&](
auto bundle) {
959 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
960 auto elt = bundle.getElement(i);
964 return bundle.getNumElements() == 0;
966 .Case<FVectorType>([&](
auto vector) {
967 if (vector.getNumElements() == 0)
971 .Case<FIRRTLBaseType>([](
auto groundType) {
974 .Case<RefType>([](
auto ref) {
return hasZeroBitWidth(ref.getType()); })
975 .Default([](
auto) {
return false; });
985 BundleType::BundleElement srcElement,
986 bool destOuterTypeIsConst,
987 bool srcOuterTypeIsConst,
988 bool requiresSameWidth) {
989 if (destElement.name != srcElement.name)
991 if (destElement.isFlip != srcElement.isFlip)
994 if (destElement.isFlip) {
995 std::swap(destElement, srcElement);
996 std::swap(destOuterTypeIsConst, srcOuterTypeIsConst);
1000 destOuterTypeIsConst, srcOuterTypeIsConst,
1009 bool destOuterTypeIsConst,
1010 bool srcOuterTypeIsConst,
1011 bool requireSameWidths) {
1012 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1013 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1016 if (!destType || !srcType)
1017 return destFType == srcFType;
1019 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
1020 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
1023 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1024 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1025 if (destVectorType && srcVectorType)
1026 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1028 srcVectorType.getElementType(), destIsConst,
1029 srcIsConst, requireSameWidths);
1033 auto destBundleType = type_dyn_cast<BundleType>(destType);
1034 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1035 if (destBundleType && srcBundleType) {
1036 auto destElements = destBundleType.getElements();
1037 auto srcElements = srcBundleType.getElements();
1038 size_t numDestElements = destElements.size();
1039 if (numDestElements != srcElements.size())
1042 for (
size_t i = 0; i < numDestElements; ++i) {
1043 auto destElement = destElements[i];
1044 auto srcElement = srcElements[i];
1046 srcIsConst, requireSameWidths))
1054 auto dstEnumType = type_dyn_cast<FEnumType>(destType);
1055 auto srcEnumType = type_dyn_cast<FEnumType>(srcType);
1057 if (dstEnumType && srcEnumType) {
1058 if (dstEnumType.getNumElements() != srcEnumType.getNumElements())
1061 for (
const auto &[dst, src] : llvm::zip(dstEnumType, srcEnumType)) {
1063 if (dst.name != src.name)
1075 if (destIsConst && !srcIsConst)
1079 if (firrtl::type_isa<ResetType>(destType))
1080 return srcType.isResetType();
1083 if (firrtl::type_isa<ResetType>(srcType))
1084 return destType.isResetType();
1088 if (!requireSameWidths || destType.getBitWidthOrSentinel() == -1)
1089 srcType = srcType.getWidthlessType();
1090 if (!requireSameWidths || srcType.getBitWidthOrSentinel() == -1)
1091 destType = destType.getWidthlessType();
1094 return destType.getConstType(
false) == srcType.getConstType(
false);
1099 bool srcOuterTypeIsConst) {
1101 if (destFType == srcFType)
1104 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1105 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1108 if (!destType || !srcType)
1112 if (!destType.isPassive() || !srcType.isPassive())
1115 bool srcIsConst = srcType.isConst() || srcOuterTypeIsConst;
1118 if (destType.isConst() && !srcIsConst)
1123 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1124 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1125 if (destVectorType && srcVectorType)
1126 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1128 srcVectorType.getElementType(), srcIsConst);
1129 if (destVectorType != srcVectorType)
1134 auto destBundleType = type_dyn_cast<BundleType>(destType);
1135 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1136 if (destBundleType && srcBundleType) {
1137 auto destElements = destBundleType.getElements();
1138 auto srcElements = srcBundleType.getElements();
1139 size_t numDestElements = destElements.size();
1140 if (numDestElements != srcElements.size())
1143 return llvm::all_of_zip(
1144 destElements, srcElements,
1145 [&](
const auto &destElement,
const auto &srcElement) {
1146 return destElement.name == srcElement.name &&
1151 if (destBundleType != srcBundleType)
1156 return destType == srcType.getConstType(destType.isConst());
1160 auto dstRefType = type_dyn_cast<RefType>(dstType);
1161 auto srcRefType = type_dyn_cast<RefType>(srcType);
1162 if (!dstRefType || !srcRefType)
1164 if (dstRefType == srcRefType)
1166 if (dstRefType.getForceable() && !srcRefType.getForceable())
1178 bool srcOuterTypeIsConst) ->
bool {
1184 assert(dest.isPassive() && src.isPassive());
1186 bool srcIsConst = src.isConst() || srcOuterTypeIsConst;
1189 if (dest.isConst() && !srcIsConst)
1195 if (
auto destVectorType = type_dyn_cast<FVectorType>(dest)) {
1196 auto srcVectorType = type_dyn_cast<FVectorType>(src);
1197 return srcVectorType &&
1198 destVectorType.getNumElements() ==
1199 srcVectorType.getNumElements() &&
1200 f(f, destVectorType.getElementType(),
1201 srcVectorType.getElementType(), srcIsConst);
1204 if (
auto destBundleType = type_dyn_cast<BundleType>(dest)) {
1205 auto srcBundleType = type_dyn_cast<BundleType>(src);
1209 auto destElements = destBundleType.getElements();
1210 auto srcElements = srcBundleType.getElements();
1212 return destElements.size() == srcElements.size() &&
1214 destElements, srcElements,
1215 [&](
const auto &destElement,
const auto &srcElement) {
1216 return destElement.name == srcElement.name &&
1217 f(f, destElement.type, srcElement.type, srcIsConst);
1221 if (
auto destEnumType = type_dyn_cast<FEnumType>(dest)) {
1222 auto srcEnumType = type_dyn_cast<FEnumType>(src);
1225 auto destElements = destEnumType.getElements();
1226 auto srcElements = srcEnumType.getElements();
1228 return destElements.size() == srcElements.size() &&
1230 destElements, srcElements,
1231 [&](
const auto &destElement,
const auto &srcElement) {
1232 return destElement.name == srcElement.name &&
1233 f(f, destElement.type, srcElement.type, srcIsConst);
1238 if (type_isa<ResetType>(dest))
1239 return src.isResetType();
1243 src = src.getConstType(dest.isConst());
1246 if (dest.getBitWidthOrSentinel() == -1)
1247 src = src.getWidthlessType();
1252 return recurse(recurse, dstRefType.getType(), srcRefType.getType(),
false);
1259 return TypeSwitch<FIRRTLBaseType, bool>(dstType)
1260 .Case<BundleType>([&](
auto dstBundle) {
1261 auto srcBundle = type_cast<BundleType>(srcType);
1262 for (
size_t i = 0, n = dstBundle.getNumElements(); i < n; ++i) {
1263 auto srcElem = srcBundle.getElement(i);
1264 auto dstElem = dstBundle.getElement(i);
1265 if (dstElem.isFlip) {
1275 .Case<FVectorType>([&](
auto vector) {
1277 type_cast<FVectorType>(srcType).getElementType());
1279 .Default([&](
auto dstGround) {
1282 return destWidth <= -1 || srcWidth <= -1 || destWidth >= srcWidth;
1293 if (
auto destBaseType = type_dyn_cast<FIRRTLBaseType>(lhs))
1294 if (
auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(rhs))
1297 if (
auto destRefType = type_dyn_cast<RefType>(lhs))
1298 if (
auto srcRefType = type_dyn_cast<RefType>(rhs))
1300 srcRefType.getType());
1308 return type_cast<FIRRTLBaseType>(anyBaseFIRRTLType).getPassiveType();
1312 return llvm::TypeSwitch<Type, bool>(type)
1314 return !type.containsReference() &&
1315 (!type.isPassive() || type.containsAnalog());
1327 int32_t widthOrSentinel,
bool isConst) {
1334 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1335 return sintType.getWidthOrSentinel();
1336 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1337 return uintType.getWidthOrSentinel();
1348 using KeyTy = std::tuple<int32_t, char>;
1365 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1374SIntType SIntType::get(MLIRContext *
context) {
return get(
context, -1,
false); }
1376SIntType SIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1381LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1382 int32_t widthOrSentinel,
bool isConst) {
1383 if (widthOrSentinel < -1)
1384 return emitError() <<
"invalid width";
1388int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1390SIntType SIntType::getConstType(
bool isConst)
const {
1393 return get(getContext(), getWidthOrSentinel(),
isConst);
1402UIntType UIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1407LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1408 int32_t widthOrSentinel,
bool isConst) {
1409 if (widthOrSentinel < -1)
1410 return emitError() <<
"invalid width";
1414int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1416UIntType UIntType::getConstType(
bool isConst)
const {
1419 return get(getContext(), getWidthOrSentinel(),
isConst);
1428 using KeyTy = std::tuple<ArrayRef<BundleType::BundleElement>,
char>;
1433 props{true, false, false,
isConst, false, false, false} {
1434 uint64_t fieldID = 0;
1437 auto type = element.type;
1438 auto eltInfo = type.getRecursiveTypeProperties();
1465 std::get<0>(key),
static_cast<bool>(std::get<1>(key)));
1479BundleType BundleType::get(MLIRContext *
context,
1480 ArrayRef<BundleElement> elements,
bool isConst) {
1484auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1485 return getImpl()->elements;
1490 return getImpl()->props;
1495 auto *impl = getImpl();
1498 if (impl->passiveType)
1499 return impl->passiveType;
1502 if (impl->props.isPassive) {
1503 impl->passiveType = *
this;
1508 SmallVector<BundleType::BundleElement, 16> newElements;
1509 newElements.reserve(impl->elements.size());
1510 for (
auto &elt : impl->elements) {
1511 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1514 auto passiveType = BundleType::get(getContext(), newElements,
isConst());
1515 impl->passiveType = passiveType;
1519BundleType BundleType::getConstType(
bool isConst)
const {
1522 return get(getContext(), getElements(),
isConst);
1525BundleType BundleType::getAllConstDroppedType() {
1529 SmallVector<BundleElement> constDroppedElements(
1530 llvm::map_range(getElements(), [](BundleElement element) {
1531 element.type = element.type.getAllConstDroppedType();
1534 return get(getContext(), constDroppedElements,
false);
1537std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1538 for (
const auto &it :
llvm::enumerate(getElements())) {
1539 auto element = it.value();
1540 if (element.name == name) {
1541 return unsigned(it.index());
1544 return std::nullopt;
1547std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1548 for (
const auto &it :
llvm::enumerate(getElements())) {
1549 auto element = it.value();
1550 if (element.name.getValue() == name) {
1551 return unsigned(it.index());
1554 return std::nullopt;
1557StringAttr BundleType::getElementNameAttr(
size_t index) {
1558 assert(index < getNumElements() &&
1559 "index must be less than number of fields in bundle");
1560 return getElements()[index].name;
1563StringRef BundleType::getElementName(
size_t index) {
1564 return getElementNameAttr(index).getValue();
1567std::optional<BundleType::BundleElement>
1568BundleType::getElement(StringAttr name) {
1569 if (
auto maybeIndex = getElementIndex(name))
1570 return getElements()[*maybeIndex];
1571 return std::nullopt;
1574std::optional<BundleType::BundleElement>
1575BundleType::getElement(StringRef name) {
1576 if (
auto maybeIndex = getElementIndex(name))
1577 return getElements()[*maybeIndex];
1578 return std::nullopt;
1582BundleType::BundleElement BundleType::getElement(
size_t index) {
1583 assert(index < getNumElements() &&
1584 "index must be less than number of fields in bundle");
1585 return getElements()[index];
1589 auto element = getElement(name);
1594 auto element = getElement(name);
1599 assert(index < getNumElements() &&
1600 "index must be less than number of fields in bundle");
1601 return getElements()[index].type;
1604uint64_t BundleType::getFieldID(uint64_t index)
const {
1605 return getImpl()->fieldIDs[index];
1608uint64_t BundleType::getIndexForFieldID(uint64_t fieldID)
const {
1609 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1610 auto fieldIDs = getImpl()->fieldIDs;
1611 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1612 return std::distance(fieldIDs.begin(), it);
1615std::pair<uint64_t, uint64_t>
1616BundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1619 return {index, fieldID - elementFieldID};
1622std::pair<Type, uint64_t>
1623BundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1627 auto subfieldType = getElementType(subfieldIndex);
1628 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1629 return {subfieldType, subfieldID};
1632uint64_t BundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1634std::pair<uint64_t, bool>
1635BundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1637 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1639 return std::make_pair(fieldID - childRoot,
1640 fieldID >= childRoot && fieldID <= rangeEnd);
1643bool BundleType::isConst()
const {
return getImpl()->isConst; }
1645BundleType::ElementType
1646BundleType::getElementTypePreservingConst(
size_t index) {
1647 auto type = getElementType(index);
1648 return type.getConstType(type.isConst() ||
isConst());
1653 auto *impl = getImpl();
1656 if (impl->anonymousType)
1657 return impl->anonymousType;
1660 if (!impl->props.containsTypeAlias) {
1661 impl->anonymousType = *
this;
1667 SmallVector<BundleType::BundleElement, 16> newElements;
1668 newElements.reserve(impl->elements.size());
1669 for (
auto &elt : impl->elements)
1670 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1672 auto anonymousType = BundleType::get(getContext(), newElements,
isConst());
1673 impl->anonymousType = anonymousType;
1674 return anonymousType;
1677LogicalResult BundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1678 ArrayRef<BundleElement> elements,
1680 SmallPtrSet<StringAttr, 4> nameSet;
1681 for (
auto &element : elements) {
1682 if (!nameSet.insert(element.name).second)
1683 return emitErrorFn() <<
"duplicate field name " << element.name
1695 using KeyTy = std::tuple<ArrayRef<OpenBundleType::BundleElement>,
char>;
1700 props{true, false, false,
isConst, false, false, false},
1702 uint64_t fieldID = 0;
1705 auto type = element.type;
1706 auto eltInfo = type.getRecursiveTypeProperties();
1735 static_cast<bool>(std::get<1>(key)));
1738 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1750OpenBundleType OpenBundleType::get(MLIRContext *
context,
1751 ArrayRef<BundleElement> elements,
1756auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1757 return getImpl()->elements;
1762 return getImpl()->props;
1765OpenBundleType OpenBundleType::getConstType(
bool isConst)
const {
1768 return get(getContext(), getElements(),
isConst);
1771std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1772 for (
const auto &it :
llvm::enumerate(getElements())) {
1773 auto element = it.value();
1774 if (element.name == name) {
1775 return unsigned(it.index());
1778 return std::nullopt;
1781std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1782 for (
const auto &it :
llvm::enumerate(getElements())) {
1783 auto element = it.value();
1784 if (element.name.getValue() == name) {
1785 return unsigned(it.index());
1788 return std::nullopt;
1791StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1792 assert(index < getNumElements() &&
1793 "index must be less than number of fields in bundle");
1794 return getElements()[index].name;
1797StringRef OpenBundleType::getElementName(
size_t index) {
1798 return getElementNameAttr(index).getValue();
1801std::optional<OpenBundleType::BundleElement>
1802OpenBundleType::getElement(StringAttr name) {
1803 if (
auto maybeIndex = getElementIndex(name))
1804 return getElements()[*maybeIndex];
1805 return std::nullopt;
1808std::optional<OpenBundleType::BundleElement>
1809OpenBundleType::getElement(StringRef name) {
1810 if (
auto maybeIndex = getElementIndex(name))
1811 return getElements()[*maybeIndex];
1812 return std::nullopt;
1816OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1817 assert(index < getNumElements() &&
1818 "index must be less than number of fields in bundle");
1819 return getElements()[index];
1822OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1823 auto element = getElement(name);
1827OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1828 auto element = getElement(name);
1832OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1833 assert(index < getNumElements() &&
1834 "index must be less than number of fields in bundle");
1835 return getElements()[index].type;
1838uint64_t OpenBundleType::getFieldID(uint64_t index)
const {
1839 return getImpl()->fieldIDs[index];
1842uint64_t OpenBundleType::getIndexForFieldID(uint64_t fieldID)
const {
1843 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1844 auto fieldIDs = getImpl()->fieldIDs;
1845 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1846 return std::distance(fieldIDs.begin(), it);
1849std::pair<uint64_t, uint64_t>
1850OpenBundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1853 return {index, fieldID - elementFieldID};
1856std::pair<Type, uint64_t>
1857OpenBundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1861 auto subfieldType = getElementType(subfieldIndex);
1862 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1863 return {subfieldType, subfieldID};
1866uint64_t OpenBundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1868std::pair<uint64_t, bool>
1869OpenBundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1871 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1873 return std::make_pair(fieldID - childRoot,
1874 fieldID >= childRoot && fieldID <= rangeEnd);
1877bool OpenBundleType::isConst()
const {
return getImpl()->isConst; }
1879OpenBundleType::ElementType
1880OpenBundleType::getElementTypePreservingConst(
size_t index) {
1881 auto type = getElementType(index);
1883 return TypeSwitch<FIRRTLType, ElementType>(type)
1884 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1885 return type.getConstType(type.isConst() ||
isConst());
1891OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1892 ArrayRef<BundleElement> elements,
bool isConst) {
1893 SmallPtrSet<StringAttr, 4> nameSet;
1894 for (
auto &element : elements) {
1895 if (!nameSet.insert(element.name).second)
1896 return emitErrorFn() <<
"duplicate field name " << element.name
1897 <<
" in openbundle";
1899 return emitErrorFn()
1900 <<
"'const' bundle cannot have references, but element "
1901 << element.name <<
" has type " << element.type;
1902 if (type_isa<LHSType>(element.type))
1903 return emitErrorFn() <<
"bundle element " << element.name
1904 <<
" cannot have a left-hand side type";
1916 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1934 static_cast<bool>(std::get<2>(key)));
1953 return getImpl()->elementType;
1956size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1960 return getImpl()->props;
1965 auto *impl = getImpl();
1968 if (impl->passiveType)
1969 return impl->passiveType;
1972 if (impl->elementType.getRecursiveTypeProperties().isPassive)
1973 return impl->passiveType = *
this;
1976 auto passiveType = FVectorType::get(getElementType().
getPassiveType(),
1978 impl->passiveType = passiveType;
1982FVectorType FVectorType::getConstType(
bool isConst)
const {
1985 return get(getElementType(), getNumElements(),
isConst);
1988FVectorType FVectorType::getAllConstDroppedType() {
1991 return get(getElementType().getAllConstDroppedType(), getNumElements(),
1997 auto *impl = getImpl();
1999 if (impl->anonymousType)
2000 return impl->anonymousType;
2003 if (!impl->props.containsTypeAlias)
2004 return impl->anonymousType = *
this;
2007 auto anonymousType = FVectorType::get(getElementType().getAnonymousType(),
2009 impl->anonymousType = anonymousType;
2010 return anonymousType;
2013uint64_t FVectorType::getFieldID(uint64_t index)
const {
2017uint64_t FVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2018 assert(fieldID &&
"fieldID must be at least 1");
2023std::pair<uint64_t, uint64_t>
2024FVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2027 return {index, fieldID - elementFieldID};
2030std::pair<Type, uint64_t>
2031FVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2037uint64_t FVectorType::getMaxFieldID()
const {
2038 return getNumElements() *
2042std::pair<uint64_t, bool>
2043FVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2047 return std::make_pair(fieldID - childRoot,
2048 fieldID >= childRoot && fieldID <= rangeEnd);
2051bool FVectorType::isConst()
const {
return getImpl()->isConst; }
2053FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
2054 auto type = getElementType();
2055 return type.getConstType(type.isConst() ||
isConst());
2063 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
2081 static_cast<bool>(std::get<2>(key)));
2096FIRRTLType OpenVectorType::getElementType()
const {
2097 return getImpl()->elementType;
2100size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
2104 return getImpl()->props;
2107OpenVectorType OpenVectorType::getConstType(
bool isConst)
const {
2110 return get(getElementType(), getNumElements(),
isConst);
2113uint64_t OpenVectorType::getFieldID(uint64_t index)
const {
2117uint64_t OpenVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2118 assert(fieldID &&
"fieldID must be at least 1");
2123std::pair<uint64_t, uint64_t>
2124OpenVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2127 return {index, fieldID - elementFieldID};
2130std::pair<Type, uint64_t>
2131OpenVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2137uint64_t OpenVectorType::getMaxFieldID()
const {
2139 return getNumElements() *
2143std::pair<uint64_t, bool>
2144OpenVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2148 return std::make_pair(fieldID - childRoot,
2149 fieldID >= childRoot && fieldID <= rangeEnd);
2152bool OpenVectorType::isConst()
const {
return getImpl()->isConst; }
2154OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2155 auto type = getElementType();
2157 return TypeSwitch<FIRRTLType, ElementType>(type)
2158 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2159 return type.getConstType(type.isConst() ||
isConst());
2165OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2169 return emitErrorFn() <<
"vector cannot be const with references";
2171 return emitErrorFn() <<
"vector cannot have a left-hand side type";
2180 using KeyTy = std::tuple<ArrayRef<FEnumType::EnumElement>,
char>;
2186 false,
false,
false};
2189 auto type = element.type;
2190 auto eltInfo = type.getRecursiveTypeProperties();
2192 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2219FEnumType FEnumType::get(::mlir::MLIRContext *
context,
2220 ArrayRef<EnumElement> elements,
bool isConst) {
2224ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2225 return getImpl()->elements;
2228FEnumType FEnumType::getConstType(
bool isConst)
const {
2229 return get(getContext(), getElements(),
isConst);
2232FEnumType FEnumType::getAllConstDroppedType() {
2236 SmallVector<EnumElement> constDroppedElements(
2237 llvm::map_range(getElements(), [](EnumElement element) {
2238 element.type = element.type.getAllConstDroppedType();
2241 return get(getContext(), constDroppedElements,
false);
2246 return getImpl()->recProps;
2249std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2250 for (
const auto &it :
llvm::enumerate(getElements())) {
2251 auto element = it.value();
2252 if (element.name == name) {
2253 return unsigned(it.index());
2256 return std::nullopt;
2259size_t FEnumType::getBitWidth() {
return getDataWidth() + getTagWidth(); }
2261size_t FEnumType::getDataWidth() {
return getImpl()->dataSize; }
2263size_t FEnumType::getTagWidth() {
2264 if (getElements().size() == 0)
2267 return cast<IntegerType>(getElements()[0].value.getType()).getWidth();
2270std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2271 for (
const auto &it :
llvm::enumerate(getElements())) {
2272 auto element = it.value();
2273 if (element.name.getValue() == name) {
2274 return unsigned(it.index());
2277 return std::nullopt;
2280StringAttr FEnumType::getElementNameAttr(
size_t index) {
2281 assert(index < getNumElements() &&
2282 "index must be less than number of fields in enum");
2283 return getElements()[index].name;
2286StringRef FEnumType::getElementName(
size_t index) {
2287 return getElementNameAttr(index).getValue();
2290IntegerAttr FEnumType::getElementValueAttr(
size_t index) {
2291 return getElements()[index].value;
2294APInt FEnumType::getElementValue(
size_t index) {
2295 return getElementValueAttr(index).getValue();
2299 return getElements()[index].type;
2302std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2303 if (
auto maybeIndex = getElementIndex(name))
2304 return getElements()[*maybeIndex];
2305 return std::nullopt;
2308std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2309 if (
auto maybeIndex = getElementIndex(name))
2310 return getElements()[*maybeIndex];
2311 return std::nullopt;
2315FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2316 assert(index < getNumElements() &&
2317 "index must be less than number of fields in enum");
2318 return getElements()[index];
2322 auto element = getElement(name);
2327 auto element = getElement(name);
2332 assert(index < getNumElements() &&
2333 "index must be less than number of fields in enum");
2334 return getElements()[index].type;
2337FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2338 auto type = getElementType(index);
2339 return type.getConstType(type.isConst() ||
isConst());
2342LogicalResult FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2343 ArrayRef<EnumElement> elements,
bool isConst) {
2345 IntegerAttr previous;
2346 SmallPtrSet<Attribute, 4> nameSet;
2348 for (
auto &elt : elements) {
2349 auto r = elt.type.getRecursiveTypeProperties();
2351 return emitErrorFn() <<
"enum field " << elt.name <<
" not passive";
2352 if (r.containsAnalog)
2353 return emitErrorFn() <<
"enum field " << elt.name <<
" contains analog";
2354 if (r.hasUninferredWidth)
2355 return emitErrorFn() <<
"enum field " << elt.name
2356 <<
" has uninferred width";
2357 if (r.hasUninferredReset)
2358 return emitErrorFn() <<
"enum field " << elt.name
2359 <<
" has uninferred reset";
2360 if (r.containsConst && !
isConst)
2361 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2363 if (!nameSet.insert(elt.name).second)
2364 return emitErrorFn() <<
"duplicate variant name " << elt.name
2368 previous = elt.value;
2371 auto current = elt.value;
2372 if (previous.getType() != current.getType())
2373 return emitErrorFn() <<
"enum variant " << elt.name <<
" has type"
2374 << current.getType()
2375 <<
" which is different than previous variant "
2376 << previous.getType();
2378 if (previous.getValue().getBitWidth() != current.getValue().getBitWidth())
2379 return emitErrorFn() <<
"enum variant " << elt.name <<
" has bitwidth"
2380 << current.getValue().getBitWidth()
2381 <<
" which is different than previous variant "
2382 << previous.getValue().getBitWidth();
2383 if (previous.getValue().uge(current.getValue()))
2384 return emitErrorFn()
2385 <<
"enum variant " << elt.name <<
" has value " << current
2386 <<
" which is not greater than previous variant " << previous;
2395 auto *impl = getImpl();
2397 if (impl->anonymousType)
2398 return impl->anonymousType;
2400 if (!impl->recProps.containsTypeAlias)
2401 return impl->anonymousType = *
this;
2403 SmallVector<FEnumType::EnumElement, 4> elements;
2405 for (
auto element : getElements())
2407 {element.name, element.value, element.type.getAnonymousType()});
2408 return impl->anonymousType = FEnumType::get(getContext(), elements);
2417 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2441auto BaseTypeAliasType::get(StringAttr name,
FIRRTLBaseType innerType)
2442 -> BaseTypeAliasType {
2443 return Base::get(name.getContext(), name, innerType);
2446auto BaseTypeAliasType::getName() const -> StringAttr {
2447 return getImpl()->name;
2451 return getImpl()->innerType;
2455 auto *impl = getImpl();
2456 if (impl->anonymousType)
2457 return impl->anonymousType;
2458 return impl->anonymousType = getInnerType().getAnonymousType();
2466 auto rtp = getInnerType().getRecursiveTypeProperties();
2474BaseTypeAliasType::getModifiedType(
FIRRTLBaseType newInnerType)
const {
2475 if (newInnerType == getInnerType())
2477 return newInnerType;
2482 return getModifiedType(getInnerType().getAllConstDroppedType());
2486 return getModifiedType(getInnerType().getConstType(
isConst));
2489std::pair<Type, uint64_t>
2490BaseTypeAliasType::getSubTypeByFieldID(uint64_t fieldID)
const {
2494uint64_t BaseTypeAliasType::getMaxFieldID()
const {
2498std::pair<uint64_t, bool>
2499BaseTypeAliasType::projectToChildFieldID(uint64_t fieldID,
2500 uint64_t index)
const {
2504uint64_t BaseTypeAliasType::getIndexForFieldID(uint64_t fieldID)
const {
2508uint64_t BaseTypeAliasType::getFieldID(uint64_t index)
const {
2512std::pair<uint64_t, uint64_t>
2513BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2522 return LHSType::get(type.getContext(), type);
2525LogicalResult LHSType::verify(function_ref<InFlightDiagnostic()> emitError,
2527 if (type.containsAnalog())
2528 return emitError() <<
"lhs type cannot contain an AnalogType";
2530 return emitError() <<
"lhs type cannot contain a non-passive type";
2531 if (type.containsReference())
2532 return emitError() <<
"lhs type cannot contain a reference";
2533 if (type_isa<LHSType>(type))
2534 return emitError() <<
"lhs type cannot contain a lhs type";
2543auto RefType::get(
FIRRTLBaseType type,
bool forceable, SymbolRefAttr layer)
2545 return Base::get(type.getContext(), type, forceable, layer);
2548auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2551 if (!base.isPassive())
2552 return emitErrorFn() <<
"reference base type must be passive";
2553 if (forceable && base.containsConst())
2554 return emitErrorFn()
2555 <<
"forceable reference base type cannot contain const";
2560 auto rtp = getType().getRecursiveTypeProperties();
2563 rtp.isPassive =
false;
2571AnalogType AnalogType::get(mlir::MLIRContext *
context) {
2572 return AnalogType::get(
context, -1,
false);
2575AnalogType AnalogType::get(mlir::MLIRContext *
context,
2576 std::optional<int32_t> width,
bool isConst) {
2580LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2581 int32_t widthOrSentinel,
bool isConst) {
2582 if (widthOrSentinel < -1)
2583 return emitError() <<
"invalid width";
2587int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2589AnalogType AnalogType::getConstType(
bool isConst)
const {
2592 return get(getContext(), getWidthOrSentinel(),
isConst);
2599ClockType ClockType::getConstType(
bool isConst)
const {
2609ResetType ResetType::getConstType(
bool isConst)
const {
2619AsyncResetType AsyncResetType::getConstType(
bool isConst)
const {
2630 using KeyTy = std::tuple<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2634 auto name = std::get<0>(key);
2635 auto elements = allocator.copyInto(std::get<1>(key));
2638 SmallVector<uint64_t, 4> ids;
2647 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2669ClassType ClassType::get(FlatSymbolRefAttr name,
2670 ArrayRef<ClassElement> elements) {
2671 return get(name.getContext(), name, elements);
2674StringRef ClassType::getName()
const {
2675 return getNameAttr().getAttr().getValue();
2678FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2680ArrayRef<ClassElement> ClassType::getElements()
const {
2681 return getImpl()->elements;
2684const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2685 return getElement(index.getValue().getZExtValue());
2688const ClassElement &ClassType::getElement(
size_t index)
const {
2689 return getElements()[index];
2692std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2693 for (
const auto [i, e] :
llvm::enumerate(getElements()))
2694 if (fieldName == e.name)
2699void ClassType::printInterface(AsmPrinter &p)
const {
2703 for (
const auto &element : getElements()) {
2707 p.printKeywordOrString(element.name);
2708 p <<
": " << element.type;
2714uint64_t ClassType::getFieldID(uint64_t index)
const {
2715 return getImpl()->fieldIDs[index];
2718uint64_t ClassType::getIndexForFieldID(uint64_t fieldID)
const {
2719 assert(!getElements().
empty() &&
"Class must have >0 fields");
2720 auto fieldIDs = getImpl()->fieldIDs;
2721 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2722 return std::distance(fieldIDs.begin(), it);
2725std::pair<uint64_t, uint64_t>
2726ClassType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2729 return {index, fieldID - elementFieldID};
2732std::pair<Type, uint64_t>
2733ClassType::getSubTypeByFieldID(uint64_t fieldID)
const {
2737 auto subfieldType = getElement(subfieldIndex).type;
2738 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2739 return {subfieldType, subfieldID};
2742uint64_t ClassType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2744std::pair<uint64_t, bool>
2745ClassType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2747 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2749 return std::make_pair(fieldID - childRoot,
2750 fieldID >= childRoot && fieldID <= rangeEnd);
2757struct InterfaceParser {
2760 InterfaceParser(AsmParser &parser) : parser(parser) {}
2763 template <
typename FieldContainer>
2765 function_ref<ParseResult(FieldContainer &, AsmParser &parser)> parseField,
2766 StringAttr &symbolName, FieldContainer &fields) {
2768 if (parser.parseSymbolName(symbolName))
2772 if (parser.parseLParen())
2776 if (failed(parser.parseOptionalRParen())) {
2777 auto parseElement = [&]() -> ParseResult {
2778 return parseField(fields, parser);
2781 if (parser.parseCommaSeparatedList(parseElement) || parser.parseRParen())
2790ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2791 InterfaceParser helper(parser);
2793 auto parseField = [](SmallVector<ClassElement> &elements,
2794 AsmParser &parser) -> ParseResult {
2797 if (succeeded(parser.parseOptionalKeyword(
"out")))
2799 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2805 std::string keyword;
2806 if (parser.parseKeywordOrString(&keyword))
2808 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2812 if (parser.parseColonType(type))
2815 elements.emplace_back(name, type, direction);
2819 StringAttr symbolName;
2820 SmallVector<ClassElement> elements;
2821 if (helper.parse<SmallVector<ClassElement>>(parseField, symbolName, elements))
2824 result = ClassType::get(FlatSymbolRefAttr::get(symbolName), elements);
2832ParseResult DomainType::parseInterface(AsmParser &parser, DomainType &result) {
2833 InterfaceParser helper(parser);
2835 auto parseField = [](SmallVector<Attribute> &fields,
2836 AsmParser &parser) -> ParseResult {
2837 std::string fieldNameStr;
2839 if (parser.parseKeywordOrString(&fieldNameStr) || parser.parseColon() ||
2840 parser.parseType(fieldTypeRaw))
2843 auto fieldType = dyn_cast<PropertyType>(fieldTypeRaw);
2845 return parser.emitError(parser.getCurrentLocation(),
2846 "expected property type");
2848 auto fieldName = StringAttr::get(parser.getContext(), fieldNameStr);
2850 DomainFieldAttr::get(parser.getContext(), fieldName, fieldType));
2854 StringAttr symbolName;
2855 SmallVector<Attribute> fields;
2856 if (helper.parse<SmallVector<Attribute>>(parseField, symbolName, fields))
2859 result = DomainType::get(FlatSymbolRefAttr::get(symbolName),
2860 ArrayAttr::get(parser.getContext(), fields));
2864DomainType DomainType::get(FlatSymbolRefAttr name, ArrayAttr fields) {
2865 return Base::get(name.getContext(), name, fields);
2868DomainType DomainType::getFromDomainOp(DomainOp domainOp) {
2869 auto name = FlatSymbolRefAttr::get(domainOp.getNameAttr());
2870 return DomainType::get(name, domainOp.getFieldsAttr());
2873DomainFieldAttr DomainType::getField(
size_t index)
const {
2874 assert(index < getNumFields() &&
"index out of bounds");
2875 return cast<DomainFieldAttr>(getFields()[index]);
2878std::optional<uint64_t> DomainType::getFieldIndex(StringRef fieldName)
const {
2879 for (
const auto [i, attr] :
llvm::enumerate(getFields())) {
2880 auto field = cast<DomainFieldAttr>(attr);
2881 if (fieldName == field.getName())
2887std::pair<Type, uint64_t>
2888DomainType::getSubTypeByFieldID(uint64_t fieldID)
const {
2894 if (fieldID > getNumFields())
2895 return {Type(), fieldID};
2897 return {getField(fieldID - 1).getType(), 0};
2900uint64_t DomainType::getMaxFieldID()
const {
2902 return getNumFields();
2905std::pair<uint64_t, bool>
2906DomainType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2908 if (index >= getNumFields())
2911 uint64_t childFieldID = index + 1;
2912 return {0, fieldID == childFieldID};
2915uint64_t DomainType::getFieldID(uint64_t index)
const {
2917 assert(index < getNumFields() &&
"index out of bounds");
2921uint64_t DomainType::getIndexForFieldID(uint64_t fieldID)
const {
2923 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2927std::pair<uint64_t, uint64_t>
2928DomainType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2930 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2931 return {fieldID - 1, 0};
2935DomainType::verifySymbolUses(Operation *op,
2936 SymbolTableCollection &symbolTable)
const {
2938 auto circuitOp = op->getParentOfType<CircuitOp>();
2940 return op->emitError() <<
"domain type used outside of a circuit";
2943 auto *symbol = symbolTable.lookupSymbolIn(circuitOp,
getName());
2945 return op->emitError() <<
"domain type references undefined symbol '"
2946 <<
getName().getValue() <<
"'";
2949 auto domainOp = dyn_cast<DomainOp>(symbol);
2951 return op->emitError() <<
"domain type references symbol '"
2952 <<
getName().getValue() <<
"' which is not a domain";
2955 auto expectedFields = domainOp.getFieldsAttr();
2956 auto actualFields = getFields();
2959 if (actualFields.size() != expectedFields.size())
2960 return op->emitError() <<
"domain type has " << actualFields.size()
2961 <<
" fields but domain definition has "
2962 << expectedFields.size() <<
" fields";
2965 for (
size_t i = 0; i < actualFields.size(); ++i) {
2966 auto actualField = cast<DomainFieldAttr>(actualFields[i]);
2967 auto expectedField = cast<DomainFieldAttr>(expectedFields[i]);
2970 if (actualField.getName() != expectedField.getName())
2971 return op->emitError() <<
"domain type field " << i <<
" has name '"
2972 << actualField.getName().getValue()
2973 <<
"' but domain definition expects '"
2974 << expectedField.getName().getValue() <<
"'";
2977 if (actualField.getType() != expectedField.getType())
2978 return op->emitError()
2979 <<
"domain type field '" << actualField.getName().getValue()
2980 <<
"' has type " << actualField.getType()
2981 <<
" but domain definition expects " << expectedField.getType();
2991void FIRRTLDialect::registerTypes() {
2993#define GET_TYPEDEF_LIST
2994#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
3008 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
3009 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
3011 for (
auto &elt : bundle) {
3012 if (elt.isFlip && !ignoreFlip)
3013 return std::nullopt;
3016 return std::nullopt;
3021 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
3023 for (
auto &elt : fenum) {
3026 return std::nullopt;
3027 width = std::max(width, *w);
3029 return width + fenum.getTagWidth();
3031 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
3034 return std::nullopt;
3035 return *w * vector.getNumElements();
3038 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
3039 .Default([&](
auto t) {
return std::nullopt; });
3041 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 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)