@@ -103,7 +103,7 @@ pub struct Opts {
103103 #[ cfg_attr( feature = "clap" , arg( long, value_name = "NAME" ) ) ]
104104 pub rename_world : Option < String > ,
105105
106- /// Add the specified suffix to the name of the custome section containing
106+ /// Add the specified suffix to the name of the custom section containing
107107 /// the component type.
108108 #[ cfg_attr( feature = "clap" , arg( long, value_name = "STRING" ) ) ]
109109 pub type_section_suffix : Option < String > ,
@@ -121,6 +121,14 @@ pub struct Opts {
121121
122122 #[ cfg_attr( feature = "clap" , clap( flatten) ) ]
123123 pub async_ : AsyncFilterSet ,
124+
125+ /// Force generation of async helpers even if no async functions/futures are present.
126+ #[ cfg_attr( feature = "clap" , arg( long, default_value_t = false ) ) ]
127+ pub generate_async_helpers : bool ,
128+
129+ /// Generate helpers for threading builtins. Implies `--generate-async-helpers`.
130+ #[ cfg_attr( feature = "clap" , arg( long, default_value_t = false ) ) ]
131+ pub generate_threading_helpers : bool ,
124132}
125133
126134#[ cfg( feature = "clap" ) ]
@@ -432,9 +440,16 @@ impl WorldGenerator for C {
432440 "\n union double_int64 {{ double a; int64_t b; }};"
433441 ) ;
434442 }
435- if self . needs_async || self . futures . len ( ) > 0 {
443+ if self . needs_async
444+ || self . futures . len ( ) > 0
445+ || self . opts . generate_async_helpers
446+ || self . opts . generate_threading_helpers
447+ {
436448 self . generate_async_helpers ( ) ;
437449 }
450+ if self . opts . generate_threading_helpers {
451+ self . generate_threading_helpers ( ) ;
452+ }
438453 let version = env ! ( "CARGO_PKG_VERSION" ) ;
439454 let mut h_str = wit_bindgen_core:: Source :: default ( ) ;
440455
@@ -703,6 +718,115 @@ impl C {
703718 }
704719 }
705720
721+ fn generate_threading_helpers ( & mut self ) {
722+ let snake = self . world . to_snake_case ( ) ;
723+ uwriteln ! (
724+ self . src. h_async,
725+ "
726+ void* {snake}_context_get_1(void);
727+ void {snake}_context_set_1(void* value);
728+ uint32_t {snake}_thread_yield_cancellable(void);
729+ uint32_t {snake}_thread_index(void);
730+ uint32_t {snake}_thread_new_indirect(void (*start_function)(void*), void* arg);
731+ void {snake}_thread_switch_to(uint32_t thread);
732+ uint32_t {snake}_thread_switch_to_cancellable(uint32_t thread);
733+ void {snake}_thread_resume_later(uint32_t thread);
734+ void {snake}_thread_yield_to(uint32_t thread);
735+ uint32_t {snake}_thread_yield_to_cancellable(uint32_t thread);
736+ void {snake}_thread_suspend(void);
737+ uint32_t {snake}_thread_suspend_cancellable(void);
738+ "
739+ ) ;
740+ uwriteln ! (
741+ self . src. c_async,
742+ r#"
743+ __attribute__((__import_module__("$root"), __import_name__("[context-get-1]")))
744+ extern void* __context_get_1(void);
745+
746+ void* {snake}_context_get_1(void) {{
747+ return __context_get_1();
748+ }}
749+
750+ __attribute__((__import_module__("$root"), __import_name__("[context-set-1]")))
751+ extern void __context_set_1(void*);
752+
753+ void {snake}_context_set_1(void* value) {{
754+ __context_set_1(value);
755+ }}
756+
757+ __attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-yield]")))
758+ extern uint32_t __thread_yield_cancellable(void);
759+
760+ uint32_t {snake}_thread_yield_cancellable(void) {{
761+ return __thread_yield_cancellable();
762+ }}
763+
764+ __attribute__((__import_module__("$root"), __import_name__("[thread-index]")))
765+ extern uint32_t __thread_index(void);
766+
767+ uint32_t {snake}_thread_index(void) {{
768+ return __thread_index();
769+ }}
770+
771+ __attribute__((__import_module__("$root"), __import_name__("[thread-new-indirect-v0]")))
772+ extern uint32_t __thread_new_indirect(uint32_t, void*);
773+
774+ uint32_t {snake}_thread_new_indirect(void (*start_function)(void*), void* arg) {{
775+ return __thread_new_indirect((uint32_t)(uintptr_t)start_function, arg
776+ );
777+ }}
778+
779+ __attribute__((__import_module__("$root"), __import_name__("[thread-switch-to]")))
780+ extern uint32_t __thread_switch_to(uint32_t);
781+
782+ void {snake}_thread_switch_to(uint32_t thread) {{
783+ __thread_switch_to(thread);
784+ }}
785+
786+ __attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-switch-to]")))
787+ extern uint32_t __thread_switch_to_cancellable(uint32_t);
788+
789+ uint32_t {snake}_thread_switch_to_cancellable(uint32_t thread) {{
790+ return __thread_switch_to_cancellable(thread);
791+ }}
792+
793+ __attribute__((__import_module__("$root"), __import_name__("[thread-resume-later]")))
794+ extern void __thread_resume_later(uint32_t);
795+
796+ void {snake}_thread_resume_later(uint32_t thread) {{
797+ __thread_resume_later(thread);
798+ }}
799+
800+ __attribute__((__import_module__("$root"), __import_name__("[thread-yield-to]")))
801+ extern uint32_t __thread_yield_to(uint32_t);
802+
803+ void {snake}_thread_yield_to(uint32_t thread) {{
804+ __thread_yield_to(thread);
805+ }}
806+
807+ __attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-yield-to]")))
808+ extern uint32_t __thread_yield_to_cancellable(uint32_t);
809+
810+ uint32_t {snake}_thread_yield_to_cancellable(uint32_t thread) {{
811+ return __thread_yield_to_cancellable(thread);
812+ }}
813+
814+ __attribute__((__import_module__("$root"), __import_name__("[thread-suspend]")))
815+ extern uint32_t __thread_suspend(void);
816+
817+ void {snake}_thread_suspend(void) {{
818+ __thread_suspend();
819+ }}
820+
821+ __attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-suspend]")))
822+ extern uint32_t __thread_suspend_cancellable(void);
823+ uint32_t {snake}_thread_suspend_cancellable(void) {{
824+ return __thread_suspend_cancellable();
825+ }}
826+ "#
827+ ) ;
828+ }
829+
706830 fn generate_async_helpers ( & mut self ) {
707831 let snake = self . world . to_snake_case ( ) ;
708832 let shouty = self . world . to_shouty_snake_case ( ) ;
@@ -768,10 +892,9 @@ typedef enum {snake}_waitable_state {{
768892
769893void {snake}_backpressure_inc(void);
770894void {snake}_backpressure_dec(void);
771- void* {snake}_context_get(void);
772- void {snake}_context_set(void*);
773- void {snake}_yield(void);
774- uint32_t {snake}_yield_cancellable(void);
895+ void* {snake}_context_get_0(void);
896+ void {snake}_context_set_0(void* value);
897+ void {snake}_thread_yield(void);
775898 "
776899 ) ;
777900 uwriteln ! (
@@ -847,32 +970,26 @@ void {snake}_backpressure_dec(void) {{
847970}}
848971
849972__attribute__((__import_module__("$root"), __import_name__("[context-get-0]")))
850- extern void* __context_get (void);
973+ extern void* __context_get_0 (void);
851974
852- void* {snake}_context_get( ) {{
853- return __context_get ();
975+ void* {snake}_context_get_0(void ) {{
976+ return __context_get_0 ();
854977}}
855978
856979__attribute__((__import_module__("$root"), __import_name__("[context-set-0]")))
857- extern void __context_set (void*);
980+ extern void __context_set_0 (void*);
858981
859- void {snake}_context_set(void *val) {{
860- return __context_set(val);
982+
983+ void {snake}_context_set_0(void *value) {{
984+ __context_set_0(value);
861985}}
862986
863987__attribute__((__import_module__("$root"), __import_name__("[thread-yield]")))
864988extern uint32_t __thread_yield(void);
865989
866- void {snake}_yield (void) {{
990+ void {snake}_thread_yield (void) {{
867991 __thread_yield();
868992}}
869-
870- __attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-yield]")))
871- extern uint32_t __thread_yield_cancellable(void);
872-
873- uint32_t {snake}_yield_cancellable(void) {{
874- return __thread_yield_cancellable();
875- }}
876993 "#
877994 ) ;
878995 }
0 commit comments