[Moore] Remove enum type

Remove the enum type from the Moore dialect. No passes or lowerings
currently make use of this type, but imemdiately resolve it to its
underlying integer type instead. This simplifies the dialect. Once the
need for an enum type arises again in the future, we can define a new
one.
This commit is contained in:
Fabian Schuiki 2024-05-06 20:45:34 -07:00
parent 2769f6528a
commit a36c258349
No known key found for this signature in database
GPG Key ID: C42F5825FC5275E6
6 changed files with 10 additions and 220 deletions

View File

@ -241,7 +241,6 @@ struct UnsizedDimStorage;
struct RangeDimStorage;
struct SizedDimStorage;
struct AssocDimStorage;
struct EnumTypeStorage;
struct StructTypeStorage;
} // namespace detail
@ -396,7 +395,6 @@ class VoidType;
class IntType;
class PackedIndirectType;
class PackedDim;
class EnumType;
class PackedStructType;
/// A packed SystemVerilog type.
@ -425,7 +423,7 @@ public:
static bool classof(Type type) {
return llvm::isa<VoidType>(type) || llvm::isa<IntType>(type) ||
llvm::isa<PackedIndirectType>(type) || llvm::isa<PackedDim>(type) ||
llvm::isa<EnumType>(type) || llvm::isa<PackedStructType>(type);
llvm::isa<PackedStructType>(type);
}
/// Resolve one level of name or type reference indirection.
@ -994,39 +992,6 @@ protected:
friend struct detail::DimStorage;
};
//===----------------------------------------------------------------------===//
// Enumerations
//===----------------------------------------------------------------------===//
/// An enum type.
class EnumType
: public Type::TypeBase<EnumType, PackedType, detail::EnumTypeStorage> {
public:
static EnumType get(StringAttr name, Location loc, PackedType base = {});
/// Get the base type of the enumeration.
PackedType getBase() const;
/// Returns whether the base type was explicitly specified by the user. This
/// allows us to distinguish `enum` from `enum int`.
bool isBaseExplicit() const;
/// Get the name of the surrounding typedef, if this enum is embedded in a
/// typedef. Otherwise this returns a null attribute.
StringAttr getName() const;
/// Get the location in the source text where the enum was declared. This
/// shall be the location of the `enum` keyword or, if the enum is embedded in
/// a typedef, the location of the typedef name.
Location getLoc() const;
/// Format this enum in SystemVerilog syntax. Useful to present the enum back
/// to the user in diagnostics.
void format(llvm::raw_ostream &os) const;
static constexpr StringLiteral name = "moore.enum";
protected:
using Base::Base;
};
//===----------------------------------------------------------------------===//
// Packed and Unpacked Structs
//===----------------------------------------------------------------------===//

View File

@ -148,11 +148,8 @@ struct TypeVisitor {
// Handle enums.
Type visit(const slang::ast::EnumType &type) {
auto baseType = type.baseType.visit(*this);
if (!baseType)
return {};
return moore::EnumType::get(StringAttr{}, loc,
cast<moore::PackedType>(baseType));
// Simply return the underlying type.
return type.baseType.visit(*this);
}
// Collect the members in a struct or union.

View File

@ -37,7 +37,7 @@ void MooreDialect::registerTypes() {
addTypes<IntType, RealType, PackedNamedType, PackedRefType, UnpackedNamedType,
UnpackedRefType, PackedUnsizedDim, PackedRangeDim,
UnpackedUnsizedDim, UnpackedArrayDim, UnpackedRangeDim,
UnpackedAssocDim, UnpackedQueueDim, EnumType, PackedStructType,
UnpackedAssocDim, UnpackedQueueDim, PackedStructType,
UnpackedStructType>();
addTypes<
@ -260,7 +260,6 @@ Domain PackedType::getDomain() const {
.Case<IntType>([&](auto type) { return type.getDomain(); })
.Case<PackedIndirectType, PackedDim>(
[&](auto type) { return type.getInner().getDomain(); })
.Case<EnumType>([](auto type) { return type.getBase().getDomain(); })
.Case<PackedStructType>(
[](auto type) { return type.getStruct().domain; });
}
@ -271,8 +270,7 @@ Sign PackedType::getSign() const {
.Case<IntType, PackedStructType>(
[&](auto type) { return type.getSign(); })
.Case<PackedIndirectType, PackedDim>(
[&](auto type) { return type.getInner().getSign(); })
.Case<EnumType>([](auto type) { return type.getBase().getSign(); });
[&](auto type) { return type.getInner().getSign(); });
}
std::optional<unsigned> PackedType::getBitSize() const {
@ -287,7 +285,6 @@ std::optional<unsigned> PackedType::getBitSize() const {
})
.Case<PackedIndirectType>(
[](auto type) { return type.getInner().getBitSize(); })
.Case<EnumType>([](auto type) { return type.getBase().getBitSize(); })
.Case<PackedStructType>(
[](auto type) { return type.getStruct().bitSize; });
}
@ -295,8 +292,8 @@ std::optional<unsigned> PackedType::getBitSize() const {
void PackedType::format(llvm::raw_ostream &os) const {
TypeSwitch<PackedType>(*this)
.Case<VoidType>([&](auto) { os << "void"; })
.Case<IntType, PackedRangeDim, PackedUnsizedDim, EnumType,
PackedStructType>([&](auto type) { type.format(os); })
.Case<IntType, PackedRangeDim, PackedUnsizedDim, PackedStructType>(
[&](auto type) { type.format(os); })
.Case<PackedNamedType>(
[&](auto type) { os << type.getName().getValue(); })
.Case<PackedRefType>(
@ -938,66 +935,6 @@ std::optional<unsigned> UnpackedQueueDim::getBound() const {
return bound;
}
//===----------------------------------------------------------------------===//
// Enumerations
//===----------------------------------------------------------------------===//
namespace circt {
namespace moore {
namespace detail {
struct EnumTypeStorage : TypeStorage {
using KeyTy = std::tuple<StringAttr, Location, PackedType, char>;
EnumTypeStorage(KeyTy key)
: name(std::get<0>(key)), loc(std::get<1>(key)), base(std::get<2>(key)),
explicitBase(std::get<3>(key)) {}
bool operator==(const KeyTy &key) const {
return std::get<0>(key) == name && std::get<1>(key) == loc &&
std::get<2>(key) == base && std::get<3>(key) == explicitBase;
}
static EnumTypeStorage *construct(TypeStorageAllocator &allocator,
const KeyTy &key) {
return new (allocator.allocate<EnumTypeStorage>()) EnumTypeStorage(key);
}
StringAttr name;
Location loc;
PackedType base;
bool explicitBase;
};
} // namespace detail
} // namespace moore
} // namespace circt
EnumType EnumType::get(StringAttr name, Location loc, PackedType base) {
return Base::get(loc.getContext(), name, loc,
base ? base : IntType::getInt(loc.getContext()), !!base);
}
PackedType EnumType::getBase() const { return getImpl()->base; }
bool EnumType::isBaseExplicit() const { return getImpl()->explicitBase; }
StringAttr EnumType::getName() const { return getImpl()->name; }
Location EnumType::getLoc() const { return getImpl()->loc; }
void EnumType::format(llvm::raw_ostream &os) const {
os << "enum";
// If the enum is part of a typedefm simply print it as `enum <name>`.
if (auto name = getName()) {
os << " " << name.getValue();
return;
}
// Otherwise print `enum <base-type>` or just `enum`.
if (isBaseExplicit())
os << " " << getBase();
}
//===----------------------------------------------------------------------===//
// Packed and Unpacked Structs
//===----------------------------------------------------------------------===//
@ -1227,31 +1164,6 @@ static OptionalParseResult customTypeParser(DialectAsmParser &parser,
if (auto kind = RealType::getKindFromKeyword(mnemonic))
return yieldUnpacked(RealType::get(context, *kind));
// Enums
if (mnemonic == "enum") {
if (parser.parseLess())
return failure();
StringAttr name;
auto result = parser.parseOptionalAttribute(name);
if (result.has_value())
if (*result || parser.parseComma())
return failure();
LocationAttr loc;
PackedType base;
result = parser.parseOptionalAttribute(loc);
if (result.has_value()) {
if (*result)
return failure();
} else {
if (parseMooreType(parser, {Subset::Packed, false}, base) ||
parser.parseComma() || parser.parseAttribute(loc))
return failure();
}
if (parser.parseGreater())
return failure();
return yieldPacked(EnumType::get(name, loc, base));
}
// Everything that follows can be packed or unpacked. The packing is inferred
// from the last `packed<...>` or `unpacked<...>` that we've seen. The
// `yieldImplied` function will call the first lambda to construct a packed
@ -1441,19 +1353,6 @@ static LogicalResult customTypePrinter(Type type, DialectAsmPrinter &printer,
.Case<RealType>(
[&](auto type) { return printer << type.getKeyword(), success(); })
// Enums
.Case<EnumType>([&](auto type) {
printer << "enum<";
if (type.getName())
printer << type.getName() << ", ";
if (type.isBaseExplicit()) {
printMooreType(type.getBase(), printer, subset);
printer << ", ";
}
printer << type.getLoc() << ">";
return success();
})
// Type indirections
.Case<PackedNamedType, UnpackedNamedType>([&](auto type) {
printer << "named<" << type.getName() << ", ";

View File

@ -8,9 +8,9 @@
module Enums;
typedef enum shortint { MAGIC } myEnum;
// CHECK-NEXT: %e0 = moore.variable : !moore.enum<int, loc(
// CHECK-NEXT: %e1 = moore.variable : !moore.enum<byte, loc(
// CHECK-NEXT: %e2 = moore.variable : !moore.packed<named<"myEnum", enum<shortint, loc(
// CHECK-NEXT: %e0 = moore.variable : !moore.int
// CHECK-NEXT: %e1 = moore.variable : !moore.byte
// CHECK-NEXT: %e2 = moore.variable : !moore.packed<named<"myEnum", shortint, loc(
enum { FOO, BAR } e0;
enum byte { HELLO = 0, WORLD = 1 } e1;
myEnum e2;

View File

@ -80,18 +80,6 @@ func.func @RealTypes(
%arg2: !moore.realtime
) { return }
// CHECK-LABEL: func @EnumType(
func.func @EnumType(
// CHECK-SAME: %arg0: !moore.enum<loc("foo.sv":42:9001)>
// CHECK-SAME: %arg1: !moore.enum<int, loc("foo.sv":42:9001)>
// CHECK-SAME: %arg2: !moore.enum<"Foo", loc("foo.sv":42:9001)>
// CHECK-SAME: %arg3: !moore.enum<"Foo", int, loc("foo.sv":42:9001)>
%arg0: !moore.enum<loc("foo.sv":42:9001)>,
%arg1: !moore.enum<int, loc("foo.sv":42:9001)>,
%arg2: !moore.enum<"Foo", loc("foo.sv":42:9001)>,
%arg3: !moore.enum<"Foo", int, loc("foo.sv":42:9001)>
) { return }
// CHECK-LABEL: func @IndirectTypes(
func.func @IndirectTypes(
// CHECK-SAME: %arg0: !moore.packed<named<"Foo", bit, loc("foo.sv":42:9001)>>

View File

@ -340,65 +340,6 @@ TEST(TypesTest, Structs) {
ASSERT_EQ(s3.getBitSize(), std::nullopt);
}
TEST(TypesTest, Enums) {
MLIRContext context;
context.loadDialect<MooreDialect>();
auto loc = UnknownLoc::get(&context);
auto foo = StringAttr::get(&context, "Foo");
auto intType = IntType::getInt(&context);
auto bitType = IntType::get(&context, IntType::Bit);
auto bit8Type = PackedRangeDim::get(bitType, 8);
auto slogicType = IntType::get(&context, IntType::Logic, Sign::Signed);
auto slogic8Type = PackedRangeDim::get(slogicType, 8);
auto e0 = EnumType::get({}, loc);
auto e1 = EnumType::get(foo, loc);
auto e2 = EnumType::get({}, loc, bit8Type);
auto e3 = EnumType::get(foo, loc, bit8Type);
auto e4 = EnumType::get({}, loc, slogic8Type);
auto e5 = EnumType::get(foo, loc, slogic8Type);
// Formatting
ASSERT_EQ(e0.toString(), "enum");
ASSERT_EQ(e1.toString(), "enum Foo");
ASSERT_EQ(e2.toString(), "enum bit [7:0]");
ASSERT_EQ(e3.toString(), "enum Foo");
ASSERT_EQ(e4.toString(), "enum logic signed [7:0]");
ASSERT_EQ(e5.toString(), "enum Foo");
// Base types
ASSERT_EQ(e0.getBase(), intType);
ASSERT_EQ(e1.getBase(), intType);
ASSERT_EQ(e2.getBase(), bit8Type);
ASSERT_EQ(e3.getBase(), bit8Type);
ASSERT_EQ(e4.getBase(), slogic8Type);
ASSERT_EQ(e5.getBase(), slogic8Type);
// Sign
ASSERT_EQ(e0.getSign(), Sign::Signed); // implicit int
ASSERT_EQ(e1.getSign(), Sign::Signed); // implicit int
ASSERT_EQ(e2.getSign(), Sign::Unsigned);
ASSERT_EQ(e3.getSign(), Sign::Unsigned);
ASSERT_EQ(e4.getSign(), Sign::Signed);
ASSERT_EQ(e5.getSign(), Sign::Signed);
// Value domain
ASSERT_EQ(e0.getDomain(), Domain::TwoValued);
ASSERT_EQ(e1.getDomain(), Domain::TwoValued);
ASSERT_EQ(e2.getDomain(), Domain::TwoValued);
ASSERT_EQ(e3.getDomain(), Domain::TwoValued);
ASSERT_EQ(e4.getDomain(), Domain::FourValued);
ASSERT_EQ(e5.getDomain(), Domain::FourValued);
// Bit size
ASSERT_EQ(e0.getBitSize(), 32u);
ASSERT_EQ(e1.getBitSize(), 32u);
ASSERT_EQ(e2.getBitSize(), 8u);
ASSERT_EQ(e3.getBitSize(), 8u);
ASSERT_EQ(e4.getBitSize(), 8u);
ASSERT_EQ(e5.getBitSize(), 8u);
}
TEST(TypesTest, SimpleBitVectorTypes) {
MLIRContext context;
context.loadDialect<MooreDialect>();