summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp271
1 files changed, 181 insertions, 90 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 730129892..49d7128dd 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1444,45 +1444,91 @@ uint64_t WasmBinaryBuilder::getUPtrLEB() {
return wasm.memory.is64() ? getU64LEB() : getU32LEB();
}
+bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) {
+ switch (code) {
+ case BinaryConsts::EncodedType::i32:
+ out = Type::i32;
+ return true;
+ case BinaryConsts::EncodedType::i64:
+ out = Type::i64;
+ return true;
+ case BinaryConsts::EncodedType::f32:
+ out = Type::f32;
+ return true;
+ case BinaryConsts::EncodedType::f64:
+ out = Type::f64;
+ return true;
+ case BinaryConsts::EncodedType::v128:
+ out = Type::v128;
+ return true;
+ case BinaryConsts::EncodedType::funcref:
+ out = Type::funcref;
+ return true;
+ case BinaryConsts::EncodedType::externref:
+ out = Type::externref;
+ return true;
+ case BinaryConsts::EncodedType::anyref:
+ out = Type::anyref;
+ return true;
+ case BinaryConsts::EncodedType::eqref:
+ out = Type::eqref;
+ return true;
+ case BinaryConsts::EncodedType::i31ref:
+ // FIXME: for now, force all inputs to be nullable
+ out = Type(HeapType::i31, Nullable);
+ return true;
+ case BinaryConsts::EncodedType::dataref:
+ // FIXME: for now, force all inputs to be nullable
+ out = Type(HeapType::data, Nullable);
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool WasmBinaryBuilder::getBasicHeapType(int64_t code, HeapType& out) {
+ switch (code) {
+ case BinaryConsts::EncodedHeapType::func:
+ out = HeapType::func;
+ return true;
+ case BinaryConsts::EncodedHeapType::extern_:
+ out = HeapType::ext;
+ return true;
+ case BinaryConsts::EncodedHeapType::any:
+ out = HeapType::any;
+ return true;
+ case BinaryConsts::EncodedHeapType::eq:
+ out = HeapType::eq;
+ return true;
+ case BinaryConsts::EncodedHeapType::i31:
+ out = HeapType::i31;
+ return true;
+ case BinaryConsts::EncodedHeapType::data:
+ out = HeapType::data;
+ return true;
+ default:
+ return false;
+ }
+}
+
Type WasmBinaryBuilder::getType(int initial) {
// Single value types are negative; signature indices are non-negative
if (initial >= 0) {
// TODO: Handle block input types properly.
return getSignatureByTypeIndex(initial).results;
}
+ Type type;
+ if (getBasicType(initial, type)) {
+ return type;
+ }
switch (initial) {
// None only used for block signatures. TODO: Separate out?
case BinaryConsts::EncodedType::Empty:
return Type::none;
- case BinaryConsts::EncodedType::i32:
- return Type::i32;
- case BinaryConsts::EncodedType::i64:
- return Type::i64;
- case BinaryConsts::EncodedType::f32:
- return Type::f32;
- case BinaryConsts::EncodedType::f64:
- return Type::f64;
- case BinaryConsts::EncodedType::v128:
- return Type::v128;
- case BinaryConsts::EncodedType::funcref:
- return Type::funcref;
- case BinaryConsts::EncodedType::externref:
- return Type::externref;
- case BinaryConsts::EncodedType::anyref:
- return Type::anyref;
- case BinaryConsts::EncodedType::eqref:
- return Type::eqref;
case BinaryConsts::EncodedType::nullable:
- return Type(getHeapType(), Nullable);
case BinaryConsts::EncodedType::nonnullable:
// FIXME: for now, force all inputs to be nullable
return Type(getHeapType(), Nullable);
- case BinaryConsts::EncodedType::i31ref:
- // FIXME: for now, force all inputs to be nullable
- return Type(HeapType::BasicHeapType::i31, Nullable);
- case BinaryConsts::EncodedType::dataref:
- // FIXME: for now, force all inputs to be nullable
- return Type(HeapType::BasicHeapType::data, Nullable);
case BinaryConsts::EncodedType::rtt_n: {
auto depth = getU32LEB();
auto heapType = getHeapType();
@@ -1508,54 +1554,15 @@ HeapType WasmBinaryBuilder::getHeapType() {
}
return types[type];
}
- switch (type) {
- case BinaryConsts::EncodedHeapType::func:
- return HeapType::func;
- case BinaryConsts::EncodedHeapType::extern_:
- return HeapType::ext;
- case BinaryConsts::EncodedHeapType::any:
- return HeapType::any;
- case BinaryConsts::EncodedHeapType::eq:
- return HeapType::eq;
- case BinaryConsts::EncodedHeapType::i31:
- return HeapType::i31;
- case BinaryConsts::EncodedHeapType::data:
- return HeapType::data;
- default:
- throwError("invalid wasm heap type: " + std::to_string(type));
+ HeapType ht;
+ if (getBasicHeapType(type, ht)) {
+ return ht;
+ } else {
+ throwError("invalid wasm heap type: " + std::to_string(type));
}
WASM_UNREACHABLE("unexpected type");
}
-Mutability WasmBinaryBuilder::getMutability() {
- switch (getU32LEB()) {
- case 0:
- return Immutable;
- case 1:
- return Mutable;
- default:
- throw ParseException("Expected 0 or 1 for mutability");
- }
-}
-
-Field WasmBinaryBuilder::getField() {
- // The value may be a general wasm type, or one of the types only possible in
- // a field.
- auto initial = getS32LEB();
- if (initial == BinaryConsts::EncodedType::i8) {
- auto mutable_ = getMutability();
- return Field(Field::i8, mutable_);
- }
- if (initial == BinaryConsts::EncodedType::i16) {
- auto mutable_ = getMutability();
- return Field(Field::i16, mutable_);
- }
- // It's a regular wasm value.
- auto type = getType(initial);
- auto mutable_ = getMutability();
- return Field(type, mutable_);
-}
-
Type WasmBinaryBuilder::getConcreteType() {
auto type = getType();
if (!type.isConcrete()) {
@@ -1643,37 +1650,121 @@ void WasmBinaryBuilder::readTypes() {
BYN_TRACE("== readTypes\n");
size_t numTypes = getU32LEB();
BYN_TRACE("num: " << numTypes << std::endl);
+ TypeBuilder builder(numTypes);
+
+ auto makeType = [&](int32_t typeCode) {
+ Type type;
+ if (getBasicType(typeCode, type)) {
+ return type;
+ }
+
+ switch (typeCode) {
+ case BinaryConsts::EncodedType::nullable:
+ case BinaryConsts::EncodedType::nonnullable: {
+ // FIXME: for now, force all inputs to be nullable
+ int64_t htCode = getS64LEB(); // TODO: Actually s33
+ HeapType ht;
+ if (getBasicHeapType(htCode, ht)) {
+ return Type(ht, Nullable);
+ }
+ if (size_t(htCode) >= numTypes) {
+ throwError("invalid type index: " + std::to_string(htCode));
+ }
+ return builder.getTempRefType(size_t(htCode), Nullable);
+ }
+ case BinaryConsts::EncodedType::rtt_n:
+ case BinaryConsts::EncodedType::rtt: {
+ auto depth = typeCode == BinaryConsts::EncodedType::rtt ? Rtt::NoDepth
+ : getU32LEB();
+ int64_t htCode = getS64LEB(); // TODO: Actually s33
+ HeapType ht;
+ if (getBasicHeapType(htCode, ht)) {
+ return Type(Rtt(depth, ht));
+ }
+ if (size_t(htCode) >= numTypes) {
+ throwError("invalid type index: " + std::to_string(htCode));
+ }
+ return builder.getTempRttType(htCode, depth);
+ }
+ default:
+ throwError("unexpected type index: " + std::to_string(typeCode));
+ }
+ WASM_UNREACHABLE("unexpected type");
+ };
+
+ auto readType = [&]() { return makeType(getS32LEB()); };
+
+ auto readSignatureDef = [&]() {
+ std::vector<Type> params;
+ std::vector<Type> results;
+ size_t numParams = getU32LEB();
+ BYN_TRACE("num params: " << numParams << std::endl);
+ for (size_t j = 0; j < numParams; j++) {
+ params.push_back(readType());
+ }
+ auto numResults = getU32LEB();
+ BYN_TRACE("num results: " << numResults << std::endl);
+ for (size_t j = 0; j < numResults; j++) {
+ results.push_back(readType());
+ }
+ return Signature(builder.getTempTupleType(params),
+ builder.getTempTupleType(results));
+ };
+
+ auto readMutability = [&]() {
+ switch (getU32LEB()) {
+ case 0:
+ return Immutable;
+ case 1:
+ return Mutable;
+ default:
+ throw ParseException("Expected 0 or 1 for mutability");
+ }
+ };
+
+ auto readFieldDef = [&]() {
+ // The value may be a general wasm type, or one of the types only possible
+ // in a field.
+ auto typeCode = getS32LEB();
+ if (typeCode == BinaryConsts::EncodedType::i8) {
+ auto mutable_ = readMutability();
+ return Field(Field::i8, mutable_);
+ }
+ if (typeCode == BinaryConsts::EncodedType::i16) {
+ auto mutable_ = readMutability();
+ return Field(Field::i16, mutable_);
+ }
+ // It's a regular wasm value.
+ auto type = makeType(typeCode);
+ auto mutable_ = readMutability();
+ return Field(type, mutable_);
+ };
+
+ auto readStructDef = [&]() {
+ FieldList fields;
+ size_t numFields = getU32LEB();
+ BYN_TRACE("num fields: " << numFields << std::endl);
+ for (size_t j = 0; j < numFields; j++) {
+ fields.push_back(readFieldDef());
+ }
+ return Struct(std::move(fields));
+ };
+
for (size_t i = 0; i < numTypes; i++) {
BYN_TRACE("read one\n");
auto form = getS32LEB();
if (form == BinaryConsts::EncodedType::Func) {
- std::vector<Type> params;
- std::vector<Type> results;
- size_t numParams = getU32LEB();
- BYN_TRACE("num params: " << numParams << std::endl);
- for (size_t j = 0; j < numParams; j++) {
- params.push_back(getConcreteType());
- }
- auto numResults = getU32LEB();
- BYN_TRACE("num results: " << numResults << std::endl);
- for (size_t j = 0; j < numResults; j++) {
- results.push_back(getConcreteType());
- }
- types.emplace_back(Signature(Type(params), Type(results)));
+ builder.setHeapType(i, readSignatureDef());
} else if (form == BinaryConsts::EncodedType::Struct) {
- FieldList fields;
- size_t numFields = getU32LEB();
- BYN_TRACE("num fields: " << numFields << std::endl);
- for (size_t j = 0; j < numFields; j++) {
- fields.push_back(getField());
- }
- types.emplace_back(Struct(fields));
+ builder.setHeapType(i, readStructDef());
} else if (form == BinaryConsts::EncodedType::Array) {
- types.emplace_back(Array(getField()));
+ builder.setHeapType(i, Array(readFieldDef()));
} else {
throwError("bad type form " + std::to_string(form));
}
}
+
+ types = builder.build();
}
Name WasmBinaryBuilder::getFunctionName(Index index) {