Skip to content

Commit 7fe3564

Browse files
authored
[Clang] Gut the libc wrapper headers and simplify (#168438)
Summary: These were originally intended to represent the functions that are present on the GPU as to be provided by the LLVM libc implementation. The original plan was that LLVM libc would report which functions were supported and then the offload interface would mark those as supported. The problem is that these wrapper headers are very difficult to make work given the various libc extensions everyone does so they were extremely fragile. OpenMP already declares all functions used inside of a target region as implicitly host / device, while these headers weren't even used for CUDA / HIP yet anyway. The only things we need to define right now are the stdio FILE types. If we want to make this work for CUDA we'd need to define these manually, but we're a ways off and that's way easier because they do proper overloading.
1 parent a2ddb02 commit 7fe3564

File tree

12 files changed

+31
-351
lines changed

12 files changed

+31
-351
lines changed

clang/lib/Headers/llvm_libc_wrappers/assert.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919

2020
#if defined(__HIP__) || defined(__CUDA__)
2121
#define __LIBC_ATTRS __attribute__((device))
22+
#else
23+
#define __LIBC_ATTRS
2224
#endif
2325

24-
#pragma omp begin declare target
25-
26-
#include <llvm-libc-decls/assert.h>
27-
28-
#pragma omp end declare target
26+
// TODO: Define these for CUDA / HIP.
2927

3028
#undef __LIBC_ATTRS
3129

clang/lib/Headers/llvm_libc_wrappers/ctype.h

Lines changed: 3 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -13,128 +13,16 @@
1313
#error "This file is for GPU offloading compilation only"
1414
#endif
1515

16-
// The GNU headers like to define 'toupper' and 'tolower' redundantly. This is
17-
// necessary to prevent it from doing that and remapping our implementation.
18-
#if (defined(__NVPTX__) || defined(__AMDGPU__)) && defined(__GLIBC__)
19-
#pragma push_macro("__USE_EXTERN_INLINES")
20-
#undef __USE_EXTERN_INLINES
21-
#endif
22-
2316
#include_next <ctype.h>
2417

25-
#if (defined(__NVPTX__) || defined(__AMDGPU__)) && defined(__GLIBC__)
26-
#pragma pop_macro("__USE_EXTERN_INLINES")
27-
#endif
28-
29-
#if __has_include(<llvm-libc-decls/ctype.h>)
30-
3118
#if defined(__HIP__) || defined(__CUDA__)
3219
#define __LIBC_ATTRS __attribute__((device))
20+
#else
21+
#define __LIBC_ATTRS
3322
#endif
3423

35-
// The GNU headers like to provide these as macros, we need to undefine them so
36-
// they do not conflict with the following definitions for the GPU.
37-
38-
#pragma push_macro("isalnum")
39-
#pragma push_macro("isalpha")
40-
#pragma push_macro("isascii")
41-
#pragma push_macro("isblank")
42-
#pragma push_macro("iscntrl")
43-
#pragma push_macro("isdigit")
44-
#pragma push_macro("isgraph")
45-
#pragma push_macro("islower")
46-
#pragma push_macro("isprint")
47-
#pragma push_macro("ispunct")
48-
#pragma push_macro("isspace")
49-
#pragma push_macro("isupper")
50-
#pragma push_macro("isxdigit")
51-
#pragma push_macro("toascii")
52-
#pragma push_macro("tolower")
53-
#pragma push_macro("toupper")
54-
#pragma push_macro("isalnum_l")
55-
#pragma push_macro("isalpha_l")
56-
#pragma push_macro("isascii_l")
57-
#pragma push_macro("isblank_l")
58-
#pragma push_macro("iscntrl_l")
59-
#pragma push_macro("isdigit_l")
60-
#pragma push_macro("isgraph_l")
61-
#pragma push_macro("islower_l")
62-
#pragma push_macro("isprint_l")
63-
#pragma push_macro("ispunct_l")
64-
#pragma push_macro("isspace_l")
65-
#pragma push_macro("isupper_l")
66-
#pragma push_macro("isxdigit_l")
67-
68-
#undef isalnum
69-
#undef isalpha
70-
#undef isascii
71-
#undef iscntrl
72-
#undef isdigit
73-
#undef islower
74-
#undef isgraph
75-
#undef isprint
76-
#undef ispunct
77-
#undef isspace
78-
#undef isupper
79-
#undef isblank
80-
#undef isxdigit
81-
#undef toascii
82-
#undef tolower
83-
#undef toupper
84-
#undef isalnum_l
85-
#undef isalpha_l
86-
#undef iscntrl_l
87-
#undef isdigit_l
88-
#undef islower_l
89-
#undef isgraph_l
90-
#undef isprint_l
91-
#undef ispunct_l
92-
#undef isspace_l
93-
#undef isupper_l
94-
#undef isblank_l
95-
#undef isxdigit_l
96-
97-
#pragma omp begin declare target
98-
99-
#include <llvm-libc-decls/ctype.h>
100-
101-
#pragma omp end declare target
102-
103-
// Restore the original macros when compiling on the host.
104-
#if !defined(__NVPTX__) && !defined(__AMDGPU__)
105-
#pragma pop_macro("isalnum")
106-
#pragma pop_macro("isalpha")
107-
#pragma pop_macro("isascii")
108-
#pragma pop_macro("isblank")
109-
#pragma pop_macro("iscntrl")
110-
#pragma pop_macro("isdigit")
111-
#pragma pop_macro("isgraph")
112-
#pragma pop_macro("islower")
113-
#pragma pop_macro("isprint")
114-
#pragma pop_macro("ispunct")
115-
#pragma pop_macro("isspace")
116-
#pragma pop_macro("isupper")
117-
#pragma pop_macro("isxdigit")
118-
#pragma pop_macro("toascii")
119-
#pragma pop_macro("tolower")
120-
#pragma pop_macro("toupper")
121-
#pragma pop_macro("isalnum_l")
122-
#pragma pop_macro("isalpha_l")
123-
#pragma pop_macro("isascii_l")
124-
#pragma pop_macro("isblank_l")
125-
#pragma pop_macro("iscntrl_l")
126-
#pragma pop_macro("isdigit_l")
127-
#pragma pop_macro("isgraph_l")
128-
#pragma pop_macro("islower_l")
129-
#pragma pop_macro("isprint_l")
130-
#pragma pop_macro("ispunct_l")
131-
#pragma pop_macro("isspace_l")
132-
#pragma pop_macro("isupper_l")
133-
#pragma pop_macro("isxdigit_l")
134-
#endif
24+
// TODO: Define these for CUDA / HIP.
13525

13626
#undef __LIBC_ATTRS
13727

138-
#endif
139-
14028
#endif // __CLANG_LLVM_LIBC_WRAPPERS_CTYPE_H__

clang/lib/Headers/llvm_libc_wrappers/inttypes.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919

2020
#if defined(__HIP__) || defined(__CUDA__)
2121
#define __LIBC_ATTRS __attribute__((device))
22+
#else
23+
#define __LIBC_ATTRS
2224
#endif
2325

24-
#pragma omp begin declare target
25-
26-
#include <llvm-libc-decls/inttypes.h>
27-
28-
#pragma omp end declare target
26+
// TODO: Define these for CUDA / HIP.
2927

3028
#undef __LIBC_ATTRS
3129

clang/lib/Headers/llvm_libc_wrappers/llvm-libc-decls/README.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.

clang/lib/Headers/llvm_libc_wrappers/stdio.h

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,19 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#ifndef __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__
10+
#define __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__
11+
912
#if !defined(_OPENMP) && !defined(__HIP__) && !defined(__CUDA__)
1013
#error "This file is for GPU offloading compilation only"
1114
#endif
1215

1316
#include_next <stdio.h>
1417

15-
// In some old versions of glibc, other standard headers sometimes define
16-
// special macros (e.g., __need_FILE) before including stdio.h to cause stdio.h
17-
// to produce special definitions. Future includes of stdio.h when those
18-
// special macros are undefined are expected to produce the normal definitions
19-
// from stdio.h.
20-
//
21-
// We do not apply our include guard (__CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__)
22-
// unconditionally to the above include_next. Otherwise, after an occurrence of
23-
// the first glibc stdio.h use case described above, the include_next would be
24-
// skipped for remaining includes of stdio.h, leaving required symbols
25-
// undefined.
26-
//
27-
// We make the following assumptions to handle all use cases:
28-
//
29-
// 1. If the above include_next produces special glibc definitions, then (a) it
30-
// does not produce the normal definitions that we must intercept below, (b)
31-
// the current file was included from a glibc header that already defined
32-
// __GLIBC__ (usually by including glibc's <features.h>), and (c) the above
33-
// include_next does not define _STDIO_H. In that case, we skip the rest of
34-
// the current file and don't guard against future includes.
35-
// 2. If the above include_next produces the normal stdio.h definitions, then
36-
// either (a) __GLIBC__ is not defined because C headers are from some other
37-
// libc implementation or (b) the above include_next defines _STDIO_H to
38-
// prevent the above include_next from having any effect in the future.
39-
#if !defined(__GLIBC__) || defined(_STDIO_H)
40-
41-
#ifndef __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__
42-
#define __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__
43-
44-
#if __has_include(<llvm-libc-decls/stdio.h>)
45-
4618
#if defined(__HIP__) || defined(__CUDA__)
4719
#define __LIBC_ATTRS __attribute__((device))
20+
#else
21+
#define __LIBC_ATTRS
4822
#endif
4923

5024
// Some headers provide these as macros. Temporarily undefine them so they do
@@ -60,21 +34,19 @@
6034

6135
#pragma omp begin declare target
6236

63-
#include <llvm-libc-decls/stdio.h>
37+
__LIBC_ATTRS extern FILE *stderr;
38+
__LIBC_ATTRS extern FILE *stdin;
39+
__LIBC_ATTRS extern FILE *stdout;
6440

6541
#pragma omp end declare target
6642

67-
#undef __LIBC_ATTRS
68-
6943
// Restore the original macros when compiling on the host.
7044
#if !defined(__NVPTX__) && !defined(__AMDGPU__)
71-
#pragma pop_macro("stdout")
7245
#pragma pop_macro("stderr")
7346
#pragma pop_macro("stdin")
47+
#pragma pop_macro("stdout")
7448
#endif
7549

76-
#endif
50+
#undef __LIBC_ATTRS
7751

7852
#endif // __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__
79-
80-
#endif

clang/lib/Headers/llvm_libc_wrappers/stdlib.h

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,18 @@
1515

1616
#include_next <stdlib.h>
1717

18-
#if __has_include(<llvm-libc-decls/stdlib.h>)
19-
2018
#if defined(__HIP__) || defined(__CUDA__)
2119
#define __LIBC_ATTRS __attribute__((device))
20+
#else
21+
#define __LIBC_ATTRS
2222
#endif
2323

2424
#pragma omp begin declare target
2525

26-
// The LLVM C library uses these named types so we forward declare them.
27-
typedef void (*__atexithandler_t)(void);
28-
typedef int (*__search_compare_t)(const void *, const void *);
29-
typedef int (*__qsortcompare_t)(const void *, const void *);
30-
typedef int (*__qsortrcompare_t)(const void *, const void *, void *);
31-
32-
// Enforce ABI compatibility with the structs used by the LLVM C library.
33-
_Static_assert(__builtin_offsetof(div_t, quot) == 0, "ABI mismatch!");
34-
_Static_assert(__builtin_offsetof(ldiv_t, quot) == 0, "ABI mismatch!");
35-
_Static_assert(__builtin_offsetof(lldiv_t, quot) == 0, "ABI mismatch!");
36-
37-
#if defined(__GLIBC__) && __cplusplus >= 201103L
38-
#define at_quick_exit atexit
39-
#endif
40-
41-
#include <llvm-libc-decls/stdlib.h>
42-
43-
#if defined(__GLIBC__) && __cplusplus >= 201103L
44-
#undef at_quick_exit
45-
#endif
26+
// TODO: Define these for CUDA / HIP.
4627

4728
#pragma omp end declare target
4829

4930
#undef __LIBC_ATTRS
5031

51-
#endif
52-
5332
#endif // __CLANG_LLVM_LIBC_WRAPPERS_STDLIB_H__

clang/lib/Headers/llvm_libc_wrappers/string.h

Lines changed: 2 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -15,82 +15,14 @@
1515

1616
#include_next <string.h>
1717

18-
#if __has_include(<llvm-libc-decls/string.h>)
19-
2018
#if defined(__HIP__) || defined(__CUDA__)
2119
#define __LIBC_ATTRS __attribute__((device))
22-
#endif
23-
24-
#pragma omp begin declare target
25-
26-
// The GNU headers provide C++ standard compliant headers when in C++ mode and
27-
// the LLVM libc does not. We need to manually provide the definitions using the
28-
// same prototypes.
29-
#if defined(__cplusplus) && defined(__GLIBC__) && \
30-
defined(__CORRECT_ISO_CPP_STRING_H_PROTO)
31-
32-
#ifndef __LIBC_ATTRS
33-
#define __LIBC_ATTRS
34-
#endif
35-
36-
extern "C" {
37-
void *memccpy(void *__restrict, const void *__restrict, int,
38-
size_t) __LIBC_ATTRS;
39-
int memcmp(const void *, const void *, size_t) __LIBC_ATTRS;
40-
void *memcpy(void *__restrict, const void *__restrict, size_t) __LIBC_ATTRS;
41-
void *memmem(const void *, size_t, const void *, size_t) __LIBC_ATTRS;
42-
void *memmove(void *, const void *, size_t) __LIBC_ATTRS;
43-
void *mempcpy(void *__restrict, const void *__restrict, size_t) __LIBC_ATTRS;
44-
void *memset(void *, int, size_t) __LIBC_ATTRS;
45-
char *stpcpy(char *__restrict, const char *__restrict) __LIBC_ATTRS;
46-
char *stpncpy(char *__restrict, const char *__restrict, size_t) __LIBC_ATTRS;
47-
char *strcat(char *__restrict, const char *__restrict) __LIBC_ATTRS;
48-
int strcmp(const char *, const char *) __LIBC_ATTRS;
49-
int strcoll(const char *, const char *) __LIBC_ATTRS;
50-
char *strcpy(char *__restrict, const char *__restrict) __LIBC_ATTRS;
51-
size_t strcspn(const char *, const char *) __LIBC_ATTRS;
52-
char *strdup(const char *) __LIBC_ATTRS;
53-
size_t strlen(const char *) __LIBC_ATTRS;
54-
char *strncat(char *__restrict, const char *__restrict, size_t) __LIBC_ATTRS;
55-
int strncmp(const char *, const char *, size_t) __LIBC_ATTRS;
56-
char *strncpy(char *__restrict, const char *__restrict, size_t) __LIBC_ATTRS;
57-
char *strndup(const char *, size_t) __LIBC_ATTRS;
58-
size_t strnlen(const char *, size_t) __LIBC_ATTRS;
59-
size_t strspn(const char *, const char *) __LIBC_ATTRS;
60-
char *strtok(char *__restrict, const char *__restrict) __LIBC_ATTRS;
61-
char *strtok_r(char *__restrict, const char *__restrict,
62-
char **__restrict) __LIBC_ATTRS;
63-
size_t strxfrm(char *__restrict, const char *__restrict, size_t) __LIBC_ATTRS;
64-
}
65-
66-
extern "C++" {
67-
char *strstr(char *, const char *) noexcept __LIBC_ATTRS;
68-
const char *strstr(const char *, const char *) noexcept __LIBC_ATTRS;
69-
char *strpbrk(char *, const char *) noexcept __LIBC_ATTRS;
70-
const char *strpbrk(const char *, const char *) noexcept __LIBC_ATTRS;
71-
char *strrchr(char *, int) noexcept __LIBC_ATTRS;
72-
const char *strrchr(const char *, int) noexcept __LIBC_ATTRS;
73-
char *strchr(char *, int) noexcept __LIBC_ATTRS;
74-
const char *strchr(const char *, int) noexcept __LIBC_ATTRS;
75-
char *strchrnul(char *, int) noexcept __LIBC_ATTRS;
76-
const char *strchrnul(const char *, int) noexcept __LIBC_ATTRS;
77-
char *strcasestr(char *, const char *) noexcept __LIBC_ATTRS;
78-
const char *strcasestr(const char *, const char *) noexcept __LIBC_ATTRS;
79-
void *memrchr(void *__s, int __c, size_t __n) noexcept __LIBC_ATTRS;
80-
const void *memrchr(const void *__s, int __c, size_t __n) noexcept __LIBC_ATTRS;
81-
void *memchr(void *__s, int __c, size_t __n) noexcept __LIBC_ATTRS;
82-
const void *memchr(const void *__s, int __c, size_t __n) noexcept __LIBC_ATTRS;
83-
}
84-
8520
#else
86-
#include <llvm-libc-decls/string.h>
87-
21+
#define __LIBC_ATTRS
8822
#endif
8923

90-
#pragma omp end declare target
24+
// TODO: Define these for CUDA / HIP.
9125

9226
#undef __LIBC_ATTRS
9327

94-
#endif
95-
9628
#endif // __CLANG_LLVM_LIBC_WRAPPERS_STRING_H__

0 commit comments

Comments
 (0)