summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/Precompute.cpp43
-rw-r--r--src/passes/Print.cpp15
2 files changed, 45 insertions, 13 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index dceb45fb2..ae488a01f 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -177,6 +177,9 @@ struct Precompute
if (flow.breakTo == NONCONSTANT_FLOW) {
return;
}
+ if (!canEmitConstantFor(flow.values)) {
+ return;
+ }
if (flow.breakTo == RETURN_FLOW) {
// this expression causes a return. if it's already a return, reuse the
// node
@@ -223,14 +226,7 @@ private:
// Precompute an expression, returning a flow, which may be a constant
// (that we can replace the expression with if replaceExpression is set).
Flow precomputeExpression(Expression* curr, bool replaceExpression = true) {
- // Don't try to precompute a reference. We can't replace it with a constant
- // expression, as that would make a copy of it by value.
- // TODO: do so when safe
- if (curr->type.isRef()) {
- return Flow(NONCONSTANT_FLOW);
- }
- // Don't try to precompute an Rtt. TODO figure out when that would be safe
- if (curr->type.isRtt()) {
+ if (!canEmitConstantFor(curr->type)) {
return Flow(NONCONSTANT_FLOW);
}
try {
@@ -348,6 +344,37 @@ private:
}
}
}
+
+ bool canEmitConstantFor(const Literals& values) {
+ for (auto& value : values) {
+ if (!canEmitConstantFor(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool canEmitConstantFor(const Literal& value) {
+ // A null is fine to emit a constant for - we'll emit a RefNull. Otherwise,
+ // see below about references to GC data.
+ if (value.isNull()) {
+ return true;
+ }
+ // A function is fine to emit a constant for - we'll emit a RefFunc, which
+ // is compact and immutable, so there can't be a problem.
+ if (value.type.isFunction()) {
+ return true;
+ }
+ return canEmitConstantFor(value.type);
+ }
+
+ bool canEmitConstantFor(Type type) {
+ // Don't try to precompute a reference. We can't replace it with a constant
+ // expression, as that would make a copy of it by value.
+ // For now, don't try to precompute an Rtt. TODO figure out when that would
+ // be safe and useful.
+ return !type.isRef() && !type.isRtt();
+ }
};
Pass* createPrecomputePass() { return new Precompute(false); }
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index c0e940d04..b921fb074 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1733,15 +1733,17 @@ struct PrintExpressionContents
}
void visitRefTest(RefTest* curr) {
printMedium(o, "ref.test ");
- printHeapTypeName(o, curr->rtt->type.getHeapType());
+ printHeapTypeName(o, curr->getCastType().getHeapType());
}
void visitRefCast(RefCast* curr) {
printMedium(o, "ref.cast ");
- printHeapTypeName(o, curr->rtt->type.getHeapType());
+ printHeapTypeName(o, curr->getCastType().getHeapType());
}
void visitBrOnCast(BrOnCast* curr) {
- printMedium(o, "br_on_cast");
- WASM_UNREACHABLE("TODO (gc): br_on_cast");
+ printMedium(o, "br_on_cast ");
+ printName(curr->name, o);
+ o << " ";
+ printHeapTypeName(o, curr->getCastType().getHeapType());
}
void visitRttCanon(RttCanon* curr) {
printMedium(o, "rtt.canon ");
@@ -2450,7 +2452,10 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
void visitBrOnCast(BrOnCast* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
- WASM_UNREACHABLE("TODO (gc): br_on_cast");
+ incIndent();
+ printFullLine(curr->ref);
+ printFullLine(curr->rtt);
+ decIndent();
}
void visitRttCanon(RttCanon* curr) {
o << '(';