Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/analysis/lattices/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ namespace wasm::analysis {

// A lattice whose elements are a single ascending chain in lattice `L`.
// Internally, there is only ever a single monotonically increasing element of L
// materialized. Dereferencing any element of the Shared lattice will produce
// the current value of that single element of L, which is generally safe
// because the current value always overapproximates (i.e. is higher in the
// lattice than) the value at the time of the Shared element's construction.
// materialized. Dereferencing any element of the SharedPath lattice will
// produce the current value of that single element of L, which is generally
// safe because the current value always overapproximates (i.e. is higher in the
// lattice than) the value at the time of the SharedPath element's construction.
//
// Each element of this lattice maintains a sequence number that corresponds to
// a value the shared underlying element has had at some point in time. Higher
// sequence numbers correspond to greater values of the underlying element.
// Elements of this lattice are compared and joined using these sequence
// numbers, so blocks will correctly be re-analyzed if the value has increased
// since the last time they were analyzed.
template<Lattice L> struct Shared {
template<Lattice L> struct SharedPath {
// If we ever have extremely long-running analyses, this may need to be
// changed to uint64_t.
using Seq = uint32_t;
Expand Down Expand Up @@ -70,7 +70,7 @@ template<Lattice L> struct Shared {
return !(*this == other);
}

friend Shared;
friend SharedPath;
};

L lattice;
Expand All @@ -84,7 +84,7 @@ template<Lattice L> struct Shared {
mutable typename L::Element val;
mutable Seq seq = 0;

Shared(L&& l) : lattice(std::move(l)), val(lattice.getBottom()) {}
SharedPath(L&& l) : lattice(std::move(l)), val(lattice.getBottom()) {}

// TODO: Delete the move constructor and the move assignment operator. This
// requires fixing the lattice fuzzer first, since it depends on lattices
Expand Down Expand Up @@ -119,10 +119,10 @@ template<Lattice L> struct Shared {
};

// Deduction guide.
template<typename L> Shared(L&&) -> Shared<L>;
template<typename L> SharedPath(L&&) -> SharedPath<L>;

#if __cplusplus >= 202002L
static_assert(Lattice<Shared<Bool>>);
static_assert(Lattice<SharedPath<Bool>>);
#endif // __cplusplus >= 202002L

} // namespace wasm::analysis
Expand Down
4 changes: 2 additions & 2 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) {
assert(x.type.isRef());
auto heapType = x.type.getHeapType();
if (heapType.isBasic()) {
switch (heapType.getBasic()) {
switch (heapType.getBasic(Unshared)) {
case HeapType::i31:
WASM_UNREACHABLE("TODO: i31");
case HeapType::ext:
Expand Down Expand Up @@ -132,7 +132,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
assert(type.isRef());
auto heapType = type.getHeapType();
if (heapType.isBasic()) {
switch (heapType.getBasic()) {
switch (heapType.getBasic(Unshared)) {
case HeapType::i31:
WASM_UNREACHABLE("TODO: i31");
case HeapType::ext:
Expand Down
2 changes: 1 addition & 1 deletion src/ir/type-updating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes(
i = 0;
for (auto [type, _] : typeIndices) {
typeBuilder[i].setOpen(type.isOpen());
typeBuilder[i].setShared(type.isShared());
typeBuilder[i].setShared(type.getShared());
if (type.isSignature()) {
auto sig = type.getSignature();
TypeList newParams, newResults;
Expand Down
93 changes: 60 additions & 33 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,21 @@ struct NullTypeParserCtx {
using ElemListT = Ok;
using DataStringT = Ok;

HeapTypeT makeFuncType() { return Ok{}; }
HeapTypeT makeAnyType() { return Ok{}; }
HeapTypeT makeExternType() { return Ok{}; }
HeapTypeT makeEqType() { return Ok{}; }
HeapTypeT makeI31Type() { return Ok{}; }
HeapTypeT makeStructType() { return Ok{}; }
HeapTypeT makeArrayType() { return Ok{}; }
HeapTypeT makeExnType() { return Ok{}; }
HeapTypeT makeStringType() { return Ok{}; }
HeapTypeT makeStringViewWTF8Type() { return Ok{}; }
HeapTypeT makeStringViewWTF16Type() { return Ok{}; }
HeapTypeT makeStringViewIterType() { return Ok{}; }
HeapTypeT makeContType() { return Ok{}; }
HeapTypeT makeNoneType() { return Ok{}; }
HeapTypeT makeNoextType() { return Ok{}; }
HeapTypeT makeNofuncType() { return Ok{}; }
HeapTypeT makeNoexnType() { return Ok{}; }
HeapTypeT makeNocontType() { return Ok{}; }
HeapTypeT makeFuncType(Shareability) { return Ok{}; }
HeapTypeT makeAnyType(Shareability) { return Ok{}; }
HeapTypeT makeExternType(Shareability) { return Ok{}; }
HeapTypeT makeEqType(Shareability) { return Ok{}; }
HeapTypeT makeI31Type(Shareability) { return Ok{}; }
HeapTypeT makeStructType(Shareability) { return Ok{}; }
HeapTypeT makeArrayType(Shareability) { return Ok{}; }
HeapTypeT makeExnType(Shareability) { return Ok{}; }
HeapTypeT makeStringType(Shareability) { return Ok{}; }
HeapTypeT makeContType(Shareability) { return Ok{}; }
HeapTypeT makeNoneType(Shareability) { return Ok{}; }
HeapTypeT makeNoextType(Shareability) { return Ok{}; }
HeapTypeT makeNofuncType(Shareability) { return Ok{}; }
HeapTypeT makeNoexnType(Shareability) { return Ok{}; }
HeapTypeT makeNocontType(Shareability) { return Ok{}; }

TypeT makeI32() { return Ok{}; }
TypeT makeI64() { return Ok{}; }
Expand Down Expand Up @@ -208,21 +205,51 @@ template<typename Ctx> struct TypeParserCtx {

Ctx& self() { return *static_cast<Ctx*>(this); }

HeapTypeT makeFuncType() { return HeapType::func; }
HeapTypeT makeAnyType() { return HeapType::any; }
HeapTypeT makeExternType() { return HeapType::ext; }
HeapTypeT makeEqType() { return HeapType::eq; }
HeapTypeT makeI31Type() { return HeapType::i31; }
HeapTypeT makeStructType() { return HeapType::struct_; }
HeapTypeT makeArrayType() { return HeapType::array; }
HeapTypeT makeExnType() { return HeapType::exn; }
HeapTypeT makeStringType() { return HeapType::string; }
HeapTypeT makeContType() { return HeapType::cont; }
HeapTypeT makeNoneType() { return HeapType::none; }
HeapTypeT makeNoextType() { return HeapType::noext; }
HeapTypeT makeNofuncType() { return HeapType::nofunc; }
HeapTypeT makeNoexnType() { return HeapType::noexn; }
HeapTypeT makeNocontType() { return HeapType::nocont; }
HeapTypeT makeFuncType(Shareability share) {
return HeapTypes::func.getBasic(share);
}
HeapTypeT makeAnyType(Shareability share) {
return HeapTypes::any.getBasic(share);
}
HeapTypeT makeExternType(Shareability share) {
return HeapTypes::ext.getBasic(share);
}
HeapTypeT makeEqType(Shareability share) {
return HeapTypes::eq.getBasic(share);
}
HeapTypeT makeI31Type(Shareability share) {
return HeapTypes::i31.getBasic(share);
}
HeapTypeT makeStructType(Shareability share) {
return HeapTypes::struct_.getBasic(share);
}
HeapTypeT makeArrayType(Shareability share) {
return HeapTypes::array.getBasic(share);
}
HeapTypeT makeExnType(Shareability share) {
return HeapTypes::exn.getBasic(share);
}
HeapTypeT makeStringType(Shareability share) {
return HeapTypes::string.getBasic(share);
}
HeapTypeT makeContType(Shareability share) {
return HeapTypes::cont.getBasic(share);
}
HeapTypeT makeNoneType(Shareability share) {
return HeapTypes::none.getBasic(share);
}
HeapTypeT makeNoextType(Shareability share) {
return HeapTypes::noext.getBasic(share);
}
HeapTypeT makeNofuncType(Shareability share) {
return HeapTypes::nofunc.getBasic(share);
}
HeapTypeT makeNoexnType(Shareability share) {
return HeapTypes::noexn.getBasic(share);
}
HeapTypeT makeNocontType(Shareability share) {
return HeapTypes::nocont.getBasic(share);
}

TypeT makeI32() { return Type::i32; }
TypeT makeI64() { return Type::i64; }
Expand Down
91 changes: 54 additions & 37 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace wasm::WATParser {
using namespace std::string_view_literals;

// Types
template<typename Ctx>
Result<typename Ctx::HeapTypeT> absheaptype(Ctx&, Shareability);
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::RefTypeT> maybeRefType(Ctx&);
template<typename Ctx> Result<typename Ctx::RefTypeT> reftype(Ctx&);
Expand Down Expand Up @@ -358,58 +360,73 @@ template<typename Ctx> Result<> module(Ctx&);
// Types
// =====

// heaptype ::= x:typeidx => types[x]
// | 'func' => func
// | 'extern' => extern
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
// absheaptype ::= 'func' | 'extern' | ...
template<typename Ctx>
Result<typename Ctx::HeapTypeT> absheaptype(Ctx& ctx, Shareability share) {
if (ctx.in.takeKeyword("func"sv)) {
return ctx.makeFuncType();
return ctx.makeFuncType(share);
}
if (ctx.in.takeKeyword("any"sv)) {
return ctx.makeAnyType();
return ctx.makeAnyType(share);
}
if (ctx.in.takeKeyword("extern"sv)) {
return ctx.makeExternType();
return ctx.makeExternType(share);
}
if (ctx.in.takeKeyword("eq"sv)) {
return ctx.makeEqType();
return ctx.makeEqType(share);
}
if (ctx.in.takeKeyword("i31"sv)) {
return ctx.makeI31Type();
return ctx.makeI31Type(share);
}
if (ctx.in.takeKeyword("struct"sv)) {
return ctx.makeStructType();
return ctx.makeStructType(share);
}
if (ctx.in.takeKeyword("array"sv)) {
return ctx.makeArrayType();
return ctx.makeArrayType(share);
}
if (ctx.in.takeKeyword("exn"sv)) {
return ctx.makeExnType();
return ctx.makeExnType(share);
}
if (ctx.in.takeKeyword("string"sv)) {
return ctx.makeStringType();
return ctx.makeStringType(share);
}
if (ctx.in.takeKeyword("cont"sv)) {
return ctx.makeContType();
return ctx.makeContType(share);
}
if (ctx.in.takeKeyword("none"sv)) {
return ctx.makeNoneType();
return ctx.makeNoneType(share);
}
if (ctx.in.takeKeyword("noextern"sv)) {
return ctx.makeNoextType();
return ctx.makeNoextType(share);
}
if (ctx.in.takeKeyword("nofunc"sv)) {
return ctx.makeNofuncType();
return ctx.makeNofuncType(share);
}
if (ctx.in.takeKeyword("noexn"sv)) {
return ctx.makeNoexnType();
return ctx.makeNoexnType(share);
}
if (ctx.in.takeKeyword("nocont"sv)) {
return ctx.makeNocontType();
return ctx.makeNocontType(share);
}
auto type = typeidx(ctx);
CHECK_ERR(type);
return *type;
return ctx.in.err("expected abstract heap type");
}

// heaptype ::= x:typeidx => types[x]
// | t:absheaptype => unshared t
// | '(' 'shared' t:absheaptype ')' => shared t
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
if (auto t = maybeTypeidx(ctx)) {
CHECK_ERR(t);
return *t;
}

auto share = ctx.in.takeSExprStart("shared"sv) ? Shared : Unshared;
auto t = absheaptype(ctx, share);
CHECK_ERR(t);
if (share == Shared && !ctx.in.takeRParen()) {
return ctx.in.err("expected end of shared abstract heap type");
}
return *t;
}

// reftype ::= 'funcref' => funcref
Expand All @@ -422,49 +439,49 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx& ctx) {
// | '(' ref null? t:heaptype ')' => ref null? t
template<typename Ctx> MaybeResult<typename Ctx::TypeT> maybeReftype(Ctx& ctx) {
if (ctx.in.takeKeyword("funcref"sv)) {
return ctx.makeRefType(ctx.makeFuncType(), Nullable);
return ctx.makeRefType(ctx.makeFuncType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("externref"sv)) {
return ctx.makeRefType(ctx.makeExternType(), Nullable);
return ctx.makeRefType(ctx.makeExternType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("anyref"sv)) {
return ctx.makeRefType(ctx.makeAnyType(), Nullable);
return ctx.makeRefType(ctx.makeAnyType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("eqref"sv)) {
return ctx.makeRefType(ctx.makeEqType(), Nullable);
return ctx.makeRefType(ctx.makeEqType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("i31ref"sv)) {
return ctx.makeRefType(ctx.makeI31Type(), Nullable);
return ctx.makeRefType(ctx.makeI31Type(Unshared), Nullable);
}
if (ctx.in.takeKeyword("structref"sv)) {
return ctx.makeRefType(ctx.makeStructType(), Nullable);
return ctx.makeRefType(ctx.makeStructType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("arrayref"sv)) {
return ctx.makeRefType(ctx.makeArrayType(), Nullable);
return ctx.makeRefType(ctx.makeArrayType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("exnref"sv)) {
return ctx.makeRefType(ctx.makeExnType(), Nullable);
return ctx.makeRefType(ctx.makeExnType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("stringref"sv)) {
return ctx.makeRefType(ctx.makeStringType(), Nullable);
return ctx.makeRefType(ctx.makeStringType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("contref"sv)) {
return ctx.makeRefType(ctx.makeContType(), Nullable);
return ctx.makeRefType(ctx.makeContType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("nullref"sv)) {
return ctx.makeRefType(ctx.makeNoneType(), Nullable);
return ctx.makeRefType(ctx.makeNoneType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("nullexternref"sv)) {
return ctx.makeRefType(ctx.makeNoextType(), Nullable);
return ctx.makeRefType(ctx.makeNoextType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("nullfuncref"sv)) {
return ctx.makeRefType(ctx.makeNofuncType(), Nullable);
return ctx.makeRefType(ctx.makeNofuncType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("nullexnref"sv)) {
return ctx.makeRefType(ctx.makeNoexnType(), Nullable);
return ctx.makeRefType(ctx.makeNoexnType(Unshared), Nullable);
}
if (ctx.in.takeKeyword("nullcontref"sv)) {
return ctx.makeRefType(ctx.makeNocontType(), Nullable);
return ctx.makeRefType(ctx.makeNocontType(Unshared), Nullable);
}

if (!ctx.in.takeSExprStart("ref"sv)) {
Expand Down
7 changes: 4 additions & 3 deletions src/passes/TypeGeneralizing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ using TypeRequirement = Inverted<ValType>;

// Record a type requirement for each local variable. Shared the requirements
// across basic blocks.
using LocalTypeRequirements = Shared<Vector<TypeRequirement>>;
using LocalTypeRequirements = SharedPath<Vector<TypeRequirement>>;

// The type requirements for each reference-typed value on the stack at a
// particular location.
Expand All @@ -75,7 +75,8 @@ struct State : StateLattice {
static constexpr int LocalsIndex = 0;
static constexpr int StackIndex = 1;

State(Function* func) : StateLattice{Shared{initLocals(func)}, initStack()} {}
State(Function* func)
: StateLattice{SharedPath{initLocals(func)}, initStack()} {}

void push(Element& elem, Type type) const noexcept {
stackLattice().push(stack(elem), std::move(type));
Expand Down Expand Up @@ -109,7 +110,7 @@ struct State : StateLattice {

private:
static LocalTypeRequirements initLocals(Function* func) noexcept {
return Shared{Vector{Inverted{ValType{}}, func->getNumLocals()}};
return SharedPath{Vector{Inverted{ValType{}}, func->getNumLocals()}};
}

static ValueStackTypeRequirements initStack() noexcept {
Expand Down
Loading