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"
25 using namespace circt;
30 struct LegalizeAnonEnums
31 :
public circt::impl::LegalizeAnonEnumsBase<LegalizeAnonEnums> {
34 auto topLevel = getOperation();
36 auto builder = OpBuilder::atBlockBegin(&topLevel.getRegion().front());
37 typeScope = builder.create<
TypeScopeOp>(topLevel.getLoc(),
"Enums");
38 typeScope.getBodyRegion().push_back(
new Block());
39 mlir::SymbolTable symbolTable(topLevel);
40 symbolTable.insert(typeScope);
46 Type getEnumTypeDecl(EnumType type) {
47 auto &typeAlias = enumTypeAliases[type];
50 auto *context = &getContext();
52 auto typeScope = getTypeScope();
53 auto builder = OpBuilder::atBlockEnd(&typeScope.getRegion().front());
64 auto *context = &getContext();
65 if (
auto structType = dyn_cast<StructType>(type)) {
67 SmallVector<StructType::FieldInfo> fields;
68 for (
auto &element : structType.getElements()) {
69 if (
auto newFieldType =
processType(element.type)) {
71 fields.push_back({element.name, newFieldType});
73 fields.push_back(element);
81 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
82 if (
auto newElementType =
processType(arrayType.getElementType()))
87 if (
auto unionType = dyn_cast<UnionType>(type)) {
89 SmallVector<UnionType::FieldInfo> fields;
90 for (
const auto &element : unionType.getElements()) {
91 if (
auto newFieldType =
processType(element.type)) {
92 fields.push_back({element.name, newFieldType, element.offset});
95 fields.push_back(element);
103 if (
auto typeAlias = dyn_cast<TypeAliasType>(type)) {
105 if (isa<EnumType>(typeAlias.getInnerType()))
111 if (
auto inoutType = dyn_cast<InOutType>(type)) {
112 if (
auto newType =
processType(inoutType.getElementType()))
118 if (
auto enumType = dyn_cast<EnumType>(type))
119 return getEnumTypeDecl(enumType);
121 if (
auto funcType = dyn_cast<FunctionType>(type)) {
122 bool changed =
false;
123 SmallVector<Type> inputs;
124 for (
auto &type : funcType.getInputs()) {
126 inputs.push_back(newType);
129 inputs.push_back(type);
132 SmallVector<Type> results;
133 for (
auto &type : funcType.getResults()) {
135 results.push_back(newType);
138 results.push_back(type);
145 if (
auto modType = dyn_cast<ModuleType>(type)) {
146 bool changed =
false;
147 SmallVector<ModulePort> ports;
148 for (
auto &p : modType.getPorts()) {
151 ports.back().type = newType;
164 void runOnOperation()
override {
169 getOperation().walk([&](Operation *op) {
174 if (
auto enumConst = dyn_cast<EnumConstantOp>(op)) {
175 auto fieldAttr = enumConst.getField();
176 if (
auto newType =
processType(fieldAttr.getType().getValue()))
177 enumConst.setFieldAttr(
182 if (
auto modLike = dyn_cast<HWModuleLike>(op))
183 if (
auto newType =
processType(modLike.getHWModuleType()))
184 modLike.setHWModuleType(cast<ModuleType>(newType));
187 for (
auto result : op->getResults())
189 result.setType(newType);
192 for (
auto ®ion : op->getRegions())
193 for (
auto &block : region.getBlocks())
194 for (
auto arg : block.getArguments())
196 arg.setType(newType);
199 enumTypeAliases.clear();
204 DenseMap<Type, Type> enumTypeAliases;
210 return std::make_unique<LegalizeAnonEnums>();
static Type processType(Type type)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createLegalizeAnonEnumsPass()