From d589d83d0929333da7cfeb432f72ce33d588119b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 10 Feb 2021 18:00:58 -0800 Subject: [PATCH 1/3] Don't #include inside extern "C" blocks. Also free the malloc'd error string in print_wasmer_error(). Run the C code through clang-format. --- lib/cli/src/c_gen/object_file_header.rs | 15 +-- lib/cli/src/commands/wasmer_create_exe_main.c | 110 +++++++++--------- lib/engine-object-file/README.md | 13 +-- .../tests/object_file_engine_test_c_source.c | 51 ++++---- 4 files changed, 86 insertions(+), 103 deletions(-) diff --git a/lib/cli/src/c_gen/object_file_header.rs b/lib/cli/src/c_gen/object_file_header.rs index 671c08cc3ee..f76b189a5fa 100644 --- a/lib/cli/src/c_gen/object_file_header.rs +++ b/lib/cli/src/c_gen/object_file_header.rs @@ -76,7 +76,10 @@ pub fn generate_header_file( ) -> String { let mut c_statements = vec![]; c_statements.push(CStatement::LiteralConstant { - value: "#include \n\n".to_string(), + value: "#include \n#include \n\n".to_string(), + }); + c_statements.push(CStatement::LiteralConstant { + value: "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n".to_string(), }); c_statements.push(CStatement::Declaration { name: "module_bytes_len".to_string(), @@ -285,11 +288,9 @@ pub fn generate_header_file( value: HELPER_FUNCTIONS.to_string(), }); - let inner_c = generate_c(&c_statements); + c_statements.push(CStatement::LiteralConstant { + value: "\n#ifdef __cplusplus\n}\n#endif\n\n".to_string(), + }); - // we wrap the inner C to work with C++ too - format!( - "#ifdef __cplusplus\nextern \"C\" {{\n#endif\n\n{}\n\n#ifdef __cplusplus\n}}\n#endif\n", - inner_c - ) + generate_c(&c_statements) } diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 131efbf6a39..70095523714 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -1,10 +1,6 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#include "wasmer_wasm.h" -#include "wasm.h" #include "my_wasm.h" +#include "wasm.h" +#include "wasmer_wasm.h" #include #include @@ -14,21 +10,17 @@ extern "C" { // TODO: make this define templated so that the Rust code can toggle it on/off #define WASI -#ifdef __cplusplus -} -#endif - -void print_wasmer_error() -{ +static void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); - char* error_str = (char*) malloc(error_len); + char *error_str = (char *)malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("%s\n", error_str); + free(error_str); } #ifdef WASI -int find_colon(char* string) { +static int find_colon(char *string) { int colon_location = 0; for (int j = 0; j < strlen(string); ++j) { if (string[j] == ':') { @@ -39,7 +31,7 @@ int find_colon(char* string) { return colon_location; } -void pass_mapdir_arg(wasi_config_t* wasi_config, char* mapdir) { +static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) { int colon_location = find_colon(mapdir); if (colon_location == 0) { // error malformed argument @@ -47,8 +39,8 @@ void pass_mapdir_arg(wasi_config_t* wasi_config, char* mapdir) { exit(-1); } int dir_len = strlen(mapdir) - colon_location; - char* alias = (char*)malloc(colon_location + 1); - char* dir = (char*)malloc(dir_len + 1); + char *alias = (char *)malloc(colon_location + 1); + char *dir = (char *)malloc(dir_len + 1); int j = 0; for (j = 0; j < colon_location; ++j) { alias[j] = mapdir[j]; @@ -66,40 +58,41 @@ void pass_mapdir_arg(wasi_config_t* wasi_config, char* mapdir) { // We try to parse out `--dir` and `--mapdir` ahead of time and process those // specially. All other arguments are passed to the guest program. -void handle_arguments(wasi_config_t* wasi_config, int argc, char* argv[]) { +static void handle_arguments(wasi_config_t *wasi_config, int argc, + char *argv[]) { for (int i = 1; i < argc; ++i) { - // We probably want special args like `--dir` and `--mapdir` to not be passed directly + // We probably want special args like `--dir` and `--mapdir` to not be + // passed directly if (strcmp(argv[i], "--dir") == 0) { // next arg is a preopen directory - if ((i + 1) < argc ) { + if ((i + 1) < argc) { i++; wasi_config_preopen_dir(wasi_config, argv[i]); } else { - fprintf(stderr, "--dir expects a following argument specifying which directory to preopen\n"); + fprintf(stderr, "--dir expects a following argument specifying which " + "directory to preopen\n"); exit(-1); } - } - else if (strcmp(argv[i], "--mapdir") == 0) { + } else if (strcmp(argv[i], "--mapdir") == 0) { // next arg is a mapdir - if ((i + 1) < argc ) { + if ((i + 1) < argc) { i++; pass_mapdir_arg(wasi_config, argv[i]); } else { - fprintf(stderr, "--mapdir expects a following argument specifying which directory to preopen in the form alias:directory\n"); + fprintf(stderr, + "--mapdir expects a following argument specifying which " + "directory to preopen in the form alias:directory\n"); exit(-1); } - } - else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0 ) { + } else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0) { // this arg is a preopen dir - char* dir = argv[i] + strlen("--dir="); + char *dir = argv[i] + strlen("--dir="); wasi_config_preopen_dir(wasi_config, dir); - } - else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0 ) { + } else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0) { // this arg is a mapdir - char* mapdir = argv[i] + strlen("--mapdir="); + char *mapdir = argv[i] + strlen("--mapdir="); pass_mapdir_arg(wasi_config, mapdir); - } - else { + } else { // guest argument wasi_config_arg(wasi_config, argv[i]); } @@ -107,41 +100,42 @@ void handle_arguments(wasi_config_t* wasi_config, int argc, char* argv[]) { } #endif -int main(int argc, char* argv[]) { - wasm_config_t* config = wasm_config_new(); +int main(int argc, char *argv[]) { + wasm_config_t *config = wasm_config_new(); wasm_config_set_engine(config, OBJECT_FILE); - wasm_engine_t* engine = wasm_engine_new_with_config(config); - wasm_store_t* store = wasm_store_new(engine); - - wasm_module_t* module = wasmer_object_file_engine_new(store, argv[0]); - if (! module) { + wasm_engine_t *engine = wasm_engine_new_with_config(config); + wasm_store_t *store = wasm_store_new(engine); + + wasm_module_t *module = wasmer_object_file_engine_new(store, argv[0]); + if (!module) { fprintf(stderr, "Failed to create module\n"); print_wasmer_error(); return -1; } - // We have now finished the memory buffer book keeping and we have a valid Module. - - #ifdef WASI - wasi_config_t* wasi_config = wasi_config_new(argv[0]); + // We have now finished the memory buffer book keeping and we have a valid + // Module. + +#ifdef WASI + wasi_config_t *wasi_config = wasi_config_new(argv[0]); handle_arguments(wasi_config, argc, argv); - wasi_env_t* wasi_env = wasi_env_new(wasi_config); + wasi_env_t *wasi_env = wasi_env_new(wasi_config); if (!wasi_env) { fprintf(stderr, "Error building WASI env!\n"); print_wasmer_error(); return 1; } - #endif - +#endif + wasm_importtype_vec_t import_types; wasm_module_imports(module, &import_types); wasm_extern_vec_t imports; wasm_extern_vec_new_uninitialized(&imports, import_types.size); wasm_importtype_vec_delete(&import_types); - - #ifdef WASI + +#ifdef WASI bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); wasi_env_delete(wasi_env); @@ -151,18 +145,18 @@ int main(int argc, char* argv[]) { return 1; } - #endif - - wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); +#endif + + wasm_instance_t *instance = wasm_instance_new(store, module, &imports, NULL); if (!instance) { fprintf(stderr, "Failed to create instance\n"); print_wasmer_error(); return -1; } - - #ifdef WASI - own wasm_func_t* start_function = wasi_get_start_function(instance); + +#ifdef WASI + own wasm_func_t *start_function = wasi_get_start_function(instance); if (!start_function) { fprintf(stderr, "`_start` function not found\n"); print_wasmer_error(); @@ -171,15 +165,15 @@ int main(int argc, char* argv[]) { wasm_val_vec_t args = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_EMPTY_VEC; - own wasm_trap_t* trap = wasm_func_call(start_function, &args, &results); + own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results); if (trap) { fprintf(stderr, "Trap is not NULL: TODO:\n"); return -1; } - #endif +#endif // TODO: handle non-WASI start (maybe with invoke?) - + wasm_instance_delete(instance); wasm_module_delete(module); wasm_store_delete(store); diff --git a/lib/engine-object-file/README.md b/lib/engine-object-file/README.md index 02c7ee12aa9..d8f87bc86a5 100644 --- a/lib/engine-object-file/README.md +++ b/lib/engine-object-file/README.md @@ -25,10 +25,6 @@ Target: x86_64-apple-darwin Now lets create a program to link with this object file. ```C -#ifdef __cplusplus -extern "C" { -#endif - #include "wasmer_wasm.h" #include "wasm.h" #include "my_wasm.h" @@ -38,17 +34,14 @@ extern "C" { #define own -#ifdef __cplusplus -} -#endif - -void print_wasmer_error() +static void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); char* error_str = (char*) malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); + free(error_str); } int main() { @@ -59,7 +52,7 @@ int main() { wasm_store_t* store = wasm_store_new(engine); wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); - if (! module) { + if (!module) { printf("Failed to create module\n"); print_wasmer_error(); return -1; diff --git a/tests/integration/cli/tests/object_file_engine_test_c_source.c b/tests/integration/cli/tests/object_file_engine_test_c_source.c index f39b8620748..c88088de8b8 100644 --- a/tests/integration/cli/tests/object_file_engine_test_c_source.c +++ b/tests/integration/cli/tests/object_file_engine_test_c_source.c @@ -1,53 +1,48 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#include "wasmer_wasm.h" -#include "wasm.h" #include "my_wasm.h" +#include "wasm.h" +#include "wasmer_wasm.h" #include #include #define own -#ifdef __cplusplus -} -#endif - -void print_wasmer_error() -{ +static void print_wasmer_error() { int error_len = wasmer_last_error_length(); printf("Error len: `%d`\n", error_len); - char* error_str = (char*) malloc(error_len); + char *error_str = (char *)malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); + free(error_str); } int main() { printf("Initializing...\n"); - wasm_config_t* config = wasm_config_new(); + wasm_config_t *config = wasm_config_new(); wasm_config_set_engine(config, OBJECT_FILE); - wasm_engine_t* engine = wasm_engine_new_with_config(config); - wasm_store_t* store = wasm_store_new(engine); + wasm_engine_t *engine = wasm_engine_new_with_config(config); + wasm_store_t *store = wasm_store_new(engine); - wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm"); + wasm_module_t *module = wasmer_object_file_engine_new(store, "qjs.wasm"); if (!module) { printf("Failed to create module\n"); print_wasmer_error(); return -1; } - - // We have now finished the memory buffer book keeping and we have a valid Module. - // In this example we're passing some JavaScript source code as a command line argument - // to a WASI module that can evaluate JavaScript. - wasi_config_t* wasi_config = wasi_config_new("constant_value_here"); - const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + // We have now finished the memory buffer book keeping and we have a valid + // Module. + + // In this example we're passing some JavaScript source code as a command line + // argument to a WASI module that can evaluate JavaScript. + wasi_config_t *wasi_config = wasi_config_new("constant_value_here"); + const char *js_string = + "function greet(name) { return JSON.stringify('Hello, ' + name); }; " + "print(greet('World'));"; wasi_config_arg(wasi_config, "--eval"); wasi_config_arg(wasi_config, js_string); - wasi_env_t* wasi_env = wasi_env_new(wasi_config); + wasi_env_t *wasi_env = wasi_env_new(wasi_config); if (!wasi_env) { printf("> Error building WASI env!\n"); @@ -61,7 +56,7 @@ int main() { wasm_extern_vec_t imports; wasm_extern_vec_new_uninitialized(&imports, import_types.size); wasm_importtype_vec_delete(&import_types); - + bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); wasi_env_delete(wasi_env); @@ -71,7 +66,7 @@ int main() { return 1; } - wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL); + wasm_instance_t *instance = wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("Failed to create instance\n"); @@ -81,7 +76,7 @@ int main() { wasi_env_set_instance(wasi_env, instance); // WASI is now set up. - own wasm_func_t* start_function = wasi_get_start_function(instance); + own wasm_func_t *start_function = wasi_get_start_function(instance); if (!start_function) { fprintf(stderr, "`_start` function not found\n"); print_wasmer_error(); @@ -92,7 +87,7 @@ int main() { wasm_val_vec_t args = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_EMPTY_VEC; - own wasm_trap_t* trap = wasm_func_call(start_function, &args, &results); + own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results); if (trap) { fprintf(stderr, "Trap is not NULL: TODO:\n"); return -1; From 0157016b4f0e614d89c18e69b36c69c6f02a5f80 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 15 Feb 2021 01:06:26 -0800 Subject: [PATCH 2/3] Undo reordering of #include done by clang-format. The header file generated by engine-object-file doesn't #include the wasm types it needs and relies on these being included before it. --- lib/cli/src/commands/wasmer_create_exe_main.c | 4 ++-- .../integration/cli/tests/object_file_engine_test_c_source.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 70095523714..80652f0497d 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -1,6 +1,6 @@ -#include "my_wasm.h" -#include "wasm.h" #include "wasmer_wasm.h" +#include "wasm.h" +#include "my_wasm.h" #include #include diff --git a/tests/integration/cli/tests/object_file_engine_test_c_source.c b/tests/integration/cli/tests/object_file_engine_test_c_source.c index c88088de8b8..070fc465e78 100644 --- a/tests/integration/cli/tests/object_file_engine_test_c_source.c +++ b/tests/integration/cli/tests/object_file_engine_test_c_source.c @@ -1,6 +1,6 @@ -#include "my_wasm.h" -#include "wasm.h" #include "wasmer_wasm.h" +#include "wasm.h" +#include "my_wasm.h" #include #include From 2592094fd1da0999e176a30fbbcd18d84ca34d4a Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 15 Feb 2021 01:19:34 -0800 Subject: [PATCH 3/3] Simplify string manipulation code, use more standard library functions. --- lib/cli/src/commands/wasmer_create_exe_main.c | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index 80652f0497d..cfab834a421 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -4,6 +4,7 @@ #include #include +#include #define own @@ -20,36 +21,22 @@ static void print_wasmer_error() { } #ifdef WASI -static int find_colon(char *string) { - int colon_location = 0; - for (int j = 0; j < strlen(string); ++j) { - if (string[j] == ':') { - colon_location = j; - break; - } - } - return colon_location; -} - static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) { - int colon_location = find_colon(mapdir); + int colon_location = strchr(mapdir, ':') - mapdir; if (colon_location == 0) { // error malformed argument fprintf(stderr, "Expected mapdir argument of the form alias:directory\n"); exit(-1); } - int dir_len = strlen(mapdir) - colon_location; + char *alias = (char *)malloc(colon_location + 1); + memcpy(alias, mapdir, colon_location); + alias[colon_location] = '\0'; + + int dir_len = strlen(mapdir) - colon_location; char *dir = (char *)malloc(dir_len + 1); - int j = 0; - for (j = 0; j < colon_location; ++j) { - alias[j] = mapdir[j]; - } - alias[j] = 0; - for (j = 0; j < dir_len; ++j) { - dir[j] = mapdir[j + colon_location + 1]; - } - dir[j] = 0; + memcpy(dir, &mapdir[colon_location + 1], dir_len); + dir[dir_len] = '\0'; wasi_config_mapdir(wasi_config, alias, dir); free(alias);