summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp4
-rw-r--r--src/wasm/wasm-s-parser.cpp6
-rw-r--r--src/wasm/wasm-type.cpp184
-rw-r--r--src/wasm/wasm-validator.cpp10
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(