16#include "mlir/IR/Builders.h"
17#include "mlir/IR/DialectImplementation.h"
18#include "llvm/ADT/SmallString.h"
29ConstantOp::inferReturnTypes(MLIRContext *context, std::optional<Location> loc,
30 ValueRange operands, DictionaryAttr attributes,
31 OpaqueProperties properties, RegionRange regions,
32 SmallVectorImpl<Type> &inferredReturnTypes) {
33 inferredReturnTypes.push_back(
34 properties.as<Properties *>()->getValue().getType());
38OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
return getValueAttr(); }
44LogicalResult SequenceOp::verifyRegions() {
45 if (TypeRange(getSequenceType().getElementTypes()) !=
46 getBody()->getArgumentTypes())
47 return emitOpError(
"sequence type does not match block argument types");
52ParseResult SequenceOp::parse(OpAsmParser &parser, OperationState &result) {
54 if (parser.parseSymbolName(
55 result.getOrAddProperties<SequenceOp::Properties>().sym_name))
59 SmallVector<OpAsmParser::Argument> arguments;
60 if (parser.parseArgumentList(arguments, OpAsmParser::Delimiter::Paren,
64 SmallVector<Type> argTypes;
65 SmallVector<Location> argLocs;
66 argTypes.reserve(arguments.size());
67 argLocs.reserve(arguments.size());
68 for (
auto &arg : arguments) {
69 argTypes.push_back(arg.type);
70 argLocs.push_back(arg.sourceLoc ? *arg.sourceLoc : result.location);
72 Type type = SequenceType::get(result.getContext(), argTypes);
73 result.getOrAddProperties<SequenceOp::Properties>().sequenceType =
76 auto loc = parser.getCurrentLocation();
77 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
79 if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
80 return parser.emitError(loc)
81 <<
"'" << result.name.getStringRef() <<
"' op ";
85 std::unique_ptr<Region> bodyRegionRegion = std::make_unique<Region>();
86 if (parser.parseRegion(*bodyRegionRegion, arguments))
89 if (bodyRegionRegion->empty()) {
90 bodyRegionRegion->emplaceBlock();
91 bodyRegionRegion->addArguments(argTypes, argLocs);
93 result.addRegion(std::move(bodyRegionRegion));
98void SequenceOp::print(OpAsmPrinter &p) {
100 p.printSymbolName(getSymNameAttr().getValue());
102 llvm::interleaveComma(getBody()->getArguments(), p,
103 [&](
auto arg) { p.printRegionArgument(arg); });
105 p.printOptionalAttrDictWithKeyword(
106 (*this)->getAttrs(), {getSymNameAttrName(), getSequenceTypeAttrName()});
108 p.printRegion(getBodyRegion(),
false);
111mlir::SymbolTable::Visibility SequenceOp::getVisibility() {
112 return mlir::SymbolTable::Visibility::Private;
115void SequenceOp::setVisibility(mlir::SymbolTable::Visibility visibility) {
117 assert(
false &&
"cannot change visibility of sequence");
125GetSequenceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
127 symbolTable.lookupNearestSymbolFrom<SequenceOp>(*
this, getSequenceAttr());
130 <<
"'" << getSequence()
131 <<
"' does not reference a valid 'rtg.sequence' operation";
133 if (
seq.getSequenceType() != getType())
134 return emitOpError(
"referenced 'rtg.sequence' op's type does not match");
143LogicalResult SubstituteSequenceOp::verify() {
144 if (getReplacements().
empty())
145 return emitOpError(
"must at least have one replacement value");
147 if (getReplacements().size() >
148 getSequence().getType().getElementTypes().size())
150 "must not have more replacement values than sequence arguments");
152 if (getReplacements().getTypes() !=
153 getSequence().getType().getElementTypes().take_front(
154 getReplacements().size()))
155 return emitOpError(
"replacement types must match the same number of "
156 "sequence argument types from the front");
161LogicalResult SubstituteSequenceOp::inferReturnTypes(
162 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
163 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
164 SmallVectorImpl<Type> &inferredReturnTypes) {
165 ArrayRef<Type> argTypes =
166 cast<SequenceType>(operands[0].getType()).getElementTypes();
168 SequenceType::get(context, argTypes.drop_front(operands.size() - 1));
169 inferredReturnTypes.push_back(seqType);
173ParseResult SubstituteSequenceOp::parse(::mlir::OpAsmParser &parser,
174 ::mlir::OperationState &result) {
175 OpAsmParser::UnresolvedOperand sequenceRawOperand;
176 SmallVector<OpAsmParser::UnresolvedOperand, 4> replacementsOperands;
177 Type sequenceRawType;
179 if (parser.parseOperand(sequenceRawOperand) || parser.parseLParen())
182 auto replacementsOperandsLoc = parser.getCurrentLocation();
183 if (parser.parseOperandList(replacementsOperands) || parser.parseRParen() ||
184 parser.parseColon() || parser.parseType(sequenceRawType) ||
185 parser.parseOptionalAttrDict(result.attributes))
188 if (!isa<SequenceType>(sequenceRawType))
189 return parser.emitError(parser.getNameLoc())
190 <<
"'sequence' must be handle to a sequence or sequence family, but "
194 if (parser.resolveOperand(sequenceRawOperand, sequenceRawType,
198 if (parser.resolveOperands(replacementsOperands,
199 cast<SequenceType>(sequenceRawType)
201 .take_front(replacementsOperands.size()),
202 replacementsOperandsLoc, result.operands))
205 SmallVector<Type> inferredReturnTypes;
206 if (failed(inferReturnTypes(
207 parser.getContext(), result.location, result.operands,
208 result.attributes.getDictionary(parser.getContext()),
209 result.getRawProperties(), result.regions, inferredReturnTypes)))
212 result.addTypes(inferredReturnTypes);
216void SubstituteSequenceOp::print(OpAsmPrinter &p) {
217 p <<
' ' << getSequence() <<
"(" << getReplacements()
218 <<
") : " << getSequence().getType();
219 p.printOptionalAttrDict((*this)->getAttrs(), {});
226LogicalResult InterleaveSequencesOp::verify() {
227 if (getSequences().
empty())
228 return emitOpError(
"must have at least one sequence in the list");
233OpFoldResult InterleaveSequencesOp::fold(FoldAdaptor adaptor) {
234 if (getSequences().size() == 1)
235 return getSequences()[0];
244ParseResult SetCreateOp::parse(OpAsmParser &parser, OperationState &result) {
245 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
248 if (parser.parseOperandList(operands) ||
249 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
250 parser.parseType(elemType))
253 result.addTypes({SetType::get(result.getContext(), elemType)});
255 for (
auto operand : operands)
256 if (parser.resolveOperand(operand, elemType, result.operands))
262void SetCreateOp::print(OpAsmPrinter &p) {
264 p.printOperands(getElements());
265 p.printOptionalAttrDict((*this)->getAttrs());
266 p <<
" : " << getSet().getType().getElementType();
269LogicalResult SetCreateOp::verify() {
270 if (getElements().size() > 0) {
273 if (getElements()[0].getType() != getSet().getType().getElementType())
274 return emitOpError() <<
"operand types must match set element type";
284LogicalResult SetCartesianProductOp::inferReturnTypes(
285 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
286 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
287 SmallVectorImpl<Type> &inferredReturnTypes) {
288 if (operands.empty()) {
290 return mlir::emitError(*loc) <<
"at least one set must be provided";
294 SmallVector<Type> elementTypes;
295 for (
auto operand : operands)
296 elementTypes.push_back(cast<SetType>(operand.getType()).getElementType());
297 inferredReturnTypes.push_back(
298 SetType::get(rtg::TupleType::get(context, elementTypes)));
306ParseResult BagCreateOp::parse(OpAsmParser &parser, OperationState &result) {
307 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> elementOperands,
311 if (!parser.parseOptionalLParen()) {
313 OpAsmParser::UnresolvedOperand elementOperand, multipleOperand;
314 if (parser.parseOperand(multipleOperand) || parser.parseKeyword(
"x") ||
315 parser.parseOperand(elementOperand))
318 elementOperands.push_back(elementOperand);
319 multipleOperands.push_back(multipleOperand);
321 if (parser.parseOptionalComma()) {
322 if (parser.parseRParen())
329 if (parser.parseColon() || parser.parseType(elemType) ||
330 parser.parseOptionalAttrDict(result.attributes))
333 result.addTypes({BagType::get(result.getContext(), elemType)});
335 for (
auto operand : elementOperands)
336 if (parser.resolveOperand(operand, elemType, result.operands))
339 for (
auto operand : multipleOperands)
340 if (parser.resolveOperand(operand, IndexType::
get(result.getContext()),
347void BagCreateOp::print(OpAsmPrinter &p) {
349 if (!getElements().
empty())
351 llvm::interleaveComma(llvm::zip(getElements(), getMultiples()), p,
352 [&](
auto elAndMultiple) {
353 auto [el, multiple] = elAndMultiple;
354 p << multiple <<
" x " << el;
356 if (!getElements().
empty())
359 p <<
" : " << getBag().getType().getElementType();
360 p.printOptionalAttrDict((*this)->getAttrs());
363LogicalResult BagCreateOp::verify() {
364 if (!llvm::all_equal(getElements().getTypes()))
365 return emitOpError() <<
"types of all elements must match";
367 if (getElements().size() > 0)
368 if (getElements()[0].getType() != getBag().getType().getElementType())
369 return emitOpError() <<
"operand types must match bag element type";
378LogicalResult TupleCreateOp::inferReturnTypes(
379 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
380 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
381 SmallVectorImpl<Type> &inferredReturnTypes) {
382 SmallVector<Type> elementTypes;
383 for (
auto operand : operands)
384 elementTypes.push_back(operand.getType());
385 inferredReturnTypes.push_back(rtg::TupleType::get(context, elementTypes));
393LogicalResult TupleExtractOp::inferReturnTypes(
394 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
395 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
396 SmallVectorImpl<Type> &inferredReturnTypes) {
397 assert(operands.size() == 1 &&
"must have exactly one operand");
399 auto tupleTy = dyn_cast<rtg::TupleType>(operands[0].getType());
400 size_t idx = properties.as<Properties *>()->getIndex().getInt();
403 return mlir::emitError(*loc) <<
"only RTG tuples are supported";
407 if (tupleTy.getFieldTypes().size() <= idx) {
409 return mlir::emitError(*loc)
411 <<
") must be smaller than number of elements in tuple ("
412 << tupleTy.getFieldTypes().size() <<
")";
416 inferredReturnTypes.push_back(tupleTy.getFieldTypes()[idx]);
424LogicalResult FixedRegisterOp::inferReturnTypes(
425 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
426 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
427 SmallVectorImpl<Type> &inferredReturnTypes) {
428 inferredReturnTypes.push_back(
429 properties.as<Properties *>()->getReg().getType());
433OpFoldResult FixedRegisterOp::fold(FoldAdaptor adaptor) {
return getRegAttr(); }
436 setNameFn(getResult(), getReg().getRegisterAssembly());
443LogicalResult VirtualRegisterOp::inferReturnTypes(
444 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
445 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
446 SmallVectorImpl<Type> &inferredReturnTypes) {
447 auto allowedRegs = properties.as<Properties *>()->getAllowedRegs();
448 inferredReturnTypes.push_back(allowedRegs.getType());
456LogicalResult ContextSwitchOp::verify() {
457 auto elementTypes = getSequence().getType().getElementTypes();
458 if (elementTypes.size() != 3)
459 return emitOpError(
"sequence type must have exactly 3 element types");
461 if (getFrom().getType() != elementTypes[0])
463 "first sequence element type must match 'from' attribute type");
465 if (getTo().getType() != elementTypes[1])
467 "second sequence element type must match 'to' attribute type");
469 auto seqTy = dyn_cast<SequenceType>(elementTypes[2]);
470 if (!seqTy || !seqTy.getElementTypes().empty())
472 "third sequence element type must be a fully substituted sequence");
481LogicalResult TestOp::verifyRegions() {
482 if (!getTargetType().entryTypesMatch(getBody()->getArgumentTypes()))
483 return emitOpError(
"argument types must match dict entry types");
488LogicalResult TestOp::verify() {
489 if (getTemplateName().
empty())
490 return emitOpError(
"template name must not be empty");
495LogicalResult TestOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
496 if (!getTargetAttr())
500 symbolTable.lookupNearestSymbolFrom<TargetOp>(*
this, getTargetAttr());
503 <<
"'" << *getTarget()
504 <<
"' does not reference a valid 'rtg.target' operation";
508 size_t targetIdx = 0;
509 auto targetEntries = target.getTarget().getEntries();
510 for (
auto testEntry : getTargetType().getEntries()) {
512 while (targetIdx < targetEntries.size() &&
513 targetEntries[targetIdx].name.getValue() < testEntry.name.getValue())
517 if (targetIdx >= targetEntries.size() ||
518 targetEntries[targetIdx].name != testEntry.name ||
519 targetEntries[targetIdx].type != testEntry.type) {
520 return emitOpError(
"referenced 'rtg.target' op's type is invalid: "
521 "missing entry called '")
522 << testEntry.name.getValue() <<
"' of type " << testEntry.type;
529ParseResult TestOp::parse(OpAsmParser &parser, OperationState &result) {
531 StringAttr symNameAttr;
532 if (parser.parseSymbolName(symNameAttr))
535 result.getOrAddProperties<TestOp::Properties>().sym_name = symNameAttr;
538 SmallVector<OpAsmParser::Argument> arguments;
539 SmallVector<StringAttr> names;
541 auto parseOneArgument = [&]() -> ParseResult {
543 if (parser.parseKeywordOrString(&name) || parser.parseEqual() ||
544 parser.parseArgument(arguments.emplace_back(),
true,
548 names.push_back(StringAttr::get(result.getContext(), name));
551 if (parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
552 parseOneArgument,
" in argument list"))
555 SmallVector<Type> argTypes;
556 SmallVector<DictEntry> entries;
557 SmallVector<Location> argLocs;
558 argTypes.reserve(arguments.size());
559 argLocs.reserve(arguments.size());
560 for (
auto [name, arg] :
llvm::zip(names, arguments)) {
561 argTypes.push_back(arg.type);
562 argLocs.push_back(arg.sourceLoc ? *arg.sourceLoc : result.location);
563 entries.push_back({name, arg.type});
565 auto emitError = [&]() -> InFlightDiagnostic {
566 return parser.emitError(parser.getCurrentLocation());
568 Type type = DictType::getChecked(emitError, result.getContext(),
569 ArrayRef<DictEntry>(entries));
572 result.getOrAddProperties<TestOp::Properties>().targetType =
575 std::string templateName;
576 if (!parser.parseOptionalKeyword(
"template")) {
577 auto loc = parser.getCurrentLocation();
578 if (parser.parseString(&templateName))
581 if (templateName.empty())
582 return parser.emitError(loc,
"template name must not be empty");
585 StringAttr templateNameAttr = symNameAttr;
586 if (!templateName.empty())
587 templateNameAttr = StringAttr::get(result.getContext(), templateName);
589 StringAttr targetName;
590 if (!parser.parseOptionalKeyword(
"target"))
591 if (parser.parseSymbolName(targetName))
594 result.getOrAddProperties<TestOp::Properties>().templateName =
596 result.getOrAddProperties<TestOp::Properties>().target = targetName;
598 auto loc = parser.getCurrentLocation();
599 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
601 if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
602 return parser.emitError(loc)
603 <<
"'" << result.name.getStringRef() <<
"' op ";
607 std::unique_ptr<Region> bodyRegionRegion = std::make_unique<Region>();
608 if (parser.parseRegion(*bodyRegionRegion, arguments))
611 if (bodyRegionRegion->empty()) {
612 bodyRegionRegion->emplaceBlock();
613 bodyRegionRegion->addArguments(argTypes, argLocs);
615 result.addRegion(std::move(bodyRegionRegion));
620void TestOp::print(OpAsmPrinter &p) {
622 p.printSymbolName(getSymNameAttr().getValue());
624 SmallString<32> resultNameStr;
625 llvm::interleaveComma(
626 llvm::zip(getTargetType().getEntries(), getBody()->getArguments()), p,
627 [&](
auto entryAndArg) {
628 auto [entry, arg] = entryAndArg;
629 p << entry.name.getValue() <<
" = ";
630 p.printRegionArgument(arg);
634 if (getSymNameAttr() != getTemplateNameAttr())
635 p <<
" template " << getTemplateNameAttr();
637 if (getTargetAttr()) {
639 p.printSymbolName(getTargetAttr().getValue());
642 p.printOptionalAttrDictWithKeyword(
643 (*this)->getAttrs(), {getSymNameAttrName(), getTargetTypeAttrName(),
644 getTargetAttrName(), getTemplateNameAttrName()});
646 p.printRegion(getBodyRegion(),
false);
649void TestOp::getAsmBlockArgumentNames(Region ®ion,
651 for (
auto [entry, arg] :
652 llvm::zip(getTargetType().getEntries(), region.getArguments()))
653 setNameFn(arg, entry.name.getValue());
660LogicalResult TargetOp::verifyRegions() {
661 if (!getTarget().entryTypesMatch(
662 getBody()->getTerminator()->getOperandTypes()))
663 return emitOpError(
"terminator operand types must match dict entry types");
672LogicalResult ValidateOp::verify() {
673 if (!getRef().getType().isValidContentType(getValue().getType()))
675 "result type must be a valid content type for the ref value");
684LogicalResult ArrayCreateOp::verify() {
685 if (!getElements().
empty() &&
686 getElements()[0].getType() != getType().getElementType())
687 return emitOpError(
"operand types must match array element type, expected ")
688 << getType().getElementType() <<
" but got "
689 << getElements()[0].getType();
694ParseResult ArrayCreateOp::parse(OpAsmParser &parser, OperationState &result) {
695 SmallVector<OpAsmParser::UnresolvedOperand> operands;
698 if (parser.parseOperandList(operands) || parser.parseColon() ||
700 parser.parseOptionalAttrDict(result.attributes))
703 if (failed(parser.resolveOperands(operands,
elementType, result.operands)))
711void ArrayCreateOp::print(OpAsmPrinter &p) {
713 p.printOperands(getElements());
714 p <<
" : " << getType().getElementType();
715 p.printOptionalAttrDict((*this)->getAttrs(), {});
722LogicalResult MemoryBlockDeclareOp::verify() {
725 "base address width must match memory block address width");
729 "end address width must match memory block address width");
731 if (getBaseAddress().ugt(getEndAddress()))
733 "base address must be smaller than or equal to the end address");
738ParseResult MemoryBlockDeclareOp::parse(OpAsmParser &parser,
739 OperationState &result) {
740 SmallVector<OpAsmParser::UnresolvedOperand> operands;
741 MemoryBlockType memoryBlockType;
744 if (parser.parseLSquare())
747 auto startLoc = parser.getCurrentLocation();
748 if (parser.parseInteger(start))
751 if (parser.parseMinus())
754 auto endLoc = parser.getCurrentLocation();
755 if (parser.parseInteger(end) || parser.parseRSquare() ||
756 parser.parseColonType(memoryBlockType) ||
757 parser.parseOptionalAttrDict(result.attributes))
760 auto width = memoryBlockType.getAddressWidth();
761 auto adjustAPInt = [&](APInt value, llvm::SMLoc loc) -> FailureOr<APInt> {
762 if (value.getBitWidth() > width) {
763 if (!value.isIntN(width))
764 return parser.emitError(
766 "address out of range for memory block with address width ")
769 return value.trunc(width);
772 if (value.getBitWidth() < width)
773 return value.zext(width);
778 auto startRes = adjustAPInt(start, startLoc);
779 auto endRes = adjustAPInt(end, endLoc);
780 if (failed(startRes) || failed(endRes))
783 auto intType = IntegerType::get(result.getContext(), width);
784 result.addAttribute(getBaseAddressAttrName(result.name),
785 IntegerAttr::get(intType, *startRes));
786 result.addAttribute(getEndAddressAttrName(result.name),
787 IntegerAttr::get(intType, *endRes));
789 result.addTypes(memoryBlockType);
793void MemoryBlockDeclareOp::print(OpAsmPrinter &p) {
794 SmallVector<char> str;
795 getBaseAddress().toString(str, 16,
false,
false,
false);
799 getEndAddress().toString(str, 16,
false,
false,
false);
800 p << str <<
"] : " << getType();
801 p.printOptionalAttrDict((*this)->getAttrs(),
802 {getBaseAddressAttrName(), getEndAddressAttrName()});
809LogicalResult MemoryBaseAddressOp::inferReturnTypes(
810 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
811 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
812 SmallVectorImpl<Type> &inferredReturnTypes) {
813 if (operands.empty())
815 auto memTy = dyn_cast<MemoryType>(operands[0].getType());
818 inferredReturnTypes.push_back(
819 ImmediateType::get(context, memTy.getAddressWidth()));
827LogicalResult ConcatImmediateOp::inferReturnTypes(
828 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
829 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
830 SmallVectorImpl<Type> &inferredReturnTypes) {
831 if (operands.empty()) {
833 return mlir::emitError(*loc) <<
"at least one operand must be provided";
837 unsigned totalWidth = 0;
838 for (
auto operand : operands) {
839 auto immType = dyn_cast<ImmediateType>(operand.getType());
842 return mlir::emitError(*loc)
843 <<
"all operands must be of immediate type";
846 totalWidth += immType.getWidth();
849 inferredReturnTypes.push_back(ImmediateType::get(context, totalWidth));
853OpFoldResult ConcatImmediateOp::fold(FoldAdaptor adaptor) {
855 if (getOperands().size() == 1)
856 return getOperands()[0];
859 if (llvm::all_of(adaptor.getOperands(), [](Attribute attr) {
860 return isa_and_nonnull<ImmediateAttr>(attr);
862 auto result = APInt::getZeroWidth();
863 for (
auto attr : adaptor.getOperands())
864 result = result.
concat(cast<ImmediateAttr>(attr).getValue());
866 return ImmediateAttr::get(getContext(), result);
876LogicalResult SliceImmediateOp::verify() {
877 auto srcWidth = getInput().getType().getWidth();
878 auto dstWidth = getResult().getType().getWidth();
880 if (getLowBit() >= srcWidth)
881 return emitOpError(
"from bit too large for input (got ")
882 << getLowBit() <<
", but input width is " << srcWidth <<
")";
884 if (srcWidth - getLowBit() < dstWidth)
885 return emitOpError(
"slice does not fit in input (trying to extract ")
886 << dstWidth <<
" bits starting at index " << getLowBit()
887 <<
", but only " << (srcWidth - getLowBit())
888 <<
" bits are available)";
893OpFoldResult SliceImmediateOp::fold(FoldAdaptor adaptor) {
894 if (
auto inputAttr = dyn_cast_or_null<ImmediateAttr>(adaptor.getInput())) {
895 auto resultWidth = getType().getWidth();
896 APInt sliced = inputAttr.getValue().extractBits(resultWidth, getLowBit());
897 return ImmediateAttr::get(getContext(), sliced);
907#define GET_OP_CLASSES
908#include "circt/Dialect/RTG/IR/RTG.cpp.inc"
assert(baseType &&"element must be base type")
static SmallVector< T > concat(const SmallVectorImpl< T > &a, const SmallVectorImpl< T > &b)
Returns a new vector containing the concatenation of vectors a and b.
static size_t getAddressWidth(size_t depth)
static InstancePath empty
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn