Coverage Report

Created: 2023-05-31 04:38

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/nvptx-arch/NVPTXArch.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- NVPTXArch.cpp - list installed NVPTX devies ------*- 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 CUDA gpus installed in the
10
// system.
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 <cstdint>
19
#include <cstdio>
20
#include <memory>
21
22
using namespace llvm;
23
24
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
25
26
0
static void PrintVersion(raw_ostream &OS) {
27
0
  OS << clang::getClangToolFullVersion("nvptx-arch") << '\n';
28
0
}
29
// Mark all our options with this category, everything else (except for -version
30
// and -help) will be hidden.
31
static cl::OptionCategory NVPTXArchCategory("nvptx-arch options");
32
33
typedef enum cudaError_enum {
34
  CUDA_SUCCESS = 0,
35
  CUDA_ERROR_NO_DEVICE = 100,
36
} CUresult;
37
38
typedef enum CUdevice_attribute_enum {
39
  CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR = 75,
40
  CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR = 76,
41
} CUdevice_attribute;
42
43
typedef uint32_t CUdevice;
44
45
CUresult (*cuInit)(unsigned int);
46
CUresult (*cuDeviceGetCount)(int *);
47
CUresult (*cuGetErrorString)(CUresult, const char **);
48
CUresult (*cuDeviceGet)(CUdevice *, int);
49
CUresult (*cuDeviceGetAttribute)(int *, CUdevice_attribute, CUdevice);
50
51
constexpr const char *DynamicCudaPath = "libcuda.so.1";
52
53
0
llvm::Error loadCUDA() {
54
0
  std::string ErrMsg;
55
0
  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
56
0
      llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicCudaPath, &ErrMsg));
57
0
  if (!DynlibHandle->isValid()) {
58
0
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
59
0
                                   "Failed to 'dlopen' %s", DynamicCudaPath);
60
0
  }
61
0
#define DYNAMIC_INIT(SYMBOL)                                                   \
62
0
  {                                                                            \
63
0
    void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
64
0
    if (!SymbolPtr)                                                            \
65
0
      return llvm::createStringError(llvm::inconvertibleErrorCode(),           \
66
0
                                     "Failed to 'dlsym' " #SYMBOL);            \
67
0
    SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
68
0
  }
69
0
  DYNAMIC_INIT(cuInit);
70
0
  DYNAMIC_INIT(cuDeviceGetCount);
71
0
  DYNAMIC_INIT(cuGetErrorString);
72
0
  DYNAMIC_INIT(cuDeviceGet);
73
0
  DYNAMIC_INIT(cuDeviceGetAttribute);
74
0
#undef DYNAMIC_INIT
75
0
  return llvm::Error::success();
76
0
}
77
78
0
static int handleError(CUresult Err) {
79
0
  const char *ErrStr = nullptr;
80
0
  CUresult Result = cuGetErrorString(Err, &ErrStr);
81
0
  if (Result != CUDA_SUCCESS)
82
0
    return 1;
83
0
  fprintf(stderr, "CUDA error: %s\n", ErrStr);
84
0
  return 1;
85
0
}
86
87
int main(int argc, char *argv[]) {
88
  cl::HideUnrelatedOptions(NVPTXArchCategory);
89
90
  cl::SetVersionPrinter(PrintVersion);
91
  cl::ParseCommandLineOptions(
92
      argc, argv,
93
      "A tool to detect the presence of NVIDIA devices on the system. \n\n"
94
      "The tool will output each detected GPU architecture separated by a\n"
95
      "newline character. If multiple GPUs of the same architecture are found\n"
96
      "a string will be printed for each\n");
97
98
  if (Help) {
99
    cl::PrintHelpMessage();
100
    return 0;
101
  }
102
103
  // Attempt to load the NVPTX driver runtime.
104
  if (llvm::Error Err = loadCUDA()) {
105
    logAllUnhandledErrors(std::move(Err), llvm::errs());
106
    return 1;
107
  }
108
109
  if (CUresult Err = cuInit(0)) {
110
    if (Err == CUDA_ERROR_NO_DEVICE)
111
      return 0;
112
    else
113
      return handleError(Err);
114
  }
115
116
  int Count = 0;
117
  if (CUresult Err = cuDeviceGetCount(&Count))
118
    return handleError(Err);
119
  if (Count == 0)
120
    return 0;
121
  for (int DeviceId = 0; DeviceId < Count; ++DeviceId) {
122
    CUdevice Device;
123
    if (CUresult Err = cuDeviceGet(&Device, DeviceId))
124
      return handleError(Err);
125
126
    int32_t Major, Minor;
127
    if (CUresult Err = cuDeviceGetAttribute(
128
            &Major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, Device))
129
      return handleError(Err);
130
    if (CUresult Err = cuDeviceGetAttribute(
131
            &Minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, Device))
132
      return handleError(Err);
133
134
    printf("sm_%d%d\n", Major, Minor);
135
  }
136
  return 0;
137
}