summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/possible-contents.cpp24
-rw-r--r--src/ir/possible-contents.h20
-rw-r--r--test/lit/passes/gufa-refs.wast26
3 files changed, 49 insertions, 21 deletions
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp
index cd8bd1516..2efd61391 100644
--- a/src/ir/possible-contents.cpp
+++ b/src/ir/possible-contents.cpp
@@ -1205,6 +1205,9 @@ struct InfoCollector
PossibleContents contents = PossibleContents::many()) {
// TODO Use a cone type here when relevant
if (isRelevant(curr)) {
+ if (contents.isMany()) {
+ contents = PossibleContents::fromType(curr->type);
+ }
addRoot(ExpressionLocation{curr, 0}, contents);
}
}
@@ -1399,8 +1402,10 @@ Flower::Flower(Module& wasm) : wasm(wasm) {
if (func->imported()) {
// Imports return unknown values.
- for (Index i = 0; i < func->getResults().size(); i++) {
- finder.addRoot(ResultLocation{func, i}, PossibleContents::many());
+ auto results = func->getResults();
+ for (Index i = 0; i < results.size(); i++) {
+ finder.addRoot(ResultLocation{func, i},
+ PossibleContents::fromType(results[i]));
}
return;
}
@@ -1423,7 +1428,8 @@ Flower::Flower(Module& wasm) : wasm(wasm) {
for (auto& global : wasm.globals) {
if (global->imported()) {
// Imports are unknown values.
- finder.addRoot(GlobalLocation{global->name}, PossibleContents::many());
+ finder.addRoot(GlobalLocation{global->name},
+ PossibleContents::fromType(global->type));
continue;
}
auto* init = global->init;
@@ -1477,8 +1483,9 @@ Flower::Flower(Module& wasm) : wasm(wasm) {
// that we can't see, so anything might arrive there.
auto calledFromOutside = [&](Name funcName) {
auto* func = wasm.getFunction(funcName);
+ auto params = func->getParams();
for (Index i = 0; i < func->getParams().size(); i++) {
- roots[ParamLocation{func, i}] = PossibleContents::many();
+ roots[ParamLocation{func, i}] = PossibleContents::fromType(params[i]);
}
};
@@ -1509,8 +1516,9 @@ Flower::Flower(Module& wasm) : wasm(wasm) {
// Exported mutable globals are roots, since the outside may write any
// value to them.
auto name = ex->value;
- if (wasm.getGlobal(name)->mutable_) {
- roots[GlobalLocation{name}] = PossibleContents::many();
+ auto* global = wasm.getGlobal(name);
+ if (global->mutable_) {
+ roots[GlobalLocation{name}] = PossibleContents::fromType(global->type);
}
}
}
@@ -1974,9 +1982,9 @@ void Flower::dump(Location location) {
std::cout << " tagloc " << loc->tag << '\n';
} else if (auto* loc = std::get_if<ParamLocation>(&location)) {
std::cout << " paramloc " << loc->func->name << " : " << loc->index
- << " tupleIndex " << loc->tupleIndex << '\n';
+ << '\n';
} else if (auto* loc = std::get_if<ResultLocation>(&location)) {
- std::cout << " resultloc " << loc->func->name << " : " << loc->index
+ std::cout << " resultloc $" << loc->func->name << " : " << loc->index
<< '\n';
} else if (auto* loc = std::get_if<GlobalLocation>(&location)) {
std::cout << " globalloc " << loc->name << '\n';
diff --git a/src/ir/possible-contents.h b/src/ir/possible-contents.h
index ee817deae..14ed36b4d 100644
--- a/src/ir/possible-contents.h
+++ b/src/ir/possible-contents.h
@@ -131,6 +131,26 @@ public:
}
static PossibleContents many() { return PossibleContents{Many()}; }
+ // Helper for creating a PossibleContents based on a wasm type, that is, where
+ // all we know is the wasm type.
+ static PossibleContents fromType(Type type) {
+ assert(type != Type::none);
+
+ if (type.isRef()) {
+ // For a reference, subtyping matters.
+ return fullConeType(type);
+ }
+
+ if (type == Type::unreachable) {
+ // Nothing is possible here.
+ return none();
+ }
+
+ // Otherwise, this is a concrete MVP type.
+ assert(type.isConcrete());
+ return exactType(type);
+ }
+
PossibleContents& operator=(const PossibleContents& other) = default;
bool operator==(const PossibleContents& other) const {
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index a1ff92522..48f6edc34 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -2552,14 +2552,19 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.cast_static $struct
- ;; CHECK-NEXT: (select (result i31ref)
- ;; CHECK-NEXT: (ref.null none)
- ;; CHECK-NEXT: (i31.new
- ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (block (result nullref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.cast_static $struct
+ ;; CHECK-NEXT: (select (result i31ref)
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: (i31.new
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
@@ -2948,10 +2953,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
- ;; CHECK-NEXT: (ref.eq
- ;; CHECK-NEXT: (local.get $nn-struct)
- ;; CHECK-NEXT: (local.get $nn-other)
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.eq
@@ -3022,9 +3024,7 @@
(local.get $nn-struct2)
)
)
- ;; Non-null on both sides, and incompatible types, so we should be able to
- ;; infer 0, but we need cone types for that. Until we have them, these are
- ;; Many and so we infer nothing. TODO
+ ;; Non-null on both sides, and incompatible types. We can infer 0 here.
(drop
(ref.eq
(local.get $nn-struct)