diff --git a/clang/tools/amdgpu-arch/AMDGPUArch.cpp b/clang/tools/amdgpu-arch/AMDGPUArch.cpp --- a/clang/tools/amdgpu-arch/AMDGPUArch.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArch.cpp @@ -11,6 +11,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Error.h" +#include +#include +#include + #if defined(__has_include) #if __has_include("hsa/hsa.h") #define HSA_HEADER_FOUND 1 @@ -26,11 +32,62 @@ #endif #if !HSA_HEADER_FOUND -int main() { return 1; } -#else +// Forward declaration of the status enumeration used by HSA. +typedef enum { + HSA_STATUS_SUCCESS = 0x0, +} hsa_status_t; -#include -#include +// Forward declaration of the device types used by HSA. +typedef enum { + HSA_DEVICE_TYPE_CPU = 0, + HSA_DEVICE_TYPE_GPU = 1, +} hsa_device_type_t; + +// Forward declaration of the agent information types we use. +typedef enum { + HSA_AGENT_INFO_NAME = 0, + HSA_AGENT_INFO_DEVICE = 17, +} hsa_agent_info_t; + +typedef struct hsa_agent_s { + uint64_t handle; +} hsa_agent_t; + +hsa_status_t (*hsa_init)(); +hsa_status_t (*hsa_shut_down)(); +hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *); +hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*callback)(hsa_agent_t, + void *), + void *); + +constexpr const char *DynamicHSAPath = "libhsa-runtime64.so"; + +llvm::Error loadHSA() { + std::string ErrMsg; + auto DynlibHandle = std::make_unique( + llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg)); + if (!DynlibHandle->isValid()) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Failed to 'dlopen' %s\n", DynamicHSAPath); + } +#define DYNAMIC_INIT(SYMBOL) \ + { \ + void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ + if (!SymbolPtr) \ + return llvm::createStringError(llvm::inconvertibleErrorCode(), \ + "Failed to 'dlsym' " #SYMBOL); \ + SYMBOL = reinterpret_cast(SymbolPtr); \ + } + DYNAMIC_INIT(hsa_init); + DYNAMIC_INIT(hsa_shut_down); + DYNAMIC_INIT(hsa_agent_get_info); + DYNAMIC_INIT(hsa_iterate_agents); +#undef DYNAMIC_INIT + return llvm::Error::success(); +} +#else +llvm::Error loadHSA() { return llvm::Error::success(); } +#endif static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) { hsa_device_type_t DeviceType; @@ -53,7 +110,13 @@ return HSA_STATUS_SUCCESS; } -int main() { +int main(int argc, char *argv[]) { + // Attempt to load the HSA runtime. + if (llvm::Error Err = loadHSA()) { + logAllUnhandledErrors(std::move(Err), llvm::errs()); + return 1; + } + hsa_status_t Status = hsa_init(); if (Status != HSA_STATUS_SUCCESS) { return 1; @@ -74,5 +137,3 @@ hsa_shut_down(); return 0; } - -#endif diff --git a/clang/tools/amdgpu-arch/CMakeLists.txt b/clang/tools/amdgpu-arch/CMakeLists.txt --- a/clang/tools/amdgpu-arch/CMakeLists.txt +++ b/clang/tools/amdgpu-arch/CMakeLists.txt @@ -6,14 +6,13 @@ # // # //===----------------------------------------------------------------------===// -find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) -if (NOT ${hsa-runtime64_FOUND}) - message(STATUS "Not building amdgpu-arch: hsa-runtime64 not found") - return() -endif() +set(LLVM_LINK_COMPONENTS Support) add_clang_tool(amdgpu-arch AMDGPUArch.cpp) -set_target_properties(amdgpu-arch PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON) - -clang_target_link_libraries(amdgpu-arch PRIVATE hsa-runtime64::hsa-runtime64) +# If we find the HSA runtime we link with it directly. +find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) +if (${hsa-runtime64_FOUND}) + set_target_properties(amdgpu-arch PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON) + clang_target_link_libraries(amdgpu-arch PRIVATE hsa-runtime64::hsa-runtime64) +endif()