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());
1323 if (isa<FIRRTLBaseType>(type))
1326 if (
auto bundle = dyn_cast<OpenBundleType>(type))
1327 return llvm::any_of(bundle,
1329 if (
auto vector = dyn_cast<OpenVectorType>(type))
1342 int32_t widthOrSentinel,
bool isConst) {
1349 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1350 return sintType.getWidthOrSentinel();
1351 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1352 return uintType.getWidthOrSentinel();
1363 using KeyTy = std::tuple<int32_t, char>;
1380 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1389SIntType SIntType::get(MLIRContext *
context) {
return get(
context, -1,
false); }
1391SIntType SIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1396LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1397 int32_t widthOrSentinel,
bool isConst) {
1398 if (widthOrSentinel < -1)
1399 return emitError() <<
"invalid width";
1403int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1405SIntType SIntType::getConstType(
bool isConst)
const {
1408 return get(getContext(), getWidthOrSentinel(),
isConst);
1417UIntType UIntType::get(MLIRContext *
context, std::optional<int32_t> width,
1422LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1423 int32_t widthOrSentinel,
bool isConst) {
1424 if (widthOrSentinel < -1)
1425 return emitError() <<
"invalid width";
1429int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1431UIntType UIntType::getConstType(
bool isConst)
const {
1434 return get(getContext(), getWidthOrSentinel(),
isConst);
1443 using KeyTy = std::tuple<ArrayRef<BundleType::BundleElement>,
char>;
1448 props{true, false, false,
isConst, false, false, false} {
1449 uint64_t fieldID = 0;
1452 auto type = element.type;
1453 auto eltInfo = type.getRecursiveTypeProperties();
1480 std::get<0>(key),
static_cast<bool>(std::get<1>(key)));
1494BundleType BundleType::get(MLIRContext *
context,
1495 ArrayRef<BundleElement> elements,
bool isConst) {
1499auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1500 return getImpl()->elements;
1505 return getImpl()->props;
1510 auto *impl = getImpl();
1513 if (impl->passiveType)
1514 return impl->passiveType;
1517 if (impl->props.isPassive) {
1518 impl->passiveType = *
this;
1523 SmallVector<BundleType::BundleElement, 16> newElements;
1524 newElements.reserve(impl->elements.size());
1525 for (
auto &elt : impl->elements) {
1526 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1529 auto passiveType = BundleType::get(getContext(), newElements,
isConst());
1530 impl->passiveType = passiveType;
1534BundleType BundleType::getConstType(
bool isConst)
const {
1537 return get(getContext(), getElements(),
isConst);
1540BundleType BundleType::getAllConstDroppedType() {
1544 SmallVector<BundleElement> constDroppedElements(
1545 llvm::map_range(getElements(), [](BundleElement element) {
1546 element.type = element.type.getAllConstDroppedType();
1549 return get(getContext(), constDroppedElements,
false);
1552std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1553 for (
const auto &it :
llvm::enumerate(getElements())) {
1554 auto element = it.value();
1555 if (element.name == name) {
1556 return unsigned(it.index());
1559 return std::nullopt;
1562std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1563 for (
const auto &it :
llvm::enumerate(getElements())) {
1564 auto element = it.value();
1565 if (element.name.getValue() == name) {
1566 return unsigned(it.index());
1569 return std::nullopt;
1572StringAttr BundleType::getElementNameAttr(
size_t index) {
1573 assert(index < getNumElements() &&
1574 "index must be less than number of fields in bundle");
1575 return getElements()[index].name;
1578StringRef BundleType::getElementName(
size_t index) {
1579 return getElementNameAttr(index).getValue();
1582std::optional<BundleType::BundleElement>
1583BundleType::getElement(StringAttr name) {
1584 if (
auto maybeIndex = getElementIndex(name))
1585 return getElements()[*maybeIndex];
1586 return std::nullopt;
1589std::optional<BundleType::BundleElement>
1590BundleType::getElement(StringRef name) {
1591 if (
auto maybeIndex = getElementIndex(name))
1592 return getElements()[*maybeIndex];
1593 return std::nullopt;
1597BundleType::BundleElement BundleType::getElement(
size_t index) {
1598 assert(index < getNumElements() &&
1599 "index must be less than number of fields in bundle");
1600 return getElements()[index];
1604 auto element = getElement(name);
1609 auto element = getElement(name);
1614 assert(index < getNumElements() &&
1615 "index must be less than number of fields in bundle");
1616 return getElements()[index].type;
1619uint64_t BundleType::getFieldID(uint64_t index)
const {
1620 return getImpl()->fieldIDs[index];
1623uint64_t BundleType::getIndexForFieldID(uint64_t fieldID)
const {
1624 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1625 auto fieldIDs = getImpl()->fieldIDs;
1626 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1627 return std::distance(fieldIDs.begin(), it);
1630std::pair<uint64_t, uint64_t>
1631BundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1634 return {index, fieldID - elementFieldID};
1637std::pair<Type, uint64_t>
1638BundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1642 auto subfieldType = getElementType(subfieldIndex);
1643 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1644 return {subfieldType, subfieldID};
1647uint64_t BundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1649std::pair<uint64_t, bool>
1650BundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1652 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1654 return std::make_pair(fieldID - childRoot,
1655 fieldID >= childRoot && fieldID <= rangeEnd);
1658bool BundleType::isConst()
const {
return getImpl()->isConst; }
1660BundleType::ElementType
1661BundleType::getElementTypePreservingConst(
size_t index) {
1662 auto type = getElementType(index);
1663 return type.getConstType(type.isConst() ||
isConst());
1668 auto *impl = getImpl();
1671 if (impl->anonymousType)
1672 return impl->anonymousType;
1675 if (!impl->props.containsTypeAlias) {
1676 impl->anonymousType = *
this;
1682 SmallVector<BundleType::BundleElement, 16> newElements;
1683 newElements.reserve(impl->elements.size());
1684 for (
auto &elt : impl->elements)
1685 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1687 auto anonymousType = BundleType::get(getContext(), newElements,
isConst());
1688 impl->anonymousType = anonymousType;
1689 return anonymousType;
1692LogicalResult BundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1693 ArrayRef<BundleElement> elements,
1695 SmallPtrSet<StringAttr, 4> nameSet;
1696 for (
auto &element : elements) {
1697 if (!nameSet.insert(element.name).second)
1698 return emitErrorFn() <<
"duplicate field name " << element.name
1710 using KeyTy = std::tuple<ArrayRef<OpenBundleType::BundleElement>,
char>;
1715 props{true, false, false,
isConst, false, false, false},
1717 uint64_t fieldID = 0;
1720 auto type = element.type;
1721 auto eltInfo = type.getRecursiveTypeProperties();
1750 static_cast<bool>(std::get<1>(key)));
1753 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1765OpenBundleType OpenBundleType::get(MLIRContext *
context,
1766 ArrayRef<BundleElement> elements,
1771auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1772 return getImpl()->elements;
1777 return getImpl()->props;
1780OpenBundleType OpenBundleType::getConstType(
bool isConst)
const {
1783 return get(getContext(), getElements(),
isConst);
1786std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1787 for (
const auto &it :
llvm::enumerate(getElements())) {
1788 auto element = it.value();
1789 if (element.name == name) {
1790 return unsigned(it.index());
1793 return std::nullopt;
1796std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1797 for (
const auto &it :
llvm::enumerate(getElements())) {
1798 auto element = it.value();
1799 if (element.name.getValue() == name) {
1800 return unsigned(it.index());
1803 return std::nullopt;
1806StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1807 assert(index < getNumElements() &&
1808 "index must be less than number of fields in bundle");
1809 return getElements()[index].name;
1812StringRef OpenBundleType::getElementName(
size_t index) {
1813 return getElementNameAttr(index).getValue();
1816std::optional<OpenBundleType::BundleElement>
1817OpenBundleType::getElement(StringAttr name) {
1818 if (
auto maybeIndex = getElementIndex(name))
1819 return getElements()[*maybeIndex];
1820 return std::nullopt;
1823std::optional<OpenBundleType::BundleElement>
1824OpenBundleType::getElement(StringRef name) {
1825 if (
auto maybeIndex = getElementIndex(name))
1826 return getElements()[*maybeIndex];
1827 return std::nullopt;
1831OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1832 assert(index < getNumElements() &&
1833 "index must be less than number of fields in bundle");
1834 return getElements()[index];
1837OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1838 auto element = getElement(name);
1842OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1843 auto element = getElement(name);
1847OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1848 assert(index < getNumElements() &&
1849 "index must be less than number of fields in bundle");
1850 return getElements()[index].type;
1853uint64_t OpenBundleType::getFieldID(uint64_t index)
const {
1854 return getImpl()->fieldIDs[index];
1857uint64_t OpenBundleType::getIndexForFieldID(uint64_t fieldID)
const {
1858 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1859 auto fieldIDs = getImpl()->fieldIDs;
1860 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1861 return std::distance(fieldIDs.begin(), it);
1864std::pair<uint64_t, uint64_t>
1865OpenBundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1868 return {index, fieldID - elementFieldID};
1871std::pair<Type, uint64_t>
1872OpenBundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1876 auto subfieldType = getElementType(subfieldIndex);
1877 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1878 return {subfieldType, subfieldID};
1881uint64_t OpenBundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1883std::pair<uint64_t, bool>
1884OpenBundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1886 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1888 return std::make_pair(fieldID - childRoot,
1889 fieldID >= childRoot && fieldID <= rangeEnd);
1892bool OpenBundleType::isConst()
const {
return getImpl()->isConst; }
1894OpenBundleType::ElementType
1895OpenBundleType::getElementTypePreservingConst(
size_t index) {
1896 auto type = getElementType(index);
1898 return TypeSwitch<FIRRTLType, ElementType>(type)
1899 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1900 return type.getConstType(type.isConst() ||
isConst());
1906OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1907 ArrayRef<BundleElement> elements,
bool isConst) {
1908 SmallPtrSet<StringAttr, 4> nameSet;
1909 for (
auto &element : elements) {
1910 if (!nameSet.insert(element.name).second)
1911 return emitErrorFn() <<
"duplicate field name " << element.name
1912 <<
" in openbundle";
1914 return emitErrorFn()
1915 <<
"'const' bundle cannot have references, but element "
1916 << element.name <<
" has type " << element.type;
1917 if (type_isa<LHSType>(element.type))
1918 return emitErrorFn() <<
"bundle element " << element.name
1919 <<
" cannot have a left-hand side type";
1931 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1949 static_cast<bool>(std::get<2>(key)));
1968 return getImpl()->elementType;
1971size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1975 return getImpl()->props;
1980 auto *impl = getImpl();
1983 if (impl->passiveType)
1984 return impl->passiveType;
1987 if (impl->elementType.getRecursiveTypeProperties().isPassive)
1988 return impl->passiveType = *
this;
1991 auto passiveType = FVectorType::get(getElementType().
getPassiveType(),
1993 impl->passiveType = passiveType;
1997FVectorType FVectorType::getConstType(
bool isConst)
const {
2000 return get(getElementType(), getNumElements(),
isConst);
2003FVectorType FVectorType::getAllConstDroppedType() {
2006 return get(getElementType().getAllConstDroppedType(), getNumElements(),
2012 auto *impl = getImpl();
2014 if (impl->anonymousType)
2015 return impl->anonymousType;
2018 if (!impl->props.containsTypeAlias)
2019 return impl->anonymousType = *
this;
2022 auto anonymousType = FVectorType::get(getElementType().getAnonymousType(),
2024 impl->anonymousType = anonymousType;
2025 return anonymousType;
2028uint64_t FVectorType::getFieldID(uint64_t index)
const {
2032uint64_t FVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2033 assert(fieldID &&
"fieldID must be at least 1");
2038std::pair<uint64_t, uint64_t>
2039FVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2042 return {index, fieldID - elementFieldID};
2045std::pair<Type, uint64_t>
2046FVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2052uint64_t FVectorType::getMaxFieldID()
const {
2053 return getNumElements() *
2057std::pair<uint64_t, bool>
2058FVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2062 return std::make_pair(fieldID - childRoot,
2063 fieldID >= childRoot && fieldID <= rangeEnd);
2066bool FVectorType::isConst()
const {
return getImpl()->isConst; }
2068FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
2069 auto type = getElementType();
2070 return type.getConstType(type.isConst() ||
isConst());
2078 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
2096 static_cast<bool>(std::get<2>(key)));
2111FIRRTLType OpenVectorType::getElementType()
const {
2112 return getImpl()->elementType;
2115size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
2119 return getImpl()->props;
2122OpenVectorType OpenVectorType::getConstType(
bool isConst)
const {
2125 return get(getElementType(), getNumElements(),
isConst);
2128uint64_t OpenVectorType::getFieldID(uint64_t index)
const {
2132uint64_t OpenVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2133 assert(fieldID &&
"fieldID must be at least 1");
2138std::pair<uint64_t, uint64_t>
2139OpenVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2142 return {index, fieldID - elementFieldID};
2145std::pair<Type, uint64_t>
2146OpenVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2152uint64_t OpenVectorType::getMaxFieldID()
const {
2154 return getNumElements() *
2158std::pair<uint64_t, bool>
2159OpenVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2163 return std::make_pair(fieldID - childRoot,
2164 fieldID >= childRoot && fieldID <= rangeEnd);
2167bool OpenVectorType::isConst()
const {
return getImpl()->isConst; }
2169OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2170 auto type = getElementType();
2172 return TypeSwitch<FIRRTLType, ElementType>(type)
2173 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2174 return type.getConstType(type.isConst() ||
isConst());
2180OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2184 return emitErrorFn() <<
"vector cannot be const with references";
2186 return emitErrorFn() <<
"vector cannot have a left-hand side type";
2195 using KeyTy = std::tuple<ArrayRef<FEnumType::EnumElement>,
char>;
2201 false,
false,
false};
2204 auto type = element.type;
2205 auto eltInfo = type.getRecursiveTypeProperties();
2207 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2234FEnumType FEnumType::get(::mlir::MLIRContext *
context,
2235 ArrayRef<EnumElement> elements,
bool isConst) {
2239ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2240 return getImpl()->elements;
2243FEnumType FEnumType::getConstType(
bool isConst)
const {
2244 return get(getContext(), getElements(),
isConst);
2247FEnumType FEnumType::getAllConstDroppedType() {
2251 SmallVector<EnumElement> constDroppedElements(
2252 llvm::map_range(getElements(), [](EnumElement element) {
2253 element.type = element.type.getAllConstDroppedType();
2256 return get(getContext(), constDroppedElements,
false);
2261 return getImpl()->recProps;
2264std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2265 for (
const auto &it :
llvm::enumerate(getElements())) {
2266 auto element = it.value();
2267 if (element.name == name) {
2268 return unsigned(it.index());
2271 return std::nullopt;
2274size_t FEnumType::getBitWidth() {
return getDataWidth() + getTagWidth(); }
2276size_t FEnumType::getDataWidth() {
return getImpl()->dataSize; }
2278size_t FEnumType::getTagWidth() {
2279 if (getElements().size() == 0)
2282 return cast<IntegerType>(getElements()[0].value.getType()).getWidth();
2285std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2286 for (
const auto &it :
llvm::enumerate(getElements())) {
2287 auto element = it.value();
2288 if (element.name.getValue() == name) {
2289 return unsigned(it.index());
2292 return std::nullopt;
2295StringAttr FEnumType::getElementNameAttr(
size_t index) {
2296 assert(index < getNumElements() &&
2297 "index must be less than number of fields in enum");
2298 return getElements()[index].name;
2301StringRef FEnumType::getElementName(
size_t index) {
2302 return getElementNameAttr(index).getValue();
2305IntegerAttr FEnumType::getElementValueAttr(
size_t index) {
2306 return getElements()[index].value;
2309APInt FEnumType::getElementValue(
size_t index) {
2310 return getElementValueAttr(index).getValue();
2314 return getElements()[index].type;
2317std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2318 if (
auto maybeIndex = getElementIndex(name))
2319 return getElements()[*maybeIndex];
2320 return std::nullopt;
2323std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2324 if (
auto maybeIndex = getElementIndex(name))
2325 return getElements()[*maybeIndex];
2326 return std::nullopt;
2330FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2331 assert(index < getNumElements() &&
2332 "index must be less than number of fields in enum");
2333 return getElements()[index];
2337 auto element = getElement(name);
2342 auto element = getElement(name);
2347 assert(index < getNumElements() &&
2348 "index must be less than number of fields in enum");
2349 return getElements()[index].type;
2352FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2353 auto type = getElementType(index);
2354 return type.getConstType(type.isConst() ||
isConst());
2357LogicalResult FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2358 ArrayRef<EnumElement> elements,
bool isConst) {
2360 IntegerAttr previous;
2361 SmallPtrSet<Attribute, 4> nameSet;
2363 for (
auto &elt : elements) {
2364 auto r = elt.type.getRecursiveTypeProperties();
2366 return emitErrorFn() <<
"enum field " << elt.name <<
" not passive";
2367 if (r.containsAnalog)
2368 return emitErrorFn() <<
"enum field " << elt.name <<
" contains analog";
2369 if (r.hasUninferredWidth)
2370 return emitErrorFn() <<
"enum field " << elt.name
2371 <<
" has uninferred width";
2372 if (r.hasUninferredReset)
2373 return emitErrorFn() <<
"enum field " << elt.name
2374 <<
" has uninferred reset";
2375 if (r.containsConst && !
isConst)
2376 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2378 if (!nameSet.insert(elt.name).second)
2379 return emitErrorFn() <<
"duplicate variant name " << elt.name
2383 previous = elt.value;
2386 auto current = elt.value;
2387 if (previous.getType() != current.getType())
2388 return emitErrorFn() <<
"enum variant " << elt.name <<
" has type"
2389 << current.getType()
2390 <<
" which is different than previous variant "
2391 << previous.getType();
2393 if (previous.getValue().getBitWidth() != current.getValue().getBitWidth())
2394 return emitErrorFn() <<
"enum variant " << elt.name <<
" has bitwidth"
2395 << current.getValue().getBitWidth()
2396 <<
" which is different than previous variant "
2397 << previous.getValue().getBitWidth();
2398 if (previous.getValue().uge(current.getValue()))
2399 return emitErrorFn()
2400 <<
"enum variant " << elt.name <<
" has value " << current
2401 <<
" which is not greater than previous variant " << previous;
2410 auto *impl = getImpl();
2412 if (impl->anonymousType)
2413 return impl->anonymousType;
2415 if (!impl->recProps.containsTypeAlias)
2416 return impl->anonymousType = *
this;
2418 SmallVector<FEnumType::EnumElement, 4> elements;
2420 for (
auto element : getElements())
2422 {element.name, element.value, element.type.getAnonymousType()});
2423 return impl->anonymousType = FEnumType::get(getContext(), elements);
2432 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2456auto BaseTypeAliasType::get(StringAttr name,
FIRRTLBaseType innerType)
2457 -> BaseTypeAliasType {
2458 return Base::get(name.getContext(), name, innerType);
2461auto BaseTypeAliasType::getName() const -> StringAttr {
2462 return getImpl()->name;
2466 return getImpl()->innerType;
2470 auto *impl = getImpl();
2471 if (impl->anonymousType)
2472 return impl->anonymousType;
2473 return impl->anonymousType = getInnerType().getAnonymousType();
2481 auto rtp = getInnerType().getRecursiveTypeProperties();
2489BaseTypeAliasType::getModifiedType(
FIRRTLBaseType newInnerType)
const {
2490 if (newInnerType == getInnerType())
2492 return newInnerType;
2497 return getModifiedType(getInnerType().getAllConstDroppedType());
2501 return getModifiedType(getInnerType().getConstType(
isConst));
2504std::pair<Type, uint64_t>
2505BaseTypeAliasType::getSubTypeByFieldID(uint64_t fieldID)
const {
2509uint64_t BaseTypeAliasType::getMaxFieldID()
const {
2513std::pair<uint64_t, bool>
2514BaseTypeAliasType::projectToChildFieldID(uint64_t fieldID,
2515 uint64_t index)
const {
2519uint64_t BaseTypeAliasType::getIndexForFieldID(uint64_t fieldID)
const {
2523uint64_t BaseTypeAliasType::getFieldID(uint64_t index)
const {
2527std::pair<uint64_t, uint64_t>
2528BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2537 return LHSType::get(type.getContext(), type);
2540LogicalResult LHSType::verify(function_ref<InFlightDiagnostic()> emitError,
2542 if (type.containsAnalog())
2543 return emitError() <<
"lhs type cannot contain an AnalogType";
2545 return emitError() <<
"lhs type cannot contain a non-passive type";
2546 if (type.containsReference())
2547 return emitError() <<
"lhs type cannot contain a reference";
2548 if (type_isa<LHSType>(type))
2549 return emitError() <<
"lhs type cannot contain a lhs type";
2558auto RefType::get(
FIRRTLBaseType type,
bool forceable, SymbolRefAttr layer)
2560 return Base::get(type.getContext(), type, forceable, layer);
2563auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2566 if (!base.isPassive())
2567 return emitErrorFn() <<
"reference base type must be passive";
2568 if (forceable && base.containsConst())
2569 return emitErrorFn()
2570 <<
"forceable reference base type cannot contain const";
2575 auto rtp = getType().getRecursiveTypeProperties();
2578 rtp.isPassive =
false;
2586AnalogType AnalogType::get(mlir::MLIRContext *
context) {
2587 return AnalogType::get(
context, -1,
false);
2590AnalogType AnalogType::get(mlir::MLIRContext *
context,
2591 std::optional<int32_t> width,
bool isConst) {
2595LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2596 int32_t widthOrSentinel,
bool isConst) {
2597 if (widthOrSentinel < -1)
2598 return emitError() <<
"invalid width";
2602int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2604AnalogType AnalogType::getConstType(
bool isConst)
const {
2607 return get(getContext(), getWidthOrSentinel(),
isConst);
2614ClockType ClockType::getConstType(
bool isConst)
const {
2624ResetType ResetType::getConstType(
bool isConst)
const {
2634AsyncResetType AsyncResetType::getConstType(
bool isConst)
const {
2645 using KeyTy = std::tuple<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2649 auto name = std::get<0>(key);
2650 auto elements = allocator.copyInto(std::get<1>(key));
2653 SmallVector<uint64_t, 4> ids;
2662 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2684ClassType ClassType::get(FlatSymbolRefAttr name,
2685 ArrayRef<ClassElement> elements) {
2686 return get(name.getContext(), name, elements);
2689StringRef ClassType::getName()
const {
2690 return getNameAttr().getAttr().getValue();
2693FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2695ArrayRef<ClassElement> ClassType::getElements()
const {
2696 return getImpl()->elements;
2699const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2700 return getElement(index.getValue().getZExtValue());
2703const ClassElement &ClassType::getElement(
size_t index)
const {
2704 return getElements()[index];
2707std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2708 for (
const auto [i, e] :
llvm::enumerate(getElements()))
2709 if (fieldName == e.name)
2714void ClassType::printInterface(AsmPrinter &p)
const {
2718 for (
const auto &element : getElements()) {
2722 p.printKeywordOrString(element.name);
2723 p <<
": " << element.type;
2729uint64_t ClassType::getFieldID(uint64_t index)
const {
2730 return getImpl()->fieldIDs[index];
2733uint64_t ClassType::getIndexForFieldID(uint64_t fieldID)
const {
2734 assert(!getElements().
empty() &&
"Class must have >0 fields");
2735 auto fieldIDs = getImpl()->fieldIDs;
2736 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2737 return std::distance(fieldIDs.begin(), it);
2740std::pair<uint64_t, uint64_t>
2741ClassType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2744 return {index, fieldID - elementFieldID};
2747std::pair<Type, uint64_t>
2748ClassType::getSubTypeByFieldID(uint64_t fieldID)
const {
2752 auto subfieldType = getElement(subfieldIndex).type;
2753 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2754 return {subfieldType, subfieldID};
2757uint64_t ClassType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2759std::pair<uint64_t, bool>
2760ClassType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2762 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2764 return std::make_pair(fieldID - childRoot,
2765 fieldID >= childRoot && fieldID <= rangeEnd);
2772struct InterfaceParser {
2775 InterfaceParser(AsmParser &parser) : parser(parser) {}
2778 template <
typename FieldContainer>
2780 function_ref<ParseResult(FieldContainer &, AsmParser &parser)> parseField,
2781 StringAttr &symbolName, FieldContainer &fields) {
2783 if (parser.parseSymbolName(symbolName))
2787 if (parser.parseLParen())
2791 if (failed(parser.parseOptionalRParen())) {
2792 auto parseElement = [&]() -> ParseResult {
2793 return parseField(fields, parser);
2796 if (parser.parseCommaSeparatedList(parseElement) || parser.parseRParen())
2805ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2806 InterfaceParser helper(parser);
2808 auto parseField = [](SmallVector<ClassElement> &elements,
2809 AsmParser &parser) -> ParseResult {
2812 if (succeeded(parser.parseOptionalKeyword(
"out")))
2814 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2820 std::string keyword;
2821 if (parser.parseKeywordOrString(&keyword))
2823 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2827 if (parser.parseColonType(type))
2830 elements.emplace_back(name, type, direction);
2834 StringAttr symbolName;
2835 SmallVector<ClassElement> elements;
2836 if (helper.parse<SmallVector<ClassElement>>(parseField, symbolName, elements))
2839 result = ClassType::get(FlatSymbolRefAttr::get(symbolName), elements);
2847ParseResult DomainType::parseInterface(AsmParser &parser, DomainType &result) {
2848 InterfaceParser helper(parser);
2850 auto parseField = [](SmallVector<Attribute> &fields,
2851 AsmParser &parser) -> ParseResult {
2852 std::string fieldNameStr;
2854 if (parser.parseKeywordOrString(&fieldNameStr) || parser.parseColon() ||
2855 parser.parseType(fieldTypeRaw))
2858 auto fieldType = dyn_cast<PropertyType>(fieldTypeRaw);
2860 return parser.emitError(parser.getCurrentLocation(),
2861 "expected property type");
2863 auto fieldName = StringAttr::get(parser.getContext(), fieldNameStr);
2865 DomainFieldAttr::get(parser.getContext(), fieldName, fieldType));
2869 StringAttr symbolName;
2870 SmallVector<Attribute> fields;
2871 if (helper.parse<SmallVector<Attribute>>(parseField, symbolName, fields))
2874 result = DomainType::get(FlatSymbolRefAttr::get(symbolName),
2875 ArrayAttr::get(parser.getContext(), fields));
2879DomainType DomainType::get(FlatSymbolRefAttr name, ArrayAttr fields) {
2880 return Base::get(name.getContext(), name, fields);
2883DomainType DomainType::getFromDomainOp(DomainOp domainOp) {
2884 auto name = FlatSymbolRefAttr::get(domainOp.getNameAttr());
2885 return DomainType::get(name, domainOp.getFieldsAttr());
2888DomainFieldAttr DomainType::getField(
size_t index)
const {
2889 assert(index < getNumFields() &&
"index out of bounds");
2890 return cast<DomainFieldAttr>(getFields()[index]);
2893std::optional<uint64_t> DomainType::getFieldIndex(StringRef fieldName)
const {
2894 for (
const auto [i, attr] :
llvm::enumerate(getFields())) {
2895 auto field = cast<DomainFieldAttr>(attr);
2896 if (fieldName == field.getName())
2902std::pair<Type, uint64_t>
2903DomainType::getSubTypeByFieldID(uint64_t fieldID)
const {
2909 if (fieldID > getNumFields())
2910 return {Type(), fieldID};
2912 return {getField(fieldID - 1).getType(), 0};
2915uint64_t DomainType::getMaxFieldID()
const {
2917 return getNumFields();
2920std::pair<uint64_t, bool>
2921DomainType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2923 if (index >= getNumFields())
2926 uint64_t childFieldID = index + 1;
2927 return {0, fieldID == childFieldID};
2930uint64_t DomainType::getFieldID(uint64_t index)
const {
2932 assert(index < getNumFields() &&
"index out of bounds");
2936uint64_t DomainType::getIndexForFieldID(uint64_t fieldID)
const {
2938 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2942std::pair<uint64_t, uint64_t>
2943DomainType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2945 assert(fieldID > 0 && fieldID <= getNumFields() &&
"fieldID out of bounds");
2946 return {fieldID - 1, 0};
2950DomainType::verifySymbolUses(Operation *op,
2951 SymbolTableCollection &symbolTable)
const {
2953 auto circuitOp = op->getParentOfType<CircuitOp>();
2955 return op->emitError() <<
"domain type used outside of a circuit";
2958 auto *symbol = symbolTable.lookupSymbolIn(circuitOp,
getName());
2960 return op->emitError() <<
"domain type references undefined symbol '"
2961 <<
getName().getValue() <<
"'";
2964 auto domainOp = dyn_cast<DomainOp>(symbol);
2966 return op->emitError() <<
"domain type references symbol '"
2967 <<
getName().getValue() <<
"' which is not a domain";
2970 auto expectedFields = domainOp.getFieldsAttr();
2971 auto actualFields = getFields();
2974 if (actualFields.size() != expectedFields.size())
2975 return op->emitError() <<
"domain type has " << actualFields.size()
2976 <<
" fields but domain definition has "
2977 << expectedFields.size() <<
" fields";
2980 for (
size_t i = 0; i < actualFields.size(); ++i) {
2981 auto actualField = cast<DomainFieldAttr>(actualFields[i]);
2982 auto expectedField = cast<DomainFieldAttr>(expectedFields[i]);
2985 if (actualField.getName() != expectedField.getName())
2986 return op->emitError() <<
"domain type field " << i <<
" has name '"
2987 << actualField.getName().getValue()
2988 <<
"' but domain definition expects '"
2989 << expectedField.getName().getValue() <<
"'";
2992 if (actualField.getType() != expectedField.getType())
2993 return op->emitError()
2994 <<
"domain type field '" << actualField.getName().getValue()
2995 <<
"' has type " << actualField.getType()
2996 <<
" but domain definition expects " << expectedField.getType();
3006void FIRRTLDialect::registerTypes() {
3008#define GET_TYPEDEF_LIST
3009#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
3023 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
3024 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
3026 for (
auto &elt : bundle) {
3027 if (elt.isFlip && !ignoreFlip)
3028 return std::nullopt;
3031 return std::nullopt;
3036 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
3038 for (
auto &elt : fenum) {
3041 return std::nullopt;
3042 width = std::max(width, *w);
3044 return width + fenum.getTagWidth();
3046 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
3049 return std::nullopt;
3050 return *w * vector.getNumElements();
3053 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
3054 .Default([&](
auto t) {
return std::nullopt; });
3056 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)