mirror of https://github.com/llvm/circt.git
[ImportVerilog][Moore] Support union type (#7084)
* [ImportVerilog]Support union types. * [ImportVerilog]Rename structMember with structLikeMember * [ImportVerilog] check the type of new Expressions. * [ImportVerilog]Add value check for new Expressions. * clang-format modify recommand * [importVerilog]Remove useless inlcludes * [ImportVerilog]Add union size and domain * [ImportVerilog]Give more specefic errors
This commit is contained in:
parent
55610921c2
commit
00edb48ed5
|
@ -790,7 +790,7 @@ def ExtractOp : MooreOp<"extract"> {
|
|||
$input `from` $lowBit attr-dict `:`
|
||||
type($input) `,` type($lowBit) `->` type($result)
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
def StructCreateOp : MooreOp<"struct_create", [SameOperandsAndResultType]> {
|
||||
let summary = "Struct Create operation";
|
||||
|
@ -817,11 +817,11 @@ def StructCreateOp : MooreOp<"struct_create", [SameOperandsAndResultType]> {
|
|||
```
|
||||
See IEEE 1800-2017 § 7.2. "Structures".
|
||||
}];
|
||||
let arguments = (ins UnpackedType:$structName);
|
||||
let arguments = (ins UnpackedType:$input);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let hasCustomAssemblyFormat = 1;
|
||||
let assemblyFormat = [{
|
||||
$structName attr-dict `:` type($structName)
|
||||
$input attr-dict `:` type($input)
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -853,11 +853,12 @@ def StructExtractOp : MooreOp<"struct_extract"> {
|
|||
```
|
||||
See IEEE 1800-2017 § 7.2.1 "Assigning to structures".
|
||||
}];
|
||||
let arguments = (ins StrAttr:$memberName, UnpackedType:$structName);
|
||||
let arguments = (ins StrAttr:$memberName, UnpackedType:$input);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
$structName `,` $memberName attr-dict `:`
|
||||
type($structName) `->` type($result)
|
||||
$input `,` $memberName attr-dict `:`
|
||||
type($input) `->`
|
||||
type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -894,4 +895,67 @@ def StructInjectOp : MooreOp<"struct_inject"> {
|
|||
}];
|
||||
}
|
||||
|
||||
def UnionCreateOp : MooreOp<"union_create"> {
|
||||
let summary = "Union Create operation";
|
||||
let description = [{
|
||||
A union is a data type that represents a single piece
|
||||
of storage that can be accessed using one of
|
||||
the named member data types. Only one of the
|
||||
data types in the union can be used at a time.
|
||||
By default, a union is unpacked, meaning there
|
||||
is no required representation for how members
|
||||
of the union are stored. Dynamic types and chandle
|
||||
types can only be used in tagged unions.
|
||||
See IEEE 1800-2017 § 7.3 "Unions"
|
||||
|
||||
Example:
|
||||
```
|
||||
typedef union { int i; shortreal f; } num; // named union type
|
||||
num n;
|
||||
n.f = 0.0; // set n in floating point format
|
||||
typedef struct {
|
||||
bit isfloat;
|
||||
union { int i; shortreal f; } n; // anonymous union type
|
||||
} tagged_st; // named structure
|
||||
```
|
||||
See IEEE 1800-2017 § 7.3 "Unions"
|
||||
}];
|
||||
let arguments = (ins StrAttr:$unionName, UnpackedType:$input);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
$unionName `,` $input attr-dict `:`
|
||||
type($input) `->` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
def UnionExtractOp : MooreOp<"union_extract"> {
|
||||
let summary = "Union Extract operation";
|
||||
let description = [{
|
||||
With packed unions, writing one member and reading another is
|
||||
independent of the byte ordering of the machine,
|
||||
unlike an unpacked union of unpacked structures,
|
||||
which are C-compatible and have members in ascending address order.
|
||||
See IEEE 1800-2017 § 7.3.1 "Packed unions"
|
||||
|
||||
Example:
|
||||
```
|
||||
typedef union packed { // default unsigned
|
||||
s_atmcell acell;
|
||||
bit [423:0] bit_slice;
|
||||
bit [52:0][7:0] byte_slice;
|
||||
} u_atmcell;
|
||||
u_atmcell u1;
|
||||
byte b; bit [3:0] nib;
|
||||
b = u1.bit_slice[415:408]; // same as b = u1.byte_slice[51];
|
||||
nib = u1.bit_slice [423:420];
|
||||
```
|
||||
See IEEE 1800-2017 § 7.3.1 "Packed unions"
|
||||
}];
|
||||
let arguments = (ins StrAttr:$memberName, UnpackedType:$input);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
$input `,` $memberName attr-dict `:`
|
||||
type($input) `->` type($result)
|
||||
}];
|
||||
}
|
||||
#endif // CIRCT_DIALECT_MOORE_MOOREOPS
|
||||
|
|
|
@ -35,9 +35,11 @@ class QueueType;
|
|||
class RealType;
|
||||
class StringType;
|
||||
class StructType;
|
||||
class UnionType;
|
||||
class UnpackedType;
|
||||
class UnpackedArrayType;
|
||||
class UnpackedStructType;
|
||||
class UnpackedUnionType;
|
||||
class VoidType;
|
||||
|
||||
/// The number of values each bit of a type can assume.
|
||||
|
@ -81,7 +83,7 @@ public:
|
|||
static bool classof(Type type) {
|
||||
return llvm::isa<PackedType, StringType, ChandleType, EventType, RealType,
|
||||
UnpackedArrayType, OpenUnpackedArrayType, AssocArrayType,
|
||||
QueueType, UnpackedStructType>(type);
|
||||
QueueType, UnpackedStructType, UnpackedUnionType>(type);
|
||||
}
|
||||
|
||||
/// Get the value domain of this type.
|
||||
|
@ -130,8 +132,8 @@ protected:
|
|||
class PackedType : public UnpackedType {
|
||||
public:
|
||||
static bool classof(Type type) {
|
||||
return llvm::isa<VoidType, IntType, ArrayType, OpenArrayType, StructType>(
|
||||
type);
|
||||
return llvm::isa<VoidType, IntType, ArrayType, OpenArrayType, StructType,
|
||||
UnionType>(type);
|
||||
}
|
||||
|
||||
/// Get the value domain of this type.
|
||||
|
@ -151,19 +153,19 @@ protected:
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// A member of a struct.
|
||||
struct StructMember {
|
||||
struct StructLikeMember {
|
||||
/// The name of this member.
|
||||
StringAttr name;
|
||||
/// The type of this member.
|
||||
UnpackedType type;
|
||||
|
||||
bool operator==(const StructMember &other) const {
|
||||
bool operator==(const StructLikeMember &other) const {
|
||||
return name == other.name && type == other.type;
|
||||
}
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
inline llvm::hash_code hash_value(const StructMember &x) {
|
||||
inline llvm::hash_code hash_value(const StructLikeMember &x) {
|
||||
return llvm::hash_combine(x.name, x.type);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ def QueueType : MooreTypeDef<"Queue", [], "moore::UnpackedType"> {
|
|||
class StructLikeType<
|
||||
string name, list<Trait> traits = [], string baseCppClass = "::mlir::Type"
|
||||
> : MooreTypeDef<name, traits, baseCppClass> {
|
||||
let parameters = (ins ArrayRefParameter<"StructMember">:$members);
|
||||
let parameters = (ins ArrayRefParameter<"StructLikeMember">:$members);
|
||||
let assemblyFormat = [{
|
||||
`<` custom<Members>($members) `>`
|
||||
}];
|
||||
|
@ -305,6 +305,25 @@ def UnpackedStructType : StructLikeType<
|
|||
}];
|
||||
}
|
||||
|
||||
def UnionType : StructLikeType<"Union", [], "moore::PackedType"> {
|
||||
let mnemonic = "union";
|
||||
let summary = "a packed union type";
|
||||
let description = [{
|
||||
A packed union. All members are guaranteed to be packed as well.
|
||||
}];
|
||||
let genVerifyDecl = 1;
|
||||
}
|
||||
|
||||
|
||||
def UnpackedUnionType : StructLikeType<
|
||||
"UnpackedUnion", [], "moore::UnpackedType"
|
||||
> {
|
||||
let mnemonic = "uunion";
|
||||
let summary = "an unpacked union type";
|
||||
let description = [{
|
||||
An unpacked union.
|
||||
}];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Constraints
|
||||
|
|
|
@ -429,10 +429,20 @@ struct ExprVisitor {
|
|||
}
|
||||
|
||||
Value visit(const slang::ast::MemberAccessExpression &expr) {
|
||||
return builder.create<moore::StructExtractOp>(
|
||||
loc, context.convertType(*expr.type),
|
||||
builder.getStringAttr(expr.member.name),
|
||||
context.convertExpression(expr.value()));
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto valueType = expr.value().type;
|
||||
auto value = context.convertExpression(expr.value());
|
||||
if (!type || !value)
|
||||
return {};
|
||||
if (valueType->isStruct()) {
|
||||
return builder.create<moore::StructExtractOp>(
|
||||
loc, type, builder.getStringAttr(expr.member.name), value);
|
||||
}
|
||||
if (valueType->isPackedUnion() || valueType->isUnpackedUnion()) {
|
||||
return builder.create<moore::UnionExtractOp>(
|
||||
loc, type, builder.getStringAttr(expr.member.name), value);
|
||||
}
|
||||
llvm_unreachable("unsupported symbol kind");
|
||||
}
|
||||
|
||||
// Handle set membership operator.
|
||||
|
|
|
@ -101,8 +101,9 @@ struct TypeVisitor {
|
|||
}
|
||||
|
||||
// Collect the members in a struct or union.
|
||||
LogicalResult collectMembers(const slang::ast::Scope &structType,
|
||||
SmallVectorImpl<moore::StructMember> &members) {
|
||||
LogicalResult
|
||||
collectMembers(const slang::ast::Scope &structType,
|
||||
SmallVectorImpl<moore::StructLikeMember> &members) {
|
||||
for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
|
||||
auto name = StringAttr::get(context.getContext(), field.name);
|
||||
auto innerType = context.convertType(*field.getDeclaredType());
|
||||
|
@ -115,19 +116,33 @@ struct TypeVisitor {
|
|||
|
||||
// Handle packed and unpacked structs.
|
||||
Type visit(const slang::ast::PackedStructType &type) {
|
||||
SmallVector<moore::StructMember> members;
|
||||
SmallVector<moore::StructLikeMember> members;
|
||||
if (failed(collectMembers(type, members)))
|
||||
return {};
|
||||
return moore::StructType::get(context.getContext(), members);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::UnpackedStructType &type) {
|
||||
SmallVector<moore::StructMember> members;
|
||||
SmallVector<moore::StructLikeMember> members;
|
||||
if (failed(collectMembers(type, members)))
|
||||
return {};
|
||||
return moore::UnpackedStructType::get(context.getContext(), members);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::PackedUnionType &type) {
|
||||
SmallVector<moore::StructLikeMember> members;
|
||||
if (failed(collectMembers(type, members)))
|
||||
return {};
|
||||
return moore::UnionType::get(context.getContext(), members);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::UnpackedUnionType &type) {
|
||||
SmallVector<moore::StructLikeMember> members;
|
||||
if (failed(collectMembers(type, members)))
|
||||
return {};
|
||||
return moore::UnpackedUnionType::get(context.getContext(), members);
|
||||
}
|
||||
|
||||
/// Emit an error for all other types.
|
||||
template <typename T>
|
||||
Type visit(T &&node) {
|
||||
|
|
|
@ -22,8 +22,9 @@ using mlir::AsmParser;
|
|||
using mlir::AsmPrinter;
|
||||
|
||||
static LogicalResult parseMembers(AsmParser &parser,
|
||||
SmallVector<StructMember> &members);
|
||||
static void printMembers(AsmPrinter &printer, ArrayRef<StructMember> members);
|
||||
SmallVector<StructLikeMember> &members);
|
||||
static void printMembers(AsmPrinter &printer,
|
||||
ArrayRef<StructLikeMember> members);
|
||||
|
||||
static ParseResult parseMooreType(AsmParser &parser, Type &type);
|
||||
static void printMooreType(Type type, AsmPrinter &printer);
|
||||
|
@ -38,7 +39,7 @@ Domain UnpackedType::getDomain() const {
|
|||
.Case<UnpackedArrayType, OpenUnpackedArrayType, AssocArrayType,
|
||||
QueueType>(
|
||||
[&](auto type) { return type.getElementType().getDomain(); })
|
||||
.Case<UnpackedStructType>([](auto type) {
|
||||
.Case<UnpackedStructType, UnpackedUnionType>([](auto type) {
|
||||
for (const auto &member : type.getMembers())
|
||||
if (member.type.getDomain() == Domain::FourValued)
|
||||
return Domain::FourValued;
|
||||
|
@ -67,6 +68,17 @@ std::optional<unsigned> UnpackedType::getBitSize() const {
|
|||
}
|
||||
return size;
|
||||
})
|
||||
.Case<UnpackedUnionType>([](auto type) -> std::optional<unsigned> {
|
||||
unsigned size = 0;
|
||||
for (const auto &member : type.getMembers()) {
|
||||
if (auto memberSize = member.type.getBitSize()) {
|
||||
size = (*memberSize > size) ? *memberSize : size;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
})
|
||||
.Default([](auto) { return std::nullopt; });
|
||||
}
|
||||
|
||||
|
@ -91,7 +103,7 @@ Domain PackedType::getDomain() const {
|
|||
.Case<IntType>([&](auto type) { return type.getDomain(); })
|
||||
.Case<ArrayType, OpenArrayType>(
|
||||
[&](auto type) { return type.getElementType().getDomain(); })
|
||||
.Case<StructType>([](auto type) {
|
||||
.Case<StructType, UnionType>([](auto type) {
|
||||
for (const auto &member : type.getMembers())
|
||||
if (member.type.getDomain() == Domain::FourValued)
|
||||
return Domain::FourValued;
|
||||
|
@ -119,7 +131,19 @@ std::optional<unsigned> PackedType::getBitSize() const {
|
|||
}
|
||||
}
|
||||
return size;
|
||||
});
|
||||
})
|
||||
.Case<UnionType>([](auto type) -> std::optional<unsigned> {
|
||||
unsigned size = 0;
|
||||
for (const auto &member : type.getMembers()) {
|
||||
if (auto memberSize = member.type.getBitSize()) {
|
||||
size = (*memberSize > size) ? *memberSize : size;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
})
|
||||
.Default([](auto) { return std::nullopt; });
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -128,7 +152,7 @@ std::optional<unsigned> PackedType::getBitSize() const {
|
|||
|
||||
/// Parse a list of struct members.
|
||||
static LogicalResult parseMembers(AsmParser &parser,
|
||||
SmallVector<StructMember> &members) {
|
||||
SmallVector<StructLikeMember> &members) {
|
||||
return parser.parseCommaSeparatedList(AsmParser::Delimiter::Braces, [&]() {
|
||||
std::string name;
|
||||
UnpackedType type;
|
||||
|
@ -142,10 +166,11 @@ static LogicalResult parseMembers(AsmParser &parser,
|
|||
}
|
||||
|
||||
/// Print a list of struct members.
|
||||
static void printMembers(AsmPrinter &printer, ArrayRef<StructMember> members) {
|
||||
static void printMembers(AsmPrinter &printer,
|
||||
ArrayRef<StructLikeMember> members) {
|
||||
printer << "{";
|
||||
llvm::interleaveComma(members, printer.getStream(),
|
||||
[&](const StructMember &member) {
|
||||
[&](const StructLikeMember &member) {
|
||||
printer.printKeywordOrString(member.name);
|
||||
printer << ": ";
|
||||
printer.printStrippedAttrOrType(member.type);
|
||||
|
@ -153,15 +178,26 @@ static void printMembers(AsmPrinter &printer, ArrayRef<StructMember> members) {
|
|||
printer << "}";
|
||||
}
|
||||
|
||||
LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
|
||||
ArrayRef<StructMember> members) {
|
||||
static LogicalResult
|
||||
verifyAllMembersPacked(function_ref<InFlightDiagnostic()> emitError,
|
||||
ArrayRef<StructLikeMember> members) {
|
||||
if (!llvm::all_of(members, [](const auto &member) {
|
||||
return llvm::isa<PackedType>(member.type);
|
||||
}))
|
||||
return emitError() << "StructType members must be packed types";
|
||||
return emitError() << "StructType/UnionType members must be packed types";
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
|
||||
ArrayRef<StructLikeMember> members) {
|
||||
return verifyAllMembersPacked(emitError, members);
|
||||
}
|
||||
|
||||
LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
|
||||
ArrayRef<StructLikeMember> members) {
|
||||
return verifyAllMembersPacked(emitError, members);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Generated logic
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -122,7 +122,7 @@ module Statements;
|
|||
automatic int a;
|
||||
// CHECK moore.blocking_assign %i, %a : i32
|
||||
i = a;
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Conditional statements
|
||||
|
||||
|
@ -321,6 +321,16 @@ module Expressions;
|
|||
int a, b;
|
||||
} c, d;
|
||||
} struct1;
|
||||
// CHECK: %union0 = moore.variable : union<{a: i32, b: i32}>
|
||||
union packed {
|
||||
int a, b;
|
||||
} union0;
|
||||
// CHECK: %union1 = moore.variable : union<{c: union<{a: i32, b: i32}>, d: union<{a: i32, b: i32}>}>
|
||||
union packed {
|
||||
union packed {
|
||||
int a, b;
|
||||
} c, d;
|
||||
} union1;
|
||||
|
||||
initial begin
|
||||
// CHECK: moore.constant 0 : i32
|
||||
|
@ -660,6 +670,24 @@ module Expressions;
|
|||
// CHECK: [[TMP2:%.+]] = moore.struct_extract [[TMP1]], "b" : struct<{a: i32, b: i32}> -> i32
|
||||
// CHECK: moore.blocking_assign %b, [[TMP2]] : i32
|
||||
b = struct1.d.b;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.union_extract %union0, "a" : union<{a: i32, b: i32}> -> i32
|
||||
// CHECK: moore.blocking_assign [[TMP]], %a : i32
|
||||
union0.a = a;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.union_extract %union0, "b" : union<{a: i32, b: i32}> -> i32
|
||||
// CHECK: moore.blocking_assign %b, [[TMP]] : i32
|
||||
b = union0.b;
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.union_extract %union1, "c" : union<{c: union<{a: i32, b: i32}>, d: union<{a: i32, b: i32}>}> -> union<{a: i32, b: i32}>
|
||||
// CHECK: [[TMP2:%.+]] = moore.union_extract [[TMP1]], "a" : union<{a: i32, b: i32}> -> i32
|
||||
// CHECK: moore.blocking_assign [[TMP2]], %a : i32
|
||||
union1.c.a = a;
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.union_extract %union1, "d" : union<{c: union<{a: i32, b: i32}>, d: union<{a: i32, b: i32}>}> -> union<{a: i32, b: i32}>
|
||||
// CHECK: [[TMP2:%.+]] = moore.union_extract [[TMP1]], "b" : union<{a: i32, b: i32}> -> i32
|
||||
// CHECK: moore.blocking_assign %b, [[TMP2]] : i32
|
||||
b = union1.d.b;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
module Foo;
|
||||
// expected-error @below {{unsupported type}}
|
||||
// expected-note @below {{}}
|
||||
union { bit a; logic b; } x;
|
||||
event notDone;
|
||||
endmodule
|
||||
|
|
|
@ -11,5 +11,9 @@ unrealized_conversion_cast to !moore.array<4 x string>
|
|||
unrealized_conversion_cast to !moore.open_array<string>
|
||||
|
||||
// -----
|
||||
// expected-error @below {{StructType members must be packed types}}
|
||||
// expected-error @below {{StructType/UnionType members must be packed types}}
|
||||
unrealized_conversion_cast to !moore.struct<{foo: string}>
|
||||
|
||||
// -----
|
||||
// expected-error @below {{StructType/UnionType members must be packed types}}
|
||||
unrealized_conversion_cast to !moore.union<{foo: string}>
|
||||
|
|
|
@ -131,14 +131,14 @@ TEST(TypesTest, Structs) {
|
|||
auto bit8Type = IntType::getInt(&context, 8);
|
||||
auto bitDynArrayType = OpenUnpackedArrayType::get(bitType);
|
||||
|
||||
auto s0 = StructType::get(&context, {StructMember{foo, bitType}});
|
||||
auto s1 = StructType::get(
|
||||
&context, {StructMember{foo, bitType}, StructMember{bar, bit8Type}});
|
||||
auto s2 = StructType::get(
|
||||
&context, {StructMember{foo, bitType}, StructMember{bar, logicType}});
|
||||
auto s3 =
|
||||
UnpackedStructType::get(&context, {StructMember{foo, bitType},
|
||||
StructMember{bar, bitDynArrayType}});
|
||||
auto s0 = StructType::get(&context, {StructLikeMember{foo, bitType}});
|
||||
auto s1 = StructType::get(&context, {StructLikeMember{foo, bitType},
|
||||
StructLikeMember{bar, bit8Type}});
|
||||
auto s2 = StructType::get(&context, {StructLikeMember{foo, bitType},
|
||||
StructLikeMember{bar, logicType}});
|
||||
auto s3 = UnpackedStructType::get(
|
||||
&context,
|
||||
{StructLikeMember{foo, bitType}, StructLikeMember{bar, bitDynArrayType}});
|
||||
|
||||
// Value domain
|
||||
ASSERT_EQ(s0.getDomain(), Domain::TwoValued);
|
||||
|
@ -151,6 +151,27 @@ TEST(TypesTest, Structs) {
|
|||
ASSERT_EQ(s1.getBitSize(), 9u);
|
||||
ASSERT_EQ(s2.getBitSize(), 2u);
|
||||
ASSERT_EQ(s3.getBitSize(), std::nullopt);
|
||||
|
||||
auto u0 = UnionType::get(&context, {StructLikeMember{foo, bitType}});
|
||||
auto u1 = UnionType::get(&context, {StructLikeMember{foo, bitType},
|
||||
StructLikeMember{bar, bit8Type}});
|
||||
auto u2 = UnionType::get(&context, {StructLikeMember{foo, bitType},
|
||||
StructLikeMember{bar, logicType}});
|
||||
auto u3 = UnpackedUnionType::get(
|
||||
&context,
|
||||
{StructLikeMember{foo, bitType}, StructLikeMember{bar, bitDynArrayType}});
|
||||
|
||||
// Value domain
|
||||
ASSERT_EQ(u0.getDomain(), Domain::TwoValued);
|
||||
ASSERT_EQ(u1.getDomain(), Domain::TwoValued);
|
||||
ASSERT_EQ(u2.getDomain(), Domain::FourValued);
|
||||
ASSERT_EQ(u3.getDomain(), Domain::TwoValued);
|
||||
|
||||
// Bit size
|
||||
ASSERT_EQ(u0.getBitSize(), 1u);
|
||||
ASSERT_EQ(u1.getBitSize(), 8u);
|
||||
ASSERT_EQ(u2.getBitSize(), 1u);
|
||||
ASSERT_EQ(u3.getBitSize(), std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue