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.cpp145
1 files changed, 129 insertions, 16 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b343c6caf..a96039bc2 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -221,7 +221,7 @@ void WasmBinaryWriter::writeTypes() {
for (auto& sigType : {sig.params, sig.results}) {
o << U32LEB(sigType.size());
for (const auto& type : sigType) {
- o << binaryType(type);
+ writeType(type);
}
}
}
@@ -250,7 +250,7 @@ void WasmBinaryWriter::writeImports() {
BYN_TRACE("write one global\n");
writeImportHeader(global);
o << U32LEB(int32_t(ExternalKind::Global));
- o << binaryType(global->type);
+ writeType(global->type);
o << U32LEB(global->mutable_);
});
ModuleUtils::iterImportedEvents(*wasm, [&](Event* event) {
@@ -389,7 +389,7 @@ void WasmBinaryWriter::writeGlobals() {
BYN_TRACE("write one\n");
size_t i = 0;
for (const auto& t : global->type) {
- o << binaryType(t);
+ writeType(t);
o << U32LEB(global->mutable_);
if (global->type.size() == 1) {
writeExpression(global->init);
@@ -492,7 +492,12 @@ uint32_t WasmBinaryWriter::getEventIndex(Name name) const {
uint32_t WasmBinaryWriter::getTypeIndex(Signature sig) const {
auto it = typeIndices.find(sig);
- assert(it != typeIndices.end());
+#ifndef NDEBUG
+ if (it == typeIndices.end()) {
+ std::cout << "Missing signature: " << sig << '\n';
+ assert(0);
+ }
+#endif
return it->second;
}
@@ -799,6 +804,8 @@ void WasmBinaryWriter::writeFeaturesSection() {
return BinaryConsts::UserSections::GCFeature;
case FeatureSet::Memory64:
return BinaryConsts::UserSections::Memory64Feature;
+ case FeatureSet::TypedFunctionReferences:
+ return BinaryConsts::UserSections::TypedFunctionReferencesFeature;
default:
WASM_UNREACHABLE("unexpected feature flag");
}
@@ -950,6 +957,100 @@ void WasmBinaryWriter::finishUp() {
}
}
+void WasmBinaryWriter::writeType(Type type) {
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ // TODO: fully handle non-signature reference types (GC), and in reading
+ if (heapType.isSignature()) {
+ if (type.isNullable()) {
+ o << S32LEB(BinaryConsts::EncodedType::nullable);
+ } else {
+ o << S32LEB(BinaryConsts::EncodedType::nonnullable);
+ }
+ writeHeapType(heapType);
+ return;
+ }
+ }
+ int ret = 0;
+ TODO_SINGLE_COMPOUND(type);
+ switch (type.getBasic()) {
+ // None only used for block signatures. TODO: Separate out?
+ case Type::none:
+ ret = BinaryConsts::EncodedType::Empty;
+ break;
+ case Type::i32:
+ ret = BinaryConsts::EncodedType::i32;
+ break;
+ case Type::i64:
+ ret = BinaryConsts::EncodedType::i64;
+ break;
+ case Type::f32:
+ ret = BinaryConsts::EncodedType::f32;
+ break;
+ case Type::f64:
+ ret = BinaryConsts::EncodedType::f64;
+ break;
+ case Type::v128:
+ ret = BinaryConsts::EncodedType::v128;
+ break;
+ case Type::funcref:
+ ret = BinaryConsts::EncodedType::funcref;
+ break;
+ case Type::externref:
+ ret = BinaryConsts::EncodedType::externref;
+ break;
+ case Type::exnref:
+ ret = BinaryConsts::EncodedType::exnref;
+ break;
+ case Type::anyref:
+ ret = BinaryConsts::EncodedType::anyref;
+ break;
+ case Type::eqref:
+ ret = BinaryConsts::EncodedType::eqref;
+ break;
+ case Type::i31ref:
+ ret = BinaryConsts::EncodedType::i31ref;
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+ o << S32LEB(ret);
+}
+
+void WasmBinaryWriter::writeHeapType(HeapType type) {
+ if (type.isSignature()) {
+ auto sig = type.getSignature();
+ o << S32LEB(getTypeIndex(sig));
+ return;
+ }
+ int ret = 0;
+ switch (type.kind) {
+ case HeapType::FuncKind:
+ ret = BinaryConsts::EncodedHeapType::func;
+ break;
+ case HeapType::ExternKind:
+ ret = BinaryConsts::EncodedHeapType::extern_;
+ break;
+ case HeapType::ExnKind:
+ ret = BinaryConsts::EncodedHeapType::exn;
+ break;
+ case HeapType::AnyKind:
+ ret = BinaryConsts::EncodedHeapType::any;
+ break;
+ case HeapType::EqKind:
+ ret = BinaryConsts::EncodedHeapType::eq;
+ break;
+ case HeapType::I31Kind:
+ ret = BinaryConsts::EncodedHeapType::i31;
+ break;
+ case HeapType::SignatureKind:
+ case HeapType::StructKind:
+ case HeapType::ArrayKind:
+ WASM_UNREACHABLE("TODO: compound GC types");
+ }
+ o << S32LEB(ret); // TODO: Actually encoded as s33
+}
+
// reader
bool WasmBinaryBuilder::hasDWARFSections() {
@@ -1253,6 +1354,10 @@ Type WasmBinaryBuilder::getType() {
return Type::anyref;
case BinaryConsts::EncodedType::eqref:
return Type::eqref;
+ case BinaryConsts::EncodedType::nullable:
+ return Type(getHeapType(), /* nullable = */ true);
+ case BinaryConsts::EncodedType::nonnullable:
+ return Type(getHeapType(), /* nullable = */ false);
case BinaryConsts::EncodedType::i31ref:
return Type::i31ref;
default:
@@ -1581,6 +1686,18 @@ void WasmBinaryBuilder::readFunctionSignatures() {
}
}
+Signature WasmBinaryBuilder::getFunctionSignatureByIndex(Index index) {
+ Signature sig;
+ if (index < functionImports.size()) {
+ return functionImports[index]->sig;
+ }
+ Index adjustedIndex = index - functionImports.size();
+ if (adjustedIndex >= functionSignatures.size()) {
+ throwError("invalid function index");
+ }
+ return functionSignatures[adjustedIndex];
+}
+
void WasmBinaryBuilder::readFunctions() {
BYN_TRACE("== readFunctions\n");
size_t total = getU32LEB();
@@ -2471,6 +2588,9 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) {
wasm.features.setGC();
} else if (name == BinaryConsts::UserSections::Memory64Feature) {
wasm.features.setMemory64();
+ } else if (name ==
+ BinaryConsts::UserSections::TypedFunctionReferencesFeature) {
+ wasm.features.setTypedFunctionReferences();
}
}
}
@@ -3042,17 +3162,7 @@ void WasmBinaryBuilder::visitSwitch(Switch* curr) {
void WasmBinaryBuilder::visitCall(Call* curr) {
BYN_TRACE("zz node: Call\n");
auto index = getU32LEB();
- Signature sig;
- if (index < functionImports.size()) {
- auto* import = functionImports[index];
- sig = import->sig;
- } else {
- Index adjustedIndex = index - functionImports.size();
- if (adjustedIndex >= functionSignatures.size()) {
- throwError("invalid call index");
- }
- sig = functionSignatures[adjustedIndex];
- }
+ auto sig = getFunctionSignatureByIndex(index);
auto num = sig.params.size();
curr->operands.resize(num);
for (size_t i = 0; i < num; i++) {
@@ -5169,7 +5279,10 @@ void WasmBinaryBuilder::visitRefFunc(RefFunc* curr) {
throwError("ref.func: invalid call index");
}
functionRefs[index].push_back(curr); // we don't know function names yet
- curr->finalize();
+ // To support typed function refs, we give the reference not just a general
+ // funcref, but a specific subtype with the actual signature.
+ curr->finalize(
+ Type(HeapType(getFunctionSignatureByIndex(index)), /* nullable = */ true));
}
void WasmBinaryBuilder::visitRefEq(RefEq* curr) {