summaryrefslogtreecommitdiff
path: root/src/ir/possible-contents.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-10-11 13:41:49 -0700
committerGitHub <noreply@github.com>2022-10-11 20:41:49 +0000
commit5129f8894bc8f197864a8f136cab191a2c9ea741 (patch)
tree6890e918b638b944b8274980f6939de29efd03f2 /src/ir/possible-contents.h
parentebe30fd682535e43e54d4a76f3ff5f09a6340d3a (diff)
downloadbinaryen-5129f8894bc8f197864a8f136cab191a2c9ea741.tar.gz
binaryen-5129f8894bc8f197864a8f136cab191a2c9ea741.tar.bz2
binaryen-5129f8894bc8f197864a8f136cab191a2c9ea741.zip
[Wasm GC] [GUFA] Add initial ConeType support (#5116)
A cone type is a PossibleContents that has a base type and a depth, and it contains all subtypes up to that depth. So depth 0 is an exact type from before, etc. This only adds cone type computations when combining types, that is, when we combine two exact types we might get a cone, etc. This does not yet use the cone info in all places (like struct gets and sets), and it does not yet define roots of cone types, all of which is left for later. IOW this is the MVP of cone types that is just enough to add them + pass tests + test the new functionality.
Diffstat (limited to 'src/ir/possible-contents.h')
-rw-r--r--src/ir/possible-contents.h55
1 files changed, 54 insertions, 1 deletions
diff --git a/src/ir/possible-contents.h b/src/ir/possible-contents.h
index a6a27062a..ee817deae 100644
--- a/src/ir/possible-contents.h
+++ b/src/ir/possible-contents.h
@@ -50,6 +50,7 @@ namespace wasm {
// then only the exact type is possible; if the depth is 1
// then either that type or its immediate subtypes, and so
// forth.
+// A depth of -1 means unlimited: all subtypes are allowed.
// If the type here is nullable then null is also allowed.
// TODO: Add ConeTypePlusContents or such, which would be
// used on e.g. a struct.new with an immutable field
@@ -96,6 +97,12 @@ class PossibleContents {
// type.
static ConeType ExactType(Type type) { return ConeType{type, 0}; }
+ static constexpr Index FullDepth = -1;
+
+ // Internal convenience for creating a cone type of unbounded depth, i.e., the
+ // full cone of all subtypes for that type.
+ static ConeType FullConeType(Type type) { return ConeType{type, FullDepth}; }
+
public:
PossibleContents() : value(None()) {}
PossibleContents(const PossibleContents& other) = default;
@@ -114,8 +121,13 @@ public:
static PossibleContents exactType(Type type) {
return PossibleContents{ExactType(type)};
}
+ // Helper for a cone with unbounded depth, i.e., the full cone of all subtypes
+ // for that type.
+ static PossibleContents fullConeType(Type type) {
+ return PossibleContents{FullConeType(type)};
+ }
static PossibleContents coneType(Type type, Index depth) {
- WASM_UNREACHABLE("actual cones are not supported yet");
+ return PossibleContents{ConeType{type, depth}};
}
static PossibleContents many() { return PossibleContents{Many()}; }
@@ -133,6 +145,11 @@ public:
// contents here will then include whatever content was possible in |other|.
void combine(const PossibleContents& other);
+ // Removes anything not in |other| from this object, so that it ends up with
+ // only their intersection. Currently this only handles an intersection with a
+ // full cone.
+ void intersectWithFullCone(const PossibleContents& other);
+
bool isNone() const { return std::get_if<None>(&value); }
bool isLiteral() const { return std::get_if<Literal>(&value); }
bool isGlobal() const { return std::get_if<GlobalInfo>(&value); }
@@ -174,6 +191,37 @@ public:
}
}
+ // Returns cone type info. This can be called on non-cone types as well, and
+ // it returns a cone that best describes them. That is, this is like getType()
+ // but it also provides an indication about the depth, if relevant. (If cone
+ // info is not relevant, like when getType() returns none or unreachable, the
+ // depth is set to 0.)
+ ConeType getCone() const {
+ if (auto* literal = std::get_if<Literal>(&value)) {
+ return ExactType(literal->type);
+ } else if (auto* global = std::get_if<GlobalInfo>(&value)) {
+ return FullConeType(global->type);
+ } else if (auto* coneType = std::get_if<ConeType>(&value)) {
+ return *coneType;
+ } else if (std::get_if<None>(&value)) {
+ return ExactType(Type::unreachable);
+ } else if (std::get_if<Many>(&value)) {
+ return ExactType(Type::none);
+ } else {
+ WASM_UNREACHABLE("bad value");
+ }
+ }
+
+ // Returns whether the relevant cone for this, as computed by getCone(), is of
+ // full size, that is, includes all subtypes.
+ bool hasFullCone() const { return getCone().depth == FullDepth; }
+
+ // Returns whether this is a cone type and also is of full size. This differs
+ // from hasFullCone() in that the former can return true for a global, for
+ // example, while this cannot (a global is not a cone type, but the
+ // information we have about its cone is that it is full).
+ bool isFullConeType() const { return isConeType() && hasFullCone(); }
+
// Returns whether the type we can report here is exact, that is, nothing of a
// strict subtype might show up - the contents here have an exact type.
//
@@ -197,6 +245,11 @@ public:
static bool haveIntersection(const PossibleContents& a,
const PossibleContents& b);
+ // Returns whether |a| is a subset of |b|, that is, all possible contents of
+ // |a| are also possible in |b|.
+ static bool isSubContents(const PossibleContents& a,
+ const PossibleContents& b);
+
// Whether we can make an Expression* for this containing the proper contents.
// We can do that for a Literal (emitting a Const or RefFunc etc.) or a
// Global (emitting a GlobalGet), but not for anything else yet.