Skip to content

Commit

Permalink
Remove signature mangling from wasm2c output
Browse files Browse the repository at this point in the history
This effectively means that we no longer support imports that are
overloaded by signature only, which is not something that we need to
support in order to support the core wasm spec.

This feature is available in the JS embedding but there is no good
reason (AFAICT) to support it in wasm2c, and this simplifies the
generated code.

Fixes #1858
  • Loading branch information
sbc100 committed Apr 13, 2022
1 parent 39022f8 commit 8e6fb55
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 77 deletions.
37 changes: 4 additions & 33 deletions src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,8 @@ class CWriter {
static std::string Deref(const std::string&);

static char MangleType(Type);
static std::string MangleTypes(const TypeVector&);
static std::string MangleMultivalueTypes(const TypeVector&);
static std::string MangleName(std::string_view);
static std::string MangleFuncName(std::string_view,
const TypeVector& param_types,
const TypeVector& result_types);
static std::string MangleGlobalName(std::string_view, Type);
static std::string LegalizeName(std::string_view);
static std::string ExportName(std::string_view mangled_name);
Expand Down Expand Up @@ -395,18 +391,6 @@ char CWriter::MangleType(Type type) {
}
}

// static
std::string CWriter::MangleTypes(const TypeVector& types) {
if (types.empty())
return std::string("v");

std::string result;
for (auto type : types) {
result += MangleType(type);
}
return result;
}

// static
std::string CWriter::MangleMultivalueTypes(const TypeVector& types) {
assert(types.size() >= 2);
Expand Down Expand Up @@ -436,14 +420,6 @@ std::string CWriter::MangleName(std::string_view name) {
return result;
}

// static
std::string CWriter::MangleFuncName(std::string_view name,
const TypeVector& param_types,
const TypeVector& result_types) {
std::string sig = MangleTypes(result_types) + MangleTypes(param_types);
return MangleName(name) + MangleName(sig);
}

// static
std::string CWriter::MangleGlobalName(std::string_view name, Type type) {
std::string sig(1, MangleType(type));
Expand Down Expand Up @@ -889,12 +865,9 @@ void CWriter::WriteImports() {
switch (import->kind()) {
case ExternalKind::Func: {
const Func& func = cast<FuncImport>(import)->func;
WriteFuncDeclaration(
func.decl,
DefineImportName(
func.name, import->module_name,
MangleFuncName(import->field_name, func.decl.sig.param_types,
func.decl.sig.result_types)));
WriteFuncDeclaration(func.decl,
DefineImportName(func.name, import->module_name,
MangleName(import->field_name)));
Write(";");
break;
}
Expand Down Expand Up @@ -1177,9 +1150,7 @@ void CWriter::WriteExports(WriteExportsKind kind) {
switch (export_->kind) {
case ExternalKind::Func: {
const Func* func = module_->GetFunc(export_->var);
mangled_name =
ExportName(MangleFuncName(export_->name, func->decl.sig.param_types,
func->decl.sig.result_types));
mangled_name = ExportName(MangleName(export_->name));
internal_name = func->name;
if (kind != WriteExportsKind::Initializers) {
WriteFuncDeclaration(func->decl, Deref(mangled_name));
Expand Down
14 changes: 1 addition & 13 deletions test/run-spec-wasm2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,24 +311,12 @@ def _Compare(self, num, const):
def _CompareList(self, consts):
return ' && '.join(self._Compare(num, const) for num, const in enumerate(consts))

def _ActionSig(self, action, expected):
type_ = action['type']
result_types = [result['type'] for result in expected]
arg_types = [arg['type'] for arg in action.get('args', [])]
if type_ == 'invoke':
return MangleTypes(result_types) + MangleTypes(arg_types)
elif type_ == 'get':
return MangleType(result_types[0])
else:
raise Error('Unexpected action type: %s' % type_)

def _Action(self, command):
action = command['action']
expected = command['expected']
type_ = action['type']
mangled_module_name = self.GetModulePrefix(action.get('module'))
field = (mangled_module_name + MangleName(action['field']) +
MangleName(self._ActionSig(action, expected)))
field = mangled_module_name + MangleName(action['field'])
if type_ == 'invoke':
return '%s(%s)' % (field, self._ConstantList(action.get('args', [])))
elif type_ == 'get':
Expand Down
18 changes: 8 additions & 10 deletions test/spec-wasm2c-prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,16 @@ static wasm_rt_memory_t spectest_memory;
static uint32_t spectest_global_i32 = 666;
static uint64_t spectest_global_i64 = 666l;

void (*Z_spectestZ_printZ_vv)(void) = &spectest_print;
void (*Z_spectestZ_print_i32Z_vi)(uint32_t) = &spectest_print_i32;
void (*Z_spectestZ_print_f32Z_vf)(float) = &spectest_print_f32;
void (*Z_spectestZ_print_i32_f32Z_vif)(uint32_t,
float) = &spectest_print_i32_f32;
void (*Z_spectestZ_print_f64Z_vd)(double) = &spectest_print_f64;
void (*Z_spectestZ_print_f64_f64Z_vdd)(double,
double) = &spectest_print_f64_f64;
void (*Z_spectestZ_print)(void) = &spectest_print;
void (*Z_spectestZ_print_i32)(uint32_t) = &spectest_print_i32;
void (*Z_spectestZ_print_f32)(float) = &spectest_print_f32;
void (*Z_spectestZ_print_i32_f32)(uint32_t, float) = &spectest_print_i32_f32;
void (*Z_spectestZ_print_f64)(double) = &spectest_print_f64;
void (*Z_spectestZ_print_f64_f64)(double, double) = &spectest_print_f64_f64;
wasm_rt_table_t* Z_spectestZ_table = &spectest_table;
wasm_rt_memory_t* Z_spectestZ_memory = &spectest_memory;
uint32_t* Z_spectestZ_global_i32Z_i = &spectest_global_i32;
uint64_t* Z_spectestZ_global_i64Z_j = &spectest_global_i64;
uint32_t* Z_spectestZ_global_i32 = &spectest_global_i32;
uint64_t* Z_spectestZ_global_i64 = &spectest_global_i64;

static void init_spectest_module(void) {
wasm_rt_allocate_memory(&spectest_memory, 1, 2);
Expand Down
17 changes: 8 additions & 9 deletions wasm2c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,21 @@ 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 symbols for us, `init` and `Z_facZ_ii`. `init`
initializes the module, and `Z_facZ_ii` is our exported `fac` function, but
`wasm2c` generates a few symbols for us, `init` and `Z_fac`. `init`
initializes the module, and `Z_fac` is our exported `fac` function, but
[name-mangled](https://en.wikipedia.org/wiki/Name_mangling) to include the
function signature.

We can define `WASM_RT_MODULE_PREFIX` before including `fac.h` to generate
these symbols with a prefix, in case we already have a symbol called `init` (or
even `Z_facZ_ii`!) Note that you'll have to compile `fac.c` with this macro
even `Z_fac`!) Note that you'll have to compile `fac.c` with this macro
too, for this to work.

```c
#include <stdio.h>
#include <stdlib.h>

/* Uncomment this to define fac_init and fac_Z_facZ_ii instead. */
/* Uncomment this to define fac_init and fac_Z_fac instead. */
/* #define WASM_RT_MODULE_PREFIX fac_ */

#include "fac.h"
Expand All @@ -83,7 +83,7 @@ int main(int argc, char** argv) {
init();

/* Call `fac`, using the mangled name. */
u32 result = Z_facZ_ii(x);
u32 result = Z_fac(x);

/* Print the result. */
printf("fac(%u) -> %u\n", x, result);
Expand Down Expand Up @@ -138,7 +138,7 @@ extern "C" {
extern void WASM_RT_ADD_PREFIX(init)(void);

/* export: 'fac' */
extern u32 (*WASM_RT_ADD_PREFIX(Z_facZ_ii))(u32);
extern u32 (*WASM_RT_ADD_PREFIX(Z_fac))(u32);
#ifdef __cplusplus
}
#endif
Expand Down Expand Up @@ -345,15 +345,14 @@ the module can be used:
extern void WASM_RT_ADD_PREFIX(init)(void);
/* export: 'fac' */
extern u32 (*WASM_RT_ADD_PREFIX(Z_facZ_ii))(u32);
extern u32 (*WASM_RT_ADD_PREFIX(Z_fac))(u32);
```

All exported names use `WASM_RT_ADD_PREFIX` (as described above) to allow the
symbols to placed in a namespace as decided by the embedder. All symbols are
also mangled so they include the types of the function signature.

In our example, `Z_facZ_ii` is the mangling for a function named `fac` that
takes one `i32` parameter and returns one `i32` result.
In our example, `Z_fac` is the mangling for a function named `fac`.

## A quick look at `fac.c`

Expand Down
4 changes: 2 additions & 2 deletions wasm2c/examples/fac/fac.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,11 @@ static void init_table(void) {
}

/* export: 'fac' */
u32 (*WASM_RT_ADD_PREFIX(Z_facZ_ii))(u32);
u32 (*WASM_RT_ADD_PREFIX(Z_fac))(u32);

static void init_exports(void) {
/* export: 'fac' */
WASM_RT_ADD_PREFIX(Z_facZ_ii) = (&w2c_fac);
WASM_RT_ADD_PREFIX(Z_fac) = (&w2c_fac);
}

void WASM_RT_ADD_PREFIX(init)(void) {
Expand Down
2 changes: 1 addition & 1 deletion wasm2c/examples/fac/fac.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ typedef double f64;
extern void WASM_RT_ADD_PREFIX(init)(void);

/* export: 'fac' */
extern u32 (*WASM_RT_ADD_PREFIX(Z_facZ_ii))(u32);
extern u32 (*WASM_RT_ADD_PREFIX(Z_fac))(u32);
#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions wasm2c/examples/fac/main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <stdlib.h>

/* Uncomment this to define fac_init and fac_Z_facZ_ii instead. */
/* Uncomment this to define fac_init and fac_Z_fac instead. */
/* #define WASM_RT_MODULE_PREFIX fac_ */

#include "fac.h"
Expand All @@ -22,7 +22,7 @@ int main(int argc, char** argv) {
init();

/* Call `fac`, using the mangled name. */
u32 result = Z_facZ_ii(x);
u32 result = Z_fac(x);

/* Print the result. */
printf("fac(%u) -> %u\n", x, result);
Expand Down
14 changes: 7 additions & 7 deletions wasm2c/examples/rot13/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
#include <stdio.h>
#include <stdlib.h>

/* Uncomment this to define rot13_init rot13_Z_rot13Z_vv instead. */
/* Uncomment this to define rot13_init rot13_Z_rot13 instead. */
/* #define WASM_RT_MODULE_PREFIX rot13_ */

#include "rot13.h"

/* Define the imports as declared in rot13.h. */
wasm_rt_memory_t (*Z_hostZ_mem);
u32 (*Z_hostZ_fill_bufZ_iii)(u32, u32);
void (*Z_hostZ_buf_doneZ_vii)(u32, u32);
u32 (*Z_hostZ_fill_buf)(u32, u32);
void (*Z_hostZ_buf_done)(u32, u32);

/* Define the implementations of the imports. */
static wasm_rt_memory_t s_memory;
Expand All @@ -49,18 +49,18 @@ int main(int argc, char** argv) {

/* Provide the imports expected by the module: "host.mem", "host.fill_buf"
* and "host.buf_done". Their mangled names are `Z_hostZ_mem`,
* `Z_hostZ_fill_bufZ_iii` and `Z_hostZ_buf_doneZ_vii`. */
* `Z_hostZ_fill_bufZ_iii` and `Z_hostZ_buf_done`. */
Z_hostZ_mem = &s_memory;
Z_hostZ_fill_bufZ_iii = &fill_buf;
Z_hostZ_buf_doneZ_vii = &buf_done;
Z_hostZ_fill_buf = &fill_buf;
Z_hostZ_buf_done = &buf_done;

/* Call `rot13` on each argument, using the mangled name. */
while (argc > 1) {
/* Move to next arg. Do this first, so the program name is skipped. */
argc--; argv++;

s_input = argv[0];
Z_rot13Z_vv();
Z_rot13();
}

/* Free the Wasm runtime state. */
Expand Down

0 comments on commit 8e6fb55

Please sign in to comment.