diff options
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 2ee528392..b351a46e5 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -69,6 +69,7 @@ void WasmBinaryWriter::write() { } writeLateUserSections(); + writeFeaturesSection(); finishUp(); } @@ -356,7 +357,9 @@ void WasmBinaryWriter::writeFunctionTableDeclaration() { } void WasmBinaryWriter::writeTableElements() { - if (!wasm->table.exists) return; + if (!wasm->table.exists || wasm->table.segments.size() == 0) { + return; + } if (debug) std::cerr << "== writeTableElements" << std::endl; auto start = startSection(BinaryConsts::Section::Element); @@ -486,7 +489,7 @@ void WasmBinaryWriter::writeLateUserSections() { } void WasmBinaryWriter::writeUserSection(const UserSection& section) { - auto start = startSection(0); + auto start = startSection(BinaryConsts::User); writeInlineString(section.name.c_str()); for (size_t i = 0; i < section.data.size(); i++) { o << uint8_t(section.data[i]); @@ -494,6 +497,41 @@ void WasmBinaryWriter::writeUserSection(const UserSection& section) { finishSection(start); } +void WasmBinaryWriter::writeFeaturesSection() { + if (!wasm->hasFeaturesSection || wasm->features.isMVP()) { + return; + } + + // TODO(tlively): unify feature names with rest of toolchain and use + // FeatureSet::toString() + auto toString = [](FeatureSet::Feature f) { + switch (f) { + case FeatureSet::Atomics: return "atomics"; + case FeatureSet::MutableGlobals: return "mutable-globals"; + case FeatureSet::TruncSat: return "nontrapping-fptoint"; + case FeatureSet::SIMD: return "simd128"; + case FeatureSet::BulkMemory: return "bulk-memory"; + case FeatureSet::SignExt: return "sign-ext"; + default: WASM_UNREACHABLE(); + } + }; + + std::vector<const char*> features; + wasm->features.iterFeatures([&](FeatureSet::Feature f) { + features.push_back(toString(f)); + }); + + auto start = startSection(BinaryConsts::User); + writeInlineString(BinaryConsts::UserSections::TargetFeatures); + o << U32LEB(features.size()); + for (auto& f : features) { + o << uint8_t(BinaryConsts::FeatureUsed); + writeInlineString(f); + } + finishSection(start); +} + + void WasmBinaryWriter::writeDebugLocation(const Function::DebugLocation& loc) { if (loc == lastDebugLocation) { return; @@ -648,6 +686,8 @@ void WasmBinaryBuilder::readUserSection(size_t payloadLen) { payloadLen -= read; if (sectionName.equals(BinaryConsts::UserSections::Name)) { readNames(payloadLen); + } else if (sectionName.equals(BinaryConsts::UserSections::TargetFeatures)) { + readFeatures(payloadLen); } else { // an unfamiliar custom section if (sectionName.equals(BinaryConsts::UserSections::Linking)) { @@ -1600,6 +1640,48 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) { } } +void WasmBinaryBuilder::readFeatures(size_t payloadLen) { + wasm.hasFeaturesSection = true; + wasm.features = FeatureSet::MVP; + + auto sectionPos = pos; + size_t num_feats = getU32LEB(); + for (size_t i = 0; i < num_feats; ++i) { + uint8_t prefix = getInt8(); + if (prefix != BinaryConsts::FeatureUsed) { + if (prefix == BinaryConsts::FeatureRequired) { + throwError("Required features not supported"); + } else if (prefix == BinaryConsts::FeatureDisallowed) { + throwError("Disallowed features not supported"); + } else { + throwError("Unrecognized feature policy prefix"); + } + } + + Name name = getInlineString(); + if (pos > sectionPos + payloadLen) { + throwError("ill-formed string extends beyond section"); + } + + if (name == BinaryConsts::UserSections::AtomicsFeature) { + wasm.features.setAtomics(); + } else if (name == BinaryConsts::UserSections::BulkMemoryFeature) { + wasm.features.setBulkMemory(); + } else if (name == BinaryConsts::UserSections::ExceptionHandlingFeature) { + WASM_UNREACHABLE(); // TODO: exception handling + } else if (name == BinaryConsts::UserSections::TruncSatFeature) { + wasm.features.setTruncSat(); + } else if (name == BinaryConsts::UserSections::SignExtFeature) { + wasm.features.setSignExt(); + } else if (name == BinaryConsts::UserSections::SIMD128Feature) { + wasm.features.setSIMD(); + } + } + if (pos != sectionPos + payloadLen) { + throwError("bad features section size"); + } +} + BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (pos == endOfFunction) { throwError("Reached function end without seeing End opcode"); |