mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 15:41:43 +00:00 
			
		
		
		
	With https://github.com/llvm/llvm-project/pull/150201 being merged, there is now a better way to generate the Emscripten trampoline, instead of including hand-generated binary WASM content. Requires Emscripten 4.0.12.
		
			
				
	
	
		
			38 lines
		
	
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			38 lines
		
	
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// This file must be compiled with -mgc to enable the extra wasm-gc
 | 
						|
// instructions. It has to be compiled separately because not enough JS runtimes
 | 
						|
// support wasm-gc yet. If the JS runtime does not support wasm-gc (or has buggy
 | 
						|
// support like iOS), we will use the JS trampoline fallback.
 | 
						|
 | 
						|
// We can't import Python.h here because it is compiled/linked with -nostdlib.
 | 
						|
// We don't need to know what's inside PyObject* anyways. We could just call it
 | 
						|
// void* everywhere. There are two reasons to do this:
 | 
						|
// 1. to improve readability
 | 
						|
// 2. eventually when we are comfortable requiring wasm-gc, we can merge this
 | 
						|
//    into emscripten_trampoline.c without worrying about it.
 | 
						|
typedef void PyObject;
 | 
						|
 | 
						|
typedef PyObject* (*three_arg)(PyObject*, PyObject*, PyObject*);
 | 
						|
typedef PyObject* (*two_arg)(PyObject*, PyObject*);
 | 
						|
typedef PyObject* (*one_arg)(PyObject*);
 | 
						|
typedef PyObject* (*zero_arg)(void);
 | 
						|
 | 
						|
#define TRY_RETURN_CALL(ty, args...) \
 | 
						|
  if (__builtin_wasm_test_function_pointer_signature((ty)func)) { \
 | 
						|
    return ((ty)func)(args); \
 | 
						|
  }
 | 
						|
 | 
						|
__attribute__((export_name("trampoline_call"))) PyObject*
 | 
						|
trampoline_call(int* success,
 | 
						|
                void* func,
 | 
						|
                PyObject* self,
 | 
						|
                PyObject* args,
 | 
						|
                PyObject* kw)
 | 
						|
{
 | 
						|
  *success = 1;
 | 
						|
  TRY_RETURN_CALL(three_arg, self, args, kw);
 | 
						|
  TRY_RETURN_CALL(two_arg, self, args);
 | 
						|
  TRY_RETURN_CALL(one_arg, self);
 | 
						|
  TRY_RETURN_CALL(zero_arg);
 | 
						|
  *success = 0;
 | 
						|
  return 0;
 | 
						|
}
 |