brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.2 KiB · ce8f5bb Raw
82 lines · cpp
1//===-- Implementation of crt for nvptx -----------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "config/gpu/app.h"10#include "src/__support/GPU/utils.h"11#include "src/__support/RPC/rpc_client.h"12#include "src/__support/macros/config.h"13#include "src/stdlib/atexit.h"14#include "src/stdlib/exit.h"15 16extern "C" int main(int argc, char **argv, char **envp);17extern "C" void __cxa_finalize(void *dso);18 19namespace LIBC_NAMESPACE_DECL {20 21DataEnvironment app;22 23// FIXME: Factor this out into common logic so we don't need to stub it here.24void teardown_main_tls() {}25 26// FIXME: Touch this symbol to force this to be linked in statically.27volatile void *dummy = &LIBC_NAMESPACE::rpc::client;28 29extern "C" {30// Nvidia's 'nvlink' linker does not provide these symbols. We instead need31// to manually create them and update the globals in the loader implememtation.32uintptr_t *__init_array_start [[gnu::visibility("protected")]];33uintptr_t *__init_array_end [[gnu::visibility("protected")]];34uintptr_t *__fini_array_start [[gnu::visibility("protected")]];35uintptr_t *__fini_array_end [[gnu::visibility("protected")]];36}37 38// Nvidia requires that the signature of the function pointers match. This means39// we cannot support the extended constructor arguments.40using InitCallback = void(void);41using FiniCallback = void(void);42 43static void call_init_array_callbacks(int, char **, char **) {44  size_t init_array_size = __init_array_end - __init_array_start;45  for (size_t i = 0; i < init_array_size; ++i)46    reinterpret_cast<InitCallback *>(__init_array_start[i])();47}48 49static void call_fini_array_callbacks() {50  size_t fini_array_size = __fini_array_end - __fini_array_start;51  for (size_t i = fini_array_size; i > 0; --i)52    reinterpret_cast<FiniCallback *>(__fini_array_start[i - 1])();53}54 55} // namespace LIBC_NAMESPACE_DECL56 57extern "C" [[gnu::visibility("protected"), clang::nvptx_kernel]] void58_begin(int argc, char **argv, char **env) {59  __atomic_store_n(&LIBC_NAMESPACE::app.env_ptr,60                   reinterpret_cast<uintptr_t *>(env), __ATOMIC_RELAXED);61 62  // We want the fini array callbacks to be run after other atexit63  // callbacks are run. So, we register them before running the init64  // array callbacks as they can potentially register their own atexit65  // callbacks.66  LIBC_NAMESPACE::atexit(&LIBC_NAMESPACE::call_fini_array_callbacks);67  LIBC_NAMESPACE::call_init_array_callbacks(argc, argv, env);68}69 70extern "C" [[gnu::visibility("protected"), clang::nvptx_kernel]] void71_start(int argc, char **argv, char **envp, int *ret) {72  // Invoke the 'main' function with every active thread that the user launched73  // the _start kernel with.74  __atomic_fetch_or(ret, main(argc, argv, envp), __ATOMIC_RELAXED);75}76 77extern "C" [[gnu::visibility("protected"), clang::nvptx_kernel]] void _end() {78  // Only a single thread should call the destructors registred with 'atexit'.79  // The loader utility will handle the actual exit and return code cleanly.80  __cxa_finalize(nullptr);81}82