| /* | |
| * Copyright 2026 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <iostream> | |
| #include <string> | |
| #include "tools/wasm2c/c-printer.h" | |
| #include "tools/wasm2c/wasm2c-builder.h" | |
| #include "wasm.h" | |
| // code to be inserted into the generated output | |
| extern const char* HeaderTop; | |
| extern const char* HeaderBottom; | |
| extern const char* SourceIncludes; | |
| extern const char* SourceDeclarations; | |
| namespace wasm { | |
| namespace { | |
| std::string mangleName(const std::string& name) { | |
| if (name.empty()) { | |
| return ""; | |
| } | |
| std::string result; | |
| bool isFirst = true; | |
| for (char c : name) { | |
| if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || | |
| (c >= '0' && c <= '9')) { | |
| result += c; | |
| isFirst = false; | |
| } else if (c == '_') { | |
| if (isFirst) { | |
| result += "0x5F"; | |
| isFirst = false; | |
| } else { | |
| result += '_'; | |
| } | |
| } else { | |
| char buf[8]; | |
| snprintf(buf, sizeof(buf), "0x%02X", (unsigned char)c); | |
| result += buf; | |
| isFirst = false; | |
| } | |
| } | |
| return result; | |
| } | |
| } // anonymous namespace | |
| void Wasm2CBuilder::processWasm(Module* wasm, | |
| std::ostream& cOut, | |
| std::ostream& hOut) { | |
| this->module = wasm; | |
| std::string moduleName = | |
| flags.moduleName.empty() ? "test" : mangleName(flags.moduleName); | |
| std::string guardName = "WASM_H_GENERATED_" + moduleName; | |
| std::transform( | |
| guardName.begin(), guardName.end(), guardName.begin(), ::toupper); | |
| CPrinter h(hOut); | |
| CPrinter c(cOut); | |
| // Header file prefix | |
| h << "/* Automatically generated by wasm2c */" << endl; | |
| h << "#ifndef " << guardName << endl; | |
| h << "#define " << guardName << endl << endl; | |
| h << "#include \"wasm-rt.h\"" << endl << endl; | |
| h << HeaderTop << endl; | |
| // Source file prefix | |
| c << "/* Automatically generated by wasm2c */" << endl; | |
| c << SourceIncludes << endl; | |
| if (!flags.headerName.empty()) { | |
| c << "#include \"" << flags.headerName << "\"" << endl; | |
| } else { | |
| c << "#include \"wasm.h\"" << endl; | |
| } | |
| c << SourceDeclarations << endl; | |
| // Structure context definition | |
| h << "typedef struct w2c_" << moduleName << " {" << endl; | |
| h.indent(); | |
| h << "char dummy_member;" << endl; | |
| h.outdent(); | |
| h << "} w2c_" << moduleName << ";" << endl << endl; | |
| // Lifecycle signatures in header | |
| h << "void wasm2c_" << moduleName << "_instantiate(w2c_" << moduleName << "*"; | |
| h << ");" << endl; | |
| h << "void wasm2c_" << moduleName << "_free(w2c_" << moduleName << "*);" | |
| << endl; | |
| h << "wasm_rt_func_type_t wasm2c_" << moduleName | |
| << "_get_func_type(uint32_t param_count, uint32_t result_count, ...);" | |
| << endl; | |
| // Instantiate hooks | |
| c << "void wasm2c_" << moduleName << "_instantiate(w2c_" << moduleName | |
| << "* instance"; | |
| c << ") {" << endl; | |
| c.indent(); | |
| c << "assert(wasm_rt_is_initialized());" << endl; | |
| c.outdent(); | |
| c << "}" << endl << endl; | |
| // Free hooks | |
| c << "void wasm2c_" << moduleName << "_free(w2c_" << moduleName | |
| << "* instance) {" << endl; | |
| c << "}" << endl << endl; | |
| // Signature match ladders | |
| c << "wasm_rt_func_type_t wasm2c_" << moduleName | |
| << "_get_func_type(uint32_t param_count, uint32_t result_count, ...) {" | |
| << endl; | |
| c.indent(); | |
| c << "va_list args;" << endl << endl; | |
| c << "return NULL;" << endl; | |
| c.outdent(); | |
| c << "}" << endl << endl; | |
| // Header file suffix | |
| h << endl; | |
| h << HeaderBottom << endl; | |
| h << "#endif /* " << guardName << " */" << endl; | |
| } | |
| } // namespace wasm |