17#include "mlir/IR/Builders.h"
18#include "mlir/IR/ImplicitLocOpBuilder.h"
19#include "mlir/IR/SymbolTable.h"
20#include "llvm/ADT/STLExtras.h"
30 auto *
context = parser.getContext();
31 auto loc = parser.getCurrentLocation();
33 if (parser.parseString(&rawPath))
36 return parser.emitError(loc,
"invalid base path");
45 p << elt.module.getValue() <<
'/' << elt.
instance.getValue();
52 StringAttr &module, StringAttr &ref,
55 auto *
context = parser.getContext();
56 auto loc = parser.getCurrentLocation();
58 if (parser.parseString(&rawPath))
61 return parser.emitError(loc,
"invalid path");
66 StringAttr module, StringAttr ref,
69 for (
const auto &elt : path)
70 p << elt.module.getValue() <<
'/' << elt.instance.getValue() <<
':';
71 if (!module.getValue().empty())
72 p << module.getValue();
73 if (!ref.getValue().empty())
74 p <<
'>' << ref.getValue();
75 if (!field.getValue().empty())
76 p << field.getValue();
80static ParseResult
parseFieldLocs(OpAsmParser &parser, ArrayAttr &fieldLocs) {
81 if (parser.parseOptionalKeyword(
"field_locs"))
83 if (parser.parseLParen() || parser.parseAttribute(fieldLocs) ||
84 parser.parseRParen()) {
91 ArrayAttr fieldLocs) {
92 mlir::OpPrintingFlags flags;
93 if (!flags.shouldPrintDebugInfo() || !fieldLocs)
95 printer <<
"field_locs(";
96 printer.printAttribute(fieldLocs);
104 SmallVectorImpl<Attribute> &fieldNames,
105 SmallVectorImpl<Type> &fieldTypes) {
107 llvm::StringMap<SMLoc> nameLocMap;
108 auto parseElt = [&]() -> ParseResult {
110 std::string fieldName;
111 if (parser.parseKeywordOrString(&fieldName))
113 SMLoc currLoc = parser.getCurrentLocation();
114 if (nameLocMap.count(fieldName)) {
115 parser.emitError(currLoc,
"field \"")
116 << fieldName <<
"\" is defined twice";
117 parser.emitError(nameLocMap[fieldName]) <<
"previous definition is here";
120 nameLocMap[fieldName] = currLoc;
121 fieldNames.push_back(StringAttr::get(parser.getContext(), fieldName));
124 fieldTypes.emplace_back();
125 if (parser.parseColonType(fieldTypes.back()))
131 return parser.parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
137 (void)mlir::impl::parseOptionalVisibilityKeyword(parser, state.attributes);
141 if (parser.parseSymbolName(symName, mlir::SymbolTable::getSymbolAttrName(),
146 SmallVector<OpAsmParser::Argument> args;
147 if (parser.parseArgumentList(args, OpAsmParser::Delimiter::Paren,
151 SmallVector<Type> fieldTypes;
152 SmallVector<Attribute> fieldNames;
153 if (succeeded(parser.parseOptionalArrow()))
157 SmallVector<NamedAttribute> fieldTypesMap;
158 if (!fieldNames.empty()) {
159 for (
auto [name, type] : zip(fieldNames, fieldTypes))
160 fieldTypesMap.push_back(
161 NamedAttribute(cast<StringAttr>(name), TypeAttr::get(type)));
163 auto *ctx = parser.getContext();
164 state.addAttribute(
"fieldNames", mlir::ArrayAttr::get(ctx, fieldNames));
165 state.addAttribute(
"fieldTypes",
166 mlir::DictionaryAttr::get(ctx, fieldTypesMap));
169 if (failed(parser.parseOptionalAttrDictWithKeyword(state.attributes)))
173 Region *region = state.addRegion();
174 if (parser.parseRegion(*region, args))
179 region->emplaceBlock();
182 auto argNames = llvm::map_range(args, [&](OpAsmParser::Argument arg) {
183 return StringAttr::get(parser.getContext(), arg.ssaName.name.drop_front());
187 ArrayAttr::get(parser.getContext(), SmallVector<Attribute>(argNames)));
196 StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
197 if (
auto visibility =
198 classLike->getAttrOfType<StringAttr>(visibilityAttrName))
199 printer << visibility.getValue() <<
' ';
202 printer.printSymbolName(classLike.getSymName());
205 auto argNames = SmallVector<StringRef>(
206 classLike.getFormalParamNames().getAsValueRange<StringAttr>());
207 ArrayRef<BlockArgument> args = classLike.getBodyBlock()->getArguments();
211 for (
size_t i = 0, e = args.size(); i < e; ++i) {
212 printer <<
'%' << argNames[i] <<
": " << args[i].getType();
218 ArrayRef<Attribute> fieldNames =
219 cast<ArrayAttr>(classLike->getAttr(
"fieldNames")).getValue();
221 if (!fieldNames.empty()) {
223 for (
size_t i = 0, e = fieldNames.size(); i < e; ++i) {
226 StringAttr name = cast<StringAttr>(fieldNames[i]);
227 printer.printKeywordOrString(name.getValue());
229 Type type = classLike.getFieldType(name).value();
230 printer.printType(type);
236 SmallVector<StringRef> elidedAttrs{
237 classLike.getSymNameAttrName(), classLike.getFormalParamNamesAttrName(),
238 visibilityAttrName,
"fieldTypes",
"fieldNames"};
239 printer.printOptionalAttrDictWithKeyword(classLike.getOperation()->getAttrs(),
243 printer.printRegion(classLike.getBody(),
false,
249 if (classLike.getFormalParamNames().size() !=
250 classLike.getBodyBlock()->getArguments().size()) {
251 auto error = classLike.emitOpError(
252 "formal parameter name list doesn't match formal parameter value list");
253 error.attachNote(classLike.getLoc())
254 <<
"formal parameter names: " << classLike.getFormalParamNames();
255 error.attachNote(classLike.getLoc())
256 <<
"formal parameter values: "
257 << classLike.getBodyBlock()->getArguments();
267 auto argNames = SmallVector<StringRef>(
268 classLike.getFormalParamNames().getAsValueRange<StringAttr>());
269 ArrayRef<BlockArgument> args = classLike.getBodyBlock()->getArguments();
272 for (
size_t i = 0, e = args.size(); i < e; ++i)
273 setNameFn(args[i], argNames[i]);
277 return NamedAttribute(name, TypeAttr::get(type));
282 return NamedAttribute(StringAttr(name),
283 mlir::IntegerAttr::get(mlir::IndexType::get(ctx), i));
288 DictionaryAttr fieldTypes = mlir::cast<DictionaryAttr>(
289 classLike.getOperation()->getAttr(
"fieldTypes"));
290 Attribute type = fieldTypes.get(name);
291 if (
auto field = dyn_cast_or_null<TypeAttr>(type))
292 return field.getValue();
297 AttrTypeReplacer &replacer) {
298 classLike->setAttr(
"fieldTypes", cast<DictionaryAttr>(replacer.replace(
299 classLike.getFieldTypes())));
306ParseResult circt::om::ClassOp::parse(OpAsmParser &parser,
307 OperationState &state) {
311circt::om::ClassOp circt::om::ClassOp::buildSimpleClassOp(
312 OpBuilder &odsBuilder, Location loc, Twine name,
313 ArrayRef<StringRef> formalParamNames, ArrayRef<StringRef> fieldNames,
314 ArrayRef<Type> fieldTypes) {
315 circt::om::ClassOp classOp = circt::om::ClassOp::create(
316 odsBuilder, loc, odsBuilder.getStringAttr(name),
317 odsBuilder.getStrArrayAttr(formalParamNames),
318 odsBuilder.getStrArrayAttr(fieldNames),
319 odsBuilder.getDictionaryAttr(llvm::map_to_vector(
320 llvm::zip(fieldNames, fieldTypes), [&](
auto field) -> NamedAttribute {
321 return NamedAttribute(odsBuilder.getStringAttr(std::get<0>(field)),
322 TypeAttr::get(std::get<1>(field)));
324 Block *body = &classOp.getRegion().emplaceBlock();
325 auto prevLoc = odsBuilder.saveInsertionPoint();
326 odsBuilder.setInsertionPointToEnd(body);
328 mlir::SmallVector<Attribute> locAttrs(fieldNames.size(), LocationAttr(loc));
330 ClassFieldsOp::create(odsBuilder, loc,
331 llvm::map_to_vector(fieldTypes,
332 [&](Type type) -> Value {
333 return body->addArgument(type,
336 odsBuilder.getArrayAttr(locAttrs));
338 odsBuilder.restoreInsertionPoint(prevLoc);
343void circt::om::ClassOp::print(OpAsmPrinter &printer) {
347LogicalResult circt::om::ClassOp::verify() {
return verifyClassLike(*
this); }
349LogicalResult circt::om::ClassOp::verifyRegions() {
351 dyn_cast_or_null<ClassFieldsOp>(this->
getBodyBlock()->getTerminator());
353 return this->emitOpError(
"expected terminator to be ClassFieldsOp");
356 if (fieldsOp.getNumOperands() != this->getFieldNames().size()) {
357 auto diag = this->emitOpError()
358 <<
"returns '" << this->getFieldNames().size()
359 <<
"' fields, but its terminator returned '"
360 << fieldsOp.getNumOperands() <<
"' fields";
361 return diag.attachNote(fieldsOp.getLoc()) <<
"see terminator:";
365 auto types = this->getFieldTypes();
366 for (
auto [fieldName, terminatorOperandType] :
367 llvm::zip(this->getFieldNames(), fieldsOp.getOperandTypes())) {
369 auto fieldNameAttr = dyn_cast_or_null<StringAttr>(fieldName);
371 return this->emitOpError(
"field name is not a StringAttr");
373 if (
auto fieldType = types.get(fieldNameAttr))
374 if (
auto typeAttr = dyn_cast<TypeAttr>(fieldType))
375 if (typeAttr.getValue() == terminatorOperandType)
378 auto diag = this->emitOpError()
379 <<
"returns different field types than its terminator";
380 return diag.attachNote(fieldsOp.getLoc()) <<
"see terminator:";
386void circt::om::ClassOp::getAsmBlockArgumentNames(
391std::optional<mlir::Type>
392circt::om::ClassOp::getFieldType(mlir::StringAttr field) {
396void circt::om::ClassOp::replaceFieldTypes(AttrTypeReplacer replacer) {
400void circt::om::ClassOp::updateFields(
401 mlir::ArrayRef<mlir::Location> newLocations,
402 mlir::ArrayRef<mlir::Value> newValues,
403 mlir::ArrayRef<mlir::Attribute> newNames) {
405 auto fieldsOp = getFieldsOp();
406 assert(fieldsOp &&
"The fields op should exist");
408 SmallVector<Attribute> names(getFieldNamesAttr().getAsRange<StringAttr>());
410 SmallVector<NamedAttribute> fieldTypes(getFieldTypesAttr().getValue());
412 SmallVector<Value> fieldVals(fieldsOp.getFields());
414 Location fieldOpLoc = fieldsOp->getLoc();
417 SmallVector<Location> locations;
418 if (
auto fl = dyn_cast<FusedLoc>(fieldOpLoc)) {
419 auto metadataArr = dyn_cast<ArrayAttr>(fl.getMetadata());
420 assert(metadataArr &&
"Expected the metadata for the fused location");
421 auto r = metadataArr.getAsRange<LocationAttr>();
422 locations.append(r.begin(), r.end());
425 locations.append(names.size(), fieldOpLoc);
429 names.append(newNames.begin(), newNames.end());
430 locations.append(newLocations.begin(), newLocations.end());
431 fieldVals.append(newValues.begin(), newValues.end());
434 for (
auto [v, n] :
llvm::zip(newValues, newNames))
435 fieldTypes.emplace_back(
436 NamedAttribute(
llvm::cast<StringAttr>(n), TypeAttr::
get(v.getType())));
439 SmallVector<Attribute> locationsAttr;
440 llvm::for_each(locations, [&](Location &l) {
441 locationsAttr.push_back(cast<Attribute>(l));
444 ImplicitLocOpBuilder builder(
getLoc(), *
this);
446 setFieldNamesAttr(builder.getArrayAttr(names));
448 setFieldTypesAttr(builder.getDictionaryAttr(fieldTypes));
449 fieldsOp.getFieldsMutable().assign(fieldVals);
451 fieldsOp->setLoc(builder.getFusedLoc(
452 locations, ArrayAttr::get(getContext(), locationsAttr)));
455void circt::om::ClassOp::addNewFieldsOp(mlir::OpBuilder &builder,
456 mlir::ArrayRef<Location> locs,
457 mlir::ArrayRef<Value> values) {
460 assert(locs.size() == values.size() &&
"Expected a location per value");
461 mlir::SmallVector<Attribute> locAttrs;
462 for (
auto loc : locs) {
463 locAttrs.push_back(cast<Attribute>(LocationAttr(loc)));
467 ClassFieldsOp::create(builder, builder.getFusedLoc(locs), values,
468 builder.getArrayAttr(locAttrs));
471mlir::Location circt::om::ClassOp::getFieldLocByIndex(
size_t i) {
472 auto fieldsOp = this->getFieldsOp();
473 auto fieldLocs = fieldsOp.getFieldLocs();
474 if (!fieldLocs.has_value())
475 return fieldsOp.getLoc();
476 assert(i < fieldLocs.value().size() &&
477 "field index too large for location array");
478 return cast<LocationAttr>(fieldLocs.value()[i]);
485ParseResult circt::om::ClassExternOp::parse(OpAsmParser &parser,
486 OperationState &state) {
490void circt::om::ClassExternOp::print(OpAsmPrinter &printer) {
494LogicalResult circt::om::ClassExternOp::verify() {
500 return this->emitOpError(
"external class body should be empty");
506void circt::om::ClassExternOp::getAsmBlockArgumentNames(
511std::optional<mlir::Type>
512circt::om::ClassExternOp::getFieldType(mlir::StringAttr field) {
516void circt::om::ClassExternOp::replaceFieldTypes(AttrTypeReplacer replacer) {
524LogicalResult circt::om::ClassFieldsOp::verify() {
525 auto fieldLocs = this->getFieldLocs();
526 if (fieldLocs.has_value()) {
527 auto fieldLocsVal = fieldLocs.value();
528 if (fieldLocsVal.size() != this->getFields().size()) {
529 auto error = this->emitOpError(
"size of field_locs (")
530 << fieldLocsVal.size()
531 <<
") does not match number of fields ("
532 << this->getFields().size() <<
")";
542void circt::om::ObjectOp::build(::mlir::OpBuilder &odsBuilder,
543 ::mlir::OperationState &odsState,
545 ::mlir::ValueRange actualParams) {
546 return build(odsBuilder, odsState,
547 om::ClassType::get(odsBuilder.getContext(),
548 mlir::FlatSymbolRefAttr::get(classOp)),
549 classOp.getNameAttr(), actualParams);
552static FailureOr<ClassLike>
554 ClassType resultType, StringAttr className) {
555 StringAttr resultClassName = resultType.getClassName().getAttr();
556 if (resultClassName != className)
557 return op->emitOpError(
"result type (")
558 << resultClassName <<
") does not match referred to class ("
561 auto classDef = dyn_cast_or_null<ClassLike>(
562 symbolTable.lookupNearestSymbolFrom(op, className));
564 return op->emitOpError(
"refers to non-existant class (")
570circt::om::ObjectOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
572 (*
this), symbolTable, getResult().getType(), getClassNameAttr());
573 if (failed(classDef))
576 auto actualTypes = getActualParams().getTypes();
577 auto formalTypes = classDef->getBodyBlock()->getArgumentTypes();
580 if (actualTypes.size() != formalTypes.size()) {
581 auto error = emitOpError(
582 "actual parameter list doesn't match formal parameter list");
583 error.attachNote(classDef->getLoc())
584 <<
"formal parameters: " << classDef->getBodyBlock()->getArguments();
585 error.attachNote(
getLoc()) <<
"actual parameters: " << getActualParams();
590 for (
size_t i = 0, e = actualTypes.size(); i < e; ++i) {
591 if (actualTypes[i] != formalTypes[i]) {
592 return emitOpError(
"actual parameter type (")
593 << actualTypes[i] <<
") doesn't match formal parameter type ("
594 << formalTypes[i] <<
')';
606circt::om::ObjectFieldOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
607 auto classType = getObject().getType();
608 auto className = classType.getClassName().getAttr();
611 auto classDef = dyn_cast_or_null<ClassLike>(
612 symbolTable.lookupNearestSymbolFrom(*
this, className));
614 return emitOpError(
"class ") << className <<
" was not found";
617 auto fieldName = getFieldAttr();
618 std::optional<Type> fieldType = classDef.getFieldType(fieldName);
620 auto diag = emitOpError(
"referenced non-existent field ") << fieldName;
621 diag.attachNote(classDef.getLoc()) <<
"class defined here";
626 if (getResult().getType() != fieldType.value())
627 return emitOpError(
"expected type ")
628 << getResult().getType() <<
", but accessed field has type "
629 << fieldType.value();
637void circt::om::ElaboratedObjectOp::build(OpBuilder &odsBuilder,
638 OperationState &odsState,
639 om::ClassLike classOp,
640 ValueRange fieldValues) {
641 return build(odsBuilder, odsState,
643 odsBuilder.getContext(),
644 mlir::FlatSymbolRefAttr::get(classOp.getSymNameAttr())),
645 classOp.getSymNameAttr(), fieldValues);
648LogicalResult circt::om::ElaboratedObjectOp::verifySymbolUses(
649 SymbolTableCollection &symbolTable) {
651 (*
this), symbolTable, getResult().getType(), getClassNameAttr());
652 if (failed(classDef))
655 auto fieldNames = classDef->getFieldNames();
656 auto fieldValues = getFieldValues();
657 if (fieldValues.size() != fieldNames.size())
658 return emitOpError(
"field value list doesn't match class field list, "
660 << fieldNames.size() <<
" values but got " << fieldValues.size();
662 for (
auto [fieldName, fieldValue] :
llvm::zip(fieldNames, fieldValues)) {
664 classDef->getFieldType(cast<StringAttr>(fieldName)).value();
665 if (fieldValue.getType() != expectedType)
666 return emitOpError(
"field value type for ")
667 << cast<StringAttr>(fieldName) <<
" (" << fieldValue.getType()
668 <<
") doesn't match class field type (" << expectedType <<
')';
678void circt::om::ConstantOp::build(::mlir::OpBuilder &odsBuilder,
679 ::mlir::OperationState &odsState,
680 ::mlir::TypedAttr constVal) {
681 return build(odsBuilder, odsState, constVal.getType(), constVal);
684OpFoldResult circt::om::ConstantOp::fold(FoldAdaptor adaptor) {
685 assert(adaptor.getOperands().empty() &&
"constant has no operands");
686 return getValueAttr();
693void circt::om::ListCreateOp::print(OpAsmPrinter &p) {
695 p.printOperands(getInputs());
696 p.printOptionalAttrDict((*this)->getAttrs());
697 p <<
" : " << getType().getElementType();
700ParseResult circt::om::ListCreateOp::parse(OpAsmParser &parser,
701 OperationState &result) {
702 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
705 if (parser.parseOperandList(operands) ||
706 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
707 parser.parseType(elemType))
709 result.addTypes({circt::om::ListType::get(elemType)});
711 for (
auto operand : operands)
712 if (parser.resolveOperand(operand, elemType, result.operands))
722BasePathCreateOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
723 auto hierPath = symbolTable.lookupNearestSymbolFrom<hw::HierPathOp>(
724 *
this, getTargetAttr());
726 return emitOpError(
"invalid symbol reference");
735PathCreateOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
736 auto hierPath = symbolTable.lookupNearestSymbolFrom<hw::HierPathOp>(
737 *
this, getTargetAttr());
739 return emitOpError(
"invalid symbol reference");
750 auto lhs = dyn_cast_or_null<circt::om::IntegerAttr>(lhsAttr);
751 auto rhs = dyn_cast_or_null<circt::om::IntegerAttr>(rhsAttr);
758 APSInt lhsVal = lhs.getValue().getAPSInt();
759 APSInt rhsVal = rhs.getValue().getAPSInt();
760 if (lhsVal.getBitWidth() > rhsVal.getBitWidth())
761 rhsVal = rhsVal.extend(lhsVal.getBitWidth());
762 else if (rhsVal.getBitWidth() > lhsVal.getBitWidth())
763 lhsVal = lhsVal.extend(rhsVal.getBitWidth());
766 auto result = op.evaluateIntegerOperation(lhsVal, rhsVal);
770 auto *ctx = op.getContext();
772 return circt::om::IntegerAttr::get(
773 ctx, mlir::IntegerAttr::get(ctx, result.value()));
780FailureOr<llvm::APSInt>
781IntegerAddOp::evaluateIntegerOperation(
const llvm::APSInt &lhs,
782 const llvm::APSInt &rhs) {
783 return success(lhs + rhs);
786OpFoldResult IntegerAddOp::fold(FoldAdaptor adaptor) {
794FailureOr<llvm::APSInt>
795IntegerMulOp::evaluateIntegerOperation(
const llvm::APSInt &lhs,
796 const llvm::APSInt &rhs) {
797 return success(lhs * rhs);
800OpFoldResult IntegerMulOp::fold(FoldAdaptor adaptor) {
808FailureOr<llvm::APSInt>
809IntegerShrOp::evaluateIntegerOperation(
const llvm::APSInt &lhs,
810 const llvm::APSInt &rhs) {
812 if (!rhs.isNonNegative())
813 return emitOpError(
"shift amount must be non-negative");
815 if (!rhs.isRepresentableByInt64())
816 return emitOpError(
"shift amount must be representable in 64 bits");
817 return success(lhs >> rhs.getExtValue());
820OpFoldResult IntegerShrOp::fold(FoldAdaptor adaptor) {
828FailureOr<llvm::APSInt>
829IntegerShlOp::evaluateIntegerOperation(
const llvm::APSInt &lhs,
830 const llvm::APSInt &rhs) {
832 if (!rhs.isNonNegative())
833 return emitOpError(
"shift amount must be non-negative");
835 if (!rhs.isRepresentableByInt64())
836 return emitOpError(
"shift amount must be representable in 64 bits");
837 return success(lhs << rhs.getExtValue());
840OpFoldResult IntegerShlOp::fold(FoldAdaptor adaptor) {
848OpFoldResult StringConcatOp::fold(FoldAdaptor adaptor) {
850 if (getStrings().size() == 1) {
851 if (
auto strAttr = adaptor.getStrings()[0])
854 return getStrings()[0];
858 if (!llvm::all_of(adaptor.getStrings(), [](Attribute operand) {
859 return isa_and_nonnull<StringAttr>(operand);
864 SmallString<64> result;
865 for (
auto operand : adaptor.getStrings())
866 result += cast<StringAttr>(operand).getValue();
868 return StringAttr::get(result, getResult().getType());
876 using OpRewritePattern::OpRewritePattern;
879 matchAndRewrite(StringConcatOp concat,
880 mlir::PatternRewriter &rewriter)
const override {
884 bool hasNestedConcat = llvm::any_of(concat.getStrings(), [](Value operand) {
885 auto nestedConcat = operand.getDefiningOp<StringConcatOp>();
886 return nestedConcat && operand.hasOneUse();
889 if (!hasNestedConcat)
893 SmallVector<Value> flatOperands;
894 for (
auto input : concat.getStrings()) {
895 if (
auto nestedConcat = input.getDefiningOp<StringConcatOp>();
896 nestedConcat && input.hasOneUse())
897 llvm::append_range(flatOperands, nestedConcat.getStrings());
899 flatOperands.push_back(input);
902 rewriter.modifyOpInPlace(concat,
903 [&]() { concat->setOperands(flatOperands); });
910class MergeAdjacentOMStringConstants
913 using OpRewritePattern::OpRewritePattern;
916 matchAndRewrite(StringConcatOp concat,
917 mlir::PatternRewriter &rewriter)
const override {
919 SmallVector<Value> newOperands;
920 SmallString<64> accumulatedLit;
921 SmallVector<ConstantOp> accumulatedOps;
922 bool changed =
false;
924 auto flushLiterals = [&]() {
925 if (accumulatedOps.empty())
929 if (accumulatedOps.size() == 1) {
930 newOperands.push_back(accumulatedOps[0]);
933 auto newLit = rewriter.createOrFold<ConstantOp>(
935 StringAttr::get(accumulatedLit, concat.getResult().getType()));
936 newOperands.push_back(newLit);
939 accumulatedLit.clear();
940 accumulatedOps.clear();
943 for (
auto operand : concat.getStrings()) {
944 if (
auto litOp = operand.getDefiningOp<ConstantOp>()) {
945 if (
auto strAttr = dyn_cast<StringAttr>(litOp.getValue())) {
947 if (strAttr.getValue().empty()) {
951 accumulatedLit += strAttr.getValue();
952 accumulatedOps.push_back(litOp);
958 newOperands.push_back(operand);
968 if (newOperands.empty())
969 return rewriter.replaceOpWithNewOp<ConstantOp>(
970 concat, StringAttr::get(
"", concat.getResult().getType())),
974 rewriter.modifyOpInPlace(concat,
975 [&]() { concat->setOperands(newOperands); });
982void StringConcatOp::getCanonicalizationPatterns(RewritePatternSet &results,
984 results.insert<FlattenOMStringConcat, MergeAdjacentOMStringConstants>(
992FailureOr<mlir::Attribute>
993PropEqOp::evaluateBinaryEquality(mlir::Attribute lhsAttr,
994 mlir::Attribute rhsAttr) {
995 auto resultType = mlir::IntegerType::get(getContext(), 1);
998 if (
auto lhs = dyn_cast<mlir::StringAttr>(lhsAttr))
999 if (
auto rhs = dyn_cast<mlir::StringAttr>(rhsAttr))
1000 return mlir::Attribute(
1001 mlir::IntegerAttr::get(resultType, lhs == rhs ? 1 : 0));
1004 if (
auto lhs = dyn_cast<om::IntegerAttr>(lhsAttr))
1005 if (
auto rhs = dyn_cast<om::IntegerAttr>(rhsAttr)) {
1006 APSInt lhsVal = lhs.getValue().getAPSInt();
1007 APSInt rhsVal = rhs.getValue().getAPSInt();
1008 if (lhsVal.getBitWidth() > rhsVal.getBitWidth())
1009 rhsVal = rhsVal.extend(lhsVal.getBitWidth());
1010 else if (rhsVal.getBitWidth() > lhsVal.getBitWidth())
1011 lhsVal = lhsVal.extend(rhsVal.getBitWidth());
1012 return mlir::Attribute(
1013 mlir::IntegerAttr::get(resultType, lhsVal == rhsVal ? 1 : 0));
1017 if (
auto lhs = dyn_cast<mlir::IntegerAttr>(lhsAttr))
1018 if (
auto rhs = dyn_cast<mlir::IntegerAttr>(rhsAttr))
1019 return mlir::Attribute(
1020 mlir::IntegerAttr::get(resultType, lhs == rhs ? 1 : 0));
1025OpFoldResult PropEqOp::fold(FoldAdaptor adaptor) {
1026 auto lhsAttr = adaptor.getLhs();
1027 auto rhsAttr = adaptor.getRhs();
1028 if (!lhsAttr || !rhsAttr)
1031 auto result = evaluateBinaryEquality(lhsAttr, rhsAttr);
1043 Attribute rhsAttr) {
1044 auto lhsInt = dyn_cast_or_null<mlir::IntegerAttr>(lhsAttr);
1045 auto rhsInt = dyn_cast_or_null<mlir::IntegerAttr>(rhsAttr);
1046 if (!lhsInt || !rhsInt)
1048 APSInt lhsVal(lhsInt.getValue());
1049 APSInt rhsVal(rhsInt.getValue());
1050 auto result = op.evaluateIntegerOperation(lhsVal, rhsVal);
1053 return mlir::IntegerAttr::get(
1054 lhsInt.getType(), result->extOrTrunc(lhsInt.getValue().getBitWidth()));
1059 auto i = dyn_cast_or_null<mlir::IntegerAttr>(a);
1060 return i && i.getValue().isZero();
1065 auto i = dyn_cast_or_null<mlir::IntegerAttr>(a);
1066 return i && i.getValue().isAllOnes();
1069FailureOr<APSInt> IntegerAndOp::evaluateIntegerOperation(
const APSInt &lhs,
1070 const APSInt &rhs) {
1071 return success(APSInt(lhs & rhs,
false));
1074OpFoldResult IntegerAndOp::fold(FoldAdaptor adaptor) {
1080 return mlir::IntegerAttr::get(getResult().getType(),
1081 APInt::getZero(getType().
getWidth()));
1090FailureOr<APSInt> IntegerOrOp::evaluateIntegerOperation(
const APSInt &lhs,
1091 const APSInt &rhs) {
1092 return success(APSInt(lhs | rhs,
false));
1095OpFoldResult IntegerOrOp::fold(FoldAdaptor adaptor) {
1101 return mlir::IntegerAttr::get(getResult().getType(),
1102 APInt::getAllOnes(getType().
getWidth()));
1111FailureOr<APSInt> IntegerXorOp::evaluateIntegerOperation(
const APSInt &lhs,
1112 const APSInt &rhs) {
1113 return success(APSInt(lhs ^ rhs,
false));
1116OpFoldResult IntegerXorOp::fold(FoldAdaptor adaptor) {
1132LogicalResult circt::om::UnknownValueOp::verifySymbolUses(
1133 SymbolTableCollection &symbolTable) {
1136 auto classType = dyn_cast<ClassType>(getType());
1141 auto className = classType.getClassName();
1142 if (symbolTable.lookupNearestSymbolFrom<ClassLike>(*
this, className))
1145 return emitOpError() <<
"refers to non-existant class (\""
1146 << className.getValue() <<
"\")";
1153#define GET_OP_CLASSES
1154#include "circt/Dialect/OM/OM.cpp.inc"
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static Location getLoc(DefSlot slot)
static ParseResult parseClassLike(OpAsmParser &parser, OperationState &state)
LogicalResult verifyClassLike(ClassLike classLike)
std::optional< Type > getClassLikeFieldType(ClassLike classLike, StringAttr name)
void getClassLikeAsmBlockArgumentNames(ClassLike classLike, Region ®ion, OpAsmSetValueNameFn setNameFn)
static ParseResult parseBasePathString(OpAsmParser &parser, PathAttr &path)
static ParseResult parsePathString(OpAsmParser &parser, PathAttr &path, StringAttr &module, StringAttr &ref, StringAttr &field)
static void printBasePathString(OpAsmPrinter &p, Operation *op, PathAttr path)
static OpFoldResult foldIntegerBitwise(IntegerBinaryOp op, Attribute lhsAttr, Attribute rhsAttr)
static FailureOr< ClassLike > verifyClassLikeSymbolUser(Operation *op, SymbolTableCollection &symbolTable, ClassType resultType, StringAttr className)
static void printFieldLocs(OpAsmPrinter &printer, Operation *op, ArrayAttr fieldLocs)
static OpFoldResult foldIntegerBinaryArithmetic(IntegerBinaryOp op, Attribute lhsAttr, Attribute rhsAttr)
static bool isZeroInt(Attribute a)
static ParseResult parseFieldLocs(OpAsmParser &parser, ArrayAttr &fieldLocs)
static ParseResult parseClassFieldsList(OpAsmParser &parser, SmallVectorImpl< Attribute > &fieldNames, SmallVectorImpl< Type > &fieldTypes)
static void printClassLike(ClassLike classLike, OpAsmPrinter &printer)
void replaceClassLikeFieldTypes(ClassLike classLike, AttrTypeReplacer &replacer)
NamedAttribute makeFieldType(StringAttr name, Type type)
NamedAttribute makeFieldIdx(MLIRContext *ctx, mlir::StringAttr name, unsigned i)
static void printPathString(OpAsmPrinter &p, Operation *op, PathAttr path, StringAttr module, StringAttr ref, StringAttr field)
static bool isAllOnesInt(Attribute a)
static Block * getBodyBlock(FModuleLike mod)
static InstancePath empty
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
uint64_t getWidth(Type t)
void error(Twine message)
ParseResult parsePath(MLIRContext *context, StringRef spelling, PathAttr &path, StringAttr &module, StringAttr &ref, StringAttr &field)
Parse a target string in to a path.
ParseResult parseBasePath(MLIRContext *context, StringRef spelling, PathAttr &path)
Parse a target string of the form "Foo/bar:Bar/baz" in to a base path.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
A module name, and the name of an instance inside that module.
mlir::StringAttr mlir::StringAttr instance