CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
16#include "mlir/IR/Builders.h"
17#include "mlir/IR/ImplicitLocOpBuilder.h"
18
19using namespace mlir;
20using namespace circt::om;
21
22//===----------------------------------------------------------------------===//
23// Path Printers and Parsers
24//===----------------------------------------------------------------------===//
25
26static 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
37static 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
48static 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
62static 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//===----------------------------------------------------------------------===//
80static 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
112static 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
166static 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
214LogicalResult 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
231void 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
243NamedAttribute makeFieldType(StringAttr name, Type type) {
244 return NamedAttribute(name, TypeAttr::get(type));
245}
246
247NamedAttribute makeFieldIdx(MLIRContext *ctx, mlir::StringAttr name,
248 unsigned i) {
249 return NamedAttribute(StringAttr(name),
250 mlir::IntegerAttr::get(mlir::IndexType::get(ctx), i));
251}
252
253std::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
263void replaceClassLikeFieldTypes(ClassLike classLike,
264 AttrTypeReplacer &replacer) {
265 classLike->setAttr("fieldTypes", cast<DictionaryAttr>(replacer.replace(
266 classLike.getFieldTypes())));
267}
268
269//===----------------------------------------------------------------------===//
270// ClassOp
271//===----------------------------------------------------------------------===//
272
273ParseResult circt::om::ClassOp::parse(OpAsmParser &parser,
274 OperationState &state) {
275 return parseClassLike(parser, state);
276}
277
278circt::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
303void circt::om::ClassOp::print(OpAsmPrinter &printer) {
304 printClassLike(*this, printer);
305}
306
307LogicalResult circt::om::ClassOp::verify() { return verifyClassLike(*this); }
308
309LogicalResult 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
338void circt::om::ClassOp::getAsmBlockArgumentNames(
339 Region &region, OpAsmSetValueNameFn setNameFn) {
340 getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
341}
342
343std::optional<mlir::Type>
344circt::om::ClassOp::getFieldType(mlir::StringAttr field) {
345 return getClassLikeFieldType(*this, field);
346}
347
348void circt::om::ClassOp::replaceFieldTypes(AttrTypeReplacer replacer) {
349 replaceClassLikeFieldTypes(*this, replacer);
350}
351
352void 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
407void 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
422mlir::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
443ParseResult circt::om::ClassExternOp::parse(OpAsmParser &parser,
444 OperationState &state) {
445 return parseClassLike(parser, state);
446}
447
448void circt::om::ClassExternOp::print(OpAsmPrinter &printer) {
449 printClassLike(*this, printer);
450}
451
452LogicalResult 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
464void circt::om::ClassExternOp::getAsmBlockArgumentNames(
465 Region &region, OpAsmSetValueNameFn setNameFn) {
466 getClassLikeAsmBlockArgumentNames(*this, region, setNameFn);
467}
468
469std::optional<mlir::Type>
470circt::om::ClassExternOp::getFieldType(mlir::StringAttr field) {
471 return getClassLikeFieldType(*this, field);
472}
473
474void circt::om::ClassExternOp::replaceFieldTypes(AttrTypeReplacer replacer) {
475 replaceClassLikeFieldTypes(*this, replacer);
476}
477
478//===----------------------------------------------------------------------===//
479// ObjectOp
480//===----------------------------------------------------------------------===//
481
482void 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(),
488 mlir::FlatSymbolRefAttr::get(classOp)),
489 classOp.getNameAttr(), actualParams);
490}
491
492LogicalResult
493circt::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
537void 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
543OpFoldResult 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
552void circt::om::ListCreateOp::print(OpAsmPrinter &p) {
553 p << " ";
554 p.printOperands(getInputs());
555 p.printOptionalAttrDict((*this)->getAttrs());
556 p << " : " << getType().getElementType();
557}
558
559ParseResult 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
580LogicalResult 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
595LogicalResult 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
622void 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
630ParseResult 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
654LogicalResult
655BasePathCreateOp::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
667LogicalResult
668PathCreateOp::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
680FailureOr<llvm::APSInt>
681IntegerAddOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
682 const llvm::APSInt &rhs) {
683 return success(lhs + rhs);
684}
685
686//===----------------------------------------------------------------------===//
687// IntegerMulOp
688//===----------------------------------------------------------------------===//
689
690FailureOr<llvm::APSInt>
691IntegerMulOp::evaluateIntegerOperation(const llvm::APSInt &lhs,
692 const llvm::APSInt &rhs) {
693 return success(lhs * rhs);
694}
695
696//===----------------------------------------------------------------------===//
697// IntegerShrOp
698//===----------------------------------------------------------------------===//
699
700FailureOr<llvm::APSInt>
701IntegerShrOp::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
716FailureOr<llvm::APSInt>
717IntegerShlOp::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
std::optional< Type > getClassLikeFieldType(ClassLike classLike, StringAttr name)
Definition OMOps.cpp:253
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
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)
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.
mlir::StringAttr mlir::StringAttr instance