blob: 9b6b2180bc5780f43922c420bc9d2ee6bf0d0d3a [file] [edit]
/*
* 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