CIRCT 23.0.0git
Loading...
Searching...
No Matches
DebugOps.cpp
Go to the documentation of this file.
1//===- DebugOps.cpp - Debug dialect operations ----------------------------===//
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
10#include "mlir/IR/OpImplementation.h"
11#include "llvm/ADT/DenseSet.h"
12
13using namespace circt;
14using namespace debug;
15using namespace mlir;
16
17//===----------------------------------------------------------------------===//
18// StructOp
19//===----------------------------------------------------------------------===//
20
21ParseResult StructOp::parse(OpAsmParser &parser, OperationState &result) {
22 // Parse the struct fields.
23 SmallVector<Attribute> names;
24 SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
25 std::string nameBuffer;
26 auto parseField = [&]() {
27 nameBuffer.clear();
28 if (parser.parseString(&nameBuffer) || parser.parseColon() ||
29 parser.parseOperand(operands.emplace_back()))
30 return failure();
31 names.push_back(StringAttr::get(parser.getContext(), nameBuffer));
32 return success();
33 };
34 if (parser.parseCommaSeparatedList(AsmParser::Delimiter::Braces, parseField))
35 return failure();
36
37 // Parse the attribute dictionary.
38 if (parser.parseOptionalAttrDict(result.attributes))
39 return failure();
40
41 // Parse the field types, if there are any fields.
42 SmallVector<Type> types;
43 if (!operands.empty()) {
44 if (parser.parseColon())
45 return failure();
46 auto typesLoc = parser.getCurrentLocation();
47 if (parser.parseTypeList(types))
48 return failure();
49 if (types.size() != operands.size())
50 return parser.emitError(typesLoc,
51 "number of fields and types must match");
52 }
53
54 // Resolve the operands.
55 for (auto [operand, type] : llvm::zip(operands, types))
56 if (parser.resolveOperand(operand, type, result.operands))
57 return failure();
58
59 // Finalize the op.
60 result.addAttribute("names", ArrayAttr::get(parser.getContext(), names));
61 result.addTypes(StructType::get(parser.getContext()));
62 return success();
63}
64
65void StructOp::print(OpAsmPrinter &printer) {
66 printer << " {";
67 llvm::interleaveComma(llvm::zip(getFields(), getNames()), printer.getStream(),
68 [&](auto pair) {
69 auto [field, name] = pair;
70 printer.printAttribute(name);
71 printer << ": ";
72 printer.printOperand(field);
73 });
74 printer << '}';
75 printer.printOptionalAttrDict(getOperation()->getAttrs(), {"names"});
76 if (!getFields().empty()) {
77 printer << " : ";
78 printer << getFields().getTypes();
79 }
80}
81
82//===----------------------------------------------------------------------===//
83// ArrayOp
84//===----------------------------------------------------------------------===//
85
86ParseResult ArrayOp::parse(OpAsmParser &parser, OperationState &result) {
87 // Parse the elements, attributes and types.
88 SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
89 if (parser.parseOperandList(operands, AsmParser::Delimiter::Square) ||
90 parser.parseOptionalAttrDict(result.attributes))
91 return failure();
92
93 // Resolve the operands.
94 if (!operands.empty()) {
95 Type type;
96 if (parser.parseColon() || parser.parseType(type))
97 return failure();
98 for (auto operand : operands)
99 if (parser.resolveOperand(operand, type, result.operands))
100 return failure();
101 }
102
103 // Finalize the op.
104 result.addTypes(ArrayType::get(parser.getContext()));
105 return success();
106}
107
108void ArrayOp::print(OpAsmPrinter &printer) {
109 printer << " [";
110 printer << getElements();
111 printer << ']';
112 printer.printOptionalAttrDict(getOperation()->getAttrs());
113 if (!getElements().empty()) {
114 printer << " : ";
115 printer << getElements()[0].getType();
116 }
117}
118
119//===----------------------------------------------------------------------===//
120// Generated operation code
121//===----------------------------------------------------------------------===//
122#define GET_OP_CLASSES
123#include "circt/Dialect/Debug/Debug.cpp.inc"
124
125void DebugDialect::registerOps() {
126 addOperations<
127#define GET_OP_LIST
128#include "circt/Dialect/Debug/Debug.cpp.inc"
129 >();
130}
131
132//===----------------------------------------------------------------------===//
133// ValueOp
134//===----------------------------------------------------------------------===//
135
136LogicalResult ValueOp::verify() {
137 // Final IR is expected to have >=1 user (dbg.variable/dbg.struct/dbg.array).
138 if (!llvm::all_of(getResult().getUsers(), [](Operation *user) {
139 return isa<VariableOp, StructOp, ArrayOp>(user);
140 }))
141 return emitOpError(
142 "must only be used as an operand of dbg.variable, dbg.struct, or "
143 "dbg.array");
144
145 return success();
146}
147
148//===----------------------------------------------------------------------===//
149// EnumOp
150//===----------------------------------------------------------------------===//
151
152LogicalResult EnumOp::verify() {
153 if (getVariantsMap().empty())
154 return emitOpError("variantsMap must not be empty");
155
156 llvm::SmallDenseSet<int64_t> seenValues{};
157 for (auto namedAttr : getVariantsMap()) {
158 auto intAttr = dyn_cast<IntegerAttr>(namedAttr.getValue());
159 if (!intAttr)
160 return emitOpError("variantsMap entry '")
161 << namedAttr.getName().getValue()
162 << "' must be an IntegerAttr, got " << namedAttr.getValue();
163 if (!intAttr.getType().isSignlessInteger())
164 return emitOpError() << "variant '" << namedAttr.getName().getValue()
165 << "' must have a signless integer value";
166 auto value = intAttr.getInt();
167 if (!seenValues.insert(value).second)
168 return emitOpError("duplicate enum value ") << value;
169 }
170 return success();
171}
static InstancePath empty
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition debug.py:1