summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/global-utils.h6
-rw-r--r--src/ir/properties.h18
-rw-r--r--src/literal.h2
-rw-r--r--src/tools/fuzzing.h39
-rw-r--r--src/wasm-builder.h4
-rw-r--r--src/wasm/literal.cpp8
-rw-r--r--src/wasm/wasm.cpp15
7 files changed, 61 insertions, 31 deletions
diff --git a/src/ir/global-utils.h b/src/ir/global-utils.h
index b575d6952..7dc4c6af3 100644
--- a/src/ir/global-utils.h
+++ b/src/ir/global-utils.h
@@ -56,15 +56,13 @@ getGlobalInitializedToImport(Module& wasm, Name module, Name base) {
inline bool canInitializeGlobal(const Expression* curr) {
if (auto* tuple = curr->dynCast<TupleMake>()) {
for (auto* op : tuple->operands) {
- if (!op->is<Const>() && !op->is<RefNull>() &&
- !op->is<RefFunc>() & !op->is<GlobalGet>()) {
+ if (!Properties::isSingleConstantExpression(op) && !op->is<GlobalGet>()) {
return false;
}
}
return true;
}
- return curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>() ||
- curr->is<GlobalGet>();
+ return Properties::isSingleConstantExpression(curr) || curr->is<GlobalGet>();
}
} // namespace GlobalUtils
diff --git a/src/ir/properties.h b/src/ir/properties.h
index 56723631a..d0495f4a9 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -79,13 +79,18 @@ inline bool isNamedControlFlow(Expression* curr) {
return false;
}
+inline bool isSingleConstantExpression(const Expression* curr) {
+ return curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>() ||
+ (curr->is<I31New>() && curr->cast<I31New>()->value->is<Const>());
+}
+
inline bool isConstantExpression(const Expression* curr) {
- if (curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>()) {
+ if (isSingleConstantExpression(curr)) {
return true;
}
if (auto* tuple = curr->dynCast<TupleMake>()) {
for (auto* op : tuple->operands) {
- if (!op->is<Const>() && !op->is<RefNull>() && !op->is<RefFunc>()) {
+ if (!isSingleConstantExpression(op)) {
return false;
}
}
@@ -101,13 +106,16 @@ inline Literal getSingleLiteral(const Expression* curr) {
return Literal(n->type);
} else if (auto* r = curr->dynCast<RefFunc>()) {
return Literal(r->func);
- } else {
- WASM_UNREACHABLE("non-constant expression");
+ } else if (auto* i = curr->dynCast<I31New>()) {
+ if (auto* c = i->value->dynCast<Const>()) {
+ return Literal::makeI31(c->value.geti32());
+ }
}
+ WASM_UNREACHABLE("non-constant expression");
}
inline Literals getLiterals(const Expression* curr) {
- if (curr->is<Const>() || curr->is<RefNull>() || curr->is<RefFunc>()) {
+ if (isSingleConstantExpression(curr)) {
return {getSingleLiteral(curr)};
} else if (auto* tuple = curr->dynCast<TupleMake>()) {
Literals literals;
diff --git a/src/literal.h b/src/literal.h
index c0e43eb88..eedccabcc 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -158,7 +158,7 @@ public:
assert(type == Type::i32);
return i32;
}
- int32_t geti31(bool signed_) const {
+ int32_t geti31(bool signed_ = true) const {
assert(type == Type::i31ref);
return signed_ ? (i32 << 1) >> 1 : i32;
}
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index cab33e3b5..ecc548e22 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -326,13 +326,13 @@ private:
}
if (wasm.features.hasGC()) {
options.push_back(Type::eqref);
- // TODO: i31ref
+ options.push_back(Type::i31ref);
}
}
break;
case Type::eqref:
if (wasm.features.hasGC()) {
- // TODO: i31ref
+ options.push_back(Type::i31ref);
}
break;
default:
@@ -893,11 +893,16 @@ private:
if (type == Type::i32) {
options.add(FeatureSet::ReferenceTypes, &Self::makeRefIsNull);
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
- &Self::makeRefEq);
+ &Self::makeRefEq,
+ &Self::makeI31Get);
}
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
}
+ if (type == Type::i31ref) {
+ options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
+ &Self::makeI31New);
+ }
return (this->*pick(options))(type);
}
@@ -1786,6 +1791,9 @@ private:
}
return builder.makeRefFunc(target->name);
}
+ if (type == Type::i31ref) {
+ return builder.makeI31New(makeConst(Type::i32));
+ }
return builder.makeRefNull(type);
}
if (type.isTuple()) {
@@ -2652,6 +2660,20 @@ private:
return builder.makeRefEq(left, right);
}
+ Expression* makeI31New(Type type) {
+ assert(type == Type::i31ref);
+ assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
+ auto* value = make(Type::i32);
+ return builder.makeI31New(value);
+ }
+
+ Expression* makeI31Get(Type type) {
+ assert(type == Type::i32);
+ assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
+ auto* i31 = make(Type::i31ref);
+ return builder.makeI31Get(i31, bool(oneIn(2)));
+ }
+
Expression* makeMemoryInit() {
if (!allowMemory) {
return makeTrivial(Type::none);
@@ -2717,7 +2739,8 @@ private:
Type::exnref)
.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
Type::anyref,
- Type::eqref)); // TODO: i31ref
+ Type::eqref,
+ Type::i31ref));
}
Type getSingleConcreteType() { return pick(getSingleConcreteTypes()); }
@@ -2730,15 +2753,15 @@ private:
Type::exnref)
.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
Type::anyref,
- Type::eqref)); // TODO: i31ref
+ Type::eqref,
+ Type::i31ref));
}
Type getReferenceType() { return pick(getReferenceTypes()); }
std::vector<Type> getEqReferenceTypes() {
- return items(
- FeatureOptions<Type>().add(FeatureSet::ReferenceTypes | FeatureSet::GC,
- Type::eqref)); // TODO: i31ref
+ return items(FeatureOptions<Type>().add(
+ FeatureSet::ReferenceTypes | FeatureSet::GC, Type::eqref, Type::i31ref));
}
Type getEqReferenceType() { return pick(getEqReferenceTypes()); }
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index d78640200..d90ccb9ae 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -666,7 +666,7 @@ public:
assert(value.isNull() && "unexpected non-null reference type literal");
return makeRefNull(value.type);
case Type::i31ref:
- WASM_UNREACHABLE("TODO: i31ref");
+ return makeI31New(makeConst(value.geti31()));
default:
assert(value.type.isNumber());
return makeConst(value);
@@ -863,7 +863,7 @@ public:
case Type::eqref:
return ExpressionManipulator::refNull(curr, curr->type);
case Type::i31ref:
- WASM_UNREACHABLE("TODO: i31ref");
+ return makeI31New(makeConst(0));
case Type::none:
return ExpressionManipulator::nop(curr);
case Type::unreachable:
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index a7c14fdb6..d309be308 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -139,7 +139,11 @@ Literals Literal::makeZero(Type type) {
Literal Literal::makeSingleZero(Type type) {
assert(type.isSingle());
if (type.isRef()) {
- return makeNull(type);
+ if (type == Type::i31ref) {
+ return makeI31(0);
+ } else {
+ return makeNull(type);
+ }
} else {
return makeFromInt32(0, type);
}
@@ -438,7 +442,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
o << "eqref(null)";
break;
case Type::i31ref:
- o << "i31ref(" << literal.geti31(false) << ")";
+ o << "i31ref(" << literal.geti31() << ")";
break;
case Type::unreachable:
WASM_UNREACHABLE("invalid type");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index c03a9b281..c857b202c 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -217,18 +217,15 @@ const char* getExpressionName(Expression* curr) {
}
Literal getSingleLiteralFromConstExpression(Expression* curr) {
- if (auto* c = curr->dynCast<Const>()) {
- return c->value;
- } else if (auto* n = curr->dynCast<RefNull>()) {
- return Literal::makeNull(n->type);
- } else if (auto* r = curr->dynCast<RefFunc>()) {
- return Literal::makeFunc(r->func);
- } else {
- WASM_UNREACHABLE("Not a constant expression");
- }
+ // TODO: Do we need this function given that Properties::getSingleLiteral
+ // (currently) does the same?
+ assert(Properties::isConstantExpression(curr));
+ return Properties::getSingleLiteral(curr);
}
Literals getLiteralsFromConstExpression(Expression* curr) {
+ // TODO: Do we need this function given that Properties::getLiterals
+ // (currently) does the same?
if (auto* t = curr->dynCast<TupleMake>()) {
Literals values;
for (auto* operand : t->operands) {