diff --git a/libc/startup/gpu/CMakeLists.txt b/libc/startup/gpu/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/startup/gpu/CMakeLists.txt @@ -0,0 +1,63 @@ +function(add_startup_object name) + cmake_parse_arguments( + "ADD_STARTUP_OBJECT" + "ALIAS" # Option argument + "SRC" # Single value arguments + "DEPENDS;COMPILE_OPTIONS" # Multi value arguments + ${ARGN} + ) + + get_fq_target_name(${name} fq_target_name) + if(ADD_STARTUP_OBJECT_ALIAS) + get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS}) + add_library(${fq_target_name} ALIAS ${fq_dep_list}) + return() + endif() + + add_object_library( + ${name} + SRCS ${ADD_STARTUP_OBJECT_SRC} + DEPENDS ${ADD_STARTUP_OBJECT_DEPENDS} + COMPILE_OPTIONS ${ADD_STARTUP_OBJECT_COMPILE_OPTIONS} + ) + set_target_properties( + ${fq_target_name} + PROPERTIES + OUTPUT_NAME ${name}.o + ) +endfunction() + +if(LIBC_GPU_TARGET_ARCHITECTURE_IS_AMDGPU) + add_subdirectory(amdgpu) + + add_startup_object( + crt1 + ALIAS + DEPENDS + .amdgpu.crt1 + ) +elseif(LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX) + add_subdirectory(nvptx) + + add_startup_object( + crt1 + ALIAS + DEPENDS + .nvptx.crt1 + ) +else() + # Skip building the startup code if there are no supported GPUs. + message(STATUS "Skipping startup for gpu target, no GPUs were detected") + return() +endif() + +add_custom_target(libc-startup) +set(startup_components crt1) +foreach(target IN LISTS startup_components) + set(fq_target_name libc.startup.gpu.${target}) + add_dependencies(libc-startup ${fq_target_name}) + install(FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + RENAME $ + COMPONENT libc) +endforeach() diff --git a/libc/startup/gpu/amdgpu/CMakeLists.txt b/libc/startup/gpu/amdgpu/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/startup/gpu/amdgpu/CMakeLists.txt @@ -0,0 +1,17 @@ +add_startup_object( + crt1 + SRC + start.cpp + COMPILE_OPTIONS + -ffreestanding # To avoid compiler warnings about calling the main function. + -fno-builtin + -nogpulib # Do not include any GPU vendor libraries. + -nostdinc + -mcpu=${LIBC_GPU_TARGET_ARCHITECTURE} + -emit-llvm # AMDGPU's intermediate object file format is bitcode. + --target=${LIBC_GPU_TARGET_TRIPLE} +) +get_fq_target_name(crt1 fq_name) + +# Ensure that clang uses the correct linker for this object type. +target_link_libraries(${fq_name} PUBLIC "--target=${LIBC_GPU_TARGET_TRIPLE}") diff --git a/libc/startup/gpu/amdgpu/start.cpp b/libc/startup/gpu/amdgpu/start.cpp new file mode 100644 --- /dev/null +++ b/libc/startup/gpu/amdgpu/start.cpp @@ -0,0 +1,14 @@ +//===-- Implementation of crt for amdgpu ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +extern "C" int main(int argc, char **argv); + +extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void +_start(int argc, char **argv, int *ret) { + __atomic_fetch_or(ret, main(argc, argv), __ATOMIC_RELAXED); +} diff --git a/libc/startup/gpu/nvptx/CMakeLists.txt b/libc/startup/gpu/nvptx/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/startup/gpu/nvptx/CMakeLists.txt @@ -0,0 +1,17 @@ +add_startup_object( + crt1 + SRC + start.cpp + COMPILE_OPTIONS + -ffreestanding # To avoid compiler warnings about calling the main function. + -fno-builtin + -nogpulib # Do not include any GPU vendor libraries. + -nostdinc + -x cuda # Use the CUDA toolchain to emit the `_start` kernel. + --offload-device-only + --offload-arch=${LIBC_GPU_TARGET_ARCHITECTURE} +) +get_fq_target_name(crt1 fq_name) + +# Ensure that clang uses the correct linker for this object type. +target_link_libraries(${fq_name} PUBLIC "--target=${LIBC_GPU_TARGET_TRIPLE}") diff --git a/libc/startup/gpu/nvptx/start.cpp b/libc/startup/gpu/nvptx/start.cpp new file mode 100644 --- /dev/null +++ b/libc/startup/gpu/nvptx/start.cpp @@ -0,0 +1,15 @@ +//===-- Implementation of crt for amdgpu ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +extern "C" __attribute__((device)) int main(int argc, char **argv); + +// TODO: We shouldn't need to use the CUDA language to emit a kernel for NVPTX. +extern "C" [[gnu::visibility("protected")]] __attribute__((global)) void +_start(int argc, char **argv, int *ret) { + __atomic_fetch_or(ret, main(argc, argv), __ATOMIC_RELAXED); +}