|
25 | 25 | #include "clang/Frontend/Utils.h"
|
26 | 26 | #include "clang/FrontendTool/Utils.h"
|
27 | 27 | #include "llvm/ADT/Statistic.h"
|
| 28 | +#include "llvm/Config/config.h" |
28 | 29 | #include "llvm/LinkAllPasses.h"
|
29 | 30 | #include "llvm/Option/ArgList.h"
|
30 | 31 | #include "llvm/Option/OptTable.h"
|
| 32 | +#include "llvm/Support/Compiler.h" |
31 | 33 | #include "llvm/Support/ErrorHandling.h"
|
32 | 34 | #include "llvm/Support/ManagedStatic.h"
|
33 | 35 | #include "llvm/Support/Signals.h"
|
34 | 36 | #include "llvm/Support/TargetSelect.h"
|
35 | 37 | #include "llvm/Support/Timer.h"
|
36 | 38 | #include "llvm/Support/raw_ostream.h"
|
37 | 39 | #include <cstdio>
|
| 40 | +#if HAVE_SYS_RESOURCE_H |
| 41 | +#include <sys/resource.h> |
| 42 | +#endif |
38 | 43 | using namespace clang;
|
39 | 44 | using namespace llvm::opt;
|
40 | 45 |
|
@@ -64,7 +69,67 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
|
64 | 69 | }
|
65 | 70 | #endif
|
66 | 71 |
|
| 72 | +#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT |
| 73 | +// The amount of stack we think is "sufficient". If less than this much is |
| 74 | +// available, we may be unable to reach our template instantiation depth |
| 75 | +// limit and other similar limits. |
| 76 | +// FIXME: Unify this with the stack we request when spawning a thread to build |
| 77 | +// a module. |
| 78 | +static const int kSufficientStack = 8 << 20; |
| 79 | + |
| 80 | +#if defined(__linux__) && defined(__PIE__) |
| 81 | +LLVM_ATTRIBUTE_NOINLINE |
| 82 | +static void ensureStackAddressSpace() { |
| 83 | + // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary |
| 84 | + // relatively close to the stack (they are only guaranteed to be 128MiB |
| 85 | + // apart). This results in crashes if we happen to heap-allocate more than |
| 86 | + // 128MiB before we reach our stack high-water mark. |
| 87 | + // |
| 88 | + // To avoid these crashes, ensure that we have sufficient virtual memory |
| 89 | + // pages allocated before we start running by touching an early page. (We |
| 90 | + // allow 512KiB for kernel/libc-provided data such as command-line arguments |
| 91 | + // and environment variables, and for main and cc1_main) |
| 92 | + volatile char ReservedStack[kSufficientStack - 512 * 1024]; |
| 93 | + volatile int N = 0; |
| 94 | + (void)+ReservedStack[N]; |
| 95 | +} |
| 96 | +#else |
| 97 | +static void ensureStackAddressSpace() {} |
| 98 | +#endif |
| 99 | + |
| 100 | +/// Attempt to ensure that we have at least 8MiB of usable stack space. |
| 101 | +static void ensureSufficientStack() { |
| 102 | + struct rlimit rlim; |
| 103 | + if (getrlimit(RLIMIT_STACK, &rlim) != 0) |
| 104 | + return; |
| 105 | + |
| 106 | + // Increase the soft stack limit to our desired level, if necessary and |
| 107 | + // possible. |
| 108 | + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) { |
| 109 | + // Try to allocate sufficient stack. |
| 110 | + if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack) |
| 111 | + rlim.rlim_cur = kSufficientStack; |
| 112 | + else if (rlim.rlim_cur == rlim.rlim_max) |
| 113 | + return; |
| 114 | + else |
| 115 | + rlim.rlim_cur = rlim.rlim_max; |
| 116 | + |
| 117 | + if (setrlimit(RLIMIT_STACK, &rlim) != 0 || |
| 118 | + rlim.rlim_cur != kSufficientStack) |
| 119 | + return; |
| 120 | + } |
| 121 | + |
| 122 | + // We should now have a stack of size at least kSufficientStack. Ensure |
| 123 | + // that we can actually use that much, if necessary. |
| 124 | + ensureStackAddressSpace(); |
| 125 | +} |
| 126 | +#else |
| 127 | +static void ensureSufficientStack() { |
| 128 | +#endif |
| 129 | + |
67 | 130 | int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
|
| 131 | + ensureSufficientStack(); |
| 132 | + |
68 | 133 | std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
|
69 | 134 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
70 | 135 |
|
|
0 commit comments