1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #include "clang/Basic/Stack.h" |
16 | #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" |
17 | #include "clang/Config/config.h" |
18 | #include "clang/Driver/DriverDiagnostic.h" |
19 | #include "clang/Driver/Options.h" |
20 | #include "clang/Frontend/CompilerInstance.h" |
21 | #include "clang/Frontend/CompilerInvocation.h" |
22 | #include "clang/Frontend/FrontendDiagnostic.h" |
23 | #include "clang/Frontend/TextDiagnosticBuffer.h" |
24 | #include "clang/Frontend/TextDiagnosticPrinter.h" |
25 | #include "clang/Frontend/Utils.h" |
26 | #include "clang/FrontendTool/Utils.h" |
27 | #include "llvm/ADT/Statistic.h" |
28 | #include "llvm/Config/llvm-config.h" |
29 | #include "llvm/LinkAllPasses.h" |
30 | #include "llvm/Option/Arg.h" |
31 | #include "llvm/Option/ArgList.h" |
32 | #include "llvm/Option/OptTable.h" |
33 | #include "llvm/Support/BuryPointer.h" |
34 | #include "llvm/Support/Compiler.h" |
35 | #include "llvm/Support/ErrorHandling.h" |
36 | #include "llvm/Support/ManagedStatic.h" |
37 | #include "llvm/Support/Signals.h" |
38 | #include "llvm/Support/TargetSelect.h" |
39 | #include "llvm/Support/Timer.h" |
40 | #include "llvm/Support/raw_ostream.h" |
41 | #include <cstdio> |
42 | |
43 | #ifdef CLANG_HAVE_RLIMITS |
44 | #include <sys/resource.h> |
45 | #endif |
46 | |
47 | using namespace clang; |
48 | using namespace llvm::opt; |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | static void LLVMErrorHandler(void *UserData, const std::string &Message, |
55 | bool GenCrashDiag) { |
56 | DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); |
57 | |
58 | Diags.Report(diag::err_fe_error_backend) << Message; |
59 | |
60 | |
61 | |
62 | llvm::sys::RunInterruptHandlers(); |
63 | |
64 | |
65 | |
66 | |
67 | exit(GenCrashDiag ? 70 : 1); |
68 | } |
69 | |
70 | #ifdef LINK_POLLY_INTO_TOOLS |
71 | namespace polly { |
72 | void initializePollyPasses(llvm::PassRegistry &Registry); |
73 | } |
74 | #endif |
75 | |
76 | #ifdef CLANG_HAVE_RLIMITS |
77 | #if defined(__linux__) && defined(__PIE__) |
78 | static size_t getCurrentStackAllocation() { |
79 | |
80 | |
81 | size_t Usage = 512 * 1024; |
82 | if (FILE *StatFile = fopen("/proc/self/stat", "r")) { |
83 | |
84 | |
85 | |
86 | |
87 | unsigned long StackPtr, EnvEnd; |
88 | |
89 | |
90 | |
91 | #if defined(__GNUC__) && !defined(__clang__) |
92 | #pragma GCC diagnostic push |
93 | #pragma GCC diagnostic ignored "-Wformat" |
94 | #endif |
95 | if (fscanf(StatFile, |
96 | "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " |
97 | "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " |
98 | "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " |
99 | "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", |
100 | &StackPtr, &EnvEnd) == 2) { |
101 | #if defined(__GNUC__) && !defined(__clang__) |
102 | #pragma GCC diagnostic pop |
103 | #endif |
104 | Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; |
105 | } |
106 | fclose(StatFile); |
107 | } |
108 | return Usage; |
109 | } |
110 | |
111 | #include <alloca.h> |
112 | |
113 | LLVM_ATTRIBUTE_NOINLINE |
114 | static void ensureStackAddressSpace() { |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | size_t Curr = getCurrentStackAllocation(); |
123 | const int kTargetStack = DesiredStackSize - 256 * 1024; |
124 | if (Curr < kTargetStack) { |
125 | volatile char *volatile Alloc = |
126 | static_cast<volatile char *>(alloca(kTargetStack - Curr)); |
127 | Alloc[0] = 0; |
128 | Alloc[kTargetStack - Curr - 1] = 0; |
129 | } |
130 | } |
131 | #else |
132 | static void ensureStackAddressSpace() {} |
133 | #endif |
134 | |
135 | |
136 | static void ensureSufficientStack() { |
137 | struct rlimit rlim; |
138 | if (getrlimit(RLIMIT_STACK, &rlim) != 0) |
139 | return; |
140 | |
141 | |
142 | |
143 | if (rlim.rlim_cur != RLIM_INFINITY && |
144 | rlim.rlim_cur < rlim_t(DesiredStackSize)) { |
145 | |
146 | if (rlim.rlim_max == RLIM_INFINITY || |
147 | rlim.rlim_max >= rlim_t(DesiredStackSize)) |
148 | rlim.rlim_cur = DesiredStackSize; |
149 | else if (rlim.rlim_cur == rlim.rlim_max) |
150 | return; |
151 | else |
152 | rlim.rlim_cur = rlim.rlim_max; |
153 | |
154 | if (setrlimit(RLIMIT_STACK, &rlim) != 0 || |
155 | rlim.rlim_cur != DesiredStackSize) |
156 | return; |
157 | } |
158 | |
159 | |
160 | |
161 | ensureStackAddressSpace(); |
162 | } |
163 | #else |
164 | static void ensureSufficientStack() {} |
165 | #endif |
166 | |
167 | int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { |
168 | ensureSufficientStack(); |
169 | |
170 | std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); |
171 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
172 | |
173 | |
174 | auto PCHOps = Clang->getPCHContainerOperations(); |
175 | PCHOps->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>()); |
176 | PCHOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>()); |
177 | |
178 | |
179 | llvm::InitializeAllTargets(); |
180 | llvm::InitializeAllTargetMCs(); |
181 | llvm::InitializeAllAsmPrinters(); |
182 | llvm::InitializeAllAsmParsers(); |
183 | |
184 | #ifdef LINK_POLLY_INTO_TOOLS |
185 | llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); |
186 | polly::initializePollyPasses(Registry); |
187 | #endif |
188 | |
189 | |
190 | |
191 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); |
192 | TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; |
193 | DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); |
194 | bool Success = CompilerInvocation::CreateFromArgs( |
195 | Clang->getInvocation(), Argv.begin(), Argv.end(), Diags); |
196 | |
197 | |
198 | if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && |
199 | Clang->getHeaderSearchOpts().ResourceDir.empty()) |
200 | Clang->getHeaderSearchOpts().ResourceDir = |
201 | CompilerInvocation::GetResourcesPath(Argv0, MainAddr); |
202 | |
203 | |
204 | Clang->createDiagnostics(); |
205 | if (!Clang->hasDiagnostics()) |
206 | return 1; |
207 | |
208 | |
209 | |
210 | llvm::install_fatal_error_handler(LLVMErrorHandler, |
211 | static_cast<void*>(&Clang->getDiagnostics())); |
212 | |
213 | DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); |
214 | if (!Success) |
215 | return 1; |
216 | |
217 | |
218 | Success = ExecuteCompilerInvocation(Clang.get()); |
219 | |
220 | |
221 | |
222 | llvm::TimerGroup::printAll(llvm::errs()); |
223 | |
224 | |
225 | |
226 | |
227 | llvm::remove_fatal_error_handler(); |
228 | |
229 | |
230 | if (Clang->getFrontendOpts().DisableFree) { |
231 | llvm::BuryPointer(std::move(Clang)); |
232 | return !Success; |
233 | } |
234 | |
235 | return !Success; |
236 | } |
237 | |