diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 184 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 10 |
4 files changed, 104 insertions, 100 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index fa90532d9..82eb51d7e 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2974,7 +2974,7 @@ bool WasmBinaryBuilder::maybeVisitAtomicWait(Expression*& out, uint8_t code) { curr->ptr = popNonVoidExpression(); Address readAlign; readMemoryAccess(readAlign, curr->offset); - if (readAlign != getTypeSize(curr->expectedType)) { + if (readAlign != curr->expectedType.getByteSize()) { throwError("Align of AtomicWait must match size"); } curr->finalize(); @@ -2994,7 +2994,7 @@ bool WasmBinaryBuilder::maybeVisitAtomicNotify(Expression*& out, uint8_t code) { curr->ptr = popNonVoidExpression(); Address readAlign; readMemoryAccess(readAlign, curr->offset); - if (readAlign != getTypeSize(curr->type)) { + if (readAlign != curr->type.getByteSize()) { throwError("Align of AtomicNotify must match size"); } curr->finalize(); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 1319d80fc..20aff2091 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1268,7 +1268,7 @@ SExpressionWasmBuilder::makeLoad(Element& s, Type type, bool isAtomic) { auto* ret = allocator.alloc<Load>(); ret->isAtomic = isAtomic; ret->type = type; - ret->bytes = parseMemBytes(extra, getTypeSize(type)); + ret->bytes = parseMemBytes(extra, type.getByteSize()); ret->signed_ = extra[0] && extra[1] == 's'; size_t i = parseMemAttributes(s, &ret->offset, &ret->align, ret->bytes); ret->ptr = parseExpression(s[i]); @@ -1282,7 +1282,7 @@ SExpressionWasmBuilder::makeStore(Element& s, Type type, bool isAtomic) { auto ret = allocator.alloc<Store>(); ret->isAtomic = isAtomic; ret->valueType = type; - ret->bytes = parseMemBytes(extra, getTypeSize(type)); + ret->bytes = parseMemBytes(extra, type.getByteSize()); size_t i = parseMemAttributes(s, &ret->offset, &ret->align, ret->bytes); ret->ptr = parseExpression(s[i]); ret->value = parseExpression(s[i + 1]); @@ -1294,7 +1294,7 @@ Expression* SExpressionWasmBuilder::makeAtomicRMWOrCmpxchg(Element& s, Type type) { const char* extra = findMemExtra( *s[0], 11 /* after "type.atomic.rmw" */, /* isAtomic = */ false); - auto bytes = parseMemBytes(extra, getTypeSize(type)); + auto bytes = parseMemBytes(extra, type.getByteSize()); extra = strchr(extra, '.'); // after the optional '_u' and before the opcode if (!extra) { throw ParseException("malformed atomic rmw instruction"); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 7d29b0dcd..939ee8c93 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -140,14 +140,85 @@ bool Type::operator<(const Type& other) const { [](const Type& a, const Type& b) { return uint32_t(a) < uint32_t(b); }); } -bool Signature::operator<(const Signature& other) const { - if (results < other.results) { - return true; - } else if (other.results < results) { - return false; - } else { - return params < other.params; +unsigned Type::getByteSize() const { + assert(isSingle() && "getByteSize does not works with single types"); + Type singleType = *expand().begin(); + switch (singleType) { + case Type::i32: + return 4; + case Type::i64: + return 8; + case Type::f32: + return 4; + case Type::f64: + return 8; + case Type::v128: + return 16; + case Type::anyref: // anyref type is opaque + case Type::exnref: // exnref type is opaque + case Type::none: + case Type::unreachable: + WASM_UNREACHABLE("invalid type"); } + WASM_UNREACHABLE("invalid type"); +} + +Type Type::reinterpret() const { + assert(isSingle() && "reinterpret only works with single types"); + Type singleType = *expand().begin(); + switch (singleType) { + case Type::i32: + return f32; + case Type::i64: + return f64; + case Type::f32: + return i32; + case Type::f64: + return i64; + case Type::v128: + case Type::anyref: + case Type::exnref: + case Type::none: + case Type::unreachable: + WASM_UNREACHABLE("invalid type"); + } + WASM_UNREACHABLE("invalid type"); +} + +FeatureSet Type::getFeatures() const { + FeatureSet feats = FeatureSet::MVP; + for (Type t : expand()) { + switch (t) { + case Type::v128: + feats |= FeatureSet::SIMD; + break; + case Type::anyref: + feats |= FeatureSet::ReferenceTypes; + break; + case Type::exnref: + feats |= FeatureSet::ExceptionHandling; + break; + default: + break; + } + } + return feats; +} + +Type Type::get(unsigned byteSize, bool float_) { + if (byteSize < 4) { + return Type::i32; + } + if (byteSize == 4) { + return float_ ? Type::f32 : Type::i32; + } + if (byteSize == 8) { + return float_ ? Type::f64 : Type::i64; + } + if (byteSize == 16) { + return Type::v128; + } + WASM_UNREACHABLE("invalid size"); } namespace { @@ -170,6 +241,22 @@ template<typename T> std::string genericToString(const T& t) { } // anonymous namespace +std::string Type::toString() const { return genericToString(*this); } + +std::string ParamType::toString() const { return genericToString(*this); } + +std::string ResultType::toString() const { return genericToString(*this); } + +bool Signature::operator<(const Signature& other) const { + if (results < other.results) { + return true; + } else if (other.results < results) { + return false; + } else { + return params < other.params; + } +} + std::ostream& operator<<(std::ostream& os, Type type) { switch (type) { case Type::none: @@ -226,87 +313,4 @@ std::ostream& operator<<(std::ostream& os, Signature sig) { return os << "Signature(" << sig.params << " => " << sig.results << ")"; } -std::string Type::toString() const { return genericToString(*this); } - -std::string ParamType::toString() const { return genericToString(*this); } - -std::string ResultType::toString() const { return genericToString(*this); } - -unsigned getTypeSize(Type type) { - switch (type) { - case Type::i32: - return 4; - case Type::i64: - return 8; - case Type::f32: - return 4; - case Type::f64: - return 8; - case Type::v128: - return 16; - case Type::anyref: // anyref type is opaque - case Type::exnref: // exnref type is opaque - case Type::none: - case Type::unreachable: - WASM_UNREACHABLE("invalid type"); - } - WASM_UNREACHABLE("invalid type"); -} - -FeatureSet getFeatures(Type type) { - FeatureSet feats = FeatureSet::MVP; - for (Type t : type.expand()) { - switch (t) { - case v128: - feats |= FeatureSet::SIMD; - break; - case anyref: - feats |= FeatureSet::ReferenceTypes; - break; - case exnref: - feats |= FeatureSet::ExceptionHandling; - break; - default: - break; - } - } - return feats; -} - -Type getType(unsigned size, bool float_) { - if (size < 4) { - return Type::i32; - } - if (size == 4) { - return float_ ? Type::f32 : Type::i32; - } - if (size == 8) { - return float_ ? Type::f64 : Type::i64; - } - if (size == 16) { - return Type::v128; - } - WASM_UNREACHABLE("invalid size"); -} - -Type reinterpretType(Type type) { - switch (type) { - case Type::i32: - return f32; - case Type::i64: - return f64; - case Type::f32: - return i32; - case Type::f64: - return i64; - case Type::v128: - case Type::anyref: - case Type::exnref: - case Type::none: - case Type::unreachable: - WASM_UNREACHABLE("invalid type"); - } - WASM_UNREACHABLE("invalid type"); -} - } // namespace wasm diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index dcd56892c..55e115d95 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -693,7 +693,7 @@ void FunctionValidator::visitCallIndirect(CallIndirect* curr) { } void FunctionValidator::visitConst(Const* curr) { - shouldBeTrue(getFeatures(curr->type) <= getModule()->features, + shouldBeTrue(curr->type.getFeatures() <= getModule()->features, curr, "all used features should be allowed"); } @@ -1763,15 +1763,15 @@ void FunctionValidator::visitFunction(Function* curr) { "Multivalue functions not allowed yet"); FeatureSet features; for (auto type : curr->sig.params.expand()) { - features |= getFeatures(type); + features |= type.getFeatures(); shouldBeTrue(type.isConcrete(), curr, "params must be concretely typed"); } for (auto type : curr->sig.results.expand()) { - features |= getFeatures(type); + features |= type.getFeatures(); shouldBeTrue(type.isConcrete(), curr, "results must be concretely typed"); } for (auto type : curr->vars) { - features |= getFeatures(type); + features |= type.getFeatures(); shouldBeTrue(type.isConcrete(), curr, "vars must be concretely typed"); } shouldBeTrue(features <= getModule()->features, @@ -2005,7 +2005,7 @@ static void validateExports(Module& module, ValidationInfo& info) { static void validateGlobals(Module& module, ValidationInfo& info) { ModuleUtils::iterDefinedGlobals(module, [&](Global* curr) { - info.shouldBeTrue(getFeatures(curr->type) <= module.features, + info.shouldBeTrue(curr->type.getFeatures() <= module.features, curr->name, "all used types should be allowed"); info.shouldBeTrue( |