16#include "mlir/IR/ImplicitLocOpBuilder.h"
17#include "mlir/Pass/Pass.h"
18#include "llvm/ADT/DenseSet.h"
21#define GEN_PASS_DEF_LEGALIZEANONENUMS
22#include "circt/Conversion/Passes.h.inc"
30struct LegalizeAnonEnums
31 :
public circt::impl::LegalizeAnonEnumsBase<LegalizeAnonEnums> {
34 auto topLevel = getOperation();
36 auto builder = OpBuilder::atBlockBegin(&topLevel.getRegion().front());
39 typeScope.getBodyRegion().push_back(
new Block());
40 mlir::SymbolTable symbolTable(topLevel);
41 symbolTable.insert(typeScope);
47 Type getEnumTypeDecl(EnumType type) {
48 auto &typeAlias = enumTypeAliases[type];
52 auto loc = UnknownLoc::get(
context);
53 auto typeScope = getTypeScope();
54 auto builder = OpBuilder::atBlockEnd(&typeScope.getRegion().front());
55 auto declName = StringAttr::get(
context,
"enum" + Twine(enumCount++));
57 TypeAttr::get(type),
nullptr);
58 auto symRef = SymbolRefAttr::get(typeScope.getSymNameAttr(),
59 FlatSymbolRefAttr::get(declName));
60 typeAlias = TypeAliasType::get(symRef, type);
67 if (
auto structType = dyn_cast<StructType>(type)) {
69 SmallVector<StructType::FieldInfo> fields;
70 for (
auto &element : structType.getElements()) {
71 if (
auto newFieldType =
processType(element.type)) {
73 fields.push_back({element.name, newFieldType});
75 fields.push_back(element);
79 return StructType::get(
context, fields);
83 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
84 if (
auto newElementType =
processType(arrayType.getElementType()))
85 return ArrayType::get(newElementType, arrayType.getNumElements());
89 if (
auto unionType = dyn_cast<UnionType>(type)) {
91 SmallVector<UnionType::FieldInfo> fields;
92 for (
const auto &element : unionType.getElements()) {
93 if (
auto newFieldType =
processType(element.type)) {
94 fields.push_back({element.name, newFieldType, element.offset});
97 fields.push_back(element);
101 return UnionType::get(
context, fields);
105 if (
auto typeAlias = dyn_cast<TypeAliasType>(type)) {
107 if (isa<EnumType>(typeAlias.getInnerType()))
113 if (
auto inoutType = dyn_cast<InOutType>(type)) {
114 if (
auto newType =
processType(inoutType.getElementType()))
115 return InOutType::get(newType);
120 if (
auto enumType = dyn_cast<EnumType>(type))
121 return getEnumTypeDecl(enumType);
123 if (
auto funcType = dyn_cast<FunctionType>(type)) {
124 bool changed =
false;
125 SmallVector<Type> inputs;
126 for (
auto &type : funcType.getInputs()) {
128 inputs.push_back(newType);
131 inputs.push_back(type);
134 SmallVector<Type> results;
135 for (
auto &type : funcType.getResults()) {
137 results.push_back(newType);
140 results.push_back(type);
144 return FunctionType::get(
context, inputs, results);
147 if (
auto modType = dyn_cast<ModuleType>(type)) {
148 bool changed =
false;
149 SmallVector<ModulePort> ports;
150 for (
auto &p : modType.getPorts()) {
153 ports.back().type = newType;
158 return ModuleType::get(
context, ports);
166 void runOnOperation()
override {
171 getOperation().walk([&](Operation *op) {
176 if (
auto enumConst = dyn_cast<EnumConstantOp>(op)) {
177 auto fieldAttr = enumConst.getField();
178 if (
auto newType =
processType(fieldAttr.getType().getValue()))
179 enumConst.setFieldAttr(
180 EnumFieldAttr::get(op->getLoc(), fieldAttr.getField(), newType));
184 if (
auto modLike = dyn_cast<HWModuleLike>(op))
185 if (
auto newType =
processType(modLike.getHWModuleType()))
186 modLike.setHWModuleType(cast<ModuleType>(newType));
189 for (
auto result : op->getResults())
191 result.setType(newType);
194 for (
auto ®ion : op->getRegions())
195 for (
auto &block : region.getBlocks())
196 for (
auto arg : block.getArguments())
198 arg.setType(newType);
201 enumTypeAliases.clear();
206 DenseMap<Type, Type> enumTypeAliases;
static std::unique_ptr< Context > context
static Type processType(Type type)
create(str sym_name, Type type, str verilog_name=None)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.