in plugins/experimental/wasm/lib/src/wamr/wamr.cc [252:381]
bool Wamr::link(std::string_view /*debug_name*/) {
assert(module_ != nullptr);
WasmImporttypeVec import_types;
wasm_module_imports(module_.get(), import_types.get());
std::vector<wasm_extern_t *> imports;
for (size_t i = 0; i < import_types.get()->size; i++) {
const wasm_name_t *module_name_ptr = wasm_importtype_module(import_types.get()->data[i]);
const wasm_name_t *name_ptr = wasm_importtype_name(import_types.get()->data[i]);
const wasm_externtype_t *extern_type = wasm_importtype_type(import_types.get()->data[i]);
if (std::strlen(name_ptr->data) == 0) {
fail(FailState::UnableToInitializeCode, std::string("The name field of import_types[") +
std::to_string(i) + std::string("] is empty"));
return false;
}
std::string_view module_name(module_name_ptr->data);
std::string_view name(name_ptr->data);
switch (wasm_externtype_kind(extern_type)) {
case WASM_EXTERN_FUNC: {
auto it = host_functions_.find(std::string(module_name) + "." + std::string(name));
if (it == host_functions_.end()) {
fail(FailState::UnableToInitializeCode,
std::string("Failed to load Wasm module due to a missing import: ") +
std::string(module_name) + "." + std::string(name));
return false;
}
auto *func = it->second->callback_.get();
const wasm_functype_t *exp_type = wasm_externtype_as_functype_const(extern_type);
WasmFunctypePtr actual_type = wasm_func_type(it->second->callback_.get());
if (!equalValTypes(wasm_functype_params(exp_type), wasm_functype_params(actual_type.get())) ||
!equalValTypes(wasm_functype_results(exp_type),
wasm_functype_results(actual_type.get()))) {
fail(
FailState::UnableToInitializeCode,
std::string("Failed to load Wasm module due to an import type mismatch for function ") +
std::string(module_name) + "." + std::string(name) +
", want: " + printValTypes(wasm_functype_params(exp_type)) + " -> " +
printValTypes(wasm_functype_results(exp_type)) +
", but host exports: " + printValTypes(wasm_functype_params(actual_type.get())) +
" -> " + printValTypes(wasm_functype_results(actual_type.get())));
return false;
}
imports.push_back(wasm_func_as_extern(func));
} break;
case WASM_EXTERN_GLOBAL: {
// TODO(mathetake): add support when/if needed.
fail(FailState::UnableToInitializeCode,
"Failed to load Wasm module due to a missing import: " + std::string(module_name) + "." +
std::string(name));
return false;
} break;
case WASM_EXTERN_MEMORY: {
assert(memory_ == nullptr);
const wasm_memorytype_t *memory_type =
wasm_externtype_as_memorytype_const(extern_type); // owned by `extern_type`
if (memory_type == nullptr) {
return false;
}
memory_ = wasm_memory_new(store_.get(), memory_type);
if (memory_ == nullptr) {
return false;
}
imports.push_back(wasm_memory_as_extern(memory_.get()));
} break;
case WASM_EXTERN_TABLE: {
assert(table_ == nullptr);
const wasm_tabletype_t *table_type =
wasm_externtype_as_tabletype_const(extern_type); // owned by `extern_type`
if (table_type == nullptr) {
return false;
}
table_ = wasm_table_new(store_.get(), table_type, nullptr);
if (table_ == nullptr) {
return false;
}
imports.push_back(wasm_table_as_extern(table_.get()));
} break;
}
}
if (import_types.get()->size != imports.size()) {
return false;
}
wasm_extern_vec_t imports_vec = {imports.size(), imports.data(), imports.size()};
instance_ = wasm_instance_new(store_.get(), module_.get(), &imports_vec, nullptr);
if (instance_ == nullptr) {
fail(FailState::UnableToInitializeCode, "Failed to create new Wasm instance");
return false;
}
WasmExportTypeVec export_types;
wasm_module_exports(module_.get(), export_types.get());
WasmExternVec exports;
wasm_instance_exports(instance_.get(), exports.get());
for (size_t i = 0; i < export_types.get()->size; i++) {
wasm_extern_t *actual_extern = exports.get()->data[i];
wasm_externkind_t kind = wasm_extern_kind(actual_extern);
assert(kind == wasm_externtype_kind(wasm_exporttype_type(export_types.get()->data[i])));
switch (kind) {
case WASM_EXTERN_FUNC: {
WasmFuncPtr func = wasm_func_copy(wasm_extern_as_func(actual_extern));
const wasm_name_t *name_ptr = wasm_exporttype_name(export_types.get()->data[i]);
module_functions_.insert_or_assign(std::string(name_ptr->data), std::move(func));
} break;
case WASM_EXTERN_GLOBAL: {
// TODO(mathetake): add support when/if needed.
} break;
case WASM_EXTERN_MEMORY: {
assert(memory_ == nullptr);
memory_ = wasm_memory_copy(wasm_extern_as_memory(actual_extern));
if (memory_ == nullptr) {
return false;
}
} break;
case WASM_EXTERN_TABLE: {
// TODO(mathetake): add support when/if needed.
} break;
}
}
return true;
}