CIRCT  20.0.0git
OMOps.cpp
Go to the documentation of this file.
1 //===- OMOps.cpp - Object Model operation definitions ---------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the Object Model operation definitions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "circt/Dialect/OM/OMOps.h"
14 #include "circt/Dialect/HW/HWOps.h"
16 #include "mlir/IR/Builders.h"
17 #include "mlir/IR/ImplicitLocOpBuilder.h"
18 
19 using namespace mlir;
20 using namespace circt::om;
21 
22 //===----------------------------------------------------------------------===//
23 // Path Printers and Parsers
24 //===----------------------------------------------------------------------===//
25 
26 static ParseResult parseBasePathString(OpAsmParser &parser, PathAttr &path) {
27  auto *context = parser.getContext();
28  auto loc = parser.getCurrentLocation();
29  std::string rawPath;
30  if (parser.parseString(&rawPath))
31  return failure();
32  if (parseBasePath(context, rawPath, path))
33  return parser.emitError(loc, "invalid base path");
34  return success();
35 }
36 
37 static void printBasePathString(OpAsmPrinter &p, Operation *op, PathAttr path) {
38  p << '\"';
39  llvm::interleave(
40  path, p,
41  [&](const PathElement &elt) {
42  p << elt.module.getValue() << '/' << elt.instance.getValue();
43  },
44  ":");
45  p << '\"';
46 }
47 
48 static ParseResult parsePathString(OpAsmParser &parser, PathAttr &path,
49  StringAttr &module, StringAttr &ref,
50  StringAttr &field) {
51 
52  auto *context = parser.getContext();
53  auto loc = parser.getCurrentLocation();
54  std::string rawPath;
55  if (parser.parseString(&rawPath))
56  return failure();
57  if (parsePath(context, rawPath, path, module, ref, field))
58  return parser.emitError(loc, "invalid path");
59  return success();
60 }
61 
62 static void printPathString(OpAsmPrinter &p, Operation *op, PathAttr path,
63  StringAttr module, StringAttr ref,
64  StringAttr field) {
65  p << '\"';
66  for (const auto &elt : path)
67  p << elt.module.getValue() << '/' << elt.instance.getValue() << ':';
68  if (!module.getValue().empty())
69  p << module.getValue();
70  if (!ref.getValue().empty())
71  p << '>' << ref.getValue();
72  if (!field.getValue().empty())
73  p << field.getValue();
74  p << '\"';
75 }
76 
77 //===----------------------------------------------------------------------===//
78 // Shared definitions
79 //===----------------------------------------------------------------------===//
80 static ParseResult parseClassFieldsList(OpAsmParser &parser,
81  SmallVectorImpl<Attribute> &fieldNames,
82  SmallVectorImpl<Type> &fieldTypes) {
83 
84  llvm::StringMap<SMLoc> nameLocMap;
85  auto parseElt = [&]() -> ParseResult {
86  // Parse the field name.
87  std::string fieldName;
88  if (parser.parseKeywordOrString(&fieldName))
89  return failure();
90  SMLoc currLoc = parser.getCurrentLocation();
91  if (nameLocMap.count(fieldName)) {
92  parser.emitError(currLoc, "field \"")
93  << fieldName << "\" is defined twice";
94  parser.emitError(nameLocMap[fieldName]) << "previous definition is here";
95  return failure();
96  }
97  nameLocMap[fieldName] = currLoc;
98  fieldNames.push_back(StringAttr::get(parser.getContext(), fieldName));
99 
100  // Parse the field type.
101  fieldTypes.emplace_back();
102  if (parser.parseColonType(fieldTypes.back()))
103  return failure();
104 
105  return success();
106  };
107 
108  return parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
109  parseElt);
110 }
111 
112 static ParseResult parseClassLike(OpAsmParser &parser, OperationState &state) {
113  // Parse the Class symbol name.
114  StringAttr symName;
115  if (parser.parseSymbolName(symName, mlir::SymbolTable::getSymbolAttrName(),
116  state.attributes))
117  return failure();
118 
119  // Parse the formal parameters.
120  SmallVector<OpAsmParser::Argument> args;
121  if (parser.parseArgumentList(args, OpAsmParser::Delimiter::Paren,
122  /*allowType=*/true, /*allowAttrs=*/false))
123  return failure();
124 
125  SmallVector<Type> fieldTypes;
126  SmallVector<Attribute> fieldNames;
127  if (succeeded(parser.parseOptionalArrow()))
128  if (failed(parseClassFieldsList(parser, fieldNames, fieldTypes)))
129  return failure();
130 
131  SmallVector<NamedAttribute> fieldTypesMap;
132  if (!fieldNames.empty()) {
133  for (auto [name, type] : zip(fieldNames, fieldTypes))
134  fieldTypesMap.push_back(
135  NamedAttribute(cast<StringAttr>(name), TypeAttr::get(type)));
136  }
137  auto *ctx = parser.getContext();
138  state.addAttribute("fieldNames", mlir::ArrayAttr::get(ctx, fieldNames));
139  state.addAttribute("fieldTypes",
140  mlir::DictionaryAttr::get(ctx, fieldTypesMap));
141 
142  // Parse the optional attribute dictionary.
143  if (failed(parser.parseOptionalAttrDictWithKeyword(state.attributes)))
144  return failure();
145 
146  // Parse the body.
147  Region *region = state.addRegion();
148  if (parser.parseRegion(*region, args))
149  return failure();
150 
151  // If the region was empty, add an empty block so it's still a SizedRegion<1>.
152  if (region->empty())
153  region->emplaceBlock();
154 
155  // Remember the formal parameter names in an attribute.
156  auto argNames = llvm::map_range(args, [&](OpAsmParser::Argument arg) {
157  return StringAttr::get(parser.getContext(), arg.ssaName.name.drop_front());
158  });
159  state.addAttribute(
160  "formalParamNames",
161  ArrayAttr::get(parser.getContext(), SmallVector<Attribute>(argNames)));
162 
163  return success();
164 }
165 
166 static void printClassLike(ClassLike classLike, OpAsmPrinter &printer) {
167  // Print the Class symbol name.
168  printer << " @";
169  printer << classLike.getSymName();
170 
171  // Retrieve the formal parameter names and values.
172  auto argNames = SmallVector<StringRef>(
173  classLike.getFormalParamNames().getAsValueRange<StringAttr>());
174  ArrayRef<BlockArgument> args = classLike.getBodyBlock()->getArguments();
175 
176  // Print the formal parameters.
177  printer << '(';
178  for (size_t i = 0, e = args.size(); i < e; ++i) {
179  printer << '%' << argNames[i] << ": " << args[i].getType();
180  if (i < e - 1)
181  printer << ", ";
182  }
183  printer << ") ";
184 
185  ArrayRef<Attribute> fieldNames =
186  cast<ArrayAttr>(classLike->getAttr("fieldNames")).getValue();
187 
188  if (!fieldNames.empty()) {
189  printer << " -> (";
190  for (size_t i = 0, e = fieldNames.size(); i < e; ++i) {
191  if (i != 0)
192  printer << ", ";
193  StringAttr name = cast<StringAttr>(fieldNames[i]);
194  printer.printKeywordOrString(name.getValue());
195  printer << ": ";
196  Type type = classLike.getFieldType(name).value();
197  printer.printType(type);
198  }
199  printer << ") ";
200  }
201 
202  // Print the optional attribute dictionary.
203  SmallVector<StringRef> elidedAttrs{classLike.getSymNameAttrName(),
204  classLike.getFormalParamNamesAttrName(),
205  "fieldTypes", "fieldNames"};
206  printer.printOptionalAttrDictWithKeyword(classLike.getOperation()->getAttrs(),
207  elidedAttrs);
208 
209  // Print the body.
210  printer.printRegion(classLike.getBody(), /*printEntryBlockArgs=*/false,
211  /*printBlockTerminators=*/true);
212 }
213 
214 LogicalResult verifyClassLike(ClassLike classLike) {
215  // Verify the formal parameter names match up with the values.
216  if (classLike.getFormalParamNames().size() !=
217  classLike.getBodyBlock()->getArguments().size()) {
218  auto error = classLike.emitOpError(
219  "formal parameter name list doesn't match formal parameter value list");
220  error.attachNote(classLike.getLoc())
221  << "formal parameter names: " << classLike.getFormalParamNames();
222  error.attachNote(classLike.getLoc())
223  << "formal parameter values: "
224  << classLike.getBodyBlock()->getArguments();
225  return error;
226  }
227 
228  return success();
229 }
230 
231 void getClassLikeAsmBlockArgumentNames(ClassLike classLike, Region &region,
232  OpAsmSetValueNameFn setNameFn) {
233  // Retrieve the formal parameter names and values.
234  auto argNames = SmallVector<StringRef>(
235  classLike.getFormalParamNames().getAsValueRange<StringAttr>());
236  ArrayRef<BlockArgument> args = classLike.getBodyBlock()->getArguments();
237 
238  // Use the formal parameter names as the SSA value names.
239  for (size_t i = 0, e = args.size(); i < e; ++i)
240  setNameFn(args[i], argNames[i]);
241 }
242 
243 NamedAttribute makeFieldType(StringAttr name, Type type) {
244  return NamedAttribute(name, TypeAttr::get(type));
245 }
246 
247 NamedAttribute makeFieldIdx(MLIRContext *ctx, mlir::StringAttr name,
248  unsigned i) {
249  return NamedAttribute(StringAttr(name),
251 }
252 
253 std::optional<Type> getClassLikeFieldType(ClassLike classLike,
254  StringAttr name) {
255  DictionaryAttr fieldTypes = mlir::cast<DictionaryAttr>(
256  classLike.getOperation()->getAttr("fieldTypes"));
257  Attribute type = fieldTypes.get(name);
258  if (!type)
259  return std::nullopt;
260  return cast<TypeAttr>(type).getValue();
261 }
262 
263 void replaceClassLikeFieldTypes(ClassLike classLike,
264  AttrTypeReplacer &replacer) {
265  classLike->setAttr("fieldTypes", cast<DictionaryAttr>(replacer.replace(
266  classLike.getFieldTypes())));
267 }
268 
269 //===----------------------------------------------------------------------===//
270 // ClassOp
271 //===----------------------------------------------------------------------===//
272 
273 ParseResult circt::om::ClassOp::parse(OpAsmParser &parser,
274  OperationState &state) {
275  return parseClassLike(parser, state);
276 }
277 
278 circt::om::ClassOp circt::om::ClassOp::buildSimpleClassOp(
279  OpBuilder &odsBuilder, Location loc, Twine name,
280  ArrayRef<StringRef> formalParamNames, ArrayRef<StringRef> fieldNames,
281  ArrayRef<Type> fieldTypes) {
282  circt::om::ClassOp classOp = odsBuilder.create<circt::om::ClassOp>(
283  loc, odsBuilder.getStringAttr(name),
284  odsBuilder.getStrArrayAttr(formalParamNames),
285  odsBuilder.getStrArrayAttr(fieldNames),
286  odsBuilder.getDictionaryAttr(llvm::map_to_vector(
287  llvm::zip(fieldNames, fieldTypes), [&](auto field) -> NamedAttribute {
288  return NamedAttribute(odsBuilder.getStringAttr(std::get<0>(field)),
289  TypeAttr::get(std::get<1>(field)));
290  })));
291  Block *body = &classOp.getRegion().emplaceBlock();
292  auto prevLoc = odsBuilder.saveInsertionPoint();
293  odsBuilder.setInsertionPointToEnd(body);
294  odsBuilder.create<ClassFieldsOp>(
295  loc, llvm::map_to_vector(fieldTypes, [&](Type type) -> Value {
296  return body->addArgument(type, loc);
297  }));
298  odsBuilder.restoreInsertionPoint(prevLoc);
299 
300  return classOp;
301 }
302 
303 void circt::om::ClassOp::print(OpAsmPrinter &printer) {
304  printClassLike(*this, printer);
305 }
306 
307 LogicalResult circt::om::ClassOp::verify() { return verifyClassLike(*this); }
308 
309 LogicalResult circt::om::ClassOp::verifyRegions() {
310  auto fieldsOp = cast<ClassFieldsOp>(this->getBodyBlock()->getTerminator());
311 
312  // The number of results matches the number of terminator operands.
313  if (fieldsOp.getNumOperands() != this->getFieldNames().size()) {
314  auto diag = this->emitOpError()
315  << "returns '" << this->getFieldNames().size()
316  << "' fields, but its terminator returned '"
317  << fieldsOp.getNumOperands() << "' fields";
318  return diag.attachNote(fieldsOp.getLoc()) << "see terminator:";
319  }
320 
321  // The type of each result matches the corresponding terminator operand type.
322  auto types = this->getFieldTypes();
323  for (auto [fieldName, terminatorOperandType] :
324  llvm::zip(this->getFieldNames(), fieldsOp.getOperandTypes())) {
325 
326  if (terminatorOperandType ==
327  cast<TypeAttr>(types.get(cast<StringAttr>(fieldName))).getValue())
328  continue;
329 
330  auto diag = this->emitOpError()
331  << "returns different field types than its terminator";
332  return diag.attachNote(fieldsOp.getLoc()) << "see terminator:";
333  }
334 
335  return success();
336 }
337 
338 void circt::om::ClassOp::getAsmBlockArgumentNames(
339  Region &region, OpAsmSetValueNameFn setNameFn) {
340  getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
341 }
342 
343 std::optional<mlir::Type>
344 circt::om::ClassOp::getFieldType(mlir::StringAttr field) {
345  return getClassLikeFieldType(*this, field);
346 }
347 
348 void circt::om::ClassOp::replaceFieldTypes(AttrTypeReplacer replacer) {
349  replaceClassLikeFieldTypes(*this, replacer);
350 }
351 
352 void circt::om::ClassOp::updateFields(
353  mlir::ArrayRef<mlir::Location> newLocations,
354  mlir::ArrayRef<mlir::Value> newValues,
355  mlir::ArrayRef<mlir::Attribute> newNames) {
356 
357  auto fieldsOp = getFieldsOp();
358  assert(fieldsOp && "The fields op should exist");
359  // Get field names.
360  SmallVector<Attribute> names(getFieldNamesAttr().getAsRange<StringAttr>());
361  // Get the field types.
362  SmallVector<NamedAttribute> fieldTypes(getFieldTypesAttr().getValue());
363  // Get the field values.
364  SmallVector<Value> fieldVals(fieldsOp.getFields());
365  // Get the field locations.
366  Location fieldOpLoc = fieldsOp->getLoc();
367 
368  // Extract the locations per field.
369  SmallVector<Location> locations;
370  if (auto fl = dyn_cast<FusedLoc>(fieldOpLoc)) {
371  auto metadataArr = dyn_cast<ArrayAttr>(fl.getMetadata());
372  assert(metadataArr && "Expected the metadata for the fused location");
373  auto r = metadataArr.getAsRange<LocationAttr>();
374  locations.append(r.begin(), r.end());
375  } else {
376  // Assume same loc for every field.
377  locations.append(names.size(), fieldOpLoc);
378  }
379 
380  // Append the new names, locations and values.
381  names.append(newNames.begin(), newNames.end());
382  locations.append(newLocations.begin(), newLocations.end());
383  fieldVals.append(newValues.begin(), newValues.end());
384 
385  // Construct the new field types from values and names.
386  for (auto [v, n] : llvm::zip(newValues, newNames))
387  fieldTypes.emplace_back(
388  NamedAttribute(llvm::cast<StringAttr>(n), TypeAttr::get(v.getType())));
389 
390  // Keep the locations as array on the metadata.
391  SmallVector<Attribute> locationsAttr;
392  llvm::for_each(locations, [&](Location &l) {
393  locationsAttr.push_back(cast<Attribute>(l));
394  });
395 
396  ImplicitLocOpBuilder builder(getLoc(), *this);
397  // Update the field names attribute.
398  setFieldNamesAttr(builder.getArrayAttr(names));
399  // Update the fields type attribute.
400  setFieldTypesAttr(builder.getDictionaryAttr(fieldTypes));
401  fieldsOp.getFieldsMutable().assign(fieldVals);
402  // Update the location.
403  fieldsOp->setLoc(builder.getFusedLoc(
404  locations, ArrayAttr::get(getContext(), locationsAttr)));
405 }
406 
407 void circt::om::ClassOp::addNewFieldsOp(mlir::OpBuilder &builder,
408  mlir::ArrayRef<Location> locs,
409  mlir::ArrayRef<Value> values) {
410  // Store the original locations as a metadata array so that unique locations
411  // are preserved as a mapping from field index to location
412  mlir::SmallVector<Attribute> locAttrs;
413  for (auto loc : locs) {
414  locAttrs.push_back(cast<Attribute>(LocationAttr(loc)));
415  }
416  // Also store the locations incase there's some other analysis that might
417  // be able to use the default FusedLoc representation.
418  builder.create<ClassFieldsOp>(
419  builder.getFusedLoc(locs, builder.getArrayAttr(locAttrs)), values);
420 }
421 
422 mlir::Location circt::om::ClassOp::getFieldLocByIndex(size_t i) {
423  Location loc = this->getFieldsOp()->getLoc();
424  if (auto locs = dyn_cast<FusedLoc>(loc)) {
425  // Because it's possible for a user to construct a fields op directly and
426  // place a FusedLoc that doersn't follow the storage format of
427  // addNewFieldsOp, we assert the information has been stored appropriately
428  ArrayAttr metadataArr = dyn_cast<ArrayAttr>(locs.getMetadata());
429  assert(metadataArr && "Expected fused loc to store metadata array");
430  assert(i < metadataArr.size() &&
431  "expected index to be less than array size");
432  LocationAttr locAttr = dyn_cast<LocationAttr>(metadataArr[i]);
433  assert(locAttr && "expected metadataArr entry to be location attribute");
434  loc = Location(locAttr);
435  }
436  return loc;
437 }
438 
439 //===----------------------------------------------------------------------===//
440 // ClassExternOp
441 //===----------------------------------------------------------------------===//
442 
443 ParseResult circt::om::ClassExternOp::parse(OpAsmParser &parser,
444  OperationState &state) {
445  return parseClassLike(parser, state);
446 }
447 
448 void circt::om::ClassExternOp::print(OpAsmPrinter &printer) {
449  printClassLike(*this, printer);
450 }
451 
452 LogicalResult circt::om::ClassExternOp::verify() {
453  if (failed(verifyClassLike(*this))) {
454  return failure();
455  }
456  // Verify body is empty
457  if (!this->getBodyBlock()->getOperations().empty()) {
458  return this->emitOpError("external class body should be empty");
459  }
460 
461  return success();
462 }
463 
464 void circt::om::ClassExternOp::getAsmBlockArgumentNames(
465  Region &region, OpAsmSetValueNameFn setNameFn) {
466  getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
467 }
468 
469 std::optional<mlir::Type>
470 circt::om::ClassExternOp::getFieldType(mlir::StringAttr field) {
471  return getClassLikeFieldType(*this, field);
472 }
473 
474 void circt::om::ClassExternOp::replaceFieldTypes(AttrTypeReplacer replacer) {
475  replaceClassLikeFieldTypes(*this, replacer);
476 }
477 
478 //===----------------------------------------------------------------------===//
479 // ObjectOp
480 //===----------------------------------------------------------------------===//
481 
482 void circt::om::ObjectOp::build(::mlir::OpBuilder &odsBuilder,
483  ::mlir::OperationState &odsState,
484  om::ClassOp classOp,
485  ::mlir::ValueRange actualParams) {
486  return build(odsBuilder, odsState,
487  om::ClassType::get(odsBuilder.getContext(),
489  classOp.getNameAttr(), actualParams);
490 }
491 
492 LogicalResult
493 circt::om::ObjectOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
494  // Verify the result type is the same as the referred-to class.
495  StringAttr resultClassName = getResult().getType().getClassName().getAttr();
496  StringAttr className = getClassNameAttr();
497  if (resultClassName != className)
498  return emitOpError("result type (")
499  << resultClassName << ") does not match referred to class ("
500  << className << ')';
501 
502  // Verify the referred to ClassOp exists.
503  auto classDef = dyn_cast_or_null<ClassLike>(
504  symbolTable.lookupNearestSymbolFrom(*this, className));
505  if (!classDef)
506  return emitOpError("refers to non-existant class (") << className << ')';
507 
508  auto actualTypes = getActualParams().getTypes();
509  auto formalTypes = classDef.getBodyBlock()->getArgumentTypes();
510 
511  // Verify the actual parameter list matches the formal parameter list.
512  if (actualTypes.size() != formalTypes.size()) {
513  auto error = emitOpError(
514  "actual parameter list doesn't match formal parameter list");
515  error.attachNote(classDef.getLoc())
516  << "formal parameters: " << classDef.getBodyBlock()->getArguments();
517  error.attachNote(getLoc()) << "actual parameters: " << getActualParams();
518  return error;
519  }
520 
521  // Verify the actual parameter types match the formal parameter types.
522  for (size_t i = 0, e = actualTypes.size(); i < e; ++i) {
523  if (actualTypes[i] != formalTypes[i]) {
524  return emitOpError("actual parameter type (")
525  << actualTypes[i] << ") doesn't match formal parameter type ("
526  << formalTypes[i] << ')';
527  }
528  }
529 
530  return success();
531 }
532 
533 //===----------------------------------------------------------------------===//
534 // ConstantOp
535 //===----------------------------------------------------------------------===//
536 
537 void circt::om::ConstantOp::build(::mlir::OpBuilder &odsBuilder,
538  ::mlir::OperationState &odsState,
539  ::mlir::TypedAttr constVal) {
540  return build(odsBuilder, odsState, constVal.getType(), constVal);
541 }
542 
543 OpFoldResult circt::om::ConstantOp::fold(FoldAdaptor adaptor) {
544  assert(adaptor.getOperands().empty() && "constant has no operands");
545  return getValueAttr();
546 }
547 
548 //===----------------------------------------------------------------------===//
549 // ListCreateOp
550 //===----------------------------------------------------------------------===//
551 
552 void circt::om::ListCreateOp::print(OpAsmPrinter &p) {
553  p << " ";
554  p.printOperands(getInputs());
555  p.printOptionalAttrDict((*this)->getAttrs());
556  p << " : " << getType().getElementType();
557 }
558 
559 ParseResult circt::om::ListCreateOp::parse(OpAsmParser &parser,
560  OperationState &result) {
561  llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
562  Type elemType;
563 
564  if (parser.parseOperandList(operands) ||
565  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
566  parser.parseType(elemType))
567  return failure();
568  result.addTypes({circt::om::ListType::get(elemType)});
569 
570  for (auto operand : operands)
571  if (parser.resolveOperand(operand, elemType, result.operands))
572  return failure();
573  return success();
574 }
575 
576 //===----------------------------------------------------------------------===//
577 // TupleCreateOp
578 //===----------------------------------------------------------------------===//
579 
580 LogicalResult TupleCreateOp::inferReturnTypes(
581  MLIRContext *context, std::optional<Location> location, ValueRange operands,
582  DictionaryAttr attributes, OpaqueProperties, RegionRange regions,
583  llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
584  ::llvm::SmallVector<Type> types;
585  for (auto op : operands)
586  types.push_back(op.getType());
587  inferredReturnTypes.push_back(TupleType::get(context, types));
588  return success();
589 }
590 
591 //===----------------------------------------------------------------------===//
592 // TupleGetOp
593 //===----------------------------------------------------------------------===//
594 
595 LogicalResult TupleGetOp::inferReturnTypes(
596  MLIRContext *context, std::optional<Location> location, ValueRange operands,
597  DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
598  llvm::SmallVectorImpl<Type> &inferredReturnTypes) {
599  Adaptor adaptor(operands, attributes, properties, regions);
600  auto idx = adaptor.getIndexAttr();
601  if (operands.empty() || !idx)
602  return failure();
603 
604  auto tupleTypes = cast<TupleType>(adaptor.getInput().getType()).getTypes();
605  if (tupleTypes.size() <= idx.getValue().getLimitedValue()) {
606  if (location)
607  mlir::emitError(*location,
608  "tuple index out-of-bounds, must be less than ")
609  << tupleTypes.size() << " but got "
610  << idx.getValue().getLimitedValue();
611  return failure();
612  }
613 
614  inferredReturnTypes.push_back(tupleTypes[idx.getValue().getLimitedValue()]);
615  return success();
616 }
617 
618 //===----------------------------------------------------------------------===//
619 // MapCreateOp
620 //===----------------------------------------------------------------------===//
621 
622 void circt::om::MapCreateOp::print(OpAsmPrinter &p) {
623  p << " ";
624  p.printOperands(getInputs());
625  p.printOptionalAttrDict((*this)->getAttrs());
626  p << " : " << cast<circt::om::MapType>(getType()).getKeyType() << ", "
627  << cast<circt::om::MapType>(getType()).getValueType();
628 }
629 
630 ParseResult circt::om::MapCreateOp::parse(OpAsmParser &parser,
631  OperationState &result) {
632  llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
633  Type elementType, valueType;
634 
635  if (parser.parseOperandList(operands) ||
636  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
637  parser.parseType(elementType) || parser.parseComma() ||
638  parser.parseType(valueType))
639  return failure();
640  result.addTypes({circt::om::MapType::get(elementType, valueType)});
641  auto operandType =
642  mlir::TupleType::get(valueType.getContext(), {elementType, valueType});
643 
644  for (auto operand : operands)
645  if (parser.resolveOperand(operand, operandType, result.operands))
646  return failure();
647  return success();
648 }
649 
650 //===----------------------------------------------------------------------===//
651 // BasePathCreateOp
652 //===----------------------------------------------------------------------===//
653 
654 LogicalResult
655 BasePathCreateOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
656  auto hierPath = symbolTable.lookupNearestSymbolFrom<hw::HierPathOp>(
657  *this, getTargetAttr());
658  if (!hierPath)
659  return emitOpError("invalid symbol reference");
660  return success();
661 }
662 
663 //===----------------------------------------------------------------------===//
664 // PathCreateOp
665 //===----------------------------------------------------------------------===//
666 
667 LogicalResult
668 PathCreateOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
669  auto hierPath = symbolTable.lookupNearestSymbolFrom<hw::HierPathOp>(
670  *this, getTargetAttr());
671  if (!hierPath)
672  return emitOpError("invalid symbol reference");
673  return success();
674 }
675 
676 //===----------------------------------------------------------------------===//
677 // IntegerAddOp
678 //===----------------------------------------------------------------------===//
679 
680 FailureOr<llvm::APSInt>
681 IntegerAddOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
682  const llvm::APSInt &rhs) {
683  return success(lhs + rhs);
684 }
685 
686 //===----------------------------------------------------------------------===//
687 // IntegerMulOp
688 //===----------------------------------------------------------------------===//
689 
690 FailureOr<llvm::APSInt>
691 IntegerMulOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
692  const llvm::APSInt &rhs) {
693  return success(lhs * rhs);
694 }
695 
696 //===----------------------------------------------------------------------===//
697 // IntegerShrOp
698 //===----------------------------------------------------------------------===//
699 
700 FailureOr<llvm::APSInt>
701 IntegerShrOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
702  const llvm::APSInt &rhs) {
703  // Check non-negative constraint from operation semantics.
704  if (!rhs.isNonNegative())
705  return emitOpError("shift amount must be non-negative");
706  // Check size constraint from implementation detail of using getExtValue.
707  if (!rhs.isRepresentableByInt64())
708  return emitOpError("shift amount must be representable in 64 bits");
709  return success(lhs >> rhs.getExtValue());
710 }
711 
712 //===----------------------------------------------------------------------===//
713 // IntegerShlOp
714 //===----------------------------------------------------------------------===//
715 
716 FailureOr<llvm::APSInt>
717 IntegerShlOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
718  const llvm::APSInt &rhs) {
719  // Check non-negative constraint from operation semantics.
720  if (!rhs.isNonNegative())
721  return emitOpError("shift amount must be non-negative");
722  // Check size constraint from implementation detail of using getExtValue.
723  if (!rhs.isRepresentableByInt64())
724  return emitOpError("shift amount must be representable in 64 bits");
725  return success(lhs << rhs.getExtValue());
726 }
727 
728 //===----------------------------------------------------------------------===//
729 // TableGen generated logic.
730 //===----------------------------------------------------------------------===//
731 
732 #define GET_OP_CLASSES
733 #include "circt/Dialect/OM/OM.cpp.inc"
assert(baseType &&"element must be base type")
MlirType elementType
Definition: CHIRRTL.cpp:29
static InstancePath empty
static ParseResult parseClassLike(OpAsmParser &parser, OperationState &state)
Definition: OMOps.cpp:112
LogicalResult verifyClassLike(ClassLike classLike)
Definition: OMOps.cpp:214
void getClassLikeAsmBlockArgumentNames(ClassLike classLike, Region &region, OpAsmSetValueNameFn setNameFn)
Definition: OMOps.cpp:231
static ParseResult parseBasePathString(OpAsmParser &parser, PathAttr &path)
Definition: OMOps.cpp:26
static ParseResult parsePathString(OpAsmParser &parser, PathAttr &path, StringAttr &module, StringAttr &ref, StringAttr &field)
Definition: OMOps.cpp:48
static void printBasePathString(OpAsmPrinter &p, Operation *op, PathAttr path)
Definition: OMOps.cpp:37
std::optional< Type > getClassLikeFieldType(ClassLike classLike, StringAttr name)
Definition: OMOps.cpp:253
static ParseResult parseClassFieldsList(OpAsmParser &parser, SmallVectorImpl< Attribute > &fieldNames, SmallVectorImpl< Type > &fieldTypes)
Definition: OMOps.cpp:80
static void printClassLike(ClassLike classLike, OpAsmPrinter &printer)
Definition: OMOps.cpp:166
void replaceClassLikeFieldTypes(ClassLike classLike, AttrTypeReplacer &replacer)
Definition: OMOps.cpp:263
NamedAttribute makeFieldType(StringAttr name, Type type)
Definition: OMOps.cpp:243
NamedAttribute makeFieldIdx(MLIRContext *ctx, mlir::StringAttr name, unsigned i)
Definition: OMOps.cpp:247
static void printPathString(OpAsmPrinter &p, Operation *op, PathAttr path, StringAttr module, StringAttr ref, StringAttr field)
Definition: OMOps.cpp:62
static Block * getBodyBlock(FModuleLike mod)
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Definition: SVOps.cpp:2467
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
ParseResult parsePath(MLIRContext *context, StringRef spelling, PathAttr &path, StringAttr &module, StringAttr &ref, StringAttr &field)
Parse a target string in to a path.
Definition: OMUtils.cpp:182
ParseResult parseBasePath(MLIRContext *context, StringRef spelling, PathAttr &path)
Parse a target string of the form "Foo/bar:Bar/baz" in to a base path.
Definition: OMUtils.cpp:177
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
Definition: LLVM.h:182
A module name, and the name of an instance inside that module.
Definition: OMAttributes.h:22
mlir::StringAttr module
Definition: OMAttributes.h:35
mlir::StringAttr instance
Definition: OMAttributes.h:36