106c3fb27SDimitry Andric //===-- Wrapper for C standard stdio.h declarations on the GPU ------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #if !defined(_OPENMP) && !defined(__HIP__) && !defined(__CUDA__) 1006c3fb27SDimitry Andric #error "This file is for GPU offloading compilation only" 1106c3fb27SDimitry Andric #endif 1206c3fb27SDimitry Andric 1306c3fb27SDimitry Andric #include_next <stdio.h> 1406c3fb27SDimitry Andric 15*1db9f3b2SDimitry Andric // In some old versions of glibc, other standard headers sometimes define 16*1db9f3b2SDimitry Andric // special macros (e.g., __need_FILE) before including stdio.h to cause stdio.h 17*1db9f3b2SDimitry Andric // to produce special definitions. Future includes of stdio.h when those 18*1db9f3b2SDimitry Andric // special macros are undefined are expected to produce the normal definitions 19*1db9f3b2SDimitry Andric // from stdio.h. 20*1db9f3b2SDimitry Andric // 21*1db9f3b2SDimitry Andric // We do not apply our include guard (__CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__) 22*1db9f3b2SDimitry Andric // unconditionally to the above include_next. Otherwise, after an occurrence of 23*1db9f3b2SDimitry Andric // the first glibc stdio.h use case described above, the include_next would be 24*1db9f3b2SDimitry Andric // skipped for remaining includes of stdio.h, leaving required symbols 25*1db9f3b2SDimitry Andric // undefined. 26*1db9f3b2SDimitry Andric // 27*1db9f3b2SDimitry Andric // We make the following assumptions to handle all use cases: 28*1db9f3b2SDimitry Andric // 29*1db9f3b2SDimitry Andric // 1. If the above include_next produces special glibc definitions, then (a) it 30*1db9f3b2SDimitry Andric // does not produce the normal definitions that we must intercept below, (b) 31*1db9f3b2SDimitry Andric // the current file was included from a glibc header that already defined 32*1db9f3b2SDimitry Andric // __GLIBC__ (usually by including glibc's <features.h>), and (c) the above 33*1db9f3b2SDimitry Andric // include_next does not define _STDIO_H. In that case, we skip the rest of 34*1db9f3b2SDimitry Andric // the current file and don't guard against future includes. 35*1db9f3b2SDimitry Andric // 2. If the above include_next produces the normal stdio.h definitions, then 36*1db9f3b2SDimitry Andric // either (a) __GLIBC__ is not defined because C headers are from some other 37*1db9f3b2SDimitry Andric // libc implementation or (b) the above include_next defines _STDIO_H to 38*1db9f3b2SDimitry Andric // prevent the above include_next from having any effect in the future. 39*1db9f3b2SDimitry Andric #if !defined(__GLIBC__) || defined(_STDIO_H) 40*1db9f3b2SDimitry Andric 41*1db9f3b2SDimitry Andric #ifndef __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__ 42*1db9f3b2SDimitry Andric #define __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__ 43*1db9f3b2SDimitry Andric 4406c3fb27SDimitry Andric #if __has_include(<llvm-libc-decls/stdio.h>) 4506c3fb27SDimitry Andric 4606c3fb27SDimitry Andric #if defined(__HIP__) || defined(__CUDA__) 4706c3fb27SDimitry Andric #define __LIBC_ATTRS __attribute__((device)) 4806c3fb27SDimitry Andric #endif 4906c3fb27SDimitry Andric 505f757f3fSDimitry Andric // Some headers provide these as macros. Temporarily undefine them so they do 515f757f3fSDimitry Andric // not conflict with any definitions for the GPU. 525f757f3fSDimitry Andric 535f757f3fSDimitry Andric #pragma push_macro("stdout") 545f757f3fSDimitry Andric #pragma push_macro("stdin") 555f757f3fSDimitry Andric #pragma push_macro("stderr") 565f757f3fSDimitry Andric 575f757f3fSDimitry Andric #undef stdout 585f757f3fSDimitry Andric #undef stderr 595f757f3fSDimitry Andric #undef stdin 605f757f3fSDimitry Andric 6106c3fb27SDimitry Andric #pragma omp begin declare target 6206c3fb27SDimitry Andric 6306c3fb27SDimitry Andric #include <llvm-libc-decls/stdio.h> 6406c3fb27SDimitry Andric 6506c3fb27SDimitry Andric #pragma omp end declare target 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric #undef __LIBC_ATTRS 6806c3fb27SDimitry Andric 695f757f3fSDimitry Andric // Restore the original macros when compiling on the host. 705f757f3fSDimitry Andric #if !defined(__NVPTX__) && !defined(__AMDGPU__) 715f757f3fSDimitry Andric #pragma pop_macro("stdout") 725f757f3fSDimitry Andric #pragma pop_macro("stderr") 735f757f3fSDimitry Andric #pragma pop_macro("stdin") 745f757f3fSDimitry Andric #endif 755f757f3fSDimitry Andric 7606c3fb27SDimitry Andric #endif 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric #endif // __CLANG_LLVM_LIBC_WRAPPERS_STDIO_H__ 79*1db9f3b2SDimitry Andric 80*1db9f3b2SDimitry Andric #endif 81