Skip to content

Commit d752025

Browse files
authored
Principal Types: Add signature interop (#7777)
1 parent 0ce9157 commit d752025

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

src/ir/principal-type.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,23 @@ bool PrincipalType::compose(const PrincipalType& next) {
10501050
}
10511051

10521052
std::optional<Signature> PrincipalType::getSignature() const {
1053-
WASM_UNREACHABLE("TODO");
1053+
std::vector<Type> sigParams, sigResults;
1054+
for (auto it = rparams.rbegin(); it != rparams.rend(); ++it) {
1055+
auto item = *it;
1056+
if (auto* type = std::get_if<Type>(&item)) {
1057+
sigParams.push_back(*type);
1058+
} else {
1059+
return {};
1060+
}
1061+
}
1062+
for (auto& result : results) {
1063+
if (auto* type = std::get_if<Type>(&result)) {
1064+
sigResults.push_back(*type);
1065+
} else {
1066+
return {};
1067+
}
1068+
}
1069+
return Signature(sigParams, sigResults);
10541070
}
10551071

10561072
std::ostream& operator<<(std::ostream& o, const PrincipalType& type) {

src/ir/principal-type.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ struct PrincipalType {
113113
std::reverse(rparams.begin(), rparams.end());
114114
}
115115

116+
PrincipalType(Signature sig) {
117+
for (auto param : sig.params) {
118+
rparams.push_back(param);
119+
}
120+
std::reverse(rparams.begin(), rparams.end());
121+
for (auto result : sig.results) {
122+
results.push_back(result);
123+
}
124+
}
125+
116126
// Update this type to be the composition of this and `next`.
117127
bool compose(const PrincipalType& next);
118128

test/gtest/principal-type.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,45 @@ TEST(PrincipalTypeTest, UnifyVariables) {
610610
({refE0Foo, refE0Foo}, {refE0Foo}),
611611
({}, {refFoo}));
612612
}
613+
614+
// Signature interop
615+
616+
// Test that round-tripping works of a signature to a principal type.
617+
static void testSignatureRoundTrip(const Signature& sig) {
618+
SCOPED_TRACE("Testing signature: " + sig.toString());
619+
620+
PrincipalType pt(sig);
621+
std::optional<Signature> maybeSig = pt.getSignature();
622+
ASSERT_TRUE(maybeSig.has_value());
623+
EXPECT_EQ(*maybeSig, sig);
624+
}
625+
626+
TEST(PrincipalTypeTest, SignatureRoundTrip) {
627+
testSignatureRoundTrip(Signature(Type::none, Type::none));
628+
testSignatureRoundTrip(Signature({Type::i32, Type::f64}, Type::none));
629+
testSignatureRoundTrip(Signature(Type::none, {Type::i64, Type::f32}));
630+
testSignatureRoundTrip(
631+
Signature({Type::i32, Type::f32}, {Type::i64, Type::f64}));
632+
}
633+
634+
TEST(PrincipalTypeTest, GetSignatureFailure) {
635+
// Failure due to a type variable (Index) in parameters or results.
636+
{
637+
PrincipalType pt({0u}, {});
638+
EXPECT_FALSE(pt.getSignature().has_value());
639+
}
640+
{
641+
PrincipalType pt({}, {0u});
642+
EXPECT_FALSE(pt.getSignature().has_value());
643+
}
644+
645+
// Failure due to a heap type variable (VarRef) in parameters or results.
646+
{
647+
PrincipalType pt({VarRef{NonNullable, {0u}}}, {});
648+
EXPECT_FALSE(pt.getSignature().has_value());
649+
}
650+
{
651+
PrincipalType pt({}, {VarRef{NonNullable, {0u}}});
652+
EXPECT_FALSE(pt.getSignature().has_value());
653+
}
654+
}

0 commit comments

Comments
 (0)