diff options
author | Jérôme Vouillon <jerome.vouillon@gmail.com> | 2024-03-27 17:26:57 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-27 14:26:57 -0700 |
commit | eae2638a53e778e24e1ed042f2e16aa0b3b127a5 (patch) | |
tree | e5e3bf1c41c86050cba7953f6097799bf6100ec1 /src | |
parent | 61877e9bbc6df38d3bb342a695ead0bc290fbb40 (diff) | |
download | binaryen-eae2638a53e778e24e1ed042f2e16aa0b3b127a5.tar.gz binaryen-eae2638a53e778e24e1ed042f2e16aa0b3b127a5.tar.bz2 binaryen-eae2638a53e778e24e1ed042f2e16aa0b3b127a5.zip |
wasm-merge: Check that the types of imports and exports match (#6437)
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/wasm-merge.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp index ec67d56fc..8e8e2d80d 100644 --- a/src/tools/wasm-merge.cpp +++ b/src/tools/wasm-merge.cpp @@ -381,6 +381,38 @@ void copyModuleContents(Module& input, Name inputName) { // TODO: type names, features, debug info, custom sections, dylink info, etc. } +void reportTypeMismatch(bool& valid, const char* kind, Importable* import) { + valid = false; + std::cerr << "Type mismatch when importing " << kind << " " << import->base + << " from module " << import->module << " ($" << import->name + << "): "; +} + +// Check that the export and import limits match. +template<typename T> +void checkLimit(bool& valid, const char* kind, T* export_, T* import) { + if (export_->initial < import->initial) { + reportTypeMismatch(valid, kind, import); + std::cerr << "minimal size " << export_->initial + << " is smaller than expected minimal size " << import->initial + << ".\n"; + } + if (import->hasMax()) { + if (!export_->hasMax()) { + reportTypeMismatch(valid, kind, import); + std::cerr << "expecting a bounded " << kind + << " but the " + "imported " + << kind << " is unbounded.\n"; + } else if (export_->max > import->max) { + reportTypeMismatch(valid, kind, import); + std::cerr << "maximal size " << export_->max + << " is larger than expected maximal size " << import->max + << ".\n"; + } + } +} + // Find pairs of matching imports and exports, and make uses of the import refer // to the exported item (which has been merged into the module). void fuseImportsAndExports() { @@ -428,6 +460,82 @@ void fuseImportsAndExports() { } }); + // Make sure that the export types match the import types. + bool valid = true; + ModuleUtils::iterImportedFunctions(merged, [&](Function* import) { + auto internalName = kindModuleExportMaps[ExternalKind::Function] + [import->module][import->base]; + if (internalName.is()) { + auto* export_ = merged.getFunction(internalName); + if (!HeapType::isSubType(export_->type, import->type)) { + reportTypeMismatch(valid, "function", import); + std::cerr << "type " << export_->type << " is not a subtype of " + << import->type << ".\n"; + } + } + }); + ModuleUtils::iterImportedTables(merged, [&](Table* import) { + auto internalName = + kindModuleExportMaps[ExternalKind::Table][import->module][import->base]; + if (internalName.is()) { + auto* export_ = merged.getTable(internalName); + checkLimit(valid, "table", export_, import); + if (export_->type != import->type) { + reportTypeMismatch(valid, "table", import); + std::cerr << "export type " << export_->type + << " is different from import type " << import->type << ".\n"; + } + } + }); + ModuleUtils::iterImportedMemories(merged, [&](Memory* import) { + auto internalName = + kindModuleExportMaps[ExternalKind::Memory][import->module][import->base]; + if (internalName.is()) { + auto* export_ = merged.getMemory(internalName); + if (export_->is64() != import->is64()) { + reportTypeMismatch(valid, "memory", import); + std::cerr << "index type should match.\n"; + } + checkLimit(valid, "memory", export_, import); + } + }); + ModuleUtils::iterImportedGlobals(merged, [&](Global* import) { + auto internalName = + kindModuleExportMaps[ExternalKind::Global][import->module][import->base]; + if (internalName.is()) { + auto* export_ = merged.getGlobal(internalName); + if (export_->mutable_ != import->mutable_) { + reportTypeMismatch(valid, "global", import); + std::cerr << "mutability should match.\n"; + } + if (export_->mutable_ && export_->type != import->type) { + reportTypeMismatch(valid, "global", import); + std::cerr << "export type " << export_->type + << " is different from import type " << import->type << ".\n"; + } + if (!export_->mutable_ && !Type::isSubType(export_->type, import->type)) { + reportTypeMismatch(valid, "global", import); + std::cerr << "type " << export_->type << " is not a subtype of " + << import->type << ".\n"; + } + } + }); + ModuleUtils::iterImportedTags(merged, [&](Tag* import) { + auto internalName = + kindModuleExportMaps[ExternalKind::Tag][import->module][import->base]; + if (internalName.is()) { + auto* export_ = merged.getTag(internalName); + if (HeapType(export_->sig) != HeapType(import->sig)) { + reportTypeMismatch(valid, "tag", import); + std::cerr << "export type " << export_->sig + << " is different from import type " << import->sig << ".\n"; + } + } + }); + if (!valid) { + Fatal() << "import/export mismatches"; + } + // Update the things we found. updateNames(merged, kindNameUpdates); } |