|
|
@@ -31,14 +31,17 @@ namespace {
|
|
|
static_assert(Name::Kind == InstKind::Name);
|
|
|
#include "toolchain/sem_ir/inst_kind.def"
|
|
|
|
|
|
-template <typename TypedInst>
|
|
|
-auto CommonFieldOrder() -> void {
|
|
|
- Inst inst = InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1),
|
|
|
- TypeId(2), 3, 4);
|
|
|
- EXPECT_EQ(inst.kind(), TypedInst::Kind);
|
|
|
+auto MakeInstWithNumberedFields(InstKind kind) -> Inst {
|
|
|
+ Inst inst = InstTestHelper::MakeInst(kind, Parse::Node(1), TypeId(2), 3, 4);
|
|
|
+ EXPECT_EQ(inst.kind(), kind);
|
|
|
EXPECT_EQ(inst.parse_node(), Parse::Node(1));
|
|
|
EXPECT_EQ(inst.type_id(), TypeId(2));
|
|
|
+ return inst;
|
|
|
+}
|
|
|
|
|
|
+template <typename TypedInst>
|
|
|
+auto CommonFieldOrder() -> void {
|
|
|
+ Inst inst = MakeInstWithNumberedFields(TypedInst::Kind);
|
|
|
TypedInst typed = inst.As<TypedInst>();
|
|
|
if constexpr (HasParseNode<TypedInst>) {
|
|
|
EXPECT_EQ(typed.parse_node, Parse::Node(1));
|
|
|
@@ -57,24 +60,24 @@ TEST(TypedInstTest, CommonFieldOrder) {
|
|
|
#include "toolchain/sem_ir/inst_kind.def"
|
|
|
}
|
|
|
|
|
|
-template <typename TypedInst>
|
|
|
-auto RoundTrip() -> void {
|
|
|
- Inst inst1 = InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1),
|
|
|
- TypeId(2), 3, 4);
|
|
|
- EXPECT_EQ(inst1.kind(), TypedInst::Kind);
|
|
|
- EXPECT_EQ(inst1.parse_node(), Parse::Node(1));
|
|
|
- EXPECT_EQ(inst1.type_id(), TypeId(2));
|
|
|
-
|
|
|
- TypedInst typed1 = inst1.As<TypedInst>();
|
|
|
- Inst inst2 = typed1;
|
|
|
-
|
|
|
+auto ExpectEqInsts(const Inst& inst1, const Inst& inst2,
|
|
|
+ bool compare_parse_node, bool compare_type_id) -> void {
|
|
|
EXPECT_EQ(inst1.kind(), inst2.kind());
|
|
|
- if constexpr (HasParseNode<TypedInst>) {
|
|
|
+ if (compare_parse_node) {
|
|
|
EXPECT_EQ(inst1.parse_node(), inst2.parse_node());
|
|
|
}
|
|
|
- if constexpr (HasTypeId<TypedInst>) {
|
|
|
+ if (compare_type_id) {
|
|
|
EXPECT_EQ(inst1.type_id(), inst2.type_id());
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+template <typename TypedInst>
|
|
|
+auto RoundTrip() -> void {
|
|
|
+ Inst inst1 = MakeInstWithNumberedFields(TypedInst::Kind);
|
|
|
+ TypedInst typed1 = inst1.As<TypedInst>();
|
|
|
+ Inst inst2 = typed1;
|
|
|
+
|
|
|
+ ExpectEqInsts(inst1, inst2, HasParseNode<TypedInst>, HasTypeId<TypedInst>);
|
|
|
|
|
|
// If the typed instruction has no padding, we should get exactly the same
|
|
|
// thing if we convert back from an instruction.
|
|
|
@@ -87,9 +90,7 @@ auto RoundTrip() -> void {
|
|
|
// because the fields not carried by the typed instruction are lost. But they
|
|
|
// should be stable if we round-trip again.
|
|
|
Inst inst3 = typed2;
|
|
|
- if constexpr (std::has_unique_object_representations_v<Inst>) {
|
|
|
- EXPECT_EQ(std::memcmp(&inst2, &inst3, sizeof(Inst)), 0);
|
|
|
- }
|
|
|
+ ExpectEqInsts(inst2, inst3, true, true);
|
|
|
}
|
|
|
|
|
|
TEST(TypedInstTest, RoundTrip) {
|
|
|
@@ -101,31 +102,35 @@ TEST(TypedInstTest, RoundTrip) {
|
|
|
#include "toolchain/sem_ir/inst_kind.def"
|
|
|
}
|
|
|
|
|
|
-template <typename TypedInst>
|
|
|
-auto StructLayout() -> void {
|
|
|
- TypedInst typed =
|
|
|
- InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1), TypeId(2), 3, 4)
|
|
|
- .template As<TypedInst>();
|
|
|
-
|
|
|
+auto StructLayoutHelper(void* typed_inst, std::size_t typed_inst_size,
|
|
|
+ bool has_parse_node, bool has_type_id) -> void {
|
|
|
// Check that the memory representation of the typed instruction is what we
|
|
|
// expect.
|
|
|
// TODO: Struct layout is not guaranteed, and this test could fail in some
|
|
|
// build environment. If so, we should disable it.
|
|
|
int32_t fields[4] = {};
|
|
|
int field = 0;
|
|
|
- if constexpr (HasParseNode<TypedInst>) {
|
|
|
+ if (has_parse_node) {
|
|
|
fields[field++] = 1;
|
|
|
}
|
|
|
- if constexpr (HasTypeId<TypedInst>) {
|
|
|
+ if (has_type_id) {
|
|
|
fields[field++] = 2;
|
|
|
}
|
|
|
fields[field++] = 3;
|
|
|
fields[field++] = 4;
|
|
|
|
|
|
- ASSERT_LE(sizeof(TypedInst), sizeof(fields));
|
|
|
+ ASSERT_LE(typed_inst_size, sizeof(int32_t) * field);
|
|
|
+ EXPECT_EQ(std::memcmp(&fields, typed_inst, typed_inst_size), 0);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename TypedInst>
|
|
|
+auto StructLayout() -> void {
|
|
|
// We can only do this check if the typed instruction has no padding.
|
|
|
if constexpr (std::has_unique_object_representations_v<TypedInst>) {
|
|
|
- EXPECT_EQ(std::memcmp(&fields, &typed, sizeof(TypedInst)), 0);
|
|
|
+ TypedInst typed =
|
|
|
+ MakeInstWithNumberedFields(TypedInst::Kind).template As<TypedInst>();
|
|
|
+ StructLayoutHelper(&typed, sizeof(typed), HasParseNode<TypedInst>,
|
|
|
+ HasTypeId<TypedInst>);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -138,22 +143,20 @@ TEST(TypedInstTest, StructLayout) {
|
|
|
#include "toolchain/sem_ir/inst_kind.def"
|
|
|
}
|
|
|
|
|
|
-template <typename TypedInst>
|
|
|
-auto InstKindMatches() {
|
|
|
- // TypedInst::Kind is an InstKind::Definition that extends InstKind, but
|
|
|
- // has different definitions of the `ir_name()` and `terminator_kind()`
|
|
|
- // methods. Here we test that values returned by the two different versions
|
|
|
- // of those functions match.
|
|
|
- InstKind as_kind = TypedInst::Kind;
|
|
|
- EXPECT_EQ(TypedInst::Kind.ir_name(), as_kind.ir_name());
|
|
|
- EXPECT_EQ(TypedInst::Kind.terminator_kind(), as_kind.terminator_kind());
|
|
|
+auto InstKindMatches(const InstKind::Definition& def, InstKind kind) {
|
|
|
+ EXPECT_EQ(def.ir_name(), kind.ir_name());
|
|
|
+ EXPECT_EQ(def.terminator_kind(), kind.terminator_kind());
|
|
|
}
|
|
|
|
|
|
TEST(TypedInstTest, InstKindMatches) {
|
|
|
-#define CARBON_SEM_IR_INST_KIND(Name) \
|
|
|
- { \
|
|
|
- SCOPED_TRACE(#Name); \
|
|
|
- InstKindMatches<Name>(); \
|
|
|
+ // TypedInst::Kind is an InstKind::Definition that extends InstKind, but has
|
|
|
+ // different definitions of the `ir_name()` and `terminator_kind()` methods.
|
|
|
+ // Here we test that values returned by the two different versions of those
|
|
|
+ // functions match.
|
|
|
+#define CARBON_SEM_IR_INST_KIND(Name) \
|
|
|
+ { \
|
|
|
+ SCOPED_TRACE(#Name); \
|
|
|
+ InstKindMatches(Name::Kind, Name::Kind); \
|
|
|
}
|
|
|
#include "toolchain/sem_ir/inst_kind.def"
|
|
|
}
|