142 lines · cpp
1//===-- InitLLVM.cpp -----------------------------------------------------===//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 "llvm/Support/InitLLVM.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/Support/AutoConvert.h"12#include "llvm/Support/Error.h"13#include "llvm/Support/ErrorHandling.h"14#include "llvm/Support/ManagedStatic.h"15#include "llvm/Support/Signals.h"16 17#ifdef _WIN3218#include "llvm/Support/Windows/WindowsSupport.h"19#endif20 21#if defined(HAVE_UNISTD_H)22#include <unistd.h>23#else24#ifndef STDIN_FILENO25#define STDIN_FILENO 026#endif27#ifndef STDOUT_FILENO28#define STDOUT_FILENO 129#endif30#ifndef STDERR_FILENO31#define STDERR_FILENO 232#endif33#endif34 35static void RaiseLimits() {36#ifdef _AIX37 // AIX has restrictive memory soft-limits out-of-box, so raise them if needed.38 auto RaiseLimit = [](int resource) {39 struct rlimit r;40 getrlimit(resource, &r);41 42 // Increase the soft limit to the hard limit, if necessary and43 // possible.44 if (r.rlim_cur != RLIM_INFINITY && r.rlim_cur != r.rlim_max) {45 r.rlim_cur = r.rlim_max;46 setrlimit(resource, &r);47 }48 };49 50 // Address space size.51 RaiseLimit(RLIMIT_AS);52 // Heap size.53 RaiseLimit(RLIMIT_DATA);54 // Stack size.55 RaiseLimit(RLIMIT_STACK);56#ifdef RLIMIT_RSS57 // Resident set size.58 RaiseLimit(RLIMIT_RSS);59#endif60#endif61}62 63void CleanupStdHandles(void *Cookie) {64 llvm::raw_ostream *Outs = &llvm::outs(), *Errs = &llvm::errs();65 Outs->flush();66 Errs->flush();67 llvm::restoreStdHandleAutoConversion(STDIN_FILENO);68 llvm::restoreStdHandleAutoConversion(STDOUT_FILENO);69 llvm::restoreStdHandleAutoConversion(STDERR_FILENO);70}71 72using namespace llvm;73using namespace llvm::sys;74 75InitLLVM::InitLLVM(int &Argc, const char **&Argv,76 bool InstallPipeSignalExitHandler) {77#ifndef NDEBUG78 static std::atomic<bool> Initialized{false};79 assert(!Initialized && "InitLLVM was already initialized!");80 Initialized = true;81#endif82 83 // Bring stdin/stdout/stderr into a known state.84 sys::AddSignalHandler(CleanupStdHandles, nullptr);85 86 if (InstallPipeSignalExitHandler)87 // The pipe signal handler must be installed before any other handlers are88 // registered. This is because the Unix \ref RegisterHandlers function does89 // not perform a sigaction() for SIGPIPE unless a one-shot handler is90 // present, to allow long-lived processes (like lldb) to fully opt-out of91 // llvm's SIGPIPE handling and ignore the signal safely.92 sys::SetOneShotPipeSignalFunction(sys::DefaultOneShotPipeSignalHandler);93 // Initialize the stack printer after installing the one-shot pipe signal94 // handler, so we can perform a sigaction() for SIGPIPE on Unix if requested.95 StackPrinter.emplace(Argc, Argv);96 sys::PrintStackTraceOnErrorSignal(Argv[0]);97 install_out_of_memory_new_handler();98 RaiseLimits();99 100#ifdef __MVS__101 102 // We use UTF-8 as the internal character encoding. On z/OS, all external103 // output is encoded in EBCDIC. In order to be able to read all104 // error messages, we turn conversion to EBCDIC on for stderr fd.105 std::string Banner = std::string(Argv[0]) + ": ";106 ExitOnError ExitOnErr(Banner);107 108 // If turning on conversion for stderr fails then the error message109 // may be garbled. There is no solution to this problem.110 ExitOnErr(errorCodeToError(llvm::enableAutoConversion(STDERR_FILENO)));111 ExitOnErr(errorCodeToError(llvm::enableAutoConversion(STDOUT_FILENO)));112#endif113 114#ifdef _WIN32115 // We use UTF-8 as the internal character encoding. On Windows,116 // arguments passed to main() may not be encoded in UTF-8. In order117 // to reliably detect encoding of command line arguments, we use an118 // Windows API to obtain arguments, convert them to UTF-8, and then119 // write them back to the Argv vector.120 //121 // There's probably other way to do the same thing (e.g. using122 // wmain() instead of main()), but this way seems less intrusive123 // than that.124 std::string Banner = std::string(Argv[0]) + ": ";125 ExitOnError ExitOnErr(Banner);126 127 ExitOnErr(errorCodeToError(windows::GetCommandLineArguments(Args, Alloc)));128 129 // GetCommandLineArguments doesn't terminate the vector with a130 // nullptr. Do it to make it compatible with the real argv.131 Args.push_back(nullptr);132 133 Argc = Args.size() - 1;134 Argv = Args.data();135#endif136}137 138InitLLVM::~InitLLVM() {139 CleanupStdHandles(nullptr);140 llvm_shutdown();141}142