/*
 * Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
 *
 * SPDX-License-Identifier: MIT
 */

#pragma once

#include <mutex>
#include "top.hpp"
#include "amd_comgr/amd_comgr.h"

namespace amd {
typedef void (*t_amd_comgr_get_version)(size_t* major, size_t* minor);
typedef amd_comgr_status_t (*t_amd_comgr_status_string)(amd_comgr_status_t status,
                                                        const char** status_string);
typedef amd_comgr_status_t (*t_amd_comgr_get_isa_count)(size_t* count);
typedef amd_comgr_status_t (*t_amd_comgr_get_isa_name)(size_t index, const char** isa_name);
typedef amd_comgr_status_t (*t_amd_comgr_get_isa_metadata)(const char* isa_name,
                                                           amd_comgr_metadata_node_t* metadata);
typedef amd_comgr_status_t (*t_amd_comgr_create_data)(amd_comgr_data_kind_t kind,
                                                      amd_comgr_data_t* data);
typedef amd_comgr_status_t (*t_amd_comgr_release_data)(amd_comgr_data_t data);
typedef amd_comgr_status_t (*t_amd_comgr_get_data_kind)(amd_comgr_data_t data,
                                                        amd_comgr_data_kind_t* kind);
typedef amd_comgr_status_t (*t_amd_comgr_set_data)(amd_comgr_data_t data, size_t size,
                                                   const char* bytes);
typedef amd_comgr_status_t (*t_amd_comgr_set_data_name)(amd_comgr_data_t data, const char* name);
typedef amd_comgr_status_t (*t_amd_comgr_get_data)(amd_comgr_data_t data, size_t* size,
                                                   char* bytes);
typedef amd_comgr_status_t (*t_amd_comgr_get_data_name)(amd_comgr_data_t data, size_t* size,
                                                        char* name);
typedef amd_comgr_status_t (*t_amd_comgr_get_data_isa_name)(amd_comgr_data_t data, size_t* size,
                                                            char* isa_name);
typedef amd_comgr_status_t (*t_amd_comgr_get_data_metadata)(amd_comgr_data_t data,
                                                            amd_comgr_metadata_node_t* metadata);
typedef amd_comgr_status_t (*t_amd_comgr_destroy_metadata)(amd_comgr_metadata_node_t metadata);
typedef amd_comgr_status_t (*t_amd_comgr_create_data_set)(amd_comgr_data_set_t* data_set);
typedef amd_comgr_status_t (*t_amd_comgr_destroy_data_set)(amd_comgr_data_set_t data_set);
typedef amd_comgr_status_t (*t_amd_comgr_data_set_add)(amd_comgr_data_set_t data_set,
                                                       amd_comgr_data_t data);
typedef amd_comgr_status_t (*t_amd_comgr_data_set_remove)(amd_comgr_data_set_t data_set,
                                                          amd_comgr_data_kind_t data_kind);
typedef amd_comgr_status_t (*t_amd_comgr_action_data_count)(amd_comgr_data_set_t data_set,
                                                            amd_comgr_data_kind_t data_kind,
                                                            size_t* count);
typedef amd_comgr_status_t (*t_amd_comgr_action_data_get_data)(amd_comgr_data_set_t data_set,
                                                               amd_comgr_data_kind_t data_kind,
                                                               size_t index,
                                                               amd_comgr_data_t* data);
typedef amd_comgr_status_t (*t_amd_comgr_create_action_info)(amd_comgr_action_info_t* action_info);
typedef amd_comgr_status_t (*t_amd_comgr_destroy_action_info)(amd_comgr_action_info_t action_info);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_isa_name)(
    amd_comgr_action_info_t action_info, const char* isa_name);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_isa_name)(
    amd_comgr_action_info_t action_info, size_t* size, char* isa_name);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_language)(
    amd_comgr_action_info_t action_info, amd_comgr_language_t language);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_language)(
    amd_comgr_action_info_t action_info, amd_comgr_language_t* language);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_option_list)(
    amd_comgr_action_info_t action_info, const char* options[], size_t count);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_option_list_count)(
    amd_comgr_action_info_t action_info, size_t* count);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_option_list_item)(
    amd_comgr_action_info_t action_info, size_t index, size_t* size, char* option);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_working_directory_path)(
    amd_comgr_action_info_t action_info, const char* path);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_working_directory_path)(
    amd_comgr_action_info_t action_info, size_t* size, char* path);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_logging)(
    amd_comgr_action_info_t action_info, bool logging);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_get_logging)(
    amd_comgr_action_info_t action_info, bool* logging);
typedef amd_comgr_status_t (*t_amd_comgr_do_action)(amd_comgr_action_kind_t kind,
                                                    amd_comgr_action_info_t info,
                                                    amd_comgr_data_set_t input,
                                                    amd_comgr_data_set_t result);
typedef amd_comgr_status_t (*t_amd_comgr_get_metadata_kind)(amd_comgr_metadata_node_t metadata,
                                                            amd_comgr_metadata_kind_t* kind);
typedef amd_comgr_status_t (*t_amd_comgr_get_metadata_string)(amd_comgr_metadata_node_t metadata,
                                                              size_t* size, char* string);
typedef amd_comgr_status_t (*t_amd_comgr_get_metadata_map_size)(amd_comgr_metadata_node_t metadata,
                                                                size_t* size);
typedef amd_comgr_status_t (*t_amd_comgr_iterate_map_metadata)(
    amd_comgr_metadata_node_t metadata,
    amd_comgr_status_t (*callback)(amd_comgr_metadata_node_t key, amd_comgr_metadata_node_t value,
                                   void* user_data),
    void* user_data);
typedef amd_comgr_status_t (*t_amd_comgr_metadata_lookup)(amd_comgr_metadata_node_t metadata,
                                                          const char* key,
                                                          amd_comgr_metadata_node_t* value);
typedef amd_comgr_status_t (*t_amd_comgr_get_metadata_list_size)(amd_comgr_metadata_node_t metadata,
                                                                 size_t* size);
typedef amd_comgr_status_t (*t_amd_comgr_index_list_metadata)(amd_comgr_metadata_node_t metadata,
                                                              size_t index,
                                                              amd_comgr_metadata_node_t* value);
typedef amd_comgr_status_t (*t_amd_comgr_iterate_symbols)(
    amd_comgr_data_t data,
    amd_comgr_status_t (*callback)(amd_comgr_symbol_t symbol, void* user_data), void* user_data);
typedef amd_comgr_status_t (*t_amd_comgr_symbol_lookup)(amd_comgr_data_t data, const char* name,
                                                        amd_comgr_symbol_t* symbol);
typedef amd_comgr_status_t (*t_amd_comgr_symbol_get_info)(amd_comgr_symbol_t symbol,
                                                          amd_comgr_symbol_info_t attribute,
                                                          void* value);
typedef amd_comgr_status_t (*t_amd_comgr_demangle_symbol_name)(
    amd_comgr_data_t MangledSymbolName, amd_comgr_data_t* DemangledSymbolName);
typedef amd_comgr_status_t (*t_amd_comgr_populate_mangled_names)(amd_comgr_data_t data,
                                                                 size_t* count);
typedef amd_comgr_status_t (*t_amd_comgr_get_mangled_name)(amd_comgr_data_t data, size_t index,
                                                           size_t* size, char* mangled_name);
typedef amd_comgr_status_t (*t_amd_comgr_populate_name_expression_map)(amd_comgr_data_t data,
                                                                       size_t* count);
typedef amd_comgr_status_t (*t_amd_comgr_map_name_expression_to_symbol_name)(amd_comgr_data_t data,
                                                                             size_t* size,
                                                                             char* name_expression,
                                                                             char* symbol_name);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_device_lib_linking)(
    amd_comgr_action_info_t action_info, bool link_device_lib);
typedef amd_comgr_status_t (*t_amd_comgr_action_info_set_bundle_entry_ids)(
    amd_comgr_action_info_t action_info, const char* bundle_entry_ids[], size_t count);
typedef amd_comgr_status_t (*t_amd_comgr_set_data_from_file_slice)(amd_comgr_data_t data, int fd,
                                                                   uint64_t offset, uint64_t size);
typedef amd_comgr_status_t (*t_amd_comgr_lookup_code_object)(amd_comgr_data_t data,
                                                             amd_comgr_code_object_info_t* info,
                                                             size_t size);

struct ComgrEntryPoints {
  void* handle;
  t_amd_comgr_get_version amd_comgr_get_version;
  t_amd_comgr_status_string amd_comgr_status_string;
  t_amd_comgr_get_isa_count amd_comgr_get_isa_count;
  t_amd_comgr_get_isa_name amd_comgr_get_isa_name;
  t_amd_comgr_get_isa_metadata amd_comgr_get_isa_metadata;
  t_amd_comgr_create_data amd_comgr_create_data;
  t_amd_comgr_release_data amd_comgr_release_data;
  t_amd_comgr_get_data_kind amd_comgr_get_data_kind;
  t_amd_comgr_set_data amd_comgr_set_data;
  t_amd_comgr_set_data_name amd_comgr_set_data_name;
  t_amd_comgr_get_data amd_comgr_get_data;
  t_amd_comgr_get_data_name amd_comgr_get_data_name;
  t_amd_comgr_get_data_isa_name amd_comgr_get_data_isa_name;
  t_amd_comgr_get_data_metadata amd_comgr_get_data_metadata;
  t_amd_comgr_destroy_metadata amd_comgr_destroy_metadata;
  t_amd_comgr_create_data_set amd_comgr_create_data_set;
  t_amd_comgr_destroy_data_set amd_comgr_destroy_data_set;
  t_amd_comgr_data_set_add amd_comgr_data_set_add;
  t_amd_comgr_data_set_remove amd_comgr_data_set_remove;
  t_amd_comgr_action_data_count amd_comgr_action_data_count;
  t_amd_comgr_action_data_get_data amd_comgr_action_data_get_data;
  t_amd_comgr_create_action_info amd_comgr_create_action_info;
  t_amd_comgr_destroy_action_info amd_comgr_destroy_action_info;
  t_amd_comgr_action_info_set_isa_name amd_comgr_action_info_set_isa_name;
  t_amd_comgr_action_info_get_isa_name amd_comgr_action_info_get_isa_name;
  t_amd_comgr_action_info_set_language amd_comgr_action_info_set_language;
  t_amd_comgr_action_info_get_language amd_comgr_action_info_get_language;
  t_amd_comgr_action_info_set_option_list amd_comgr_action_info_set_option_list;
  t_amd_comgr_action_info_get_option_list_count amd_comgr_action_info_get_option_list_count;
  t_amd_comgr_action_info_get_option_list_item amd_comgr_action_info_get_option_list_item;
  t_amd_comgr_action_info_set_working_directory_path
      amd_comgr_action_info_set_working_directory_path;
  t_amd_comgr_action_info_get_working_directory_path
      amd_comgr_action_info_get_working_directory_path;
  t_amd_comgr_action_info_set_logging amd_comgr_action_info_set_logging;
  t_amd_comgr_action_info_get_logging amd_comgr_action_info_get_logging;
  t_amd_comgr_do_action amd_comgr_do_action;
  t_amd_comgr_get_metadata_kind amd_comgr_get_metadata_kind;
  t_amd_comgr_get_metadata_string amd_comgr_get_metadata_string;
  t_amd_comgr_get_metadata_map_size amd_comgr_get_metadata_map_size;
  t_amd_comgr_iterate_map_metadata amd_comgr_iterate_map_metadata;
  t_amd_comgr_metadata_lookup amd_comgr_metadata_lookup;
  t_amd_comgr_get_metadata_list_size amd_comgr_get_metadata_list_size;
  t_amd_comgr_index_list_metadata amd_comgr_index_list_metadata;
  t_amd_comgr_iterate_symbols amd_comgr_iterate_symbols;
  t_amd_comgr_symbol_lookup amd_comgr_symbol_lookup;
  t_amd_comgr_symbol_get_info amd_comgr_symbol_get_info;
  t_amd_comgr_demangle_symbol_name amd_comgr_demangle_symbol_name;
  t_amd_comgr_populate_mangled_names amd_comgr_populate_mangled_names;
  t_amd_comgr_get_mangled_name amd_comgr_get_mangled_name;
  t_amd_comgr_populate_name_expression_map amd_comgr_populate_name_expression_map;
  t_amd_comgr_map_name_expression_to_symbol_name amd_comgr_map_name_expression_to_symbol_name;
  t_amd_comgr_action_info_set_device_lib_linking amd_comgr_action_info_set_device_lib_linking;
  t_amd_comgr_action_info_set_bundle_entry_ids amd_comgr_action_info_set_bundle_entry_ids;
  t_amd_comgr_set_data_from_file_slice amd_comgr_set_data_from_file_slice;
  t_amd_comgr_lookup_code_object amd_comgr_lookup_code_object;
};

#ifdef COMGR_DYN_DLL
#define COMGR_DYN(NAME) cep_.NAME
#define GET_COMGR_SYMBOL(NAME)                                                                     \
  cep_.NAME = reinterpret_cast<t_##NAME>(Os::getSymbol(cep_.handle, #NAME));                       \
  if (nullptr == cep_.NAME) {                                                                      \
    ClPrint(amd::LOG_ERROR, amd::LOG_CODE, "Failed to load COMGR function %s", #NAME);             \
    return false;                                                                                  \
  }
#define GET_COMGR_OPTIONAL_SYMBOL(NAME)                                                            \
  cep_.NAME = reinterpret_cast<t_##NAME>(Os::getSymbol(cep_.handle, #NAME));
#else
#define COMGR_DYN(NAME) NAME
#define GET_COMGR_SYMBOL(NAME)
#define GET_COMGR_OPTIONAL_SYMBOL(NAME)
#endif

class Comgr : public amd::AllStatic {
 public:
  static std::once_flag initialized;

  static bool LoadLib();

  static bool IsReady() { return is_ready_; }

  static void get_version(size_t* major, size_t* minor) {
    COMGR_DYN(amd_comgr_get_version)(major, minor);
  }
  static amd_comgr_status_t status_string(amd_comgr_status_t status, const char** status_string) {
    return COMGR_DYN(amd_comgr_status_string)(status, status_string);
  }
  static amd_comgr_status_t get_isa_count(size_t* count) {
    return COMGR_DYN(amd_comgr_get_isa_count)(count);
  }
  static amd_comgr_status_t get_isa_name(size_t index, const char** isa_name) {
    return COMGR_DYN(amd_comgr_get_isa_name)(index, isa_name);
  }
  static amd_comgr_status_t get_isa_metadata(const char* isa_name,
                                             amd_comgr_metadata_node_t* metadata) {
    return COMGR_DYN(amd_comgr_get_isa_metadata)(isa_name, metadata);
  }
  static amd_comgr_status_t create_data(amd_comgr_data_kind_t kind, amd_comgr_data_t* data) {
    return COMGR_DYN(amd_comgr_create_data)(kind, data);
  }
  static amd_comgr_status_t release_data(amd_comgr_data_t data) {
    return COMGR_DYN(amd_comgr_release_data)(data);
  }
  static amd_comgr_status_t get_data_kind(amd_comgr_data_t data, amd_comgr_data_kind_t* kind) {
    return COMGR_DYN(amd_comgr_get_data_kind)(data, kind);
  }
  static amd_comgr_status_t set_data(amd_comgr_data_t data, size_t size, const char* bytes) {
    return COMGR_DYN(amd_comgr_set_data)(data, size, bytes);
  }
  static amd_comgr_status_t set_data_name(amd_comgr_data_t data, const char* name) {
    return COMGR_DYN(amd_comgr_set_data_name)(data, name);
  }
  static amd_comgr_status_t get_data(amd_comgr_data_t data, size_t* size, char* bytes) {
    return COMGR_DYN(amd_comgr_get_data)(data, size, bytes);
  }
  static amd_comgr_status_t get_data_name(amd_comgr_data_t data, size_t* size, char* name) {
    return COMGR_DYN(amd_comgr_get_data_name)(data, size, name);
  }
  static amd_comgr_status_t get_data_isa_name(amd_comgr_data_t data, size_t* size, char* isa_name) {
    return COMGR_DYN(amd_comgr_get_data_isa_name)(data, size, isa_name);
  }
  static amd_comgr_status_t get_data_metadata(amd_comgr_data_t data,
                                              amd_comgr_metadata_node_t* metadata) {
    return COMGR_DYN(amd_comgr_get_data_metadata)(data, metadata);
  }
  static amd_comgr_status_t destroy_metadata(amd_comgr_metadata_node_t metadata) {
    return COMGR_DYN(amd_comgr_destroy_metadata)(metadata);
  }
  static amd_comgr_status_t create_data_set(amd_comgr_data_set_t* data_set) {
    return COMGR_DYN(amd_comgr_create_data_set)(data_set);
  }
  static amd_comgr_status_t destroy_data_set(amd_comgr_data_set_t data_set) {
    return COMGR_DYN(amd_comgr_destroy_data_set)(data_set);
  }
  static amd_comgr_status_t data_set_add(amd_comgr_data_set_t data_set, amd_comgr_data_t data) {
    return COMGR_DYN(amd_comgr_data_set_add)(data_set, data);
  }
  static amd_comgr_status_t data_set_remove(amd_comgr_data_set_t data_set,
                                            amd_comgr_data_kind_t data_kind) {
    return COMGR_DYN(amd_comgr_data_set_remove)(data_set, data_kind);
  }
  static amd_comgr_status_t action_data_count(amd_comgr_data_set_t data_set,
                                              amd_comgr_data_kind_t data_kind, size_t* count) {
    return COMGR_DYN(amd_comgr_action_data_count)(data_set, data_kind, count);
  }
  static amd_comgr_status_t action_data_get_data(amd_comgr_data_set_t data_set,
                                                 amd_comgr_data_kind_t data_kind, size_t index,
                                                 amd_comgr_data_t* data) {
    return COMGR_DYN(amd_comgr_action_data_get_data)(data_set, data_kind, index, data);
  }
  static amd_comgr_status_t create_action_info(amd_comgr_action_info_t* action_info) {
    return COMGR_DYN(amd_comgr_create_action_info)(action_info);
  }
  static amd_comgr_status_t destroy_action_info(amd_comgr_action_info_t action_info) {
    return COMGR_DYN(amd_comgr_destroy_action_info)(action_info);
  }
  static amd_comgr_status_t action_info_set_isa_name(amd_comgr_action_info_t action_info,
                                                     const char* isa_name) {
    return COMGR_DYN(amd_comgr_action_info_set_isa_name)(action_info, isa_name);
  }
  static amd_comgr_status_t action_info_get_isa_name(amd_comgr_action_info_t action_info,
                                                     size_t* size, char* isa_name) {
    return COMGR_DYN(amd_comgr_action_info_get_isa_name)(action_info, size, isa_name);
  }
  static amd_comgr_status_t action_info_set_language(amd_comgr_action_info_t action_info,
                                                     amd_comgr_language_t language) {
    return COMGR_DYN(amd_comgr_action_info_set_language)(action_info, language);
  }
  static amd_comgr_status_t action_info_get_language(amd_comgr_action_info_t action_info,
                                                     amd_comgr_language_t* language) {
    return COMGR_DYN(amd_comgr_action_info_get_language)(action_info, language);
  }
  static amd_comgr_status_t action_info_set_option_list(amd_comgr_action_info_t action_info,
                                                        const char* options[], size_t count) {
    return COMGR_DYN(amd_comgr_action_info_set_option_list)(action_info, options, count);
  }
  static amd_comgr_status_t action_info_get_option_list_count(amd_comgr_action_info_t action_info,
                                                              size_t* count) {
    return COMGR_DYN(amd_comgr_action_info_get_option_list_count)(action_info, count);
  }
  static amd_comgr_status_t action_info_get_option_list_item(amd_comgr_action_info_t action_info,
                                                             size_t index, size_t* size,
                                                             char* option) {
    return COMGR_DYN(amd_comgr_action_info_get_option_list_item)(action_info, index, size, option);
  }
  static amd_comgr_status_t action_info_set_working_directory_path(
      amd_comgr_action_info_t action_info, const char* path) {
    return COMGR_DYN(amd_comgr_action_info_set_working_directory_path)(action_info, path);
  }
  static amd_comgr_status_t action_info_get_working_directory_path(
      amd_comgr_action_info_t action_info, size_t* size, char* path) {
    return COMGR_DYN(amd_comgr_action_info_get_working_directory_path)(action_info, size, path);
  }
  static amd_comgr_status_t action_info_set_logging(amd_comgr_action_info_t action_info,
                                                    bool logging) {
    return COMGR_DYN(amd_comgr_action_info_set_logging)(action_info, logging);
  }
  static amd_comgr_status_t action_info_get_logging(amd_comgr_action_info_t action_info,
                                                    bool* logging) {
    return COMGR_DYN(amd_comgr_action_info_get_logging)(action_info, logging);
  }
  static amd_comgr_status_t do_action(amd_comgr_action_kind_t kind, amd_comgr_action_info_t info,
                                      amd_comgr_data_set_t input, amd_comgr_data_set_t result) {
    return COMGR_DYN(amd_comgr_do_action)(kind, info, input, result);
  }
  static amd_comgr_status_t get_metadata_kind(amd_comgr_metadata_node_t metadata,
                                              amd_comgr_metadata_kind_t* kind) {
    return COMGR_DYN(amd_comgr_get_metadata_kind)(metadata, kind);
  }
  static amd_comgr_status_t get_metadata_string(amd_comgr_metadata_node_t metadata, size_t* size,
                                                char* string) {
    return COMGR_DYN(amd_comgr_get_metadata_string)(metadata, size, string);
  }
  static amd_comgr_status_t get_metadata_map_size(amd_comgr_metadata_node_t metadata,
                                                  size_t* size) {
    return COMGR_DYN(amd_comgr_get_metadata_map_size)(metadata, size);
  }
  static amd_comgr_status_t iterate_map_metadata(
      amd_comgr_metadata_node_t metadata,
      amd_comgr_status_t (*callback)(amd_comgr_metadata_node_t key, amd_comgr_metadata_node_t value,
                                     void* user_data),
      void* user_data) {
    return COMGR_DYN(amd_comgr_iterate_map_metadata)(metadata, callback, user_data);
  }
  static amd_comgr_status_t metadata_lookup(amd_comgr_metadata_node_t metadata, const char* key,
                                            amd_comgr_metadata_node_t* value) {
    return COMGR_DYN(amd_comgr_metadata_lookup)(metadata, key, value);
  }
  static amd_comgr_status_t get_metadata_list_size(amd_comgr_metadata_node_t metadata,
                                                   size_t* size) {
    return COMGR_DYN(amd_comgr_get_metadata_list_size)(metadata, size);
  }
  static amd_comgr_status_t index_list_metadata(amd_comgr_metadata_node_t metadata, size_t index,
                                                amd_comgr_metadata_node_t* value) {
    return COMGR_DYN(amd_comgr_index_list_metadata)(metadata, index, value);
  }
  static amd_comgr_status_t iterate_symbols(
      amd_comgr_data_t data,
      amd_comgr_status_t (*callback)(amd_comgr_symbol_t symbol, void* user_data), void* user_data) {
    return COMGR_DYN(amd_comgr_iterate_symbols)(data, callback, user_data);
  }
  static amd_comgr_status_t symbol_lookup(amd_comgr_data_t data, const char* name,
                                          amd_comgr_symbol_t* symbol) {
    return COMGR_DYN(amd_comgr_symbol_lookup)(data, name, symbol);
  }
  static amd_comgr_status_t symbol_get_info(amd_comgr_symbol_t symbol,
                                            amd_comgr_symbol_info_t attribute, void* value) {
    return COMGR_DYN(amd_comgr_symbol_get_info)(symbol, attribute, value);
  }
  static amd_comgr_status_t demangle_symbol_name(amd_comgr_data_t MangledSymbolName,
                                                 amd_comgr_data_t* DemangledSymbolName) {
    return COMGR_DYN(amd_comgr_demangle_symbol_name)(MangledSymbolName, DemangledSymbolName);
  }
  static amd_comgr_status_t populate_mangled_names(amd_comgr_data_t data, size_t* count) {
    return COMGR_DYN(amd_comgr_populate_mangled_names)(data, count);
  }
  static amd_comgr_status_t get_mangled_name(amd_comgr_data_t data, size_t index, size_t* size,
                                             char* mangled_name) {
    return COMGR_DYN(amd_comgr_get_mangled_name)(data, index, size, mangled_name);
  }
  static amd_comgr_status_t populate_name_expression_map(amd_comgr_data_t data, size_t* count) {
    return COMGR_DYN(amd_comgr_populate_name_expression_map)(data, count);
  }
  static amd_comgr_status_t map_name_expression_to_symbol_name(amd_comgr_data_t data, size_t* size,
                                                               char* name_expression,
                                                               char* symbol_name) {
    return COMGR_DYN(amd_comgr_map_name_expression_to_symbol_name)(data, size, name_expression,
                                                                   symbol_name);
  }
  static amd_comgr_status_t action_info_set_device_lib_linking(amd_comgr_action_info_t action_info,
                                                               bool link_device_lib) {
    return COMGR_DYN(amd_comgr_action_info_set_device_lib_linking)(action_info, link_device_lib);
  }
  static amd_comgr_status_t set_data_from_file_slice(amd_comgr_data_t data, int fd, uint64_t offset,
                                                     uint64_t size) {
    return COMGR_DYN(amd_comgr_set_data_from_file_slice)(data, fd, offset, size);
  }
  static amd_comgr_status_t lookup_code_object(amd_comgr_data_t data,
                                               amd_comgr_code_object_info_t* info_list,
                                               size_t info_list_size) {
    return COMGR_DYN(amd_comgr_lookup_code_object)(data, info_list, info_list_size);
  }
  static amd_comgr_status_t action_info_set_bundle_entry_ids(amd_comgr_action_info_t action_info,
                                                             const char* bundle_entry_ids[],
                                                             size_t count) {
#if defined(COMGR_DYN_DLL)
    if (cep_.amd_comgr_action_info_set_bundle_entry_ids == nullptr) {
      // comgr version 2.7 or less is loaded
      ClPrint(amd::LOG_ERROR, amd::LOG_CODE,
              "Failed to load COMGR function amd_comgr_action_info_set_bundle_entry_ids");
      return AMD_COMGR_STATUS_ERROR;
    }
#endif
    return COMGR_DYN(amd_comgr_action_info_set_bundle_entry_ids)(action_info, bundle_entry_ids,
                                                                 count);
  }

 private:
  static ComgrEntryPoints cep_;
  static bool is_ready_;
};

}  // namespace amd
