// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.

#include <wrapper/hook_xrt.h>

size_t
xrt::bo::
size() const
{
  const char* func_s = "xrt::bo::size(void)";
  typedef size_t (xrt::bo::*func_t)() const;
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  size_t ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  if (need_trace) {
    xbtracer_trace_arg("size", ret_o, func_exit);
  }
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

uint64_t
xrt::bo::
address() const
{
  const char* func_s = "xrt::bo::address(void)";
  typedef uint64_t (xrt::bo::*func_t)() const;
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  uint64_t ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

void
xrt::bo::async_handle::
wait()
{
  const char* func_s = "xrt::bo::async_handle::wait(void)";
  typedef void (xrt::bo::async_handle::*func_t)();
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

void
xrt::bo::
copy(const xrt::bo& src, size_t sz, size_t src_offset, size_t dst_offset)
{
  const char* func_s = "xrt::bo::copy(const xrt::bo&, size_t, size_t, size_t)";
  typedef void (xrt::bo::*func_t)(const xrt::bo&, size_t, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  (this->*ofunc)(src, sz, src_offset, dst_offset);

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

void
xrt::bo::
read(void* dst, size_t size, size_t skip)
{
  const char* func_s = "xrt::bo::read(void*, size_t, size_t)";
  typedef void (xrt::bo::*func_t)(void*, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  (this->*ofunc)(dst, size, skip);

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

void
xrt::bo::
sync(xclBOSyncDirection dir, size_t sz, size_t offset)
{
  const char* func_s = "xrt::bo::sync(xclBOSyncDirection, size_t, size_t)";
  typedef void (xrt::bo::*func_t)(xclBOSyncDirection, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  const char* ptr = nullptr;
  if (need_trace) {
    xbtracer_trace_arg("dir", static_cast<uint32_t>(dir), func_entry);
    xbtracer_trace_arg("size", sz, func_entry);
    xbtracer_trace_arg("offset", offset, func_entry);
    // TODO: we always include content from the buffer for now
    // We will need to add an option to allow user to specify if user wants
    // to capture data or not.
    if (dir == XCL_BO_SYNC_BO_TO_DEVICE || dir == XCL_BO_SYNC_BO_GMIO_TO_AIE) {
      ptr = reinterpret_cast<const char*>(map());
      if (!ptr) {
        xbtracer_pcritical(std::string(func_s), ", failed to get mapped buffer.");
      }
      ptr += offset;
      xbtracer_trace_mem_dump(ptr, sz, 1, "data", func_entry);
    }
  }
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  (this->*ofunc)(dir, sz, offset);

  if (need_trace) {
    // TODO: we always include content from the buffer for now
    // get output data here as xbtracer_init_member_func_exit_handle() will untrace
    // this thread.
    if (dir == XCL_BO_SYNC_BO_FROM_DEVICE || dir == XCL_BO_SYNC_BO_AIE_TO_GMIO) {
      ptr = reinterpret_cast<const char*>(map());
      if (!ptr) {
        xbtracer_pcritical(std::string(func_s), ", failed to get mapped buffer.");
      }
      ptr += offset;
    }
  }
  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  if (need_trace) {
    // TODO: we always include content from the buffer for now
    if (dir == XCL_BO_SYNC_BO_FROM_DEVICE || dir == XCL_BO_SYNC_BO_AIE_TO_GMIO) {
      xbtracer_trace_mem_dump(ptr, sz, 1, "data", func_exit);
    }
  }
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

void
xrt::bo::
write(const void* src, size_t size, size_t seek)
{
  const char* func_s = "xrt::bo::write(const void*, size_t, size_t)";
  typedef void (xrt::bo::*func_t)(const void*, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  (this->*ofunc)(src, size, seek);

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

void*
xrt::bo::
map()
{
  const char* func_s = "xrt::bo::map(void)";
  typedef void* (xrt::bo::*func_t)();
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  void* ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

xrt::bo::async_handle
xrt::bo::
async(xclBOSyncDirection dir, size_t sz, size_t offset)
{
  const char* func_s = "xrt::bo::async(xclBOSyncDirection, size_t, size_t)";
  typedef xrt::bo::async_handle (xrt::bo::*func_t)(xclBOSyncDirection, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  xrt::bo::async_handle ret_o = (this->*ofunc)(dir, sz, offset);

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

xrt::bo::
bo(const xrt::bo& parent, size_t size, size_t offset)
{
  const char* func_s = "xrt::bo::bo(const xrt::bo&, size_t, size_t)";
  typedef xrt::bo* (*func_t)(void*, const xrt::bo&, size_t, size_t);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, parent, size, offset);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, size_t sz, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, sz, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, size_t sz, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, size_t, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, size_t, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, sz, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, void* userptr, size_t sz, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, void*, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, void*, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, userptr, sz, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, void* userptr, size_t sz, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, void*, size_t, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, void*, size_t, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, userptr, sz, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, xrt::bo::export_handle ehdl)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, xrt::bo::export_handle)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, xrt::bo::export_handle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, ehdl);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::device& device, xrt::pid_type pid, xrt::bo::export_handle ehdl)
{
  const char* func_s = "xrt::bo::bo(const xrt::device&, xrt::pid_type, xrt::bo::export_handle)";
  typedef xrt::bo* (*func_t)(void*, const xrt::device&, xrt::pid_type, xrt::bo::export_handle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, device, pid, ehdl);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::hw_context& hwctx, size_t sz, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::hw_context&, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::hw_context&, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, hwctx, sz, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::hw_context& hwctx, size_t sz, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::hw_context&, size_t, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::hw_context&, size_t, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, hwctx, sz, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::hw_context& hwctx, void* userptr, size_t sz, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::hw_context&, void*, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::hw_context&, void*, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, hwctx, userptr, sz, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(const xrt::hw_context& hwctx, void* userptr, size_t sz, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(const xrt::hw_context&, void*, size_t, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, const xrt::hw_context&, void*, size_t, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, hwctx, userptr, sz, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xclDeviceHandle dhdl, size_t size, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(xclDeviceHandle, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, xclDeviceHandle, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  if (need_trace) {
    xbtracer_trace_arg("dev_handle", "void*", dhdl, func_entry);
    xbtracer_trace_arg("size", size, func_entry);
    xbtracer_trace_arg("flags", flags, func_entry);
    xbtracer_trace_arg("grp", grp, func_entry);
  }
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, dhdl, size, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xclDeviceHandle dhdl, void* userptr, size_t sz, xrt::bo::flags flags, xrt::memory_group grp)
{
  const char* func_s = "xrt::bo::bo(xclDeviceHandle, void*, size_t, xrt::bo::flags, xrt::memory_group)";
  typedef xrt::bo* (*func_t)(void*, xclDeviceHandle, void*, size_t, xrt::bo::flags, xrt::memory_group);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, dhdl, userptr, sz, flags, grp);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xclDeviceHandle dhdl, xclBufferExportHandle ehdl)
{
  const char* func_s = "xrt::bo::bo(xclDeviceHandle, xclBufferExportHandle)";
  typedef xrt::bo* (*func_t)(void*, xclDeviceHandle, xclBufferExportHandle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, dhdl, ehdl);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xclDeviceHandle dhdl, xcl_buffer_handle xhdl)
{
  const char* func_s = "xrt::bo::bo(xclDeviceHandle, xcl_buffer_handle)";
  typedef xrt::bo* (*func_t)(void*, xclDeviceHandle, xcl_buffer_handle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, dhdl, xhdl);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xclDeviceHandle dhdl, xrt::pid_type pid, xclBufferExportHandle ehdl)
{
  const char* func_s = "xrt::bo::bo(xclDeviceHandle, xrt::pid_type, xclBufferExportHandle)";
  typedef xrt::bo* (*func_t)(void*, xclDeviceHandle, xrt::pid_type, xclBufferExportHandle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, dhdl, pid, ehdl);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::
bo(xrtBufferHandle arg1)
{
  const char* func_s = "xrt::bo::bo(xrtBufferHandle)";
  typedef xrt::bo* (*func_t)(void*, xrtBufferHandle);
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_constructor_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  ofunc((void*)this, arg1);

  xbtracer_proto::Func func_exit;
  xbtracer_init_constructor_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);
}

xrt::bo::export_handle
xrt::bo::
export_buffer()
{
  const char* func_s = "xrt::bo::export_buffer(void)";
  typedef xrt::bo::export_handle (xrt::bo::*func_t)();
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  xrt::bo::export_handle ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

xrt::bo::flags
xrt::bo::
get_flags() const
{
  const char* func_s = "xrt::bo::get_flags(void)";
  typedef xrt::bo::flags (xrt::bo::*func_t)() const;
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  xrt::bo::flags ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}

xrt::memory_group
xrt::bo::
get_memory_group() const
{
  const char* func_s = "xrt::bo::get_memory_group(void)";
  typedef xrt::memory_group (xrt::bo::*func_t)() const;
  xbtracer_proto::Func func_entry;
  proc_addr_type paddr_ptr = nullptr;
  func_t ofunc = nullptr;
  void **ofunc_ptr = reinterpret_cast<void **>(&ofunc);
  bool need_trace = false;

  xbtracer_init_member_func_entry_handle(func_entry, need_trace, func_s, paddr_ptr);
  xbtracer_write_protobuf_msg(func_entry, need_trace);
  *ofunc_ptr = (void*)paddr_ptr;

  xrt::memory_group ret_o = (this->*ofunc)();

  xbtracer_proto::Func func_exit;
  xbtracer_init_member_func_exit_handle(func_exit, need_trace, func_s);
  xbtracer_write_protobuf_msg(func_exit, need_trace);

  return ret_o;
}
