14 #include "../PassDetail.h"
17 #include "mlir/IR/ImplicitLocOpBuilder.h"
18 #include "llvm/ADT/DenseSet.h"
20 using namespace circt;
25 struct LegalizeAnonEnums :
public LegalizeAnonEnumsBase<LegalizeAnonEnums> {
27 TypeScopeOp getTypeScope() {
28 auto topLevel = getOperation();
30 auto builder = OpBuilder::atBlockBegin(&topLevel.getRegion().front());
31 typeScope =
builder.create<TypeScopeOp>(topLevel.getLoc(),
"Enums");
32 typeScope.getBodyRegion().push_back(
new Block());
33 mlir::SymbolTable symbolTable(topLevel);
34 symbolTable.insert(typeScope);
40 Type getEnumTypeDecl(EnumType type) {
41 auto &typeAlias = enumTypeAliases[type];
44 auto *context = &getContext();
46 auto typeScope = getTypeScope();
47 auto builder = OpBuilder::atBlockEnd(&typeScope.getRegion().front());
57 Type processType(Type type) {
58 auto *context = &getContext();
59 if (
auto structType = dyn_cast<StructType>(type)) {
61 SmallVector<StructType::FieldInfo> fields;
62 for (
auto &element : structType.getElements()) {
63 if (
auto newFieldType = processType(element.type)) {
65 fields.push_back({element.name, newFieldType});
67 fields.push_back(element);
75 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
76 if (
auto newElementType = processType(arrayType.getElementType()))
81 if (
auto unionType = dyn_cast<UnionType>(type)) {
83 SmallVector<UnionType::FieldInfo> fields;
84 for (
const auto &element : unionType.getElements()) {
85 if (
auto newFieldType = processType(element.type)) {
86 fields.push_back({element.name, newFieldType, element.offset});
89 fields.push_back(element);
97 if (
auto typeAlias = dyn_cast<TypeAliasType>(type)) {
99 if (isa<EnumType>(typeAlias.getInnerType()))
102 return processType(typeAlias.getInnerType());
105 if (
auto inoutType = dyn_cast<InOutType>(type)) {
106 if (
auto newType = processType(inoutType.getElementType()))
112 if (
auto enumType = dyn_cast<EnumType>(type))
113 return getEnumTypeDecl(enumType);
115 if (
auto funcType = dyn_cast<FunctionType>(type)) {
116 bool changed =
false;
118 for (
auto &type : funcType.getInputs()) {
119 if (
auto newType = processType(type)) {
120 inputs.push_back(newType);
126 SmallVector<Type> results;
127 for (
auto &type : funcType.getResults()) {
128 if (
auto newType = processType(type)) {
129 results.push_back(newType);
132 results.push_back(type);
139 if (
auto modType = dyn_cast<ModuleType>(type)) {
140 bool changed =
false;
141 SmallVector<ModulePort> ports;
142 for (
auto &p : modType.getPorts()) {
144 if (
auto newType = processType(p.type)) {
145 ports.back().type = newType;
158 void runOnOperation()
override {
163 getOperation().walk([&](Operation *op) {
168 if (
auto enumConst = dyn_cast<EnumConstantOp>(op)) {
169 auto fieldAttr = enumConst.getField();
170 if (
auto newType = processType(fieldAttr.getType().getValue()))
171 enumConst.setFieldAttr(
176 if (
auto modLike = dyn_cast<HWModuleLike>(op))
177 if (
auto newType = processType(modLike.getHWModuleType()))
178 modLike.setHWModuleType(cast<ModuleType>(newType));
181 for (
auto result : op->getResults())
182 if (
auto newType = processType(result.getType()))
183 result.setType(newType);
186 for (
auto ®ion : op->getRegions())
187 for (
auto &block : region.getBlocks())
188 for (
auto arg : block.getArguments())
189 if (
auto newType = processType(arg.getType()))
190 arg.setType(newType);
193 enumTypeAliases.clear();
196 TypeScopeOp typeScope;
198 DenseMap<Type, Type> enumTypeAliases;
204 return std::make_unique<LegalizeAnonEnums>();
llvm::SmallVector< StringAttr > inputs
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
std::unique_ptr< mlir::Pass > createLegalizeAnonEnumsPass()