Skip to content

Commit 2bf9858

Browse files
committed
[wasmtime] Implement basic WASIp2 components support
Signed-off-by: Maximilian Hüter <[email protected]>
1 parent df495db commit 2bf9858

File tree

1 file changed

+169
-4
lines changed

1 file changed

+169
-4
lines changed

src/libcrun/handlers/wasmtime.c

Lines changed: 169 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* You should have received a copy of the GNU Lesser General Public License
1616
* along with crun. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18+
#include <wasmtime/store.h>
1819
#define _GNU_SOURCE
1920

2021
#include <config.h>
@@ -151,7 +152,6 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine,
151152
// Load needed functions
152153
void (*wasm_engine_delete) (wasm_engine_t *);
153154
void (*wasm_byte_vec_delete) (wasm_byte_vec_t *);
154-
void (*wasm_byte_vec_new_uninitialized) (wasm_byte_vec_t *, size_t);
155155
wasi_config_t *(*wasi_config_new) (const char *);
156156
wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *));
157157
wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store);
@@ -197,7 +197,6 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine,
197197

198198
wasm_engine_delete = dlsym (cookie, "wasm_engine_delete");
199199
wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete");
200-
wasm_byte_vec_new_uninitialized = dlsym (cookie, "wasm_byte_vec_new_uninitialized");
201200
wasi_config_new = dlsym (cookie, "wasi_config_new");
202201
wasi_config_set_argv = dlsym (cookie, "wasi_config_set_argv");
203202
wasmtime_store_new = dlsym (cookie, "wasmtime_store_new");
@@ -221,7 +220,7 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine,
221220
wasi_config_preopen_dir = dlsym (cookie, "wasi_config_preopen_dir");
222221

223222
if (wasm_engine_delete == NULL || wasm_byte_vec_delete == NULL
224-
|| wasm_byte_vec_new_uninitialized == NULL || wasi_config_new == NULL || wasmtime_store_new == NULL
223+
|| wasi_config_new == NULL || wasmtime_store_new == NULL
225224
|| wasmtime_store_context == NULL || wasmtime_linker_new == NULL || wasmtime_linker_define_wasi == NULL
226225
|| wasmtime_module_new == NULL || wasi_config_inherit_argv == NULL || wasi_config_inherit_stdout == NULL
227226
|| wasi_config_inherit_stdin == NULL || wasi_config_inherit_stderr == NULL
@@ -316,7 +315,173 @@ libwasmtime_run_module (void *cookie, char *const argv[], wasm_engine_t *engine,
316315
static void
317316
libwasmtime_run_component (void *cookie, char *const argv[], wasm_engine_t *engine, wasm_byte_vec_t *wasm)
318317
{
319-
error (EXIT_FAILURE, 0, "running components is not yet implemented!");
318+
const char *wasi_cli_run_interface = "wasi:cli/[email protected]";
319+
const char *wasi_cli_run_interface_run = "run";
320+
wasm_byte_vec_t error_message;
321+
322+
// Load needed functions
323+
void (*wasm_engine_delete) (wasm_engine_t *);
324+
void (*wasm_byte_vec_delete) (wasm_byte_vec_t *);
325+
wasmtime_store_t *(*wasmtime_store_new) (wasm_engine_t *engine, void *data, void (*finalizer) (void *));
326+
void (*wasmtime_store_delete) (wasmtime_store_t *store);
327+
wasmtime_context_t *(*wasmtime_store_context) (wasmtime_store_t *store);
328+
wasmtime_error_t *(*wasmtime_component_new) (
329+
const wasm_engine_t *engine,
330+
const uint8_t *buf,
331+
size_t len,
332+
wasmtime_component_t **component_out);
333+
wasmtime_wasip2_config_t *(*wasmtime_wasip2_config_new) (void);
334+
void (*wasmtime_wasip2_config_inherit_stdin) (wasmtime_wasip2_config_t *config);
335+
void (*wasmtime_wasip2_config_inherit_stdout) (wasmtime_wasip2_config_t *config);
336+
void (*wasmtime_wasip2_config_inherit_stderr) (wasmtime_wasip2_config_t *config);
337+
void (*wasmtime_context_set_wasip2) (wasmtime_context_t *context, wasmtime_wasip2_config_t *config);
338+
wasmtime_component_linker_t *(*wasmtime_component_linker_new) (wasm_engine_t *engine);
339+
wasmtime_error_t *(*wasmtime_component_linker_add_wasip2) (wasmtime_component_linker_t *linker);
340+
wasmtime_error_t *(*wasmtime_component_linker_instantiate) (
341+
const wasmtime_component_linker_t *linker,
342+
wasmtime_context_t *context,
343+
const wasmtime_component_t *component,
344+
wasmtime_component_instance_t *instance_out);
345+
wasmtime_component_export_index_t *(*wasmtime_component_get_export_index) (
346+
wasmtime_component_t *component,
347+
wasmtime_component_export_index_t *index,
348+
const char *name,
349+
size_t name_len);
350+
wasmtime_component_export_index_t *(*wasmtime_component_instance_get_export_index) (
351+
const wasmtime_component_instance_t *instance,
352+
wasmtime_context_t *context,
353+
const wasmtime_component_export_index_t *instance_export_index,
354+
const char *name,
355+
size_t name_len);
356+
bool (*wasmtime_component_instance_get_func) (
357+
const wasmtime_component_instance_t *instance,
358+
wasmtime_context_t *context,
359+
const wasmtime_component_export_index_t *export_index,
360+
wasmtime_component_func_t *func_out);
361+
wasmtime_error_t *(*wasmtime_component_func_call) (
362+
const wasmtime_component_func_t *func,
363+
wasmtime_context_t *context,
364+
const wasmtime_component_val_t *args,
365+
size_t args_size,
366+
wasmtime_component_val_t *results,
367+
size_t results_size);
368+
void (*wasmtime_component_export_index_delete) (wasmtime_component_export_index_t *export_index);
369+
void (*wasmtime_component_delete) (wasmtime_component_t *c);
370+
void (*wasmtime_component_linker_delete) (wasmtime_component_linker_t *linker);
371+
void (*wasmtime_error_message) (const wasmtime_error_t *error, wasm_name_t *message);
372+
void (*wasmtime_error_delete) (wasmtime_error_t *error);
373+
374+
wasm_engine_delete = dlsym (cookie, "wasm_engine_delete");
375+
wasm_byte_vec_delete = dlsym (cookie, "wasm_byte_vec_delete");
376+
wasmtime_store_new = dlsym (cookie, "wasmtime_store_new");
377+
wasmtime_store_delete = dlsym (cookie, "wasmtime_store_delete");
378+
wasmtime_store_context = dlsym (cookie, "wasmtime_store_context");
379+
wasmtime_component_new = dlsym (cookie, "wasmtime_component_new");
380+
wasmtime_wasip2_config_new = dlsym (cookie, "wasmtime_wasip2_config_new");
381+
wasmtime_wasip2_config_inherit_stdin = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdin");
382+
wasmtime_wasip2_config_inherit_stdout = dlsym (cookie, "wasmtime_wasip2_config_inherit_stdout");
383+
wasmtime_wasip2_config_inherit_stderr = dlsym (cookie, "wasmtime_wasip2_config_inherit_stderr");
384+
wasmtime_context_set_wasip2 = dlsym (cookie, "wasmtime_context_set_wasip2");
385+
wasmtime_component_linker_new = dlsym (cookie, "wasmtime_component_linker_new");
386+
wasmtime_component_linker_add_wasip2 = dlsym (cookie, "wasmtime_component_linker_add_wasip2");
387+
wasmtime_component_linker_instantiate = dlsym (cookie, "wasmtime_component_linker_instantiate");
388+
wasmtime_component_get_export_index = dlsym (cookie, "wasmtime_component_get_export_index");
389+
wasmtime_component_instance_get_export_index = dlsym (cookie, "wasmtime_component_instance_get_export_index");
390+
wasmtime_component_instance_get_func = dlsym (cookie, "wasmtime_component_instance_get_func");
391+
wasmtime_component_func_call = dlsym (cookie, "wasmtime_component_func_call");
392+
wasmtime_component_export_index_delete = dlsym (cookie, "wasmtime_component_export_index_delete");
393+
wasmtime_component_delete = dlsym (cookie, "wasmtime_component_delete");
394+
wasmtime_component_linker_delete = dlsym (cookie, "wasmtime_component_linker_delete");
395+
wasmtime_error_message = dlsym (cookie, "wasmtime_error_message");
396+
wasmtime_error_delete = dlsym (cookie, "wasmtime_error_delete");
397+
398+
// Set up wasmtime context
399+
wasmtime_store_t *store = wasmtime_store_new (engine, NULL, NULL);
400+
assert (store != NULL);
401+
wasmtime_context_t *context = wasmtime_store_context (store);
402+
403+
// Compile wasm component
404+
wasmtime_component_t *component = NULL;
405+
wasmtime_error_t *err = wasmtime_component_new (engine, (uint8_t *) wasm->data, wasm->size, &component);
406+
if (! component || err != NULL)
407+
{
408+
wasmtime_error_message (err, &error_message);
409+
wasmtime_error_delete (err);
410+
error (EXIT_FAILURE, 0, "failed to compile component: %.*s", (int) error_message.size, error_message.data);
411+
}
412+
wasm_byte_vec_delete (wasm);
413+
414+
// Set up WASIp2 config
415+
wasmtime_wasip2_config_t *wasi_config = wasmtime_wasip2_config_new ();
416+
assert (wasi_config != NULL);
417+
418+
wasmtime_wasip2_config_inherit_stdin (wasi_config);
419+
wasmtime_wasip2_config_inherit_stdout (wasi_config);
420+
wasmtime_wasip2_config_inherit_stderr (wasi_config);
421+
// TODO: argv
422+
wasmtime_context_set_wasip2 (context, wasi_config);
423+
424+
// Get wasi exposing linker
425+
wasmtime_component_linker_t *linker = wasmtime_component_linker_new (engine);
426+
err = wasmtime_component_linker_add_wasip2 (linker);
427+
if (err != NULL)
428+
{
429+
wasmtime_error_message (err, &error_message);
430+
wasmtime_error_delete (err);
431+
error (EXIT_FAILURE, 0, "failed to add WASIp2 to linker: %.*s", (int) error_message.size, error_message.data);
432+
}
433+
434+
// Instantiate the component
435+
wasmtime_component_instance_t component_inst = {};
436+
err = wasmtime_component_linker_instantiate (linker, context, component, &component_inst);
437+
if (err != NULL)
438+
{
439+
wasmtime_error_message (err, &error_message);
440+
wasmtime_error_delete (err);
441+
error (EXIT_FAILURE, 0, "failed to instantiate component: %.*s", (int) error_message.size, error_message.data);
442+
}
443+
444+
// Get index of the run interface in wasi/cli world
445+
wasmtime_component_export_index_t *run_interface_idx = wasmtime_component_instance_get_export_index (
446+
&component_inst,
447+
context,
448+
NULL,
449+
wasi_cli_run_interface,
450+
strlen (wasi_cli_run_interface));
451+
assert (run_interface_idx != NULL);
452+
// Get index of the run function
453+
wasmtime_component_export_index_t *run_func_idx = wasmtime_component_instance_get_export_index (
454+
&component_inst,
455+
context,
456+
run_interface_idx,
457+
wasi_cli_run_interface_run,
458+
strlen (wasi_cli_run_interface_run));
459+
assert (run_func_idx != NULL);
460+
461+
// Actually retrieve the func
462+
wasmtime_component_func_t run_func = {};
463+
if (! wasmtime_component_instance_get_func (&component_inst, context, run_func_idx, &run_func))
464+
{
465+
error (EXIT_FAILURE, 0, "failed to retrieve run function");
466+
}
467+
468+
// Call the func
469+
wasmtime_component_val_t result = {};
470+
err = wasmtime_component_func_call (&run_func, context, NULL, 0, &result, 1);
471+
if (err != NULL)
472+
{
473+
wasmtime_error_message (err, &error_message);
474+
wasmtime_error_delete (err);
475+
error (EXIT_FAILURE, 0, "error calling run function: %.*s", (int) error_message.size, error_message.data);
476+
}
477+
478+
// Clean everything
479+
wasmtime_component_export_index_delete (run_func_idx);
480+
wasmtime_component_export_index_delete (run_interface_idx);
481+
wasmtime_component_linker_delete (linker);
482+
wasmtime_component_delete (component);
483+
wasmtime_store_delete (store);
484+
wasm_engine_delete (engine);
320485
}
321486

322487
static int

0 commit comments

Comments
 (0)