| /* |
| * 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 |