diff options
-rw-r--r-- | src/c-writer.cc | 453 | ||||
-rwxr-xr-x | test/run-spec-wasm2c.py | 30 | ||||
-rw-r--r-- | test/spec-wasm2c-prefix.c | 40 | ||||
-rw-r--r-- | test/wasm2c/add.txt | 30 | ||||
-rw-r--r-- | test/wasm2c/hello.txt | 78 | ||||
-rw-r--r-- | test/wasm2c/minimal.txt | 16 | ||||
-rw-r--r-- | wasm2c/README.md | 142 | ||||
-rw-r--r-- | wasm2c/examples/callback/callback.wat | 2 | ||||
-rw-r--r-- | wasm2c/examples/callback/main.c | 17 | ||||
-rw-r--r-- | wasm2c/examples/fac/fac.c | 20 | ||||
-rw-r--r-- | wasm2c/examples/fac/fac.h | 12 | ||||
-rw-r--r-- | wasm2c/examples/fac/main.c | 8 | ||||
-rw-r--r-- | wasm2c/examples/rot13/main.c | 48 |
13 files changed, 528 insertions, 368 deletions
diff --git a/src/c-writer.cc b/src/c-writer.cc index 9d637ee5..67b3db3c 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -180,7 +180,7 @@ class CWriter { c_stream_(c_stream), h_stream_(h_stream), header_name_(header_name) { - module_prefix_ = MangleName(options_.module_name); + module_prefix_ = MangleModuleName(options_.module_name); } Result WriteModule(const Module&); @@ -213,16 +213,32 @@ class CWriter { static constexpr char MangleField(ModuleFieldType); static std::string MangleMultivalueTypes(const TypeVector&); static std::string MangleTagTypes(const TypeVector&); + static std::string Mangle(std::string_view name, bool double_underscores); static std::string MangleName(std::string_view); - static std::string LegalizeName(std::string_view); - std::string ExportName(std::string_view mangled_name); + static std::string MangleModuleName(std::string_view); + std::string ExportName(std::string_view module_name, + std::string_view export_name); + std::string ExportName(std::string_view export_name); std::string ModuleInstanceTypeName() const; - static std::string MangleModuleInstanceName(std::string_view module_name); - static std::string MangleModuleInstanceTypeName(std::string_view module_name); - std::string DefineName(SymbolSet*, std::string_view); + static std::string ModuleInstanceTypeName(std::string_view module_name); + void ClaimName(SymbolSet& set, + SymbolMap& map, + char type_suffix, + std::string_view wasm_name, + const std::string& c_name); + std::string FindUniqueName(SymbolSet& set, std::string_view proposed_name); + std::string ClaimUniqueName(SymbolSet& set, + SymbolMap& map, + char type_suffix, + std::string_view wasm_name, + const std::string& proposed_c_name); void DefineImportName(const Import* import, std::string_view module_name, std::string_view field_name); + void ReserveExportNames(); + void ReserveExportName(std::string_view); + std::string DefineImportedModuleInstanceName(std::string_view name); + std::string DefineInstanceMemberName(ModuleFieldType, std::string_view); std::string DefineGlobalScopeName(ModuleFieldType, std::string_view); std::string DefineLocalScopeName(std::string_view name, bool is_label); std::string DefineParamName(std::string_view); @@ -408,6 +424,9 @@ static constexpr char kParamSuffix = 'a' + static_cast<char>(ModuleFieldType::Tag) + 1; static constexpr char kLabelSuffix = kParamSuffix + 1; +static constexpr char kSymbolPrefix[] = "w2c_"; +static constexpr char kAdminSymbolPrefix[] = "wasm2c_"; + size_t CWriter::MarkTypeStack() const { return type_stack_.size(); } @@ -527,87 +546,212 @@ std::string CWriter::MangleTagTypes(const TypeVector& types) { return result; } +/* The C symbol for an export from this module. */ +std::string CWriter::ExportName(std::string_view export_name) { + return kSymbolPrefix + module_prefix_ + '_' + MangleName(export_name); +} + +/* The C symbol for an export from an arbitrary module. */ // static -std::string CWriter::MangleName(std::string_view name) { - const char kPrefix = 'Z'; - std::string result = "Z_"; +std::string CWriter::ExportName(std::string_view module_name, + std::string_view export_name) { + return kSymbolPrefix + MangleModuleName(module_name) + '_' + + MangleName(export_name); +} - if (!name.empty()) { - for (unsigned char c : name) { - if ((isalnum(c) && c != kPrefix) || c == '_') { - result += c; - } else { - result += kPrefix; - result += StringPrintf("%02X", static_cast<uint8_t>(c)); - } - } - } +/* The type name of an instance of this module. */ +std::string CWriter::ModuleInstanceTypeName() const { + return kSymbolPrefix + module_prefix_; +} - return result; +/* The type name of an instance of an arbitrary module. */ +// static +std::string CWriter::ModuleInstanceTypeName(std::string_view module_name) { + return kSymbolPrefix + MangleModuleName(module_name); } -std::string CWriter::ExportName(std::string_view mangled_name) { - return module_prefix_ + std::string(mangled_name); +/* + * Hardcoded "C"-locale versions of isalpha/isdigit/isalnum/isxdigit for use + * in CWriter::Mangle(). We don't use the standard isalpha/isdigit/isalnum + * because the caller might have changed the current locale. + */ +static bool internal_isalpha(uint8_t ch) { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); } -std::string CWriter::ModuleInstanceTypeName() const { - return module_prefix_ + "_instance_t"; +static bool internal_isdigit(uint8_t ch) { + return (ch >= '0' && ch <= '9'); } -// static -std::string CWriter::MangleModuleInstanceName(std::string_view module_name) { - return MangleName(module_name) + "_instance"; +static bool internal_isalnum(uint8_t ch) { + return internal_isalpha(ch) || internal_isdigit(ch); } -// static -std::string CWriter::MangleModuleInstanceTypeName( - std::string_view module_name) { - return MangleName(module_name) + "_instance_t"; +static bool internal_ishexdigit(uint8_t ch) { + return internal_isdigit(ch) || (ch >= 'A' && ch <= 'F'); // capitals only } // static -std::string CWriter::LegalizeName(std::string_view name) { - if (name.empty()) - return "_"; +std::string CWriter::Mangle(std::string_view name, bool double_underscores) { + /* + * Name mangling transforms arbitrary Wasm names into "safe" C names + * in a deterministic way. To avoid collisions, distinct Wasm names must be + * transformed into distinct C names. + * + * The rules implemented here are: + * 1) any hex digit ('A' through 'F') that follows the sequence "0x" + * is escaped + * 2) any underscore at the beginning, at the end, or following another + * underscore, is escaped + * 3) if double_underscores is set, underscores are replaced with + * two underscores. + * 4) otherwise, any alphanumeric character is kept as-is, + * and any other character is escaped + * + * "Escaped" means the character is represented with the sequence "0xAB", + * where A B are hex digits ('0'-'9' or 'A'-'F') representing the character's + * numeric value. + * + * Module names are mangled with double_underscores=true to prevent + * collisions between, e.g., a module "alfa" with export + * "bravo_charlie" vs. a module "alfa_bravo" with export "charlie". + */ + + enum State { Any, Zero, ZeroX, ZeroXHexDigit } state{Any}; + bool last_was_underscore = false; std::string result; - result = isalpha(static_cast<unsigned char>(name[0])) ? name[0] : '_'; - for (size_t i = 1; i < name.size(); ++i) - result += isalnum(static_cast<unsigned char>(name[i])) ? name[i] : '_'; + auto append_escaped = [&](const uint8_t ch) { + result += "0x" + StringPrintf("%02X", ch); + last_was_underscore = false; + state = Any; + }; + + auto append_verbatim = [&](const uint8_t ch) { + result += ch; + last_was_underscore = (ch == '_'); + }; + + for (auto it = name.begin(); it != name.end(); ++it) { + const uint8_t ch = *it; + switch (state) { + case Any: + state = (ch == '0') ? Zero : Any; + break; + case Zero: + state = (ch == 'x') ? ZeroX : Any; + break; + case ZeroX: + state = internal_ishexdigit(ch) ? ZeroXHexDigit : Any; + break; + case ZeroXHexDigit: + WABT_UNREACHABLE; + break; + } - // In addition to containing valid characters for C, we must also avoid - // colliding with things C cares about, such as reserved words (e.g. "void") - // or a function name like main() (which a compiler will complain about if we - // define it with another type). To avoid such problems, prefix. - result = "w2c_" + result; + /* rule 1 */ + if (state == ZeroXHexDigit) { + append_escaped(ch); + continue; + } + + /* rule 2 */ + if ((ch == '_') && ((it == name.begin()) || (std::next(it) == name.end()) || + last_was_underscore)) { + append_escaped(ch); + continue; + } + + /* rule 3 */ + if (double_underscores && ch == '_') { + append_verbatim(ch); + append_verbatim(ch); + continue; + } + + /* rule 4 */ + if (internal_isalnum(ch) || (ch == '_')) { + append_verbatim(ch); + } else { + append_escaped(ch); + } + } return result; } -std::string CWriter::DefineName(SymbolSet* set, std::string_view name) { - std::string legal = LegalizeName(name); - if (set->find(legal) != set->end()) { - std::string base = legal + "_"; +// static +std::string CWriter::MangleName(std::string_view name) { + return Mangle(name, false); +} + +// static +std::string CWriter::MangleModuleName(std::string_view name) { + return Mangle(name, true); +} + +/* + * Allocate a C symbol (must be unused) in the SymbolSet, + * and a mapping from the Wasm name (tagged with + * the index space of the name) to that C symbol. + */ +void CWriter::ClaimName(SymbolSet& set, + SymbolMap& map, + char type_suffix, + std::string_view wasm_name, + const std::string& c_name) { + const std::string type_tagged_wasm_name = + std::string(wasm_name) + type_suffix; + + [[maybe_unused]] bool success; + success = set.insert(c_name).second; + assert(success); + + success = map.emplace(type_tagged_wasm_name, c_name).second; + assert(success); +} + +/* + * Make a proposed C symbol unique in a given symbol set by appending + * an integer to the symbol if necessary. + */ +std::string CWriter::FindUniqueName(SymbolSet& set, + std::string_view proposed_name) { + std::string unique{proposed_name}; + if (set.find(unique) != set.end()) { + std::string base = unique + "_"; size_t count = 0; do { - legal = base + std::to_string(count++); - } while (set->find(legal) != set->end()); + unique = base + std::to_string(count++); + } while (set.find(unique) != set.end()); } - set->insert(legal); - return legal; + return unique; +} + +/* + * Find a unique C symbol in the symbol set and claim it (mapping the + * type-tagged Wasm name to it). + */ +std::string CWriter::ClaimUniqueName(SymbolSet& set, + SymbolMap& map, + char type_suffix, + std::string_view wasm_name, + const std::string& proposed_c_name) { + const std::string unique = FindUniqueName(set, proposed_c_name); + ClaimName(set, map, type_suffix, wasm_name, unique); + return unique; } std::string_view StripLeadingDollar(std::string_view name) { - if (!name.empty() && name[0] == '$') { - name.remove_prefix(1); - } + assert(!name.empty()); + assert(name.front() == '$'); + name.remove_prefix(1); return name; } void CWriter::DefineImportName(const Import* import, std::string_view module, std::string_view field_name) { - std::string mangled = MangleName(module) + MangleName(field_name); std::string name; ModuleFieldType type; @@ -636,31 +780,40 @@ void CWriter::DefineImportName(const Import* import, import_syms_.insert(name); import_module_sym_map_.emplace(name, import->module_name); - global_syms_.insert(mangled); - [[maybe_unused]] bool success = - global_sym_map_.emplace(name + MangleField(type), mangled).second; - assert(success); + + const std::string mangled = ExportName(module, field_name); + global_syms_.erase(mangled); // duplicate imports are allowed + ClaimName(global_syms_, global_sym_map_, MangleField(type), name, mangled); +} + +/* + * Reserve a C symbol for the public name of a module's export. The + * format of these is "w2c_" + the module prefix + "_" + the mangled + * export name. Reserving the symbol prevents internal functions and + * other names from shadowing/overlapping the exports. + */ +void CWriter::ReserveExportName(std::string_view name) { + ClaimName(global_syms_, global_sym_map_, MangleField(ModuleFieldType::Export), + name, ExportName(name)); } +/* + * Names for functions, function types, tags, and segments are globally unique + * across modules (formatted the same as an export, as "w2c_" + module prefix + + * "_" + the name, made unique if necessary). + */ std::string CWriter::DefineGlobalScopeName(ModuleFieldType type, std::string_view name) { - std::string mangled = std::string(name) + MangleField(type); - std::string unique = DefineName(&global_syms_, StripLeadingDollar(name)); - [[maybe_unused]] bool success = - global_sym_map_.emplace(mangled, unique).second; - assert(success); - return unique; + return ClaimUniqueName(global_syms_, global_sym_map_, MangleField(type), name, + ExportName(StripLeadingDollar(name))); } +/* Names for params, locals, and stack vars are formatted as "w2c_" + name. */ std::string CWriter::DefineLocalScopeName(std::string_view name, bool is_label) { - std::string mangled = - std::string(name) + (is_label ? kLabelSuffix : kParamSuffix); - std::string unique = DefineName(&local_syms_, StripLeadingDollar(name)); - [[maybe_unused]] bool success = - local_sym_map_.emplace(mangled, unique).second; - assert(success); - return unique; + return ClaimUniqueName(local_syms_, local_sym_map_, + is_label ? kLabelSuffix : kParamSuffix, name, + kSymbolPrefix + MangleName(StripLeadingDollar(name))); } std::string CWriter::DefineParamName(std::string_view name) { @@ -674,7 +827,8 @@ std::string CWriter::DefineLabelName(std::string_view name) { std::string CWriter::DefineStackVarName(Index index, Type type, std::string_view name) { - std::string unique = DefineName(&local_syms_, name); + std::string unique = + FindUniqueName(local_syms_, kSymbolPrefix + MangleName(name)); StackTypePair stp = {index, type}; [[maybe_unused]] bool success = stack_var_sym_map_.emplace(stp, unique).second; @@ -682,6 +836,27 @@ std::string CWriter::DefineStackVarName(Index index, return unique; } +/* + * Members of the module instance (globals, tables, and memories) are formatted + * as "w2c_" + the mangled name of the element (made unique if necessary). + */ +std::string CWriter::DefineInstanceMemberName(ModuleFieldType type, + std::string_view name) { + return ClaimUniqueName(global_syms_, global_sym_map_, MangleField(type), name, + kSymbolPrefix + MangleName(StripLeadingDollar(name))); +} + +/* + * The name of a module-instance member that points to the originating + * instance of an imported function is formatted as "w2c_" + originating + * module prefix + "_instance". + */ +std::string CWriter::DefineImportedModuleInstanceName(std::string_view name) { + return ClaimUniqueName(global_syms_, global_sym_map_, + MangleField(ModuleFieldType::Import), name, + ExportName(name, "instance")); +} + void CWriter::Indent(int size) { indent_ += size; } @@ -980,21 +1155,21 @@ void CWriter::Write(const Const& const_) { } void CWriter::WriteInitDecl() { - Write("void " + module_prefix_ + "_instantiate(", ModuleInstanceTypeName(), - "*"); + Write("void ", kAdminSymbolPrefix, module_prefix_, "_instantiate(", + ModuleInstanceTypeName(), "*"); for (const auto& import_module_name : import_module_set_) { - Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "*"); + Write(", struct ", ModuleInstanceTypeName(import_module_name), "*"); } Write(");", Newline()); } void CWriter::WriteFreeDecl() { - Write("void " + module_prefix_ + "_free(", ModuleInstanceTypeName(), "*);", - Newline()); + Write("void ", kAdminSymbolPrefix, module_prefix_, "_free(", + ModuleInstanceTypeName(), "*);", Newline()); } void CWriter::WriteGetFuncTypeDecl() { - Write("wasm_rt_func_type_t ", module_prefix_, + Write("wasm_rt_func_type_t ", kAdminSymbolPrefix, module_prefix_, "_get_func_type(uint32_t param_count, uint32_t result_count, ...);", Newline()); } @@ -1027,8 +1202,8 @@ void CWriter::WriteInitExpr(const ExprList& expr_list) { bool is_import = import_module_sym_map_.count(func->name) != 0; if (is_import) { - Write("instance->", - MangleModuleInstanceName(import_module_sym_map_[func->name])); + Write("instance->", GlobalName(ModuleFieldType::Import, + import_module_sym_map_[func->name])); } else { Write("instance"); } @@ -1234,8 +1409,8 @@ void CWriter::BeginInstance() { // Forward declaring module instance types for (const auto& import_module : import_module_set_) { - Write("struct ", MangleModuleInstanceTypeName(import_module), ";", - Newline()); + DefineImportedModuleInstanceName(import_module); + Write("struct ", ModuleInstanceTypeName(import_module), ";", Newline()); } // Forward declaring module imports @@ -1265,9 +1440,8 @@ void CWriter::BeginInstance() { default: WABT_UNREACHABLE; } - Write("* ", MangleName(import->module_name), MangleName(import->field_name), - "(struct ", MangleModuleInstanceTypeName(import->module_name), "*);", - Newline()); + Write("* ", ExportName(import->module_name, import->field_name), "(struct ", + ModuleInstanceTypeName(import->module_name), "*);", Newline()); } Write(Newline()); @@ -1276,8 +1450,8 @@ void CWriter::BeginInstance() { // when invoked Write("typedef struct ", ModuleInstanceTypeName(), " ", OpenBrace()); for (const auto& import_module : import_func_module_set_) { - Write("struct ", MangleModuleInstanceTypeName(import_module), "* ", - MangleModuleInstanceName(import_module) + ";", Newline()); + Write("struct ", ModuleInstanceTypeName(import_module), "* ", + GlobalName(ModuleFieldType::Import, import_module), ";", Newline()); } for (const Import* import : unique_imports_) { @@ -1292,19 +1466,19 @@ void CWriter::BeginInstance() { switch (import->kind()) { case ExternalKind::Global: WriteGlobal(cast<GlobalImport>(import)->global, - "*" + MangleName(import->module_name) + - MangleName(import->field_name)); + std::string("*") + + ExportName(import->module_name, import->field_name)); break; case ExternalKind::Memory: - WriteMemory("*" + MangleName(import->module_name) + - MangleName(import->field_name)); + WriteMemory(std::string("*") + + ExportName(import->module_name, import->field_name)); break; case ExternalKind::Table: { const Table& table = cast<TableImport>(import)->table; - WriteTable("*" + MangleName(import->module_name) + - MangleName(import->field_name), + WriteTable(std::string("*") + + ExportName(import->module_name, import->field_name), table.elem_type); } break; @@ -1330,14 +1504,15 @@ void CWriter::WriteImports() { const Func& func = cast<FuncImport>(import)->func; WriteImportFuncDeclaration( func.decl, import->module_name, - MangleName(import->module_name) + MangleName(import->field_name)); + ExportName(import->module_name, import->field_name)); Write(";"); Write(Newline()); } else if (import->kind() == ExternalKind::Tag) { Write("/* import: '", import->module_name, "' '", import->field_name, "' */", Newline()); - Write("extern const wasm_rt_tag_t ", MangleName(import->module_name), - MangleName(import->field_name), ";", Newline()); + Write("extern const wasm_rt_tag_t ", + ExportName(import->module_name, import->field_name), ";", + Newline()); } } } @@ -1373,7 +1548,7 @@ void CWriter::WriteImportFuncDeclaration(const FuncDeclaration& decl, const std::string& module_name, const std::string& name) { Write(ResultType(decl.sig.result_types), " ", name, "("); - Write("struct ", MangleModuleInstanceTypeName(module_name), "*"); + Write("struct ", ModuleInstanceTypeName(module_name), "*"); WriteParamTypes(decl); Write(")"); } @@ -1409,8 +1584,8 @@ void CWriter::WriteGlobals() { for (const Global* global : module_->globals) { bool is_import = global_index < module_->num_global_imports; if (!is_import) { - WriteGlobal(*global, DefineGlobalScopeName(ModuleFieldType::Global, - global->name)); + WriteGlobal(*global, DefineInstanceMemberName(ModuleFieldType::Global, + global->name)); Write(Newline()); } ++global_index; @@ -1434,7 +1609,8 @@ void CWriter::WriteMemories() { for (const Memory* memory : module_->memories) { bool is_import = memory_index < module_->num_memory_imports; if (!is_import) { - WriteMemory(DefineGlobalScopeName(ModuleFieldType::Memory, memory->name)); + WriteMemory( + DefineInstanceMemberName(ModuleFieldType::Memory, memory->name)); Write(Newline()); } ++memory_index; @@ -1459,7 +1635,7 @@ void CWriter::WriteTables() { for (const Table* table : module_->tables) { bool is_import = table_index < module_->num_table_imports; if (!is_import) { - WriteTable(DefineGlobalScopeName(ModuleFieldType::Table, table->name), + WriteTable(DefineInstanceMemberName(ModuleFieldType::Table, table->name), table->elem_type); Write(Newline()); } @@ -1638,7 +1814,8 @@ void CWriter::WriteElemInitializers() { const bool is_import = import_module_sym_map_.count(func->name) != 0; if (is_import) { Write("offsetof(", ModuleInstanceTypeName(), ", ", - MangleModuleInstanceName(import_module_sym_map_[func->name]), + GlobalName(ModuleFieldType::Import, + import_module_sym_map_[func->name]), ")"); } else { Write("0"); @@ -1749,14 +1926,13 @@ void CWriter::WriteExports(CWriterPhase kind) { for (const Export* export_ : module_->exports) { Write(Newline(), "/* export: '", export_->name, "' */", Newline()); - std::string mangled_name; + const std::string mangled_name = ExportName(export_->name); std::string internal_name; std::vector<std::string> index_to_name; switch (export_->kind) { case ExternalKind::Func: { const Func* func = module_->GetFunc(export_->var); - mangled_name = ExportName(MangleName(export_->name)); internal_name = func->name; if (kind == CWriterPhase::Declarations) { WriteFuncDeclaration(func->decl, mangled_name); @@ -1776,7 +1952,6 @@ void CWriter::WriteExports(CWriterPhase kind) { case ExternalKind::Global: { const Global* global = module_->GetGlobal(export_->var); - mangled_name = ExportName(MangleName(export_->name)); internal_name = global->name; WriteGlobalPtr(*global, mangled_name); break; @@ -1784,7 +1959,6 @@ void CWriter::WriteExports(CWriterPhase kind) { case ExternalKind::Memory: { const Memory* memory = module_->GetMemory(export_->var); - mangled_name = ExportName(MangleName(export_->name)); internal_name = memory->name; WriteMemoryPtr(mangled_name); break; @@ -1792,7 +1966,6 @@ void CWriter::WriteExports(CWriterPhase kind) { case ExternalKind::Table: { const Table* table = module_->GetTable(export_->var); - mangled_name = ExportName(MangleName(export_->name)); internal_name = table->name; WriteTablePtr(mangled_name, *table); break; @@ -1800,7 +1973,6 @@ void CWriter::WriteExports(CWriterPhase kind) { case ExternalKind::Tag: { const Tag* tag = module_->GetTag(export_->var); - mangled_name = ExportName(MangleName(export_->name)); internal_name = tag->name; if (kind == CWriterPhase::Declarations) { Write("extern "); @@ -1827,8 +1999,9 @@ void CWriter::WriteExports(CWriterPhase kind) { bool is_import = import_module_sym_map_.count(internal_name) != 0; if (is_import) { - Write("instance->", MangleModuleInstanceName( - import_module_sym_map_[internal_name])); + Write("instance->", + GlobalName(ModuleFieldType::Import, + import_module_sym_map_[internal_name])); } else { Write("instance"); } @@ -1877,11 +2050,11 @@ void CWriter::WriteExports(CWriterPhase kind) { } void CWriter::WriteInit() { - Write(Newline(), "void " + module_prefix_ + "_instantiate(", + Write(Newline(), "void ", kAdminSymbolPrefix, module_prefix_, "_instantiate(", ModuleInstanceTypeName(), "* instance"); for (const auto& import_module_name : import_module_set_) { - Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "* ", - MangleModuleInstanceName(import_module_name)); + Write(", struct ", ModuleInstanceTypeName(import_module_name), "* ", + GlobalName(ModuleFieldType::Import, import_module_name)); } Write(") ", OpenBrace()); @@ -1890,7 +2063,7 @@ void CWriter::WriteInit() { if (!import_module_set_.empty()) { Write("init_instance_import(instance"); for (const auto& import_module_name : import_module_set_) { - Write(", ", MangleModuleInstanceName(import_module_name)); + Write(", ", GlobalName(ModuleFieldType::Import, import_module_name)); } Write(");", Newline()); } @@ -1917,9 +2090,9 @@ void CWriter::WriteInit() { import_module_sym_map_.count(module_->GetFunc(*var)->name) != 0; if (is_import) { Write("(instance->", - MangleModuleInstanceName( - import_module_sym_map_[module_->GetFunc(*var)->name]) + - ");"); + GlobalName(ModuleFieldType::Import, + import_module_sym_map_[module_->GetFunc(*var)->name]), + ");"); } else { Write("(instance);"); } @@ -1929,8 +2102,9 @@ void CWriter::WriteInit() { } void CWriter::WriteGetFuncType() { - Write(Newline(), "wasm_rt_func_type_t ", module_prefix_, - "_get_func_type(uint32_t param_count, uint32_t result_count, ...) ", + Write(Newline(), "wasm_rt_func_type_t ", kAdminSymbolPrefix, module_prefix_, + "_get_func_type(uint32_t param_count, uint32_t result_count, " + "...) ", OpenBrace()); Write("va_list args;", Newline()); @@ -1968,14 +2142,15 @@ void CWriter::WriteInitInstanceImport() { Write(Newline(), "static void init_instance_import(", ModuleInstanceTypeName(), "* instance"); for (const auto& import_module_name : import_module_set_) { - Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "* ", - MangleModuleInstanceName(import_module_name)); + Write(", struct ", ModuleInstanceTypeName(import_module_name), "* ", + GlobalName(ModuleFieldType::Import, import_module_name)); } Write(")", OpenBrace()); for (const auto& import_module : import_func_module_set_) { - Write("instance->", MangleModuleInstanceName(import_module), " = ", - MangleModuleInstanceName(import_module), ";", Newline()); + Write("instance->", GlobalName(ModuleFieldType::Import, import_module), + " = ", GlobalName(ModuleFieldType::Import, import_module), ";", + Newline()); } for (const Import* import : unique_imports_) { @@ -1987,11 +2162,9 @@ void CWriter::WriteInitInstanceImport() { case ExternalKind::Global: case ExternalKind::Memory: case ExternalKind::Table: { - Write("instance->", - MangleName(import->module_name) + MangleName(import->field_name), - " = ", - MangleName(import->module_name) + MangleName(import->field_name), - "(", MangleModuleInstanceName(import->module_name), ");", + Write("instance->", ExportName(import->module_name, import->field_name), + " = ", ExportName(import->module_name, import->field_name), "(", + GlobalName(ModuleFieldType::Import, import->module_name), ");", Newline()); break; } @@ -2013,9 +2186,9 @@ void CWriter::WriteImportProperties(CWriterPhase kind) { if (kind == CWriterPhase::Declarations) { Write("extern "); } - Write("const u32 " + module_prefix_ + "_", - prop + "_" + MangleName(import->module_name) + - MangleName(import->field_name)); + Write("const u32 ", kAdminSymbolPrefix, module_prefix_, "_", prop, "_", + MangleModuleName(import->module_name), "_", + MangleName(import->field_name)); if (kind == CWriterPhase::Definitions) { Write(" = ", value); } @@ -2037,7 +2210,7 @@ void CWriter::WriteImportProperties(CWriterPhase kind) { } void CWriter::WriteFree() { - Write(Newline(), "void " + module_prefix_ + "_free(", + Write(Newline(), "void ", kAdminSymbolPrefix, module_prefix_, "_free(", ModuleInstanceTypeName(), "* instance) ", OpenBrace()); { @@ -2505,8 +2678,8 @@ void CWriter::Write(const ExprList& exprs) { Write(ExternalRef(ModuleFieldType::Func, var.name()), "("); bool is_import = import_module_sym_map_.count(func.name) != 0; if (is_import) { - Write("instance->", - MangleModuleInstanceName(import_module_sym_map_[func.name])); + Write("instance->", GlobalName(ModuleFieldType::Import, + import_module_sym_map_[func.name])); } else { Write("instance"); } @@ -2836,8 +3009,8 @@ void CWriter::Write(const ExprList& exprs) { bool is_import = import_module_sym_map_.count(func->name) != 0; if (is_import) { - Write("instance->", - MangleModuleInstanceName(import_module_sym_map_[func->name])); + Write("instance->", GlobalName(ModuleFieldType::Import, + import_module_sym_map_[func->name])); } else { Write("instance"); } @@ -4623,7 +4796,15 @@ void CWriter::Write(const LoadZeroExpr& expr) { PushType(result_type); } +void CWriter::ReserveExportNames() { + for (const Export* export_ : module_->exports) { + ReserveExportName(export_->name); + } +} + void CWriter::WriteCHeader() { + ReserveExportNames(); + stream_ = h_stream_; std::string guard = GenerateHeaderGuard(); Write("/* Automatically generated by wasm2c */", Newline()); diff --git a/test/run-spec-wasm2c.py b/test/run-spec-wasm2c.py index e2a0cc91..4c3c1f1d 100755 --- a/test/run-spec-wasm2c.py +++ b/test/run-spec-wasm2c.py @@ -101,11 +101,19 @@ def MangleTypes(types): def MangleName(s): def Mangle(match): s = match.group(0) - return b'Z%02X' % s[0] + return b'0x%02X' % s[0] - # NOTE(binji): Z is not allowed. - pattern = b'([^_a-zA-Y0-9])' - return 'Z_' + re.sub(pattern, Mangle, s.encode('utf-8')).decode('utf-8') + # escape underscores at beginning and end + s = re.sub(b'((^_)|(_$))', Mangle, s.encode('utf-8')) + + # NOTE(keithw): forced escapes for '0x[hexdigit]' not implemented here + pattern = b'([^_a-zA-Z0-9])' + return re.sub(pattern, Mangle, s).decode('utf-8') + + +def MangleModuleName(s): + # double underscores + return MangleName(re.sub('(_)', '__', s)) def IsModuleCommand(command): @@ -169,7 +177,7 @@ class CWriter(object): name = re.sub(r'[^a-zA-Z0-9_]', '_', name) name = os.path.splitext(name)[0] self.unmangled_names[idx] = name - name = MangleName(name) + name = MangleModuleName(name) self.module_prefix_map[idx] = name @@ -180,7 +188,7 @@ class CWriter(object): idx += 1 elif command['type'] == 'register': - name = MangleName(command['as']) + name = MangleModuleName(command['as']) if 'name' in command: self.module_prefix_map[command['name']] = name name_idx = self.module_name_to_idx[command['name']] @@ -199,13 +207,13 @@ class CWriter(object): for line in f: if 'import: ' in line: line_split = line.split() - import_module_name = MangleName(line_split[2][1:-1]) + import_module_name = MangleModuleName(line_split[2][1:-1]) imported_modules.add(import_module_name) if uninstantiable: self.out_file.write('ASSERT_TRAP(') - self.out_file.write('%s_instantiate(&%s_instance' % (self.GetModulePrefix(), self.GetModulePrefix())) + self.out_file.write('wasm2c_%s_instantiate(&%s_instance' % (self.GetModulePrefix(), self.GetModulePrefix())) for imported_module in sorted(imported_modules): self.out_file.write(', &%s_instance' % imported_module) self.out_file.write(')') @@ -260,12 +268,12 @@ class CWriter(object): idx = 0 for command in self.commands: if IsModuleCommand(command): - self.out_file.write('%s_instance_t %s;\n' % (self.GetModulePrefix(idx), self.GetModuleInstanceName(idx))) + self.out_file.write('w2c_%s %s;\n' % (self.GetModulePrefix(idx), self.GetModuleInstanceName(idx))) idx += 1 def _WriteModuleCleanUps(self): for idx in range(self.module_idx): - self.out_file.write("%s_free(&%s_instance);\n" % (self.GetModulePrefix(idx), self.GetModulePrefix(idx))) + self.out_file.write("wasm2c_%s_free(&%s);\n" % (self.GetModulePrefix(idx), self.GetModuleInstanceName(idx))) def _WriteAssertUninstantiableCommand(self, command): self.module_idx += 1 @@ -422,7 +430,7 @@ class CWriter(object): action = command['action'] type_ = action['type'] mangled_module_name = self.GetModulePrefix(action.get('module')) - field = mangled_module_name + MangleName(action['field']) + field = "w2c_" + mangled_module_name + '_' + MangleName(action['field']) if type_ == 'invoke': args = self._ConstantList(action.get('args', [])) if len(args) == 0: diff --git a/test/spec-wasm2c-prefix.c b/test/spec-wasm2c-prefix.c index 99af49ab..c82a882d 100644 --- a/test/spec-wasm2c-prefix.c +++ b/test/spec-wasm2c-prefix.c @@ -277,77 +277,73 @@ static bool is_arithmetic_nan_f64(u64 x) { return (x & 0x7ff8000000000000) == 0x7ff8000000000000; } -typedef struct Z_spectest_instance_t { +typedef struct w2c_spectest { wasm_rt_funcref_table_t spectest_table; wasm_rt_memory_t spectest_memory; uint32_t spectest_global_i32; uint64_t spectest_global_i64; float spectest_global_f32; double spectest_global_f64; -} Z_spectest_instance_t; +} w2c_spectest; -static Z_spectest_instance_t Z_spectest_instance; +static w2c_spectest spectest_instance; /* * spectest implementations */ -void Z_spectestZ_print(Z_spectest_instance_t* instance) { +void w2c_spectest_print(w2c_spectest* instance) { printf("spectest.print()\n"); } -void Z_spectestZ_print_i32(Z_spectest_instance_t* instance, uint32_t i) { +void w2c_spectest_print_i32(w2c_spectest* instance, uint32_t i) { printf("spectest.print_i32(%d)\n", i); } -void Z_spectestZ_print_i64(Z_spectest_instance_t* instance, uint64_t i) { +void w2c_spectest_print_i64(w2c_spectest* instance, uint64_t i) { printf("spectest.print_i64(%" PRIu64 ")\n", i); } -void Z_spectestZ_print_f32(Z_spectest_instance_t* instance, float f) { +void w2c_spectest_print_f32(w2c_spectest* instance, float f) { printf("spectest.print_f32(%g)\n", f); } -void Z_spectestZ_print_i32_f32(Z_spectest_instance_t* instance, - uint32_t i, - float f) { +void w2c_spectest_print_i32_f32(w2c_spectest* instance, uint32_t i, float f) { printf("spectest.print_i32_f32(%d %g)\n", i, f); } -void Z_spectestZ_print_f64(Z_spectest_instance_t* instance, double d) { +void w2c_spectest_print_f64(w2c_spectest* instance, double d) { printf("spectest.print_f64(%g)\n", d); } -void Z_spectestZ_print_f64_f64(Z_spectest_instance_t* instance, - double d1, - double d2) { +void w2c_spectest_print_f64_f64(w2c_spectest* instance, double d1, double d2) { printf("spectest.print_f64_f64(%g %g)\n", d1, d2); } -wasm_rt_funcref_table_t* Z_spectestZ_table(Z_spectest_instance_t* instance) { +wasm_rt_funcref_table_t* w2c_spectest_table(w2c_spectest* instance) { return &instance->spectest_table; } -wasm_rt_memory_t* Z_spectestZ_memory(Z_spectest_instance_t* instance) { +wasm_rt_memory_t* w2c_spectest_memory(w2c_spectest* instance) { return &instance->spectest_memory; } -uint32_t* Z_spectestZ_global_i32(Z_spectest_instance_t* instance) { +uint32_t* w2c_spectest_global_i32(w2c_spectest* instance) { return &instance->spectest_global_i32; } -uint64_t* Z_spectestZ_global_i64(Z_spectest_instance_t* instance) { +uint64_t* w2c_spectest_global_i64(w2c_spectest* instance) { return &instance->spectest_global_i64; } -float* Z_spectestZ_global_f32(Z_spectest_instance_t* instance) { +float* w2c_spectest_global_f32(w2c_spectest* instance) { return &instance->spectest_global_f32; } -double* Z_spectestZ_global_f64(Z_spectest_instance_t* instance) { +double* w2c_spectest_global_f64(w2c_spectest* instance) { return &instance->spectest_global_f64; } -static void init_spectest_module(Z_spectest_instance_t* instance) { +static void init_spectest_module(w2c_spectest* instance) { instance->spectest_global_i32 = 666; instance->spectest_global_i64 = 666l; wasm_rt_allocate_memory(&instance->spectest_memory, 1, 2, false); @@ -356,7 +352,7 @@ static void init_spectest_module(Z_spectest_instance_t* instance) { int main(int argc, char** argv) { wasm_rt_init(); - init_spectest_module(&Z_spectest_instance); + init_spectest_module(&spectest_instance); run_spec_tests(); printf("%u/%u tests passed.\n", g_tests_passed, g_tests_run); wasm_rt_free(); diff --git a/test/wasm2c/add.txt b/test/wasm2c/add.txt index 4cd3c835..125f3152 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt @@ -40,16 +40,16 @@ typedef simde_v128_t v128; extern "C" { #endif -typedef struct Z_test_instance_t { +typedef struct w2c_test { char dummy_member; -} Z_test_instance_t; +} w2c_test; -void Z_test_instantiate(Z_test_instance_t*); -void Z_test_free(Z_test_instance_t*); -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); +void wasm2c_test_instantiate(w2c_test*); +void wasm2c_test_free(w2c_test*); +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* export: 'add' */ -u32 Z_testZ_add(Z_test_instance_t*, u32, u32); +u32 w2c_test_add(w2c_test*, u32, u32); #ifdef __cplusplus } @@ -782,11 +782,11 @@ DEFINE_TABLE_FILL(externref) #define FUNC_TYPE_T(x) static const char x[] #endif -FUNC_TYPE_T(w2c_t0) = "\x92\xfb\x6a\xdf\x49\x07\x0a\x83\xbe\x08\x02\x68\xcd\xf6\x95\x27\x4a\xc2\xf3\xe5\xe4\x7d\x29\x49\xe8\xed\x42\x92\x6a\x9d\xda\xf0"; +FUNC_TYPE_T(w2c_test_t0) = "\x92\xfb\x6a\xdf\x49\x07\x0a\x83\xbe\x08\x02\x68\xcd\xf6\x95\x27\x4a\xc2\xf3\xe5\xe4\x7d\x29\x49\xe8\xed\x42\x92\x6a\x9d\xda\xf0"; -static u32 w2c_add(Z_test_instance_t*, u32, u32); +static u32 w2c_test_add_0(w2c_test*, u32, u32); -static u32 w2c_add(Z_test_instance_t* instance, u32 w2c_p0, u32 w2c_p1) { +static u32 w2c_test_add_0(w2c_test* instance, u32 w2c_p0, u32 w2c_p1) { FUNC_PROLOGUE; u32 w2c_i0, w2c_i1; w2c_i0 = w2c_p0; @@ -797,25 +797,25 @@ static u32 w2c_add(Z_test_instance_t* instance, u32 w2c_p0, u32 w2c_p1) { } /* export: 'add' */ -u32 Z_testZ_add(Z_test_instance_t* instance, u32 w2c_p0, u32 w2c_p1) { - return w2c_add(instance, w2c_p0, w2c_p1); +u32 w2c_test_add(w2c_test* instance, u32 w2c_p0, u32 w2c_p1) { + return w2c_test_add_0(instance, w2c_p0, w2c_p1); } -void Z_test_instantiate(Z_test_instance_t* instance) { +void wasm2c_test_instantiate(w2c_test* instance) { assert(wasm_rt_is_initialized()); } -void Z_test_free(Z_test_instance_t* instance) { +void wasm2c_test_free(w2c_test* instance) { } -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { va_list args; if (param_count == 2 && result_count == 1) { va_start(args, result_count); if (true && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32) { va_end(args); - return w2c_t0; + return w2c_test_t0; } va_end(args); } diff --git a/test/wasm2c/hello.txt b/test/wasm2c/hello.txt index 4e756743..3eef2cc4 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt @@ -58,28 +58,28 @@ typedef simde_v128_t v128; extern "C" { #endif -struct Z_wasi_snapshot_preview1_instance_t; +struct w2c_wasi__snapshot__preview1; -typedef struct Z_test_instance_t { - struct Z_wasi_snapshot_preview1_instance_t* Z_wasi_snapshot_preview1_instance; +typedef struct w2c_test { + struct w2c_wasi__snapshot__preview1* w2c_wasi__snapshot__preview1_instance; wasm_rt_memory_t w2c_memory; wasm_rt_funcref_table_t w2c_T0; -} Z_test_instance_t; +} w2c_test; -void Z_test_instantiate(Z_test_instance_t*, struct Z_wasi_snapshot_preview1_instance_t*); -void Z_test_free(Z_test_instance_t*); -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); +void wasm2c_test_instantiate(w2c_test*, struct w2c_wasi__snapshot__preview1*); +void wasm2c_test_free(w2c_test*); +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* import: 'wasi_snapshot_preview1' 'fd_write' */ -u32 Z_wasi_snapshot_preview1Z_fd_write(struct Z_wasi_snapshot_preview1_instance_t*, u32, u32, u32, u32); +u32 w2c_wasi__snapshot__preview1_fd_write(struct w2c_wasi__snapshot__preview1*, u32, u32, u32, u32); /* import: 'wasi_snapshot_preview1' 'proc_exit' */ -void Z_wasi_snapshot_preview1Z_proc_exit(struct Z_wasi_snapshot_preview1_instance_t*, u32); +void w2c_wasi__snapshot__preview1_proc_exit(struct w2c_wasi__snapshot__preview1*, u32); /* export: 'memory' */ -wasm_rt_memory_t* Z_testZ_memory(Z_test_instance_t* instance); +wasm_rt_memory_t* w2c_test_memory(w2c_test* instance); /* export: '_start' */ -void Z_testZ__start(Z_test_instance_t*); +void w2c_test_0x5Fstart(w2c_test*); #ifdef __cplusplus } @@ -812,37 +812,37 @@ DEFINE_TABLE_FILL(externref) #define FUNC_TYPE_T(x) static const char x[] #endif -FUNC_TYPE_T(w2c_t0) = "\xf6\x98\x1b\xc6\x10\xda\xb7\xb2\x63\x37\xcd\xdc\x72\xca\xe9\x50\x00\x13\xba\x10\x6c\xde\x87\x27\x10\xf8\x86\x2f\xe3\xdb\x94\xe4"; -FUNC_TYPE_T(w2c_t1) = "\x89\x3a\x3d\x2c\x8f\x4d\x7f\x6d\x6c\x9d\x62\x67\x29\xaf\x3d\x44\x39\x8e\xc3\xf3\xe8\x51\xc1\x99\xb9\xdd\x9f\xd5\x3d\x1f\xd3\xe4"; -FUNC_TYPE_T(w2c_t2) = "\x36\xa9\xe7\xf1\xc9\x5b\x82\xff\xb9\x97\x43\xe0\xc5\xc4\xce\x95\xd8\x3c\x9a\x43\x0a\xac\x59\xf8\x4e\xf3\xcb\xfa\xb6\x14\x50\x68"; +FUNC_TYPE_T(w2c_test_t0) = "\xf6\x98\x1b\xc6\x10\xda\xb7\xb2\x63\x37\xcd\xdc\x72\xca\xe9\x50\x00\x13\xba\x10\x6c\xde\x87\x27\x10\xf8\x86\x2f\xe3\xdb\x94\xe4"; +FUNC_TYPE_T(w2c_test_t1) = "\x89\x3a\x3d\x2c\x8f\x4d\x7f\x6d\x6c\x9d\x62\x67\x29\xaf\x3d\x44\x39\x8e\xc3\xf3\xe8\x51\xc1\x99\xb9\xdd\x9f\xd5\x3d\x1f\xd3\xe4"; +FUNC_TYPE_T(w2c_test_t2) = "\x36\xa9\xe7\xf1\xc9\x5b\x82\xff\xb9\x97\x43\xe0\xc5\xc4\xce\x95\xd8\x3c\x9a\x43\x0a\xac\x59\xf8\x4e\xf3\xcb\xfa\xb6\x14\x50\x68"; -static void w2c__start(Z_test_instance_t*); +static void w2c_test_0x5Fstart_0(w2c_test*); -static const u8 data_segment_data_w2c_d0[] = { +static const u8 data_segment_data_w2c_test_d0[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x0a, }; -static void init_memories(Z_test_instance_t* instance) { +static void init_memories(w2c_test* instance) { wasm_rt_allocate_memory(&instance->w2c_memory, 1, 65536, 0); - LOAD_DATA(instance->w2c_memory, 8u, data_segment_data_w2c_d0, 14); + LOAD_DATA(instance->w2c_memory, 8u, data_segment_data_w2c_test_d0, 14); } -static void init_data_instances(Z_test_instance_t *instance) { +static void init_data_instances(w2c_test *instance) { } -static const wasm_elem_segment_expr_t elem_segment_exprs_w2c_e0[] = { - {w2c_t0, (wasm_rt_function_ptr_t)Z_wasi_snapshot_preview1Z_fd_write, offsetof(Z_test_instance_t, Z_wasi_snapshot_preview1_instance)}, +static const wasm_elem_segment_expr_t elem_segment_exprs_w2c_test_e0[] = { + {w2c_test_t0, (wasm_rt_function_ptr_t)w2c_wasi__snapshot__preview1_fd_write, offsetof(w2c_test, w2c_wasi__snapshot__preview1_instance)}, }; -static void init_tables(Z_test_instance_t* instance) { +static void init_tables(w2c_test* instance) { wasm_rt_allocate_funcref_table(&instance->w2c_T0, 1, 1); - funcref_table_init(&instance->w2c_T0, elem_segment_exprs_w2c_e0, 1, 0u, 0, 1, instance); + funcref_table_init(&instance->w2c_T0, elem_segment_exprs_w2c_test_e0, 1, 0u, 0, 1, instance); } -static void init_elem_instances(Z_test_instance_t *instance) { +static void init_elem_instances(w2c_test *instance) { } -static void w2c__start(Z_test_instance_t* instance) { +static void w2c_test_0x5Fstart_0(w2c_test* instance) { FUNC_PROLOGUE; u32 w2c_i0, w2c_i1, w2c_i2, w2c_i3, w2c_i4; w2c_i0 = 0u; @@ -856,47 +856,47 @@ static void w2c__start(Z_test_instance_t* instance) { w2c_i2 = 1u; w2c_i3 = 0u; w2c_i4 = 0u; - w2c_i0 = CALL_INDIRECT(instance->w2c_T0, u32 (*)(void*, u32, u32, u32, u32), w2c_t0, w2c_i4, instance->w2c_T0.data[w2c_i4].module_instance, w2c_i0, w2c_i1, w2c_i2, w2c_i3); - (*Z_wasi_snapshot_preview1Z_proc_exit)(instance->Z_wasi_snapshot_preview1_instance, w2c_i0); + w2c_i0 = CALL_INDIRECT(instance->w2c_T0, u32 (*)(void*, u32, u32, u32, u32), w2c_test_t0, w2c_i4, instance->w2c_T0.data[w2c_i4].module_instance, w2c_i0, w2c_i1, w2c_i2, w2c_i3); + (*w2c_wasi__snapshot__preview1_proc_exit)(instance->w2c_wasi__snapshot__preview1_instance, w2c_i0); FUNC_EPILOGUE; } /* export: 'memory' */ -wasm_rt_memory_t* Z_testZ_memory(Z_test_instance_t* instance) { +wasm_rt_memory_t* w2c_test_memory(w2c_test* instance) { return &instance->w2c_memory; } /* export: '_start' */ -void Z_testZ__start(Z_test_instance_t* instance) { - return w2c__start(instance); +void w2c_test_0x5Fstart(w2c_test* instance) { + return w2c_test_0x5Fstart_0(instance); } -static void init_instance_import(Z_test_instance_t* instance, struct Z_wasi_snapshot_preview1_instance_t* Z_wasi_snapshot_preview1_instance){ - instance->Z_wasi_snapshot_preview1_instance = Z_wasi_snapshot_preview1_instance; +static void init_instance_import(w2c_test* instance, struct w2c_wasi__snapshot__preview1* w2c_wasi__snapshot__preview1_instance){ + instance->w2c_wasi__snapshot__preview1_instance = w2c_wasi__snapshot__preview1_instance; } -void Z_test_instantiate(Z_test_instance_t* instance, struct Z_wasi_snapshot_preview1_instance_t* Z_wasi_snapshot_preview1_instance) { +void wasm2c_test_instantiate(w2c_test* instance, struct w2c_wasi__snapshot__preview1* w2c_wasi__snapshot__preview1_instance) { assert(wasm_rt_is_initialized()); - init_instance_import(instance, Z_wasi_snapshot_preview1_instance); + init_instance_import(instance, w2c_wasi__snapshot__preview1_instance); init_memories(instance); init_tables(instance); init_data_instances(instance); init_elem_instances(instance); } -void Z_test_free(Z_test_instance_t* instance) { +void wasm2c_test_free(w2c_test* instance) { wasm_rt_free_funcref_table(&instance->w2c_T0); wasm_rt_free_memory(&instance->w2c_memory); } -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { va_list args; if (param_count == 4 && result_count == 1) { va_start(args, result_count); if (true && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32) { va_end(args); - return w2c_t0; + return w2c_test_t0; } va_end(args); } @@ -905,7 +905,7 @@ wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_c va_start(args, result_count); if (true && va_arg(args, wasm_rt_type_t) == WASM_RT_I32) { va_end(args); - return w2c_t1; + return w2c_test_t1; } va_end(args); } @@ -914,7 +914,7 @@ wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_c va_start(args, result_count); if (true) { va_end(args); - return w2c_t2; + return w2c_test_t2; } va_end(args); } diff --git a/test/wasm2c/minimal.txt b/test/wasm2c/minimal.txt index bfee1a53..e56187f2 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt @@ -37,13 +37,13 @@ typedef simde_v128_t v128; extern "C" { #endif -typedef struct Z_test_instance_t { +typedef struct w2c_test { char dummy_member; -} Z_test_instance_t; +} w2c_test; -void Z_test_instantiate(Z_test_instance_t*); -void Z_test_free(Z_test_instance_t*); -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); +void wasm2c_test_instantiate(w2c_test*); +void wasm2c_test_free(w2c_test*); +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...); #ifdef __cplusplus } @@ -776,14 +776,14 @@ DEFINE_TABLE_FILL(externref) #define FUNC_TYPE_T(x) static const char x[] #endif -void Z_test_instantiate(Z_test_instance_t* instance) { +void wasm2c_test_instantiate(w2c_test* instance) { assert(wasm_rt_is_initialized()); } -void Z_test_free(Z_test_instance_t* instance) { +void wasm2c_test_free(w2c_test* instance) { } -wasm_rt_func_type_t Z_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { +wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t result_count, ...) { va_list args; return NULL; diff --git a/wasm2c/README.md b/wasm2c/README.md index 80a86952..cdc4f09e 100644 --- a/wasm2c/README.md +++ b/wasm2c/README.md @@ -49,19 +49,17 @@ files. To actually use our `fac` module, we'll use create a new file, `main.c`, that include `fac.h`, initializes the module, and calls `fac`. -`wasm2c` generates a few C symbols based on the `fac.wasm` module: `Z_fac_instantiate` -and `Z_facZ_fac`. The first constructs an instance of the module, and the second is the -exported `fac` function. - -All the exported symbols shared a common prefix (`Z_fac`) which, by default, is +`wasm2c` generates a few C symbols based on the `fac.wasm` module. +The first is `w2c_fac`, a type that represents an instance of the +`fac` module. `wasm2c` generates functions that construct and free a +`w2c_fac` instance: `wasm2c_fac_instantiate` and +`wasm2c_fac_free`. Finally, `wasm2c` generates the exported `fac` +function itself (`w2c_fac_fac`), which acts on a `w2c_fac` instance. + +All the exported symbols shared a common module ID (`fac`) which, by default, is based on the name section in the module or the name of input file. This prefix can be overridden using the `-n/--module-name` command line flag. -In addition to parameters defined in `fac.wat`, `Z_fac_instantiate` and `Z_facZ_fac` -take in a pointer to a `Z_fac_instance_t`. The structure is used to -store the context information of the module instance, and `main.c` is responsible -for providing it. - ```c #include <stdio.h> #include <stdlib.h> @@ -70,8 +68,10 @@ for providing it. int main(int argc, char** argv) { /* Make sure there is at least one command-line argument. */ - if (argc < 2) + if (argc < 2) { + printf("Invalid argument. Expected '%s NUMBER'\n", argv[0]); return 1; + } /* Convert the argument from a string to an int. We'll implicitly cast the int to a `u32`, which is what `fac` expects. */ @@ -81,19 +81,19 @@ int main(int argc, char** argv) { wasm_rt_init(); /* Declare an instance of the `fac` module. */ - Z_fac_instance_t instance; + w2c_fac fac; /* Construct the module instance. */ - Z_fac_instantiate(&instance); + wasm2c_fac_instantiate(&fac); /* Call `fac`, using the mangled name. */ - u32 result = Z_facZ_fac(&instance, x); + u32 result = w2c_fac_fac(&fac, x); /* Print the result. */ printf("fac(%u) -> %u\n", x, result); /* Free the fac module. */ - Z_fac_free(&instance); + wasm2c_fac_free(&fac); /* Free the Wasm runtime state. */ wasm_rt_free(); @@ -143,6 +143,7 @@ You can take a look at the all of these files in The generated header file looks something like this: ```c +/* Automatically generated by wasm2c */ #ifndef FAC_H_GENERATED_ #define FAC_H_GENERATED_ @@ -162,15 +163,16 @@ The generated header file looks something like this: extern "C" { #endif -typedef struct Z_fac_instance_t { +typedef struct w2c_fac { char dummy_member; -} Z_fac_instance_t; +} w2c_fac; -void Z_fac_instantiate(Z_fac_instance_t*); -void Z_fac_free(Z_fac_instance_t*); +void wasm2c_fac_instantiate(w2c_fac*); +void wasm2c_fac_free(w2c_fac*); +wasm_rt_func_type_t wasm2c_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* export: 'fac' */ -u32 Z_facZ_fac(Z_fac_instance_t*, u32); +u32 w2c_fac_fac(w2c_fac*, u32); #ifdef __cplusplus } @@ -382,10 +384,10 @@ of `fac` is essentially empty), and the exported symbols provided by the module. In our example, the only function we exported was `fac`. -`Z_fac_instantiate(Z_fac_instance_t*)` creates an instance of +`wasm2c_fac_instantiate(w2c_fac*)` creates an instance of the module and must be called before the module instance can be -used. `Z_fac_free(Z_fac_instance_t*)` frees the instance. -`Z_fac_get_func_type` can be used to look up a function type ID +used. `wasm2c_fac_free(w2c_fac*)` frees the instance. +`wasm2c_fac_get_func_type` can be used to look up a function type ID at runtime. It is a variadic function where the first two arguments give the number of parameters and results, and the following arguments are the types from the wasm_rt_type_t enum described above. The @@ -393,16 +395,16 @@ are the types from the wasm_rt_type_t enum described above. The a WebAssembly module dynamically at runtime. ```c -typedef struct Z_fac_instance_t { +typedef struct w2c_fac { char dummy_member; -} Z_fac_instance_t; +} w2c_fac; -void Z_fac_instantiate(Z_fac_instance_t*); -void Z_fac_free(Z_fac_instance_t*); -wasm_rt_func_type_t Z_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...); +void wasm2c_fac_instantiate(w2c_fac*); +void wasm2c_fac_free(w2c_fac*); +wasm_rt_func_type_t wasm2c_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* export: 'fac' */ -u32 Z_facZ_fac(Z_fac_instance_t*, u32); +u32 w2c_fac_fac(w2c_fac*, u32); ``` ## Handling other kinds of imports and exports of modules @@ -427,14 +429,15 @@ then `wasm2c` would declare the following function in the header: ```c /* export: 'mem' */ -extern wasm_rt_memory_t* Z_facZ_mem(Z_fac_instance_t*); +wasm_rt_memory_t* w2c_fac_mem(w2c_fac* instance); + ``` which would be defined as: ```c /* export: 'mem' */ -wasm_rt_memory_t* Z_fac_Z_mem(Z_fac_instance_t* instance) { - return &instance->w2c_M0; +wasm_rt_memory_t* w2c_fac_mem(w2c_fac* instance) { + return &instance->w2c_mem; } ``` @@ -455,7 +458,7 @@ module doesn't use any globals, memory or tables. The most interesting part is the definition of the function `fac`: ```c -static u32 w2c_fac(Z_fac_instance_t* instance, u32 w2c_p0) { +static u32 w2c_fac_fac_0(w2c_fac* instance, u32 w2c_p0) { FUNC_PROLOGUE; u32 w2c_i0, w2c_i1, w2c_i2; w2c_i0 = w2c_p0; @@ -468,7 +471,7 @@ static u32 w2c_fac(Z_fac_instance_t* instance, u32 w2c_p0) { w2c_i1 = w2c_p0; w2c_i2 = 1u; w2c_i1 -= w2c_i2; - w2c_i1 = w2c_fac(instance, w2c_i1); + w2c_i1 = w2c_fac_fac_0(instance, w2c_i1); w2c_i0 *= w2c_i1; } FUNC_EPILOGUE; @@ -546,62 +549,45 @@ in the same address space. #include "rot13.h" /* Define structure to hold the imports */ -struct Z_host_instance_t { +typedef struct w2c_host { wasm_rt_memory_t memory; char* input; -}; +} w2c_host; /* Accessor to access the memory member of the host */ -wasm_rt_memory_t* Z_hostZ_mem(struct Z_host_instance_t* instance) { +wasm_rt_memory_t* w2c_host_mem(w2c_host* instance) { return &instance->memory; } -/* Declare the implementations of the imports. */ -static u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size); -static void buf_done(struct Z_host_instance_t* instance, u32 ptr, u32 size); - -/* Define host-provided functions under the names imported by the `rot13` instance */ -u32 Z_hostZ_fill_buf(struct Z_host_instance_t* instance, - u32 ptr, - u32 size) { - return fill_buf(instance, ptr, size); -} - -void Z_hostZ_buf_done(struct Z_host_instance_t* instance, - u32 ptr, - u32 size) { - return buf_done(instance, ptr, size); -} - int main(int argc, char** argv) { + /* Make sure there is at least one command-line argument. */ + if (argc < 2) { + printf("Invalid argument. Expected '%s WORD...'\n", argv[0]); + return 1; + } /* Initialize the Wasm runtime. */ wasm_rt_init(); - /* Declare two instances of the `rot13` module. */ - Z_rot13_instance_t rot13_instance_1; - Z_rot13_instance_t rot13_instance_2; - - /* Create two `host` module instances to store the memory and current string */ - struct Z_host_instance_t host_instance_1; - struct Z_host_instance_t host_instance_2; - /* Allocate 1 page of wasm memory (64KiB). */ - wasm_rt_allocate_memory(&host_instance_1.memory, 1, 1, false); - wasm_rt_allocate_memory(&host_instance_2.memory, 1, 1, false); + /* Create two `host` instances to store the memory and current string */ + w2c_host host_1, host_2; + wasm_rt_allocate_memory(&host_1.memory, 1, 1, false); + wasm_rt_allocate_memory(&host_2.memory, 1, 1, false); - /* Construct the module instances */ - Z_rot13_instantiate(&rot13_instance_1, &host_instance_1); - Z_rot13_instantiate(&rot13_instance_2, &host_instance_2); + /* Construct the `rot13` module instances */ + w2c_rot13 rot13_1, rot13_2; + wasm2c_rot13_instantiate(&rot13_1, &host_1); + wasm2c_rot13_instantiate(&rot13_2, &host_2); - /* Call `rot13` on first two argument, using the mangled name. */ + /* Call `rot13` on the first two arguments. */ assert(argc > 2); - host_instance_1.input = argv[1]; - Z_rot13Z_rot13(&rot13_instance_1); - host_instance_2.input = argv[2]; - Z_rot13Z_rot13(&rot13_instance_2); + host_1.input = argv[1]; + w2c_rot13_rot13(&rot13_1); + host_2.input = argv[2]; + w2c_rot13_rot13(&rot13_2); - /* Free the rot13 modules. */ - Z_rot13_free(&rot13_instance_1); - Z_rot13_free(&rot13_instance_2); + /* Free the rot13 instances. */ + wasm2c_rot13_free(&rot13_1); + wasm2c_rot13_free(&rot13_2); /* Free the Wasm runtime state. */ wasm_rt_free(); @@ -612,12 +598,13 @@ int main(int argc, char** argv) { /* Fill the wasm buffer with the input to be rot13'd. * * params: + * instance: An instance of the w2c_host structure * ptr: The wasm memory address of the buffer to fill data. * size: The size of the buffer in wasm memory. * result: * The number of bytes filled into the buffer. (Must be <= size). */ -u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size) { +u32 w2c_host_fill_buf(w2c_host* instance, u32 ptr, u32 size) { for (size_t i = 0; i < size; ++i) { if (instance->input[i] == 0) { return i; @@ -630,10 +617,11 @@ u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size) { /* Called when the wasm buffer has been rot13'd. * * params: + * w2c_host: An instance of the w2c_host structure * ptr: The wasm memory address of the buffer. * size: The size of the buffer in wasm memory. */ -void buf_done(struct Z_host_instance_t* instance, u32 ptr, u32 size) { +void w2c_host_buf_done(w2c_host* instance, u32 ptr, u32 size) { /* The output buffer is not necessarily null-terminated, so use the %*.s * printf format to limit the number of characters printed. */ printf("%s -> %.*s\n", instance->input, (int)size, &instance->memory.data[ptr]); diff --git a/wasm2c/examples/callback/callback.wat b/wasm2c/examples/callback/callback.wat index 6a8ab233..9786209a 100644 --- a/wasm2c/examples/callback/callback.wat +++ b/wasm2c/examples/callback/callback.wat @@ -1,7 +1,7 @@ ;; Module demonstrating use of a host-installed callback function. ;; The type of the callback function. The type ID can be looked up outside the module by calling -;; Z_[modname]_get_func_type(1, 0, WASM_RT_I32) (indicating 1 param, 0 results, param type is i32). +;; wasm2c_[modname]_get_func_type(1, 0, WASM_RT_I32) (indicating 1 param, 0 results, param type is i32). (type $print_type (func (param i32))) ;; An indirect function table to hold the callback function diff --git a/wasm2c/examples/callback/main.c b/wasm2c/examples/callback/main.c index b0b37d46..8c6f9db0 100644 --- a/wasm2c/examples/callback/main.c +++ b/wasm2c/examples/callback/main.c @@ -6,8 +6,8 @@ * The callback function. Prints the null-terminated string at the given * location in the instance's exported memory. */ -void print(Z_callback_instance_t* instance, uint32_t ptr) { - puts(Z_callbackZ_memory(instance)->data + ptr); +void print(w2c_callback* instance, uint32_t ptr) { + puts(w2c_callback_memory(instance)->data + ptr); } int main(int argc, char** argv) { @@ -15,8 +15,8 @@ int main(int argc, char** argv) { wasm_rt_init(); /* Instantiate the callback module. */ - Z_callback_instance_t inst; - Z_callback_instantiate(&inst); + w2c_callback inst; + wasm2c_callback_instantiate(&inst); /* * Call the module's "set_print_function" function, which takes a funcref to @@ -24,15 +24,16 @@ int main(int argc, char** argv) { * looked up with "Z_callback_get_func_type"), a pointer to the function, and * a module instance pointer that will be passed to the function when called. */ - wasm_rt_func_type_t fn_type = Z_callback_get_func_type(1, 0, WASM_RT_I32); + wasm_rt_func_type_t fn_type = + wasm2c_callback_get_func_type(1, 0, WASM_RT_I32); wasm_rt_funcref_t fn_ref = {fn_type, (wasm_rt_function_ptr_t)print, &inst}; - Z_callbackZ_set_print_function(&inst, fn_ref); + w2c_callback_set_print_function(&inst, fn_ref); /* "say_hello" uses the previously installed callback. */ - Z_callbackZ_say_hello(&inst); + w2c_callback_say_hello(&inst); /* Free the module instance and the Wasm runtime state. */ - Z_callback_free(&inst); + wasm2c_callback_free(&inst); wasm_rt_free(); return 0; diff --git a/wasm2c/examples/fac/fac.c b/wasm2c/examples/fac/fac.c index c00a60d0..40cb43b2 100644 --- a/wasm2c/examples/fac/fac.c +++ b/wasm2c/examples/fac/fac.c @@ -724,11 +724,11 @@ DEFINE_TABLE_FILL(externref) #define FUNC_TYPE_T(x) static const char x[] #endif -FUNC_TYPE_T(w2c_t0) = "\x07\x80\x96\x7a\x42\xf7\x3e\xe6\x70\x5c\x2f\xac\x83\xf5\x67\xd2\xa2\xa0\x69\x41\x5f\xf8\xe7\x96\x7f\x23\xab\x00\x03\x5f\x4a\x3c"; +FUNC_TYPE_T(w2c_fac_t0) = "\x07\x80\x96\x7a\x42\xf7\x3e\xe6\x70\x5c\x2f\xac\x83\xf5\x67\xd2\xa2\xa0\x69\x41\x5f\xf8\xe7\x96\x7f\x23\xab\x00\x03\x5f\x4a\x3c"; -static u32 w2c_fac(Z_fac_instance_t*, u32); +static u32 w2c_fac_fac_0(w2c_fac*, u32); -static u32 w2c_fac(Z_fac_instance_t* instance, u32 w2c_p0) { +static u32 w2c_fac_fac_0(w2c_fac* instance, u32 w2c_p0) { FUNC_PROLOGUE; u32 w2c_i0, w2c_i1, w2c_i2; w2c_i0 = w2c_p0; @@ -741,7 +741,7 @@ static u32 w2c_fac(Z_fac_instance_t* instance, u32 w2c_p0) { w2c_i1 = w2c_p0; w2c_i2 = 1u; w2c_i1 -= w2c_i2; - w2c_i1 = w2c_fac(instance, w2c_i1); + w2c_i1 = w2c_fac_fac_0(instance, w2c_i1); w2c_i0 *= w2c_i1; } FUNC_EPILOGUE; @@ -749,25 +749,25 @@ static u32 w2c_fac(Z_fac_instance_t* instance, u32 w2c_p0) { } /* export: 'fac' */ -u32 Z_facZ_fac(Z_fac_instance_t* instance, u32 w2c_p0) { - return w2c_fac(instance, w2c_p0); +u32 w2c_fac_fac(w2c_fac* instance, u32 w2c_p0) { + return w2c_fac_fac_0(instance, w2c_p0); } -void Z_fac_instantiate(Z_fac_instance_t* instance) { +void wasm2c_fac_instantiate(w2c_fac* instance) { assert(wasm_rt_is_initialized()); } -void Z_fac_free(Z_fac_instance_t* instance) { +void wasm2c_fac_free(w2c_fac* instance) { } -wasm_rt_func_type_t Z_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...) { +wasm_rt_func_type_t wasm2c_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...) { va_list args; if (param_count == 1 && result_count == 1) { va_start(args, result_count); if (true && va_arg(args, wasm_rt_type_t) == WASM_RT_I32 && va_arg(args, wasm_rt_type_t) == WASM_RT_I32) { va_end(args); - return w2c_t0; + return w2c_fac_t0; } va_end(args); } diff --git a/wasm2c/examples/fac/fac.h b/wasm2c/examples/fac/fac.h index 1354411a..5450fe42 100644 --- a/wasm2c/examples/fac/fac.h +++ b/wasm2c/examples/fac/fac.h @@ -34,16 +34,16 @@ typedef simde_v128_t v128; extern "C" { #endif -typedef struct Z_fac_instance_t { +typedef struct w2c_fac { char dummy_member; -} Z_fac_instance_t; +} w2c_fac; -void Z_fac_instantiate(Z_fac_instance_t*); -void Z_fac_free(Z_fac_instance_t*); -wasm_rt_func_type_t Z_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...); +void wasm2c_fac_instantiate(w2c_fac*); +void wasm2c_fac_free(w2c_fac*); +wasm_rt_func_type_t wasm2c_fac_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* export: 'fac' */ -u32 Z_facZ_fac(Z_fac_instance_t*, u32); +u32 w2c_fac_fac(w2c_fac*, u32); #ifdef __cplusplus } diff --git a/wasm2c/examples/fac/main.c b/wasm2c/examples/fac/main.c index 37593f6e..eb85376e 100644 --- a/wasm2c/examples/fac/main.c +++ b/wasm2c/examples/fac/main.c @@ -18,19 +18,19 @@ int main(int argc, char** argv) { wasm_rt_init(); /* Declare an instance of the `fac` module. */ - Z_fac_instance_t instance; + w2c_fac fac; /* Construct the module instance. */ - Z_fac_instantiate(&instance); + wasm2c_fac_instantiate(&fac); /* Call `fac`, using the mangled name. */ - u32 result = Z_facZ_fac(&instance, x); + u32 result = w2c_fac_fac(&fac, x); /* Print the result. */ printf("fac(%u) -> %u\n", x, result); /* Free the fac module. */ - Z_fac_free(&instance); + wasm2c_fac_free(&fac); /* Free the Wasm runtime state. */ wasm_rt_free(); diff --git a/wasm2c/examples/rot13/main.c b/wasm2c/examples/rot13/main.c index d6517f39..f0164fba 100644 --- a/wasm2c/examples/rot13/main.c +++ b/wasm2c/examples/rot13/main.c @@ -20,49 +20,33 @@ #include "rot13.h" /* Define structure to hold the imports */ -struct Z_host_instance_t { +struct w2c_host { wasm_rt_memory_t memory; char* input; }; /* Accessor to access the memory member of the host */ -wasm_rt_memory_t* Z_hostZ_mem(struct Z_host_instance_t* instance) { +wasm_rt_memory_t* w2c_host_mem(struct w2c_host* instance) { return &instance->memory; } -/* Declare the implementations of the imports. */ -static u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size); -static void buf_done(struct Z_host_instance_t* instance, u32 ptr, u32 size); - -/* Define host-provided functions under the names imported by the `rot13` - * instance */ -u32 Z_hostZ_fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size) { - return fill_buf(instance, ptr, size); -} - -void Z_hostZ_buf_done(struct Z_host_instance_t* instance, u32 ptr, u32 size) { - return buf_done(instance, ptr, size); -} - int main(int argc, char** argv) { /* Make sure there is at least one command-line argument. */ if (argc < 2) { - printf("Invalid argument. Expected '%s WORD'\n", argv[0]); + printf("Invalid argument. Expected '%s WORD...'\n", argv[0]); return 1; } /* Initialize the Wasm runtime. */ wasm_rt_init(); - /* Declare an instance of the `rot13` module. */ - Z_rot13_instance_t rot13_instance; - - /* Create a `host` module instance to store the memory and current string */ - struct Z_host_instance_t host_instance; - /* Allocate 1 page of wasm memory (64KiB). */ - wasm_rt_allocate_memory(&host_instance.memory, 1, 1, false); + /* Create a structure to store the memory and current string, allocating 1 + page of Wasm memory (64 KiB) that the rot13 module instance will import. */ + struct w2c_host host; + wasm_rt_allocate_memory(&host.memory, 1, 1, false); - /* Construct the module instance */ - Z_rot13_instantiate(&rot13_instance, &host_instance); + // Construct an instance of the `rot13` module, which imports from the host. + w2c_rot13 rot13; + wasm2c_rot13_instantiate(&rot13, &host); /* Call `rot13` on each argument. */ while (argc > 1) { @@ -70,12 +54,12 @@ int main(int argc, char** argv) { argc--; argv++; - host_instance.input = argv[0]; - Z_rot13Z_rot13(&rot13_instance); + host.input = argv[0]; + w2c_rot13_rot13(&rot13); } /* Free the rot13 module. */ - Z_rot13_free(&rot13_instance); + wasm2c_rot13_free(&rot13); /* Free the Wasm runtime state. */ wasm_rt_free(); @@ -86,12 +70,13 @@ int main(int argc, char** argv) { /* Fill the wasm buffer with the input to be rot13'd. * * params: + * instance: An instance of the w2c_host structure * ptr: The wasm memory address of the buffer to fill data. * size: The size of the buffer in wasm memory. * result: * The number of bytes filled into the buffer. (Must be <= size). */ -u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size) { +u32 w2c_host_fill_buf(struct w2c_host* instance, u32 ptr, u32 size) { for (size_t i = 0; i < size; ++i) { if (instance->input[i] == 0) { return i; @@ -104,10 +89,11 @@ u32 fill_buf(struct Z_host_instance_t* instance, u32 ptr, u32 size) { /* Called when the wasm buffer has been rot13'd. * * params: + * w2c_host: An instance of the w2c_host structure * ptr: The wasm memory address of the buffer. * size: The size of the buffer in wasm memory. */ -void buf_done(struct Z_host_instance_t* instance, u32 ptr, u32 size) { +void w2c_host_buf_done(struct w2c_host* instance, u32 ptr, u32 size) { /* The output buffer is not necessarily null-terminated, so use the %*.s * printf format to limit the number of characters printed. */ printf("%s -> %.*s\n", instance->input, (int)size, |