diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/c-writer.cc | 688 | ||||
-rw-r--r-- | src/template/wasm2c.declarations.c | 2 | ||||
-rw-r--r-- | src/template/wasm2c.includes.c | 1 |
3 files changed, 542 insertions, 149 deletions
diff --git a/src/c-writer.cc b/src/c-writer.cc index 32aee51d..0c201b12 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -77,6 +77,8 @@ typedef Name<0> LocalName; typedef Name<1> GlobalName; typedef Name<2> ExternalPtr; typedef Name<3> ExternalRef; +typedef Name<4> ExternalInstancePtr; +typedef Name<5> ExternalInstanceRef; struct GotoLabel { explicit GotoLabel(const Var& var) : var(var) {} @@ -93,6 +95,11 @@ struct GlobalVar { const Var& var; }; +struct GlobalInstanceVar { + explicit GlobalInstanceVar(const Var& var) : var(var) {} + const Var& var; +}; + struct StackVar { explicit StackVar(Index index, Type type = Type::Any) : index(index), type(type) {} @@ -185,10 +192,18 @@ class CWriter { static std::string MangleName(std::string_view); static std::string LegalizeName(std::string_view); std::string ExportName(std::string_view mangled_name); + std::string ModuleInstanceTypeName() const; + static std::string MangleModuleInstanceName( + const std::string_view module_name); + static std::string MangleModuleInstanceTypeName( + const std::string_view module_name); std::string DefineName(SymbolSet*, std::string_view); std::string DefineImportName(const std::string& name, std::string_view module_name, std::string_view mangled_field_name); + std::string DefineImportInstanceName(const std::string& name, + std::string_view module_name, + std::string_view mangled_field_name); std::string DefineGlobalScopeName(const std::string&); std::string DefineLocalScopeName(const std::string&); std::string DefineStackVarName(Index, Type, std::string_view); @@ -211,7 +226,6 @@ class CWriter { enum class WriteExportsKind { Declarations, Definitions, - Initializers, }; void Write() {} @@ -224,6 +238,8 @@ class CWriter { void Write(const GlobalName&); void Write(const ExternalPtr&); void Write(const ExternalRef&); + void Write(const ExternalInstancePtr&); + void Write(const ExternalInstanceRef&); void Write(Type); void Write(SignedType); void Write(TypeEnum); @@ -231,6 +247,7 @@ class CWriter { void Write(const GotoLabel&); void Write(const LabelDecl&); void Write(const GlobalVar&); + void Write(const GlobalInstanceVar&); void Write(const StackVar&); void Write(const ResultType&); void Write(const Const&); @@ -241,9 +258,17 @@ class CWriter { void WriteTagTypes(); void WriteFuncTypes(); void WriteTags(); + void ComputeUniqueImports(); + void BeginInstance(); void WriteImports(); void WriteFuncDeclarations(); void WriteFuncDeclaration(const FuncDeclaration&, const std::string&); + void WriteImportFuncDeclaration(const FuncDeclaration&, + const std::string& module_name, + const std::string&); + void WriteCallIndirectFuncDeclaration(const FuncDeclaration&, + const std::string&); + void WriteModuleInstance(); void WriteGlobals(); void WriteGlobal(const Global&, const std::string&); void WriteGlobalPtr(const Global&, const std::string&); @@ -253,16 +278,21 @@ class CWriter { void WriteTables(); void WriteTable(const std::string&); void WriteTablePtr(const std::string&); + void WriteGlobalInitializers(); void WriteDataInitializers(); void WriteElemInitializers(); - void WriteInitExports(); void WriteExports(WriteExportsKind); + void WriteInitDecl(); + void WriteFreeDecl(); void WriteInit(); void WriteFree(); + void WriteInitInstanceImport(); void WriteFuncs(); void Write(const Func&); void WriteParamsAndLocals(); void WriteParams(const std::vector<std::string>& index_to_name); + void WriteParamSymbols(const std::vector<std::string>& index_to_name); + void WriteParamTypes(const FuncDeclaration& decl); void WriteLocals(const std::vector<std::string>& index_to_name); void WriteStackVarDeclarations(); void Write(const ExprList&); @@ -317,6 +347,7 @@ class CWriter { SymbolMap global_sym_map_; SymbolMap local_sym_map_; + SymbolMap import_module_sym_map_; StackVarSymbolMap stack_var_sym_map_; SymbolSet global_syms_; SymbolSet local_syms_; @@ -326,6 +357,10 @@ class CWriter { std::vector<TryCatchLabel> try_catch_stack_; std::string module_prefix_; + std::vector<const Import*> unique_imports_; + SymbolSet import_module_set_; // modules that are imported from + SymbolSet import_func_module_set_; // modules that funcs are imported from + std::vector<std::pair<std::string, MemoryStream>> func_sections_; SymbolSet func_includes_; }; @@ -467,11 +502,26 @@ std::string CWriter::MangleName(std::string_view name) { return result; } -// static std::string CWriter::ExportName(std::string_view mangled_name) { return module_prefix_ + std::string(mangled_name); } +std::string CWriter::ModuleInstanceTypeName() const { + return module_prefix_ + "_instance_t"; +} + +// static +std::string CWriter::MangleModuleInstanceName( + const std::string_view module_name) { + return MangleName(module_name) + "_instance"; +} + +// static +std::string CWriter::MangleModuleInstanceTypeName( + const std::string_view module_name) { + return MangleName(module_name) + "_instance_t"; +} + // static std::string CWriter::LegalizeName(std::string_view name) { if (name.empty()) @@ -513,8 +563,18 @@ std::string_view StripLeadingDollar(std::string_view name) { std::string CWriter::DefineImportName(const std::string& name, std::string_view module, - std::string_view mangled_field_name) { - std::string mangled = MangleName(module) + mangled_field_name; + std::string_view field_name) { + std::string mangled = MangleName(module) + MangleName(field_name); + import_syms_.insert(name); + global_syms_.insert(mangled); + global_sym_map_.insert(SymbolMap::value_type(name, mangled)); + return mangled; +} + +std::string CWriter::DefineImportInstanceName(const std::string& name, + std::string_view module, + std::string_view field_name) { + std::string mangled = MangleName(module) + MangleName(field_name); import_syms_.insert(name); global_syms_.insert(mangled); global_sym_map_.insert(SymbolMap::value_type(name, mangled)); @@ -628,6 +688,15 @@ void CWriter::Write(const ExternalPtr& name) { } } +void CWriter::Write(const ExternalInstancePtr& name) { + bool is_import = import_syms_.count(name.name) != 0; + if (is_import) { + Write("instance->", GetGlobalName(name.name)); + } else { + Write("&instance->", GetGlobalName(name.name)); + } +} + void CWriter::Write(const ExternalRef& name) { bool is_import = import_syms_.count(name.name) != 0; if (is_import) { @@ -637,6 +706,15 @@ void CWriter::Write(const ExternalRef& name) { } } +void CWriter::Write(const ExternalInstanceRef& name) { + bool is_import = import_syms_.count(name.name) != 0; + if (is_import) { + Write(Deref("instance->" + GetGlobalName(name.name))); + } else { + Write("instance->", GetGlobalName(name.name)); + } +} + void CWriter::Write(const Var& var) { assert(var.is_name()); Write(LocalName(var.name())); @@ -687,6 +765,11 @@ void CWriter::Write(const GlobalVar& var) { Write(ExternalRef(var.var.name())); } +void CWriter::Write(const GlobalInstanceVar& var) { + assert(var.var.is_name()); + Write(ExternalInstanceRef(var.var.name())); +} + void CWriter::Write(const StackVar& sv) { Index index = type_stack_.size() - 1 - sv.index; Type type = sv.type; @@ -808,6 +891,21 @@ void CWriter::Write(const Const& const_) { } } +void CWriter::WriteInitDecl() { + Write("void " + module_prefix_ + "_init_module(void);", Newline()); + Write("void " + module_prefix_ + "_instantiate(", ModuleInstanceTypeName(), + "*"); + for (auto import_module_name : import_module_set_) { + Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "*"); + } + Write(");", Newline()); +} + +void CWriter::WriteFreeDecl() { + Write("void " + module_prefix_ + "_free(", ModuleInstanceTypeName(), "*);", + Newline()); +} + void CWriter::WriteInitExpr(const ExprList& expr_list) { if (expr_list.empty()) return; @@ -820,7 +918,7 @@ void CWriter::WriteInitExpr(const ExprList& expr_list) { break; case ExprType::GlobalGet: - Write(GlobalVar(cast<GlobalGetExpr>(expr)->var)); + Write(GlobalInstanceVar(cast<GlobalGetExpr>(expr)->var)); break; default: @@ -960,57 +1058,151 @@ void CWriter::WriteTags() { Write(CloseBrace(), Newline()); } -void CWriter::WriteImports() { - if (module_->imports.empty()) +void CWriter::ComputeUniqueImports() { + using modname_name_pair = std::pair<std::string, std::string>; + std::map<modname_name_pair, const Import*> import_map; + for (const Import* import : module_->imports) { + // After emplacing, the returned bool says whether the insert happened; + // i.e., was there already an import with the same modname and name? + // If there was, make sure it was at least the same kind of import. + const auto iterator_and_insertion_bool = import_map.emplace( + modname_name_pair(import->module_name, import->field_name), import); + if (!iterator_and_insertion_bool.second) { + if (iterator_and_insertion_bool.first->second->kind() != import->kind()) { + UNIMPLEMENTED("contradictory import declaration"); + } else { + fprintf(stderr, "warning: duplicate import declaration \"%s\" \"%s\"\n", + import->module_name.c_str(), import->field_name.c_str()); + } + } + import_module_set_.insert(import->module_name); + if (import->kind() == ExternalKind::Func) { + import_func_module_set_.insert(import->module_name); + } + } + + for (const auto& node : import_map) { + unique_imports_.push_back(node.second); + } +} + +void CWriter::BeginInstance() { + if (module_->imports.empty()) { + Write("typedef struct ", ModuleInstanceTypeName(), " ", OpenBrace()); return; + } - Write(Newline()); + ComputeUniqueImports(); - // TODO(binji): Write imports ordered by type. + // define names of per-instance imports for (const Import* import : module_->imports) { - Write("/* import: '", import->module_name, "' '", import->field_name, - "' */", Newline()); - Write("extern "); switch (import->kind()) { case ExternalKind::Func: { const Func& func = cast<FuncImport>(import)->func; - WriteFuncDeclaration(func.decl, - DefineImportName(func.name, import->module_name, - MangleName(import->field_name))); - Write(";"); + DefineImportName(func.name, import->module_name, import->field_name); + import_module_sym_map_.emplace(func.name, import->module_name); + } break; + + case ExternalKind::Tag: { + const Tag& tag = cast<TagImport>(import)->tag; + DefineImportName(tag.name, import->module_name, import->field_name); + import_module_sym_map_.emplace(tag.name, import->module_name); + } break; + + case ExternalKind::Global: + DefineImportInstanceName(cast<GlobalImport>(import)->global.name, + import->module_name, import->field_name); break; - } + case ExternalKind::Memory: + DefineImportInstanceName(cast<MemoryImport>(import)->memory.name, + import->module_name, import->field_name); + break; + + case ExternalKind::Table: + DefineImportInstanceName(cast<TableImport>(import)->table.name, + import->module_name, import->field_name); + break; + + default: + WABT_UNREACHABLE; + } + } + + // Forward declaring module instance types + for (auto import_module : import_module_set_) { + Write("struct ", MangleModuleInstanceTypeName(import_module), ";", + Newline()); + } + + // Forward declaring module imports + for (const Import* import : unique_imports_) { + if ((import->kind() == ExternalKind::Func) || + (import->kind() == ExternalKind::Tag)) { + continue; + } + + Write("extern "); + switch (import->kind()) { case ExternalKind::Global: { const Global& global = cast<GlobalImport>(import)->global; - WriteGlobal(global, DefineImportName(global.name, import->module_name, - MangleName(import->field_name))); - Write(";"); + Write(global.type); break; } case ExternalKind::Memory: { - const Memory& memory = cast<MemoryImport>(import)->memory; - WriteMemory(DefineImportName(memory.name, import->module_name, - MangleName(import->field_name))); + Write("wasm_rt_memory_t"); break; } case ExternalKind::Table: { - const Table& table = cast<TableImport>(import)->table; - WriteTable(DefineImportName(table.name, import->module_name, - MangleName(import->field_name))); + Write("wasm_rt_table_t"); break; } - case ExternalKind::Tag: { - const Tag& tag = cast<TagImport>(import)->tag; - Write("const u32 ", - DefineImportName(tag.name, import->module_name, - MangleName(import->field_name)), - ";"); + default: + WABT_UNREACHABLE; + } + Write("* ", MangleName(import->module_name), MangleName(import->field_name), + "(struct ", MangleModuleInstanceTypeName(import->module_name), "*);", + Newline()); + } + Write(Newline()); + + // Add pointers to module instances that any func is imported from, + // so that imported functions can be given their own module instances + // when invoked + Write("typedef struct ", ModuleInstanceTypeName(), " ", OpenBrace()); + for (auto import_module : import_func_module_set_) { + Write("struct ", MangleModuleInstanceTypeName(import_module), "* ", + MangleModuleInstanceName(import_module) + ";", Newline()); + } + + for (const Import* import : unique_imports_) { + if ((import->kind() == ExternalKind::Func) || + (import->kind() == ExternalKind::Tag)) { + continue; + } + + Write("/* import: '", import->module_name, "' '", import->field_name, + "' */", Newline()); + + switch (import->kind()) { + case ExternalKind::Global: + WriteGlobal(cast<GlobalImport>(import)->global, + "*" + MangleName(import->module_name) + + MangleName(import->field_name)); + break; + + case ExternalKind::Memory: + WriteMemory("*" + MangleName(import->module_name) + + MangleName(import->field_name)); + break; + + case ExternalKind::Table: + WriteTable("*" + MangleName(import->module_name) + + MangleName(import->field_name)); break; - } default: WABT_UNREACHABLE; @@ -1020,6 +1212,32 @@ void CWriter::WriteImports() { } } +// Write module-wide imports (funcs & tags), which aren't tied to an instance. +void CWriter::WriteImports() { + if (module_->imports.empty()) + return; + + Write(Newline()); + + for (const Import* import : unique_imports_) { + if (import->kind() == ExternalKind::Func) { + Write("/* import: '", import->module_name, "' '", import->field_name, + "' */", Newline()); + const Func& func = cast<FuncImport>(import)->func; + WriteImportFuncDeclaration( + func.decl, import->module_name, + MangleName(import->module_name) + MangleName(import->field_name)); + Write(";"); + Write(Newline()); + } else if (import->kind() == ExternalKind::Tag) { + Write("/* import: '", import->module_name, "' '", import->field_name, + "' */", Newline()); + Write("extern const u32 *", MangleName(import->module_name), + MangleName(import->field_name), ";", Newline()); + } + } +} + void CWriter::WriteFuncDeclarations() { if (module_->funcs.size() == module_->num_func_imports) return; @@ -1041,68 +1259,73 @@ void CWriter::WriteFuncDeclarations() { void CWriter::WriteFuncDeclaration(const FuncDeclaration& decl, const std::string& name) { Write(ResultType(decl.sig.result_types), " ", name, "("); - if (decl.GetNumParams() == 0) { - Write("void"); - } else { - for (Index i = 0; i < decl.GetNumParams(); ++i) { - if (i != 0) - Write(", "); - Write(decl.GetParamType(i)); - } - } + Write(ModuleInstanceTypeName(), "*"); + WriteParamTypes(decl); + Write(")"); +} + +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), "*"); + WriteParamTypes(decl); + Write(")"); +} + +void CWriter::WriteCallIndirectFuncDeclaration(const FuncDeclaration& decl, + const std::string& name) { + Write(ResultType(decl.sig.result_types), " ", name, "(void*"); + WriteParamTypes(decl); Write(")"); } +void CWriter::WriteModuleInstance() { + BeginInstance(); + WriteGlobals(); + WriteMemories(); + WriteTables(); + + // C forbids an empty struct + if (module_->globals.empty() && module_->memories.empty() && + module_->tables.empty()) { + Write("char dummy_member;", Newline()); + } + + Write(CloseBrace(), " ", ModuleInstanceTypeName(), ";", Newline()); + Write(Newline()); +} + void CWriter::WriteGlobals() { Index global_index = 0; if (module_->globals.size() != module_->num_global_imports) { - Write(Newline()); - for (const Global* global : module_->globals) { bool is_import = global_index < module_->num_global_imports; if (!is_import) { - Write("static "); WriteGlobal(*global, DefineGlobalScopeName(global->name)); - Write(";", Newline()); + Write(Newline()); } ++global_index; } } - - Write(Newline(), "static void init_globals(void) ", OpenBrace()); - global_index = 0; - for (const Global* global : module_->globals) { - bool is_import = global_index < module_->num_global_imports; - if (!is_import) { - assert(!global->init_expr.empty()); - Write(GlobalName(global->name), " = "); - WriteInitExpr(global->init_expr); - Write(";", Newline()); - } - ++global_index; - } - Write(CloseBrace(), Newline()); } void CWriter::WriteGlobal(const Global& global, const std::string& name) { - Write(global.type, " ", name); + Write(global.type, " ", name, ";"); } void CWriter::WriteGlobalPtr(const Global& global, const std::string& name) { - Write(global.type, "* ", name); + Write(global.type, "* ", name, "(", ModuleInstanceTypeName(), "* instance)"); } void CWriter::WriteMemories() { if (module_->memories.size() == module_->num_memory_imports) return; - Write(Newline()); - Index memory_index = 0; for (const Memory* memory : module_->memories) { bool is_import = memory_index < module_->num_memory_imports; if (!is_import) { - Write("static "); WriteMemory(DefineGlobalScopeName(memory->name)); Write(Newline()); } @@ -1115,7 +1338,8 @@ void CWriter::WriteMemory(const std::string& name) { } void CWriter::WriteMemoryPtr(const std::string& name) { - Write("wasm_rt_memory_t* ", name, ";"); + Write("wasm_rt_memory_t* ", name, "(", ModuleInstanceTypeName(), + "* instance)"); } void CWriter::WriteTables() { @@ -1123,14 +1347,11 @@ void CWriter::WriteTables() { return; } - Write(Newline()); - assert(module_->tables.size() <= 1); Index table_index = 0; for (const Table* table : module_->tables) { bool is_import = table_index < module_->num_table_imports; if (!is_import) { - Write("static "); WriteTable(DefineGlobalScopeName(table->name)); Write(Newline()); } @@ -1143,7 +1364,25 @@ void CWriter::WriteTable(const std::string& name) { } void CWriter::WriteTablePtr(const std::string& name) { - Write("wasm_rt_table_t* ", name, ";"); + Write("wasm_rt_table_t* ", name, "(", ModuleInstanceTypeName(), + "* instance)"); +} + +void CWriter::WriteGlobalInitializers() { + Write(Newline(), "static void init_globals(", ModuleInstanceTypeName(), + "* instance) ", OpenBrace()); + Index global_index = 0; + for (const Global* global : module_->globals) { + bool is_import = global_index < module_->num_global_imports; + if (!is_import) { + assert(!global->init_expr.empty()); + Write(ExternalInstanceRef(global->name), " = "); + WriteInitExpr(global->init_expr); + Write(";", Newline()); + } + ++global_index; + } + Write(CloseBrace(), Newline()); } void CWriter::WriteDataInitializers() { @@ -1178,20 +1417,21 @@ void CWriter::WriteDataInitializers() { memory = module_->memories[0]; } - Write(Newline(), "static void init_memory(void) ", OpenBrace()); + Write("static void init_memory(", ModuleInstanceTypeName(), "* instance) ", + OpenBrace()); if (module_->memories.size() > module_->num_memory_imports) { Index memory_idx = module_->num_memory_imports; for (Index i = memory_idx; i < module_->memories.size(); i++) { memory = module_->memories[i]; uint32_t max = memory->page_limits.has_max ? memory->page_limits.max : 65536; - Write("wasm_rt_allocate_memory(", ExternalPtr(memory->name), ", ", + Write("wasm_rt_allocate_memory(", ExternalInstancePtr(memory->name), ", ", memory->page_limits.initial, ", ", max, ");", Newline()); } } data_segment_index = 0; for (const DataSegment* data_segment : module_->data_segments) { - Write("LOAD_DATA(", ExternalRef(memory->name), ", "); + Write("LOAD_DATA(", ExternalInstanceRef(memory->name), ", "); WriteInitExpr(data_segment->offset); Write(", data_segment_data_", data_segment_index, ", ", data_segment->data.size()); @@ -1203,7 +1443,8 @@ void CWriter::WriteDataInitializers() { } void CWriter::WriteElemInitializers() { - Write(Newline(), "static void init_table(void) ", OpenBrace()); + Write(Newline(), "static void init_table(", ModuleInstanceTypeName(), + "* instance) ", OpenBrace()); if (!module_->types.size()) { // If there are no types there cannot be any table entries either. @@ -1219,7 +1460,7 @@ void CWriter::WriteElemInitializers() { if (table && module_->num_table_imports == 0) { uint32_t max = table->elem_limits.has_max ? table->elem_limits.max : UINT32_MAX; - Write("wasm_rt_allocate_table(", ExternalPtr(table->name), ", ", + Write("wasm_rt_allocate_table(", ExternalInstancePtr(table->name), ", ", table->elem_limits.initial, ", ", max, ");", Newline()); } Index elem_segment_index = 0; @@ -1241,9 +1482,20 @@ void CWriter::WriteElemInitializers() { const Func* func = module_->GetFunc(cast<RefFuncExpr>(expr)->var); Index func_type_index = module_->GetFuncTypeIndex(func->decl.type_var); - Write(ExternalRef(table->name), ".data[offset + ", i, - "] = (wasm_rt_elem_t){func_types[", func_type_index, - "], (wasm_rt_funcref_t)", ExternalPtr(func->name), "};", Newline()); + bool is_import = import_module_sym_map_.count(func->name) != 0; + if (is_import) { + Write(ExternalInstanceRef(table->name), ".data[offset + ", i, + "] = (wasm_rt_elem_t){func_types[", func_type_index, + "], (wasm_rt_funcref_t)", ExternalPtr(func->name), + ", (void*)(instance->", + MangleModuleInstanceName(import_module_sym_map_[func->name]), + ")};", Newline()); + } else { + Write(ExternalInstanceRef(table->name), ".data[offset + ", i, + "] = (wasm_rt_elem_t){func_types[", func_type_index, + "], (wasm_rt_funcref_t)", ExternalPtr(func->name), + ", (void*)instance};", Newline()); + } ++i; } ++elem_segment_index; @@ -1252,37 +1504,34 @@ void CWriter::WriteElemInitializers() { Write(CloseBrace(), Newline()); } -void CWriter::WriteInitExports() { - Write(Newline(), "static void init_exports(void) ", OpenBrace()); - WriteExports(WriteExportsKind::Initializers); - Write(CloseBrace(), Newline()); -} - void CWriter::WriteExports(WriteExportsKind kind) { if (module_->exports.empty()) return; - if (kind != WriteExportsKind::Initializers) { - Write(Newline()); - } - for (const Export* export_ : module_->exports) { - Write("/* export: '", export_->name, "' */", Newline()); - if (kind == WriteExportsKind::Declarations) { - Write("extern "); - } + Write(Newline(), "/* export: '", export_->name, "' */", Newline()); std::string mangled_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 != WriteExportsKind::Initializers) { - WriteFuncDeclaration(func->decl, Deref(mangled_name)); - Write(";"); + if (kind == WriteExportsKind::Declarations) { + WriteFuncDeclaration(func->decl, mangled_name); + } else { + func_ = func; + local_syms_ = global_syms_; + local_sym_map_.clear(); + stack_var_sym_map_.clear(); + Write(ResultType(func_->decl.sig.result_types), " ", mangled_name, + "("); + MakeTypeBindingReverseMapping(func_->GetNumParamsAndLocals(), + func_->bindings, &index_to_name); + WriteParams(index_to_name); } break; } @@ -1291,10 +1540,7 @@ void CWriter::WriteExports(WriteExportsKind kind) { const Global* global = module_->GetGlobal(export_->var); mangled_name = ExportName(MangleName(export_->name)); internal_name = global->name; - if (kind != WriteExportsKind::Initializers) { - WriteGlobalPtr(*global, mangled_name); - Write(";"); - } + WriteGlobalPtr(*global, mangled_name); break; } @@ -1302,9 +1548,7 @@ void CWriter::WriteExports(WriteExportsKind kind) { const Memory* memory = module_->GetMemory(export_->var); mangled_name = ExportName(MangleName(export_->name)); internal_name = memory->name; - if (kind != WriteExportsKind::Initializers) { - WriteMemoryPtr(mangled_name); - } + WriteMemoryPtr(mangled_name); break; } @@ -1312,9 +1556,7 @@ void CWriter::WriteExports(WriteExportsKind kind) { const Table* table = module_->GetTable(export_->var); mangled_name = ExportName(MangleName(export_->name)); internal_name = table->name; - if (kind != WriteExportsKind::Initializers) { - WriteTablePtr(mangled_name); - } + WriteTablePtr(mangled_name); break; } @@ -1322,9 +1564,10 @@ void CWriter::WriteExports(WriteExportsKind kind) { const Tag* tag = module_->GetTag(export_->var); mangled_name = ExportName(MangleName(export_->name)); internal_name = tag->name; - if (kind != WriteExportsKind::Initializers) { - Write("const u32 *", mangled_name, ";"); + if (kind == WriteExportsKind::Declarations) { + Write("extern "); } + Write("const u32 *", mangled_name); break; } @@ -1332,30 +1575,145 @@ void CWriter::WriteExports(WriteExportsKind kind) { WABT_UNREACHABLE; } - if (kind == WriteExportsKind::Initializers) { - Write(mangled_name, " = ", ExternalPtr(internal_name), ";"); + if (kind == WriteExportsKind::Declarations) { + Write(";"); + continue; } - Write(Newline()); + Write(" "); + switch (export_->kind) { + case ExternalKind::Func: { + Write(OpenBrace()); + Write("return ", ExternalRef(internal_name), "("); + + bool is_import = import_module_sym_map_.count(internal_name) != 0; + if (is_import) { + Write("instance->", MangleModuleInstanceName( + import_module_sym_map_[internal_name])); + } else { + Write("instance"); + } + WriteParamSymbols(index_to_name); + Write(CloseBrace(), Newline()); + + local_sym_map_.clear(); + stack_var_sym_map_.clear(); + func_ = nullptr; + break; + } + + case ExternalKind::Global: + case ExternalKind::Memory: + case ExternalKind::Table: { + Write(OpenBrace()); + Write("return ", ExternalInstancePtr(internal_name), ";", Newline()); + Write(CloseBrace(), Newline()); + break; + } + + case ExternalKind::Tag: + Write("= ", ExternalPtr(internal_name), ";", Newline()); + break; + + default: + WABT_UNREACHABLE; + } } } void CWriter::WriteInit() { - Write(Newline(), "void ", module_prefix_, "_init(void) ", OpenBrace()); + Write(Newline(), "void " + module_prefix_ + "_init_module(void) ", + OpenBrace()); + Write("assert(wasm_rt_is_initialized());", Newline()); + Write("s_module_initialized = true;", Newline()); Write("init_func_types();", Newline()); Write("init_tags();", Newline()); - Write("init_globals();", Newline()); - Write("init_memory();", Newline()); - Write("init_table();", Newline()); - Write("init_exports();", Newline()); + Write(CloseBrace(), Newline()); + + Write(Newline(), "void " + module_prefix_ + "_instantiate(", + ModuleInstanceTypeName(), "* instance"); + for (auto import_module_name : import_module_set_) { + Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "* ", + MangleModuleInstanceName(import_module_name)); + } + Write(") ", OpenBrace()); + + Write("assert(wasm_rt_is_initialized());", Newline()); + Write("assert(s_module_initialized);", Newline()); + + if (!module_->imports.empty()) { + Write("init_instance_import(instance"); + for (auto import_module_name : import_module_set_) { + Write(", ", MangleModuleInstanceName(import_module_name)); + } + Write(");", Newline()); + } + + Write("init_globals(instance);", Newline()); + Write("init_memory(instance);", Newline()); + Write("init_table(instance);", Newline()); for (Var* var : module_->starts) { - Write(ExternalRef(module_->GetFunc(*var)->name), "();", Newline()); + Write(ExternalRef(module_->GetFunc(*var)->name)); + bool is_import = + import_module_sym_map_.count(module_->GetFunc(*var)->name) != 0; + if (is_import) { + Write("(instance->", + MangleModuleInstanceName( + import_module_sym_map_[module_->GetFunc(*var)->name]) + + ");"); + } else { + Write("(instance);"); + } + Write(Newline()); + } + Write(CloseBrace(), Newline()); +} + +void CWriter::WriteInitInstanceImport() { + if (module_->imports.empty()) + return; + + Write(Newline(), "static void init_instance_import(", + ModuleInstanceTypeName(), "* instance"); + for (auto import_module_name : import_module_set_) { + Write(", struct ", MangleModuleInstanceTypeName(import_module_name), "* ", + MangleModuleInstanceName(import_module_name)); + } + Write(")", OpenBrace()); + + for (auto import_module : import_func_module_set_) { + Write("instance->", MangleModuleInstanceName(import_module), " = ", + MangleModuleInstanceName(import_module), ";", Newline()); + } + + for (const Import* import : unique_imports_) { + switch (import->kind()) { + case ExternalKind::Func: + case ExternalKind::Tag: + break; + + 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), ");", + Newline()); + break; + } + + default: + WABT_UNREACHABLE; + } } Write(CloseBrace(), Newline()); } void CWriter::WriteFree() { - Write(Newline(), "void " + module_prefix_ + "_free(void) ", OpenBrace()); + Write(Newline(), "void " + module_prefix_ + "_free(", + ModuleInstanceTypeName(), "* instance) ", OpenBrace()); if (module_->types.size()) { // If there are no types there cannot be any table entries either. @@ -1364,7 +1722,8 @@ void CWriter::WriteFree() { for (const Table* table : module_->tables) { bool is_import = table_index < module_->num_table_imports; if (!is_import) { - Write("wasm_rt_free_table(", ExternalPtr(table->name), ");", Newline()); + Write("wasm_rt_free_table(", ExternalInstancePtr(table->name), ");", + Newline()); } ++table_index; } @@ -1375,7 +1734,7 @@ void CWriter::WriteFree() { for (const Memory* memory : module_->memories) { bool is_import = memory_index < module_->num_memory_imports; if (!is_import) { - Write("wasm_rt_free_memory(", ExternalPtr(memory->name), ");", + Write("wasm_rt_free_memory(", ExternalInstancePtr(memory->name), ");", Newline()); } ++memory_index; @@ -1463,26 +1822,49 @@ void CWriter::WriteParamsAndLocals() { MakeTypeBindingReverseMapping(func_->GetNumParamsAndLocals(), func_->bindings, &index_to_name); WriteParams(index_to_name); + Write(" ", OpenBrace()); WriteLocals(index_to_name); } void CWriter::WriteParams(const std::vector<std::string>& index_to_name) { - if (func_->GetNumParams() == 0) { - Write("void"); - } else { + Write(ModuleInstanceTypeName(), "* instance"); + if (func_->GetNumParams() != 0) { Indent(4); for (Index i = 0; i < func_->GetNumParams(); ++i) { - if (i != 0) { - Write(", "); - if ((i % 8) == 0) - Write(Newline()); + Write(", "); + if (i != 0 && (i % 8) == 0) { + Write(Newline()); } Write(func_->GetParamType(i), " ", DefineLocalScopeName(index_to_name[i])); } Dedent(4); } - Write(") ", OpenBrace()); + Write(")"); +} + +void CWriter::WriteParamSymbols(const std::vector<std::string>& index_to_name) { + if (func_->GetNumParams() != 0) { + Indent(4); + for (Index i = 0; i < func_->GetNumParams(); ++i) { + Write(", "); + if (i != 0 && (i % 8) == 0) { + Write(Newline()); + } + Write(local_sym_map_[index_to_name[i]]); + } + Dedent(4); + } + Write(");", Newline()); +} + +void CWriter::WriteParamTypes(const FuncDeclaration& decl) { + if (decl.GetNumParams() != 0) { + for (Index i = 0; i < decl.GetNumParams(); ++i) { + Write(", "); + Write(decl.GetParamType(i)); + } + } } void CWriter::WriteLocals(const std::vector<std::string>& index_to_name) { @@ -1786,10 +2168,15 @@ void CWriter::Write(const ExprList& exprs) { } Write(GlobalVar(var), "("); + bool is_import = import_module_sym_map_.count(func.name) != 0; + if (is_import) { + Write("instance->", + MangleModuleInstanceName(import_module_sym_map_[func.name])); + } else { + Write("instance"); + } for (Index i = 0; i < num_params; ++i) { - if (i != 0) { - Write(", "); - } + Write(", "); Write(StackVar(num_params - i - 1)); } Write(");", Newline()); @@ -1828,9 +2215,11 @@ void CWriter::Write(const ExprList& exprs) { assert(decl.has_func_type); Index func_type_index = module_->GetFuncTypeIndex(decl.type_var); - Write("CALL_INDIRECT(", ExternalRef(table->name), ", "); - WriteFuncDeclaration(decl, "(*)"); + Write("CALL_INDIRECT(", ExternalInstanceRef(table->name), ", "); + WriteCallIndirectFuncDeclaration(decl, "(*)"); Write(", ", func_type_index, ", ", StackVar(0)); + Write(", ", ExternalInstanceRef(table->name), ".data[", StackVar(0), + "].module_instance"); for (Index i = 0; i < num_params; ++i) { Write(", ", StackVar(num_params - i)); } @@ -1876,13 +2265,13 @@ void CWriter::Write(const ExprList& exprs) { case ExprType::GlobalGet: { const Var& var = cast<GlobalGetExpr>(&expr)->var; PushType(module_->GetGlobal(var)->type); - Write(StackVar(0), " = ", GlobalVar(var), ";", Newline()); + Write(StackVar(0), " = ", GlobalInstanceVar(var), ";", Newline()); break; } case ExprType::GlobalSet: { const Var& var = cast<GlobalSetExpr>(&expr)->var; - Write(GlobalVar(var), " = ", StackVar(0), ";", Newline()); + Write(GlobalInstanceVar(var), " = ", StackVar(0), ";", Newline()); DropTypes(1); break; } @@ -1973,8 +2362,9 @@ void CWriter::Write(const ExprList& exprs) { Memory* memory = module_->memories[module_->GetMemoryIndex( cast<MemoryGrowExpr>(&expr)->memidx)]; - Write(StackVar(0), " = wasm_rt_grow_memory(", ExternalPtr(memory->name), - ", ", StackVar(0), ");", Newline()); + Write(StackVar(0), " = wasm_rt_grow_memory(", + ExternalInstancePtr(memory->name), ", ", StackVar(0), ");", + Newline()); break; } @@ -1983,7 +2373,7 @@ void CWriter::Write(const ExprList& exprs) { cast<MemorySizeExpr>(&expr)->memidx)]; PushType(Type::I32); - Write(StackVar(0), " = ", ExternalRef(memory->name), ".pages;", + Write(StackVar(0), " = ", ExternalInstanceRef(memory->name), ".pages;", Newline()); break; } @@ -2536,8 +2926,8 @@ void CWriter::Write(const LoadExpr& expr) { Memory* memory = module_->memories[module_->GetMemoryIndex(expr.memidx)]; Type result_type = expr.opcode.GetResultType(); - Write(StackVar(0, result_type), " = ", func, "(", ExternalPtr(memory->name), - ", (u64)(", StackVar(0), ")"); + Write(StackVar(0, result_type), " = ", func, "(", + ExternalInstancePtr(memory->name), ", (u64)(", StackVar(0), ")"); if (expr.offset != 0) Write(" + ", expr.offset, "u"); Write(");", Newline()); @@ -2564,7 +2954,8 @@ void CWriter::Write(const StoreExpr& expr) { Memory* memory = module_->memories[module_->GetMemoryIndex(expr.memidx)]; - Write(func, "(", ExternalPtr(memory->name), ", (u64)(", StackVar(1), ")"); + Write(func, "(", ExternalInstancePtr(memory->name), ", (u64)(", StackVar(1), + ")"); if (expr.offset != 0) Write(" + ", expr.offset); Write(", ", StackVar(0), ");", Newline()); @@ -2750,7 +3141,7 @@ void CWriter::Write(const LoadSplatExpr& expr) { Type result_type = expr.opcode.GetResultType(); Write(StackVar(0, result_type), " = ", expr.opcode.GetName(), "(", - ExternalPtr(memory->name), ", (u64)(", StackVar(0)); + ExternalInstancePtr(memory->name), ", (u64)(", StackVar(0)); if (expr.offset != 0) Write(" + ", expr.offset); Write("));", Newline()); @@ -2771,12 +3162,13 @@ void CWriter::WriteCHeader() { Write(Newline()); Write(s_header_top); Write(Newline()); + WriteModuleInstance(); + WriteInitDecl(); + WriteFreeDecl(); WriteMultivalueTypes(); WriteImports(); - Write("void ", module_prefix_, "_init(void);", Newline()); - Write("void ", module_prefix_, "_free(void);", Newline()); WriteExports(WriteExportsKind::Declarations); - Write(s_header_bottom); + Write(Newline(), s_header_bottom); Write(Newline(), "#endif /* ", guard, " */", Newline()); } @@ -2788,14 +3180,12 @@ void CWriter::WriteCSource() { WriteTagTypes(); WriteTags(); WriteFuncDeclarations(); - WriteGlobals(); - WriteMemories(); - WriteTables(); WriteFuncs(); + WriteGlobalInitializers(); WriteDataInitializers(); WriteElemInitializers(); WriteExports(WriteExportsKind::Definitions); - WriteInitExports(); + WriteInitInstanceImport(); WriteInit(); WriteFree(); } diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index f036ba19..4459790f 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -443,3 +443,5 @@ static float wasm_sqrtf(float x) { } return sqrtf(x); } + +static bool s_module_initialized = false; diff --git a/src/template/wasm2c.includes.c b/src/template/wasm2c.includes.c index 8b61e643..59def29c 100644 --- a/src/template/wasm2c.includes.c +++ b/src/template/wasm2c.includes.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <math.h> #include <string.h> #if defined(_MSC_VER) |