void Wasm::registerCallbacks() {
#define _REGISTER(_fn)                                                                             \
  wasm_vm_->registerCallback(                                                                      \
      "env", #_fn, &_fn##Handler,                                                                  \
      &ConvertFunctionWordToUint32<decltype(_fn##Handler),                                         \
                                   _fn##Handler>::convertFunctionWordToUint32)
  if (is_emscripten_) {
    _REGISTER(pthread_equal);
  }
#undef _REGISTER

#define _REGISTER_WASI(_fn)                                                                        \
  wasm_vm_->registerCallback(                                                                      \
      "wasi_unstable", #_fn, &wasi_unstable_##_fn##Handler,                                        \
      &ConvertFunctionWordToUint32<decltype(wasi_unstable_##_fn##Handler),                         \
                                   wasi_unstable_##_fn##Handler>::convertFunctionWordToUint32)
  if (is_emscripten_) {
    _REGISTER_WASI(fd_write);
    _REGISTER_WASI(fd_seek);
    _REGISTER_WASI(fd_close);
    _REGISTER_WASI(environ_get);
    _REGISTER_WASI(environ_sizes_get);
    _REGISTER_WASI(proc_exit);
  }
#undef _REGISTER_WASI

  // Calls with the "proxy_" prefix.
#define _REGISTER_PROXY(_fn)                                                                       \
  wasm_vm_->registerCallback(                                                                      \
      "env", "proxy_" #_fn, &_fn##Handler,                                                         \
      &ConvertFunctionWordToUint32<decltype(_fn##Handler),                                         \
                                   _fn##Handler>::convertFunctionWordToUint32);
  _REGISTER_PROXY(log);

  _REGISTER_PROXY(setProperty);
  _REGISTER_PROXY(getProperty);

  _REGISTER_PROXY(continueRequest);
  _REGISTER_PROXY(continueResponse);
  _REGISTER_PROXY(sendLocalResponse);
  _REGISTER_PROXY(clearRouteCache);

  _REGISTER_PROXY(getSharedData);
  _REGISTER_PROXY(setSharedData);

  _REGISTER_PROXY(registerSharedQueue);
  _REGISTER_PROXY(resolveSharedQueue);
  _REGISTER_PROXY(dequeueSharedQueue);
  _REGISTER_PROXY(enqueueSharedQueue);

  _REGISTER_PROXY(getDownstreamDataBufferBytes);
  _REGISTER_PROXY(getUpstreamDataBufferBytes);

  _REGISTER_PROXY(getHeaderMapValue);
  _REGISTER_PROXY(addHeaderMapValue);
  _REGISTER_PROXY(replaceHeaderMapValue);
  _REGISTER_PROXY(removeHeaderMapValue);
  _REGISTER_PROXY(getHeaderMapPairs);
  _REGISTER_PROXY(setHeaderMapPairs);
  _REGISTER_PROXY(getHeaderMapSize);

  _REGISTER_PROXY(getRequestBodyBufferBytes);
  _REGISTER_PROXY(getResponseBodyBufferBytes);

  _REGISTER_PROXY(httpCall);

  _REGISTER_PROXY(grpcCall);
  _REGISTER_PROXY(grpcStream);
  _REGISTER_PROXY(grpcClose);
  _REGISTER_PROXY(grpcCancel);
  _REGISTER_PROXY(grpcSend);

  _REGISTER_PROXY(setTickPeriodMilliseconds);
  _REGISTER_PROXY(getCurrentTimeNanoseconds);

  _REGISTER_PROXY(defineMetric);
  _REGISTER_PROXY(incrementMetric);
  _REGISTER_PROXY(recordMetric);
  _REGISTER_PROXY(getMetric);

  _REGISTER_PROXY(setEffectiveContext);
#undef _REGISTER_PROXY
}