Skip to content

Commit 41caf67

Browse files
authored
Update the C API with module linking support (#2472)
* Update the C API with module linking support This commit does everything necessary (ideally) to support the module linking proposal in the C API. The changes here are: * New `wasm_{module,instance}type_t` types and accessors * New `wasm_{module,instance}_type` functions * Conversions between `wasm_extern_t` and `wasm_{instance,module}_t`, as well as `wasm_externtype_t` and the new types. * Addition of `WASM_EXTERN_{MODULE,INSTANCE}` constants * New `wasm_config_t` modifier to enable/disable module linking With these functions it should be possible to pass instances/modules to instances and also acquire them from exports. Altogether this should enable everything for module linking. An important point for this is that I've opted to add all these items under the `wasm_*` name prefix instead of `wasmtime_*`. I've done this since they're all following the idioms of existing APIs and while not standard the intention would be to standardize them (unlike many other Wasmtime-specific APIs). cc #2094 * Appease doxygen
1 parent 0f1dc9a commit 41caf67

File tree

11 files changed

+553
-114
lines changed

11 files changed

+553
-114
lines changed

crates/c-api/include/doc-wasm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,8 +793,15 @@
793793
* \typedef wasm_externkind_t
794794
* \brief Classifier for #wasm_externtype_t, defined by #wasm_externkind_enum
795795
*
796+
* This is returned from #wasm_extern_kind and #wasm_externtype_kind to
797+
* determine what kind of type is wrapped.
798+
*
796799
* \enum wasm_externkind_enum
797800
* \brief Kinds of external items for a wasm module.
801+
*
802+
* Note that this also includes #WASM_EXTERN_INSTANCE as well as
803+
* #WASM_EXTERN_MODULE and is intended to be used when #wasm_externkind_t is
804+
* used.
798805
*/
799806

800807
/**

crates/c-api/include/wasmtime.h

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ WASMTIME_CONFIG_PROP(void, wasm_bulk_memory, bool)
208208
*/
209209
WASMTIME_CONFIG_PROP(void, wasm_multi_value, bool)
210210

211+
/**
212+
* \brief Configures whether the WebAssembly module linking proposal is
213+
* enabled.
214+
*
215+
* This setting is `false` by default.
216+
*/
217+
WASMTIME_CONFIG_PROP(void, wasm_module_linking, bool)
218+
211219
/**
212220
* \brief Configures how JIT code will be compiled.
213221
*
@@ -961,6 +969,291 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_deserialize(
961969
own wasm_module_t **ret
962970
);
963971

972+
/**
973+
* \struct wasm_instancetype_t
974+
* \brief An opaque object representing the type of a function.
975+
*
976+
* \typedef wasm_instancetype_t
977+
* \brief Convenience alias for #wasm_instancetype_t
978+
*
979+
* \struct wasm_instancetype_vec_t
980+
* \brief A list of #wasm_instancetype_t values.
981+
*
982+
* \var wasm_instancetype_vec_t::size
983+
* \brief Length of this vector.
984+
*
985+
* \var wasm_instancetype_vec_t::data
986+
* \brief Pointer to the base of this vector
987+
*
988+
* \typedef wasm_instancetype_vec_t
989+
* \brief Convenience alias for #wasm_instancetype_vec_t
990+
*
991+
* \fn void wasm_instancetype_delete(own wasm_instancetype_t *);
992+
* \brief Deletes a type.
993+
*
994+
* \fn void wasm_instancetype_vec_new_empty(own wasm_instancetype_vec_t *out);
995+
* \brief Creates an empty vector.
996+
*
997+
* See #wasm_byte_vec_new_empty for more information.
998+
*
999+
* \fn void wasm_instancetype_vec_new_uninitialized(own wasm_instancetype_vec_t *out, size_t);
1000+
* \brief Creates a vector with the given capacity.
1001+
*
1002+
* See #wasm_byte_vec_new_uninitialized for more information.
1003+
*
1004+
* \fn void wasm_instancetype_vec_new(own wasm_instancetype_vec_t *out, size_t, own wasm_instancetype_t *const[]);
1005+
* \brief Creates a vector with the provided contents.
1006+
*
1007+
* See #wasm_byte_vec_new for more information.
1008+
*
1009+
* \fn void wasm_instancetype_vec_copy(own wasm_instancetype_vec_t *out, const wasm_instancetype_vec_t *)
1010+
* \brief Copies one vector to another
1011+
*
1012+
* See #wasm_byte_vec_copy for more information.
1013+
*
1014+
* \fn void wasm_instancetype_vec_delete(own wasm_instancetype_vec_t *out)
1015+
* \brief Deallocates memory for a vector.
1016+
*
1017+
* See #wasm_byte_vec_delete for more information.
1018+
*
1019+
* \fn own wasm_instancetype_t* wasm_instancetype_copy(wasm_instancetype_t *)
1020+
* \brief Creates a new value which matches the provided one.
1021+
*
1022+
* The caller is responsible for deleting the returned value.
1023+
*/
1024+
WASM_DECLARE_TYPE(instancetype)
1025+
1026+
/**
1027+
* \brief Returns the list of exports that this instance type provides.
1028+
*
1029+
* This function does not take ownership of the provided instance type but
1030+
* ownership of `out` is passed to the caller. Note that `out` is treated as
1031+
* uninitialized when passed to this function.
1032+
*/
1033+
WASM_API_EXTERN void wasm_instancetype_exports(const wasm_instancetype_t*, own wasm_exporttype_vec_t* out);
1034+
1035+
/**
1036+
* \brief Converts a #wasm_instancetype_t to a #wasm_externtype_t
1037+
*
1038+
* The returned value is owned by the #wasm_instancetype_t argument and should not
1039+
* be deleted.
1040+
*/
1041+
WASM_API_EXTERN wasm_externtype_t* wasm_instancetype_as_externtype(wasm_instancetype_t*);
1042+
1043+
/**
1044+
* \brief Attempts to convert a #wasm_externtype_t to a #wasm_instancetype_t
1045+
*
1046+
* The returned value is owned by the #wasm_instancetype_t argument and should not
1047+
* be deleted. Returns `NULL` if the provided argument is not a
1048+
* #wasm_instancetype_t.
1049+
*/
1050+
WASM_API_EXTERN wasm_instancetype_t* wasm_externtype_as_instancetype(wasm_externtype_t*);
1051+
1052+
/**
1053+
* \brief Converts a #wasm_instancetype_t to a #wasm_externtype_t
1054+
*
1055+
* The returned value is owned by the #wasm_instancetype_t argument and should not
1056+
* be deleted.
1057+
*/
1058+
WASM_API_EXTERN const wasm_externtype_t* wasm_instancetype_as_externtype_const(const wasm_instancetype_t*);
1059+
1060+
/**
1061+
* \brief Attempts to convert a #wasm_externtype_t to a #wasm_instancetype_t
1062+
*
1063+
* The returned value is owned by the #wasm_instancetype_t argument and should not
1064+
* be deleted. Returns `NULL` if the provided argument is not a
1065+
* #wasm_instancetype_t.
1066+
*/
1067+
WASM_API_EXTERN const wasm_instancetype_t* wasm_externtype_as_instancetype_const(const wasm_externtype_t*);
1068+
1069+
/**
1070+
* \struct wasm_moduletype_t
1071+
* \brief An opaque object representing the type of a function.
1072+
*
1073+
* \typedef wasm_moduletype_t
1074+
* \brief Convenience alias for #wasm_moduletype_t
1075+
*
1076+
* \struct wasm_moduletype_vec_t
1077+
* \brief A list of #wasm_moduletype_t values.
1078+
*
1079+
* \var wasm_moduletype_vec_t::size
1080+
* \brief Length of this vector.
1081+
*
1082+
* \var wasm_moduletype_vec_t::data
1083+
* \brief Pointer to the base of this vector
1084+
*
1085+
* \typedef wasm_moduletype_vec_t
1086+
* \brief Convenience alias for #wasm_moduletype_vec_t
1087+
*
1088+
* \fn void wasm_moduletype_delete(own wasm_moduletype_t *);
1089+
* \brief Deletes a type.
1090+
*
1091+
* \fn void wasm_moduletype_vec_new_empty(own wasm_moduletype_vec_t *out);
1092+
* \brief Creates an empty vector.
1093+
*
1094+
* See #wasm_byte_vec_new_empty for more information.
1095+
*
1096+
* \fn void wasm_moduletype_vec_new_uninitialized(own wasm_moduletype_vec_t *out, size_t);
1097+
* \brief Creates a vector with the given capacity.
1098+
*
1099+
* See #wasm_byte_vec_new_uninitialized for more information.
1100+
*
1101+
* \fn void wasm_moduletype_vec_new(own wasm_moduletype_vec_t *out, size_t, own wasm_moduletype_t *const[]);
1102+
* \brief Creates a vector with the provided contents.
1103+
*
1104+
* See #wasm_byte_vec_new for more information.
1105+
*
1106+
* \fn void wasm_moduletype_vec_copy(own wasm_moduletype_vec_t *out, const wasm_moduletype_vec_t *)
1107+
* \brief Copies one vector to another
1108+
*
1109+
* See #wasm_byte_vec_copy for more information.
1110+
*
1111+
* \fn void wasm_moduletype_vec_delete(own wasm_moduletype_vec_t *out)
1112+
* \brief Deallocates memory for a vector.
1113+
*
1114+
* See #wasm_byte_vec_delete for more information.
1115+
*
1116+
* \fn own wasm_moduletype_t* wasm_moduletype_copy(wasm_moduletype_t *)
1117+
* \brief Creates a new value which matches the provided one.
1118+
*
1119+
* The caller is responsible for deleting the returned value.
1120+
*/
1121+
WASM_DECLARE_TYPE(moduletype)
1122+
1123+
/**
1124+
* \brief Returns the list of imports that this module type requires.
1125+
*
1126+
* This function does not take ownership of the provided module type but
1127+
* ownership of `out` is passed to the caller. Note that `out` is treated as
1128+
* uninitialized when passed to this function.
1129+
*/
1130+
WASM_API_EXTERN void wasm_moduletype_imports(const wasm_moduletype_t*, own wasm_importtype_vec_t* out);
1131+
1132+
/**
1133+
* \brief Returns the list of exports that this module type provides.
1134+
*
1135+
* This function does not take ownership of the provided module type but
1136+
* ownership of `out` is passed to the caller. Note that `out` is treated as
1137+
* uninitialized when passed to this function.
1138+
*/
1139+
WASM_API_EXTERN void wasm_moduletype_exports(const wasm_moduletype_t*, own wasm_exporttype_vec_t* out);
1140+
1141+
/**
1142+
* \brief Converts a #wasm_moduletype_t to a #wasm_externtype_t
1143+
*
1144+
* The returned value is owned by the #wasm_moduletype_t argument and should not
1145+
* be deleted.
1146+
*/
1147+
WASM_API_EXTERN wasm_externtype_t* wasm_moduletype_as_externtype(wasm_moduletype_t*);
1148+
1149+
/**
1150+
* \brief Attempts to convert a #wasm_externtype_t to a #wasm_moduletype_t
1151+
*
1152+
* The returned value is owned by the #wasm_moduletype_t argument and should not
1153+
* be deleted. Returns `NULL` if the provided argument is not a
1154+
* #wasm_moduletype_t.
1155+
*/
1156+
WASM_API_EXTERN wasm_moduletype_t* wasm_externtype_as_moduletype(wasm_externtype_t*);
1157+
1158+
/**
1159+
* \brief Converts a #wasm_moduletype_t to a #wasm_externtype_t
1160+
*
1161+
* The returned value is owned by the #wasm_moduletype_t argument and should not
1162+
* be deleted.
1163+
*/
1164+
WASM_API_EXTERN const wasm_externtype_t* wasm_moduletype_as_externtype_const(const wasm_moduletype_t*);
1165+
1166+
/**
1167+
* \brief Attempts to convert a #wasm_externtype_t to a #wasm_moduletype_t
1168+
*
1169+
* The returned value is owned by the #wasm_moduletype_t argument and should not
1170+
* be deleted. Returns `NULL` if the provided argument is not a
1171+
* #wasm_moduletype_t.
1172+
*/
1173+
WASM_API_EXTERN const wasm_moduletype_t* wasm_externtype_as_moduletype_const(const wasm_externtype_t*);
1174+
1175+
/**
1176+
* \brief Converts a #wasm_module_t to #wasm_extern_t.
1177+
*
1178+
* The returned #wasm_extern_t is owned by the #wasm_module_t argument. Callers
1179+
* should not delete the returned value, and it only lives as long as the
1180+
* #wasm_module_t argument.
1181+
*/
1182+
WASM_API_EXTERN wasm_extern_t* wasm_module_as_extern(wasm_module_t*);
1183+
1184+
/**
1185+
* \brief Converts a #wasm_extern_t to #wasm_module_t.
1186+
*
1187+
* The returned #wasm_module_t is owned by the #wasm_extern_t argument. Callers
1188+
* should not delete the returned value, and it only lives as long as the
1189+
* #wasm_extern_t argument.
1190+
*
1191+
* If the #wasm_extern_t argument isn't a #wasm_module_t then `NULL` is returned.
1192+
*/
1193+
WASM_API_EXTERN wasm_module_t* wasm_extern_as_module(wasm_extern_t*);
1194+
1195+
/**
1196+
* \brief Converts a #wasm_extern_t to #wasm_instance_t.
1197+
*
1198+
* The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers
1199+
* should not delete the returned value, and it only lives as long as the
1200+
* #wasm_extern_t argument.
1201+
*/
1202+
WASM_API_EXTERN const wasm_module_t* wasm_extern_as_module_const(const wasm_extern_t*);
1203+
1204+
/**
1205+
* \brief Converts a #wasm_instance_t to #wasm_extern_t.
1206+
*
1207+
* The returned #wasm_extern_t is owned by the #wasm_instance_t argument. Callers
1208+
* should not delete the returned value, and it only lives as long as the
1209+
* #wasm_instance_t argument.
1210+
*/
1211+
WASM_API_EXTERN wasm_extern_t* wasm_instance_as_extern(wasm_instance_t*);
1212+
1213+
/**
1214+
* \brief Converts a #wasm_extern_t to #wasm_instance_t.
1215+
*
1216+
* The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers
1217+
* should not delete the returned value, and it only lives as long as the
1218+
* #wasm_extern_t argument.
1219+
*
1220+
* If the #wasm_extern_t argument isn't a #wasm_instance_t then `NULL` is returned.
1221+
*/
1222+
WASM_API_EXTERN wasm_instance_t* wasm_extern_as_instance(wasm_extern_t*);
1223+
1224+
/**
1225+
* \brief Converts a #wasm_extern_t to #wasm_instance_t.
1226+
*
1227+
* The returned #wasm_instance_t is owned by the #wasm_extern_t argument. Callers
1228+
* should not delete the returned value, and it only lives as long as the
1229+
* #wasm_extern_t argument.
1230+
*/
1231+
WASM_API_EXTERN const wasm_instance_t* wasm_extern_as_instance_const(const wasm_extern_t*);
1232+
1233+
/**
1234+
* \brief Returns the type of this instance.
1235+
*
1236+
* The returned #wasm_instancetype_t is expected to be deallocated by the caller.
1237+
*/
1238+
WASM_API_EXTERN own wasm_instancetype_t* wasm_instance_type(const wasm_instance_t*);
1239+
1240+
/**
1241+
* \brief Returns the type of this module.
1242+
*
1243+
* The returned #wasm_moduletype_t is expected to be deallocated by the caller.
1244+
*/
1245+
WASM_API_EXTERN own wasm_moduletype_t* wasm_module_type(const wasm_module_t*);
1246+
1247+
/**
1248+
* \brief Value of #wasm_externkind_enum corresponding to a wasm module.
1249+
*/
1250+
#define WASM_EXTERN_MODULE 4
1251+
1252+
/**
1253+
* \brief Value of #wasm_externkind_enum corresponding to a wasm instance.
1254+
*/
1255+
#define WASM_EXTERN_INSTANCE 5
1256+
9641257
#undef own
9651258

9661259
#ifdef __cplusplus

crates/c-api/src/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ pub extern "C" fn wasmtime_config_wasm_multi_value_set(c: &mut wasm_config_t, en
8585
c.config.wasm_multi_value(enable);
8686
}
8787

88+
#[no_mangle]
89+
pub extern "C" fn wasmtime_config_wasm_module_linking_set(c: &mut wasm_config_t, enable: bool) {
90+
c.config.wasm_module_linking(enable);
91+
}
92+
8893
#[no_mangle]
8994
pub extern "C" fn wasmtime_config_strategy_set(
9095
c: &mut wasm_config_t,

crates/c-api/src/extern.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use crate::wasm_externkind_t;
2-
use crate::{wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_memory_t, wasm_table_t};
1+
use crate::{
2+
wasm_externkind_t, wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_instance_t,
3+
wasm_memory_t, wasm_module_t, wasm_table_t,
4+
};
35
use wasmtime::Extern;
46

57
#[derive(Clone)]
@@ -16,10 +18,8 @@ pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
1618
Extern::Global(_) => crate::WASM_EXTERN_GLOBAL,
1719
Extern::Table(_) => crate::WASM_EXTERN_TABLE,
1820
Extern::Memory(_) => crate::WASM_EXTERN_MEMORY,
19-
20-
// FIXME(#2094)
21-
Extern::Instance(_) => unimplemented!(),
22-
Extern::Module(_) => unimplemented!(),
21+
Extern::Instance(_) => crate::WASM_EXTERN_INSTANCE,
22+
Extern::Module(_) => crate::WASM_EXTERN_MODULE,
2323
}
2424
}
2525

@@ -67,3 +67,23 @@ pub extern "C" fn wasm_extern_as_memory(e: &wasm_extern_t) -> Option<&wasm_memor
6767
pub extern "C" fn wasm_extern_as_memory_const(e: &wasm_extern_t) -> Option<&wasm_memory_t> {
6868
wasm_extern_as_memory(e)
6969
}
70+
71+
#[no_mangle]
72+
pub extern "C" fn wasm_extern_as_module(e: &wasm_extern_t) -> Option<&wasm_module_t> {
73+
wasm_module_t::try_from(e)
74+
}
75+
76+
#[no_mangle]
77+
pub extern "C" fn wasm_extern_as_module_const(e: &wasm_extern_t) -> Option<&wasm_module_t> {
78+
wasm_extern_as_module(e)
79+
}
80+
81+
#[no_mangle]
82+
pub extern "C" fn wasm_extern_as_instance(e: &wasm_extern_t) -> Option<&wasm_instance_t> {
83+
wasm_instance_t::try_from(e)
84+
}
85+
86+
#[no_mangle]
87+
pub extern "C" fn wasm_extern_as_instance_const(e: &wasm_extern_t) -> Option<&wasm_instance_t> {
88+
wasm_extern_as_instance(e)
89+
}

0 commit comments

Comments
 (0)