diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/global-utils.h | 6 | ||||
-rw-r--r-- | src/ir/properties.h | 18 | ||||
-rw-r--r-- | src/literal.h | 2 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 39 | ||||
-rw-r--r-- | src/wasm-builder.h | 4 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 15 |
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) { |