Coverage Report

Created: 2023-05-31 04:38

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/amdgpu-arch/AMDGPUArch.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- AMDGPUArch.cpp - list AMDGPU installed ----------*- C++ -*---------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements a tool for detecting name of AMDGPU installed in system
10
// using HSA. This tool is used by AMDGPU OpenMP driver.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/Basic/Version.h"
15
#include "llvm/Support/CommandLine.h"
16
#include "llvm/Support/DynamicLibrary.h"
17
#include "llvm/Support/Error.h"
18
#include <memory>
19
#include <string>
20
#include <vector>
21
22
using namespace llvm;
23
24
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
25
26
// Mark all our options with this category.
27
static cl::OptionCategory AMDGPUArchCategory("amdgpu-arch options");
28
29
0
static void PrintVersion(raw_ostream &OS) {
30
0
  OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n';
31
0
}
32
33
typedef enum {
34
  HSA_STATUS_SUCCESS = 0x0,
35
} hsa_status_t;
36
37
typedef enum {
38
  HSA_DEVICE_TYPE_CPU = 0,
39
  HSA_DEVICE_TYPE_GPU = 1,
40
} hsa_device_type_t;
41
42
typedef enum {
43
  HSA_AGENT_INFO_NAME = 0,
44
  HSA_AGENT_INFO_DEVICE = 17,
45
} hsa_agent_info_t;
46
47
typedef struct hsa_agent_s {
48
  uint64_t handle;
49
} hsa_agent_t;
50
51
hsa_status_t (*hsa_init)();
52
hsa_status_t (*hsa_shut_down)();
53
hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *);
54
hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*)(hsa_agent_t, void *),
55
                                   void *);
56
57
constexpr const char *DynamicHSAPath = "libhsa-runtime64.so";
58
59
0
llvm::Error loadHSA() {
60
0
  std::string ErrMsg;
61
0
  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
62
0
      llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg));
63
0
  if (!DynlibHandle->isValid()) {
64
0
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
65
0
                                   "Failed to 'dlopen' %s", DynamicHSAPath);
66
0
  }
67
0
#define DYNAMIC_INIT(SYMBOL)                                                   \
68
0
  {                                                                            \
69
0
    void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
70
0
    if (!SymbolPtr)                                                            \
71
0
      return llvm::createStringError(llvm::inconvertibleErrorCode(),           \
72
0
                                     "Failed to 'dlsym' " #SYMBOL);            \
73
0
    SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
74
0
  }
75
0
  DYNAMIC_INIT(hsa_init);
76
0
  DYNAMIC_INIT(hsa_shut_down);
77
0
  DYNAMIC_INIT(hsa_agent_get_info);
78
0
  DYNAMIC_INIT(hsa_iterate_agents);
79
0
#undef DYNAMIC_INIT
80
0
  return llvm::Error::success();
81
0
}
82
83
0
static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) {
84
0
  hsa_device_type_t DeviceType;
85
0
  hsa_status_t Status =
86
0
      hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DeviceType);
87
88
  // continue only if device type if GPU
89
0
  if (Status != HSA_STATUS_SUCCESS || DeviceType != HSA_DEVICE_TYPE_GPU) {
90
0
    return Status;
91
0
  }
92
93
0
  std::vector<std::string> *GPUs =
94
0
      static_cast<std::vector<std::string> *>(Data);
95
0
  char GPUName[64];
96
0
  Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, GPUName);
97
0
  if (Status != HSA_STATUS_SUCCESS) {
98
0
    return Status;
99
0
  }
100
0
  GPUs->push_back(GPUName);
101
0
  return HSA_STATUS_SUCCESS;
102
0
}
103
104
int main(int argc, char *argv[]) {
105
  cl::HideUnrelatedOptions(AMDGPUArchCategory);
106
107
  cl::SetVersionPrinter(PrintVersion);
108
  cl::ParseCommandLineOptions(
109
      argc, argv,
110
      "A tool to detect the presence of AMDGPU devices on the system. \n\n"
111
      "The tool will output each detected GPU architecture separated by a\n"
112
      "newline character. If multiple GPUs of the same architecture are found\n"
113
      "a string will be printed for each\n");
114
115
  if (Help) {
116
    cl::PrintHelpMessage();
117
    return 0;
118
  }
119
120
  // Attempt to load the HSA runtime.
121
  if (llvm::Error Err = loadHSA()) {
122
    logAllUnhandledErrors(std::move(Err), llvm::errs());
123
    return 1;
124
  }
125
126
  hsa_status_t Status = hsa_init();
127
  if (Status != HSA_STATUS_SUCCESS) {
128
    return 1;
129
  }
130
131
  std::vector<std::string> GPUs;
132
  Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs);
133
  if (Status != HSA_STATUS_SUCCESS) {
134
    return 1;
135
  }
136
137
  for (const auto &GPU : GPUs)
138
    printf("%s\n", GPU.c_str());
139
140
  if (GPUs.size() < 1)
141
    return 1;
142
143
  hsa_shut_down();
144
  return 0;
145
}