16#include "mlir/IR/Builders.h"
17#include "mlir/IR/DialectImplementation.h"
18#include "mlir/IR/Matchers.h"
19#include "mlir/IR/PatternMatch.h"
20#include "llvm/ADT/SmallString.h"
31ConstantOp::inferReturnTypes(MLIRContext *
context, std::optional<Location> loc,
32 ValueRange operands, DictionaryAttr attributes,
33 OpaqueProperties properties, RegionRange regions,
34 SmallVectorImpl<Type> &inferredReturnTypes) {
35 inferredReturnTypes.push_back(
36 properties.as<Properties *>()->getValue().getType());
40OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
return getValueAttr(); }
43 if (
auto reg = dyn_cast<rtg::RegisterAttrInterface>(getValueAttr())) {
44 setNameFn(getResult(),
reg.getRegisterAssembly());
53LogicalResult SequenceOp::verifyRegions() {
54 if (TypeRange(getSequenceType().getElementTypes()) !=
55 getBody()->getArgumentTypes())
56 return emitOpError(
"sequence type does not match block argument types");
61ParseResult SequenceOp::parse(OpAsmParser &parser, OperationState &result) {
63 if (parser.parseSymbolName(
64 result.getOrAddProperties<SequenceOp::Properties>().sym_name))
68 SmallVector<OpAsmParser::Argument> arguments;
69 if (parser.parseArgumentList(arguments, OpAsmParser::Delimiter::Paren,
73 SmallVector<Type> argTypes;
74 SmallVector<Location> argLocs;
75 argTypes.reserve(arguments.size());
76 argLocs.reserve(arguments.size());
77 for (
auto &arg : arguments) {
78 argTypes.push_back(arg.type);
79 argLocs.push_back(arg.sourceLoc ? *arg.sourceLoc : result.location);
81 Type type = SequenceType::get(result.getContext(), argTypes);
82 result.getOrAddProperties<SequenceOp::Properties>().sequenceType =
85 auto loc = parser.getCurrentLocation();
86 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
88 if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
89 return parser.emitError(loc)
90 <<
"'" << result.name.getStringRef() <<
"' op ";
94 std::unique_ptr<Region> bodyRegionRegion = std::make_unique<Region>();
95 if (parser.parseRegion(*bodyRegionRegion, arguments))
98 if (bodyRegionRegion->empty()) {
99 bodyRegionRegion->emplaceBlock();
100 bodyRegionRegion->addArguments(argTypes, argLocs);
102 result.addRegion(std::move(bodyRegionRegion));
107void SequenceOp::print(OpAsmPrinter &p) {
109 p.printSymbolName(getSymNameAttr().getValue());
111 llvm::interleaveComma(getBody()->getArguments(), p,
112 [&](
auto arg) { p.printRegionArgument(arg); });
114 p.printOptionalAttrDictWithKeyword(
115 (*this)->getAttrs(), {getSymNameAttrName(), getSequenceTypeAttrName()});
117 p.printRegion(getBodyRegion(),
false);
120mlir::SymbolTable::Visibility SequenceOp::getVisibility() {
121 return mlir::SymbolTable::Visibility::Private;
124void SequenceOp::setVisibility(mlir::SymbolTable::Visibility visibility) {
126 assert(
false &&
"cannot change visibility of sequence");
134GetSequenceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
136 symbolTable.lookupNearestSymbolFrom<SequenceOp>(*
this, getSequenceAttr());
139 <<
"'" << getSequence()
140 <<
"' does not reference a valid 'rtg.sequence' operation";
142 if (
seq.getSequenceType() != getType())
143 return emitOpError(
"referenced 'rtg.sequence' op's type does not match");
152LogicalResult SubstituteSequenceOp::verify() {
153 if (getReplacements().
empty())
154 return emitOpError(
"must at least have one replacement value");
156 if (getReplacements().size() >
157 getSequence().getType().getElementTypes().size())
159 "must not have more replacement values than sequence arguments");
161 if (getReplacements().getTypes() !=
162 getSequence().getType().getElementTypes().take_front(
163 getReplacements().size()))
164 return emitOpError(
"replacement types must match the same number of "
165 "sequence argument types from the front");
170LogicalResult SubstituteSequenceOp::inferReturnTypes(
171 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
172 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
173 SmallVectorImpl<Type> &inferredReturnTypes) {
174 ArrayRef<Type> argTypes =
175 cast<SequenceType>(operands[0].getType()).getElementTypes();
177 SequenceType::get(
context, argTypes.drop_front(operands.size() - 1));
178 inferredReturnTypes.push_back(seqType);
182ParseResult SubstituteSequenceOp::parse(::mlir::OpAsmParser &parser,
183 ::mlir::OperationState &result) {
184 OpAsmParser::UnresolvedOperand sequenceRawOperand;
185 SmallVector<OpAsmParser::UnresolvedOperand, 4> replacementsOperands;
186 Type sequenceRawType;
188 if (parser.parseOperand(sequenceRawOperand) || parser.parseLParen())
191 auto replacementsOperandsLoc = parser.getCurrentLocation();
192 if (parser.parseOperandList(replacementsOperands) || parser.parseRParen() ||
193 parser.parseColon() || parser.parseType(sequenceRawType) ||
194 parser.parseOptionalAttrDict(result.attributes))
197 if (!isa<SequenceType>(sequenceRawType))
198 return parser.emitError(parser.getNameLoc())
199 <<
"'sequence' must be handle to a sequence or sequence family, but "
203 if (parser.resolveOperand(sequenceRawOperand, sequenceRawType,
207 if (parser.resolveOperands(replacementsOperands,
208 cast<SequenceType>(sequenceRawType)
210 .take_front(replacementsOperands.size()),
211 replacementsOperandsLoc, result.operands))
214 SmallVector<Type> inferredReturnTypes;
215 if (failed(inferReturnTypes(
216 parser.getContext(), result.location, result.operands,
217 result.attributes.getDictionary(parser.getContext()),
218 result.getRawProperties(), result.regions, inferredReturnTypes)))
221 result.addTypes(inferredReturnTypes);
225void SubstituteSequenceOp::print(OpAsmPrinter &p) {
226 p <<
' ' << getSequence() <<
"(" << getReplacements()
227 <<
") : " << getSequence().getType();
228 p.printOptionalAttrDict((*this)->getAttrs(), {});
235LogicalResult InterleaveSequencesOp::verify() {
236 if (getSequences().
empty())
237 return emitOpError(
"must have at least one sequence in the list");
242OpFoldResult InterleaveSequencesOp::fold(FoldAdaptor adaptor) {
243 if (getSequences().size() == 1)
244 return getSequences()[0];
253ParseResult SetCreateOp::parse(OpAsmParser &parser, OperationState &result) {
254 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
257 if (parser.parseOperandList(operands) ||
258 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
259 parser.parseType(elemType))
262 result.addTypes({SetType::get(result.getContext(), elemType)});
264 for (
auto operand : operands)
265 if (parser.resolveOperand(operand, elemType, result.operands))
271void SetCreateOp::print(OpAsmPrinter &p) {
273 p.printOperands(getElements());
274 p.printOptionalAttrDict((*this)->getAttrs());
275 p <<
" : " << getSet().getType().getElementType();
278LogicalResult SetCreateOp::verify() {
279 if (getElements().size() > 0) {
282 if (getElements()[0].getType() != getSet().getType().getElementType())
283 return emitOpError() <<
"operand types must match set element type";
293LogicalResult SetCartesianProductOp::inferReturnTypes(
294 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
295 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
296 SmallVectorImpl<Type> &inferredReturnTypes) {
297 if (operands.empty()) {
299 return mlir::emitError(*loc) <<
"at least one set must be provided";
303 SmallVector<Type> elementTypes;
304 for (
auto operand : operands)
305 elementTypes.push_back(cast<SetType>(operand.getType()).getElementType());
306 inferredReturnTypes.push_back(
307 SetType::get(rtg::TupleType::get(
context, elementTypes)));
315ParseResult BagCreateOp::parse(OpAsmParser &parser, OperationState &result) {
316 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> elementOperands,
320 if (!parser.parseOptionalLParen()) {
322 OpAsmParser::UnresolvedOperand elementOperand, multipleOperand;
323 if (parser.parseOperand(multipleOperand) || parser.parseKeyword(
"x") ||
324 parser.parseOperand(elementOperand))
327 elementOperands.push_back(elementOperand);
328 multipleOperands.push_back(multipleOperand);
330 if (parser.parseOptionalComma()) {
331 if (parser.parseRParen())
338 if (parser.parseColon() || parser.parseType(elemType) ||
339 parser.parseOptionalAttrDict(result.attributes))
342 result.addTypes({BagType::get(result.getContext(), elemType)});
344 for (
auto operand : elementOperands)
345 if (parser.resolveOperand(operand, elemType, result.operands))
348 for (
auto operand : multipleOperands)
349 if (parser.resolveOperand(operand, IndexType::
get(result.getContext()),
356void BagCreateOp::print(OpAsmPrinter &p) {
358 if (!getElements().
empty())
360 llvm::interleaveComma(llvm::zip(getElements(), getMultiples()), p,
361 [&](
auto elAndMultiple) {
362 auto [el, multiple] = elAndMultiple;
363 p << multiple <<
" x " << el;
365 if (!getElements().
empty())
368 p <<
" : " << getBag().getType().getElementType();
369 p.printOptionalAttrDict((*this)->getAttrs());
372LogicalResult BagCreateOp::verify() {
373 if (!llvm::all_equal(getElements().getTypes()))
374 return emitOpError() <<
"types of all elements must match";
376 if (getElements().size() > 0)
377 if (getElements()[0].getType() != getBag().getType().getElementType())
378 return emitOpError() <<
"operand types must match bag element type";
387LogicalResult TupleCreateOp::inferReturnTypes(
388 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
389 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
390 SmallVectorImpl<Type> &inferredReturnTypes) {
391 SmallVector<Type> elementTypes;
392 for (
auto operand : operands)
393 elementTypes.push_back(operand.getType());
394 inferredReturnTypes.push_back(rtg::TupleType::get(
context, elementTypes));
402LogicalResult TupleExtractOp::inferReturnTypes(
403 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
404 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
405 SmallVectorImpl<Type> &inferredReturnTypes) {
406 assert(operands.size() == 1 &&
"must have exactly one operand");
408 auto tupleTy = dyn_cast<rtg::TupleType>(operands[0].getType());
409 size_t idx = properties.as<Properties *>()->getIndex().getInt();
412 return mlir::emitError(*loc) <<
"only RTG tuples are supported";
416 if (tupleTy.getFieldTypes().size() <= idx) {
418 return mlir::emitError(*loc)
420 <<
") must be smaller than number of elements in tuple ("
421 << tupleTy.getFieldTypes().size() <<
")";
425 inferredReturnTypes.push_back(tupleTy.getFieldTypes()[idx]);
433LogicalResult ConstraintOp::canonicalize(ConstraintOp op,
434 PatternRewriter &rewriter) {
435 if (mlir::matchPattern(op.getCondition(), mlir::m_One())) {
436 rewriter.eraseOp(op);
447LogicalResult VirtualRegisterOp::inferReturnTypes(
448 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
449 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
450 SmallVectorImpl<Type> &inferredReturnTypes) {
451 auto allowedRegs = properties.as<Properties *>()->getAllowedRegs();
452 inferredReturnTypes.push_back(allowedRegs.getType());
460OpFoldResult RegisterToIndexOp::fold(FoldAdaptor adaptor) {
461 if (
auto reg = dyn_cast_or_null<rtg::RegisterAttrInterface>(adaptor.getReg()))
462 return IntegerAttr::get(IndexType::get(getContext()),
reg.getClassIndex());
464 if (
auto indexToRegOp = getReg().getDefiningOp<IndexToRegisterOp>())
465 return indexToRegOp.getIndex();
474LogicalResult IndexToRegisterOp::verify() {
477 if (matchPattern(getIndex(), m_ConstantInt(&indexValue))) {
478 if (indexValue.uge(getType().getRegisterClassSize())) {
479 SmallString<16> indexStr;
480 indexValue.toString(indexStr, 10,
false);
481 return emitOpError() <<
"index " << indexStr
482 <<
" is out of range for register class "
483 << getReg().getType();
490OpFoldResult IndexToRegisterOp::fold(FoldAdaptor adaptor) {
491 if (
auto indexAttr = dyn_cast_or_null<IntegerAttr>(adaptor.getIndex()))
492 return getType().getRegisterAttrForClassIndex(
493 getContext(), indexAttr.getValue().getZExtValue());
502LogicalResult ContextSwitchOp::verify() {
503 auto elementTypes = getSequence().getType().getElementTypes();
504 if (elementTypes.size() != 3)
505 return emitOpError(
"sequence type must have exactly 3 element types");
507 if (getFrom().getType() != elementTypes[0])
509 "first sequence element type must match 'from' attribute type");
511 if (getTo().getType() != elementTypes[1])
513 "second sequence element type must match 'to' attribute type");
515 auto seqTy = dyn_cast<SequenceType>(elementTypes[2]);
516 if (!seqTy || !seqTy.getElementTypes().empty())
518 "third sequence element type must be a fully substituted sequence");
527LogicalResult TestOp::verifyRegions() {
528 if (!getTargetType().entryTypesMatch(getBody()->getArgumentTypes()))
529 return emitOpError(
"argument types must match dict entry types");
534LogicalResult TestOp::verify() {
535 if (getTemplateName().
empty())
536 return emitOpError(
"template name must not be empty");
541LogicalResult TestOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
542 if (!getTargetAttr())
546 symbolTable.lookupNearestSymbolFrom<TargetOp>(*
this, getTargetAttr());
549 <<
"'" << *getTarget()
550 <<
"' does not reference a valid 'rtg.target' operation";
554 size_t targetIdx = 0;
555 auto targetEntries = target.getTarget().getEntries();
556 for (
auto testEntry : getTargetType().getEntries()) {
558 while (targetIdx < targetEntries.size() &&
559 targetEntries[targetIdx].name.getValue() < testEntry.name.getValue())
563 if (targetIdx >= targetEntries.size() ||
564 targetEntries[targetIdx].name != testEntry.name ||
565 targetEntries[targetIdx].type != testEntry.type) {
566 return emitOpError(
"referenced 'rtg.target' op's type is invalid: "
567 "missing entry called '")
568 << testEntry.name.getValue() <<
"' of type " << testEntry.type;
575ParseResult TestOp::parse(OpAsmParser &parser, OperationState &result) {
577 StringAttr symNameAttr;
578 if (parser.parseSymbolName(symNameAttr))
581 result.getOrAddProperties<TestOp::Properties>().sym_name = symNameAttr;
584 SmallVector<OpAsmParser::Argument> arguments;
585 SmallVector<StringAttr> names;
587 auto parseOneArgument = [&]() -> ParseResult {
589 if (parser.parseKeywordOrString(&name) || parser.parseEqual() ||
590 parser.parseArgument(arguments.emplace_back(),
true,
594 names.push_back(StringAttr::get(result.getContext(), name));
597 if (parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
598 parseOneArgument,
" in argument list"))
601 SmallVector<Type> argTypes;
602 SmallVector<DictEntry> entries;
603 SmallVector<Location> argLocs;
604 argTypes.reserve(arguments.size());
605 argLocs.reserve(arguments.size());
606 for (
auto [name, arg] :
llvm::zip(names, arguments)) {
607 argTypes.push_back(arg.type);
608 argLocs.push_back(arg.sourceLoc ? *arg.sourceLoc : result.location);
609 entries.push_back({name, arg.type});
611 auto emitError = [&]() -> InFlightDiagnostic {
612 return parser.emitError(parser.getCurrentLocation());
614 Type type = DictType::getChecked(emitError, result.getContext(),
615 ArrayRef<DictEntry>(entries));
618 result.getOrAddProperties<TestOp::Properties>().targetType =
621 std::string templateName;
622 if (!parser.parseOptionalKeyword(
"template")) {
623 auto loc = parser.getCurrentLocation();
624 if (parser.parseString(&templateName))
627 if (templateName.empty())
628 return parser.emitError(loc,
"template name must not be empty");
631 StringAttr templateNameAttr = symNameAttr;
632 if (!templateName.empty())
633 templateNameAttr = StringAttr::get(result.getContext(), templateName);
635 StringAttr targetName;
636 if (!parser.parseOptionalKeyword(
"target"))
637 if (parser.parseSymbolName(targetName))
640 result.getOrAddProperties<TestOp::Properties>().templateName =
642 result.getOrAddProperties<TestOp::Properties>().target = targetName;
644 auto loc = parser.getCurrentLocation();
645 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
647 if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
648 return parser.emitError(loc)
649 <<
"'" << result.name.getStringRef() <<
"' op ";
653 std::unique_ptr<Region> bodyRegionRegion = std::make_unique<Region>();
654 if (parser.parseRegion(*bodyRegionRegion, arguments))
657 if (bodyRegionRegion->empty()) {
658 bodyRegionRegion->emplaceBlock();
659 bodyRegionRegion->addArguments(argTypes, argLocs);
661 result.addRegion(std::move(bodyRegionRegion));
666void TestOp::print(OpAsmPrinter &p) {
668 p.printSymbolName(getSymNameAttr().getValue());
670 SmallString<32> resultNameStr;
671 llvm::interleaveComma(
672 llvm::zip(getTargetType().getEntries(), getBody()->getArguments()), p,
673 [&](
auto entryAndArg) {
674 auto [entry, arg] = entryAndArg;
675 p << entry.name.getValue() <<
" = ";
676 p.printRegionArgument(arg);
680 if (getSymNameAttr() != getTemplateNameAttr())
681 p <<
" template " << getTemplateNameAttr();
683 if (getTargetAttr()) {
685 p.printSymbolName(getTargetAttr().getValue());
688 p.printOptionalAttrDictWithKeyword(
689 (*this)->getAttrs(), {getSymNameAttrName(), getTargetTypeAttrName(),
690 getTargetAttrName(), getTemplateNameAttrName()});
692 p.printRegion(getBodyRegion(),
false);
695void TestOp::getAsmBlockArgumentNames(Region ®ion,
697 for (
auto [entry, arg] :
698 llvm::zip(getTargetType().getEntries(), region.getArguments()))
699 setNameFn(arg, entry.name.getValue());
706LogicalResult TargetOp::verifyRegions() {
707 if (!getTarget().entryTypesMatch(
708 getBody()->getTerminator()->getOperandTypes()))
709 return emitOpError(
"terminator operand types must match dict entry types");
718LogicalResult ValidateOp::verify() {
719 if (!getRef().getType().isValidContentType(getValue().getType()))
721 "result type must be a valid content type for the ref value");
726bool ValidateOp::isSourceRegister(
unsigned index) {
728 return isa<RegisterTypeInterface>(getRef().getType());
732bool ValidateOp::isDestinationRegister(
unsigned index) {
return false; }
738LogicalResult ArrayCreateOp::verify() {
739 if (!getElements().
empty() &&
740 getElements()[0].getType() != getType().getElementType())
741 return emitOpError(
"operand types must match array element type, expected ")
742 << getType().getElementType() <<
" but got "
743 << getElements()[0].getType();
748ParseResult ArrayCreateOp::parse(OpAsmParser &parser, OperationState &result) {
749 SmallVector<OpAsmParser::UnresolvedOperand> operands;
752 if (parser.parseOperandList(operands) || parser.parseColon() ||
754 parser.parseOptionalAttrDict(result.attributes))
757 if (failed(parser.resolveOperands(operands,
elementType, result.operands)))
765void ArrayCreateOp::print(OpAsmPrinter &p) {
767 p.printOperands(getElements());
768 p <<
" : " << getType().getElementType();
769 p.printOptionalAttrDict((*this)->getAttrs(), {});
776LogicalResult ArrayAppendOp::canonicalize(ArrayAppendOp op,
777 PatternRewriter &rewriter) {
778 auto createOp = op.getArray().getDefiningOp<ArrayCreateOp>();
782 SmallVector<Value> newElements(createOp.getElements());
783 newElements.push_back(op.getElement());
784 rewriter.replaceOpWithNewOp<ArrayCreateOp>(op, op.getType(), newElements);
792LogicalResult MemoryBlockDeclareOp::verify() {
795 "base address width must match memory block address width");
799 "end address width must match memory block address width");
801 if (getBaseAddress().ugt(getEndAddress()))
803 "base address must be smaller than or equal to the end address");
808ParseResult MemoryBlockDeclareOp::parse(OpAsmParser &parser,
809 OperationState &result) {
810 SmallVector<OpAsmParser::UnresolvedOperand> operands;
811 MemoryBlockType memoryBlockType;
814 if (parser.parseLSquare())
817 auto startLoc = parser.getCurrentLocation();
818 if (parser.parseInteger(start))
821 if (parser.parseMinus())
824 auto endLoc = parser.getCurrentLocation();
825 if (parser.parseInteger(end) || parser.parseRSquare() ||
826 parser.parseColonType(memoryBlockType) ||
827 parser.parseOptionalAttrDict(result.attributes))
830 auto width = memoryBlockType.getAddressWidth();
831 auto adjustAPInt = [&](APInt value, llvm::SMLoc loc) -> FailureOr<APInt> {
832 if (value.getBitWidth() > width) {
833 if (!value.isIntN(width))
834 return parser.emitError(
836 "address out of range for memory block with address width ")
839 return value.trunc(width);
842 if (value.getBitWidth() < width)
843 return value.zext(width);
848 auto startRes = adjustAPInt(start, startLoc);
849 auto endRes = adjustAPInt(end, endLoc);
850 if (failed(startRes) || failed(endRes))
853 auto intType = IntegerType::get(result.getContext(), width);
854 result.addAttribute(getBaseAddressAttrName(result.name),
855 IntegerAttr::get(intType, *startRes));
856 result.addAttribute(getEndAddressAttrName(result.name),
857 IntegerAttr::get(intType, *endRes));
859 result.addTypes(memoryBlockType);
863void MemoryBlockDeclareOp::print(OpAsmPrinter &p) {
864 SmallVector<char> str;
865 getBaseAddress().toString(str, 16,
false,
false,
false);
869 getEndAddress().toString(str, 16,
false,
false,
false);
870 p << str <<
"] : " << getType();
871 p.printOptionalAttrDict((*this)->getAttrs(),
872 {getBaseAddressAttrName(), getEndAddressAttrName()});
879LogicalResult MemoryBaseAddressOp::inferReturnTypes(
880 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
881 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
882 SmallVectorImpl<Type> &inferredReturnTypes) {
883 if (operands.empty())
885 auto memTy = dyn_cast<MemoryType>(operands[0].getType());
888 inferredReturnTypes.push_back(
889 ImmediateType::get(
context, memTy.getAddressWidth()));
897LogicalResult ConcatImmediateOp::inferReturnTypes(
898 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
899 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
900 SmallVectorImpl<Type> &inferredReturnTypes) {
901 if (operands.empty()) {
903 return mlir::emitError(*loc) <<
"at least one operand must be provided";
907 unsigned totalWidth = 0;
908 for (
auto operand : operands) {
909 auto immType = dyn_cast<ImmediateType>(operand.getType());
912 return mlir::emitError(*loc)
913 <<
"all operands must be of immediate type";
916 totalWidth += immType.getWidth();
919 inferredReturnTypes.push_back(ImmediateType::get(
context, totalWidth));
923OpFoldResult ConcatImmediateOp::fold(FoldAdaptor adaptor) {
925 if (getOperands().size() == 1)
926 return getOperands()[0];
929 if (llvm::all_of(adaptor.getOperands(), [](Attribute attr) {
930 return isa_and_nonnull<ImmediateAttr>(attr);
932 auto result = APInt::getZeroWidth();
933 for (
auto attr : adaptor.getOperands())
934 result = result.concat(cast<ImmediateAttr>(attr).getValue());
936 return ImmediateAttr::get(getContext(), result);
946LogicalResult SliceImmediateOp::verify() {
947 auto srcWidth = getInput().getType().getWidth();
948 auto dstWidth = getResult().getType().getWidth();
950 if (getLowBit() >= srcWidth)
951 return emitOpError(
"from bit too large for input (got ")
952 << getLowBit() <<
", but input width is " << srcWidth <<
")";
954 if (srcWidth - getLowBit() < dstWidth)
955 return emitOpError(
"slice does not fit in input (trying to extract ")
956 << dstWidth <<
" bits starting at index " << getLowBit()
957 <<
", but only " << (srcWidth - getLowBit())
958 <<
" bits are available)";
963OpFoldResult SliceImmediateOp::fold(FoldAdaptor adaptor) {
964 if (
auto inputAttr = dyn_cast_or_null<ImmediateAttr>(adaptor.getInput())) {
965 auto resultWidth = getType().getWidth();
966 APInt sliced = inputAttr.getValue().extractBits(resultWidth, getLowBit());
967 return ImmediateAttr::get(getContext(), sliced);
977OpFoldResult StringConcatOp::fold(FoldAdaptor adaptor) {
978 SmallString<32> result;
979 for (
auto attr : adaptor.getStrings()) {
980 auto stringAttr = dyn_cast_or_null<StringAttr>(attr);
984 result += stringAttr.getValue();
987 return StringAttr::get(result, StringType::get(getContext()));
994OpFoldResult IntFormatOp::fold(FoldAdaptor adaptor) {
995 auto intAttr = dyn_cast_or_null<IntegerAttr>(adaptor.getValue());
998 if (!intAttr.getType().isIndex())
1000 return StringAttr::get(Twine(intAttr.getValue().getZExtValue()),
1001 StringType::get(getContext()));
1008OpFoldResult ImmediateFormatOp::fold(FoldAdaptor adaptor) {
1009 auto immAttr = dyn_cast_or_null<ImmediateAttr>(adaptor.getValue());
1012 SmallString<16> strBuf(
"0x");
1013 immAttr.getValue().toString(strBuf, 16,
false);
1014 return StringAttr::get(strBuf, StringType::get(getContext()));
1021OpFoldResult RegisterFormatOp::fold(FoldAdaptor adaptor) {
1022 auto regAttr = dyn_cast_or_null<RegisterAttrInterface>(adaptor.getValue());
1025 return StringAttr::get(regAttr.getRegisterAssembly(),
1026 StringType::get(getContext()));
1033OpFoldResult StringToLabelOp::fold(FoldAdaptor adaptor) {
1034 if (
auto stringAttr = dyn_cast_or_null<StringAttr>(adaptor.getString()))
1035 return LabelAttr::get(getContext(), stringAttr.getValue());
1044#define GET_OP_CLASSES
1045#include "circt/Dialect/RTG/IR/RTG.cpp.inc"
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
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
reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)