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