Loading...
Searching...
No Matches
cc1_main.cpp
1//===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the entry point to the clang -cc1 functionality, which implements the
10// core compiler functionality along with a number of additional tools for
11// demonstration and testing purposes.
12//
13//===----------------------------------------------------------------------===//
14
15#include <clang/Basic/DiagnosticSema.h>
16#undef CALLBACK
17#include "clang/Basic/FileManager.h"
18#include "clang/Basic/Stack.h"
19#include "clang/Basic/TargetOptions.h"
20#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
21#include "clang/Config/config.h"
22#include "clang/Frontend/CompilerInstance.h"
23#include "clang/Frontend/CompilerInvocation.h"
24#include "clang/Frontend/FrontendDiagnostic.h"
25#include "clang/Frontend/TextDiagnosticBuffer.h"
26#include "clang/Frontend/TextDiagnosticPrinter.h"
27#include "clang/FrontendTool/Utils.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/FileSystem.h"
37#include "llvm/Support/ManagedStatic.h"
38#include "llvm/Support/Process.h"
39#include "llvm/Support/Signals.h"
40//#include "llvm/Support/TargetRegistry.h"
41#include "llvm/Support/TargetSelect.h"
42#include "llvm/Support/TimeProfiler.h"
43#include "llvm/Support/Timer.h"
44#include "llvm/Support/raw_ostream.h"
45#include "llvm/Target/TargetMachine.h"
46
47#include <iostream>
48#include <sstream>
49
50#ifdef CLANG_HAVE_RLIMITS
51#include <sys/resource.h>
52#endif
53
54using namespace clang;
55using namespace llvm::opt;
56
57class QtDiagnosticConsumer final : public DiagnosticConsumer
58{
59
60 // DiagnosticConsumer interface
61public:
62 void finish() override { std::cerr << " == finish == \n"; }
63 void
64 HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic& Info) override
65 {
66 SmallVector<char, 1024> vec;
67 Info.FormatDiagnostic(vec);
68 std::cerr << " == diagnostic == " << vec.data() << "\n";
69 }
70};
71
72//===----------------------------------------------------------------------===//
73// Main driver
74//===----------------------------------------------------------------------===//
75#if LLVM_VERSION_MAJOR < 14
76static void
77LLVMErrorHandler(void* UserData, const std::string& Message, bool GenCrashDiag)
78#else
79static void LLVMErrorHandler(void* UserData, const char* Message, bool GenCrashDiag)
80#endif
81{
82 DiagnosticsEngine& Diags = *static_cast<DiagnosticsEngine*>(UserData);
83
84 Diags.Report(diag::err_fe_error_backend) << Message;
85
86 // Run the interrupt handlers to make sure any special cleanups get done, in
87 // particular that we remove files registered with RemoveFileOnSignal.
88 llvm::sys::RunInterruptHandlers();
89
90 // We cannot recover from llvm errors. When reporting a fatal error, exit
91 // with status 70 to generate crash diagnostics. For BSD systems this is
92 // defined as an internal software error. Otherwise, exit with status 1.
93 llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
94}
95
96#ifdef CLANG_HAVE_RLIMITS
97#if defined(__linux__) && defined(__PIE__)
98static size_t getCurrentStackAllocation()
99{
100 // If we can't compute the current stack usage, allow for 512K of command
101 // line arguments and environment.
102 size_t Usage = 512 * 1024;
103 if(FILE* StatFile = fopen("/proc/self/stat", "r"))
104 {
105 // We assume that the stack extends from its current address to the end of
106 // the environment space. In reality, there is another string literal (the
107 // program name) after the environment, but this is close enough (we only
108 // need to be within 100K or so).
109 unsigned long StackPtr, EnvEnd;
110 // Disable silly GCC -Wformat warning that complains about length
111 // modifiers on ignored format specifiers. We want to retain these
112 // for documentation purposes even though they have no effect.
113#if defined(__GNUC__) && !defined(__clang__)
114#pragma GCC diagnostic push
115#pragma GCC diagnostic ignored "-Wformat"
116#endif
117 if(fscanf(
118 StatFile,
119 "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu "
120 "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu "
121 "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d "
122 "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d",
123 &StackPtr, &EnvEnd)
124 == 2)
125 {
126#if defined(__GNUC__) && !defined(__clang__)
127#pragma GCC diagnostic pop
128#endif
129 Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd;
130 }
131 fclose(StatFile);
132 }
133 return Usage;
134}
135
136#include <alloca.h>
137
138LLVM_ATTRIBUTE_NOINLINE
139static void ensureStackAddressSpace()
140{
141 // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
142 // relatively close to the stack (they are only guaranteed to be 128MiB
143 // apart). This results in crashes if we happen to heap-allocate more than
144 // 128MiB before we reach our stack high-water mark.
145 //
146 // To avoid these crashes, ensure that we have sufficient virtual memory
147 // pages allocated before we start running.
148 size_t Curr = getCurrentStackAllocation();
149 const int kTargetStack = DesiredStackSize - 256 * 1024;
150 if(Curr < kTargetStack)
151 {
152 volatile char* volatile Alloc
153 = static_cast<volatile char*>(alloca(kTargetStack - Curr));
154 Alloc[0] = 0;
155 Alloc[kTargetStack - Curr - 1] = 0;
156 }
157}
158#else
159static void ensureStackAddressSpace() { }
160#endif
161
163static void ensureSufficientStack()
164{
165 struct rlimit rlim;
166 if(getrlimit(RLIMIT_STACK, &rlim) != 0)
167 return;
168
169 // Increase the soft stack limit to our desired level, if necessary and
170 // possible.
171 if(rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < rlim_t(DesiredStackSize))
172 {
173 // Try to allocate sufficient stack.
174 if(rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= rlim_t(DesiredStackSize))
175 rlim.rlim_cur = DesiredStackSize;
176 else if(rlim.rlim_cur == rlim.rlim_max)
177 return;
178 else
179 rlim.rlim_cur = rlim.rlim_max;
180
181 if(setrlimit(RLIMIT_STACK, &rlim) != 0 || rlim.rlim_cur != DesiredStackSize)
182 return;
183 }
184
185 // We should now have a stack of size at least DesiredStackSize. Ensure
186 // that we can actually use that much, if necessary.
187 ensureStackAddressSpace();
188}
189#else
190static void ensureSufficientStack() { }
191#endif
192
193auto printErrors(TextDiagnosticBuffer& buf, const SourceManager& mgr)
194{
195 std::stringstream ss;
196 for(auto it = buf.err_begin(); it != buf.err_end(); ++it)
197 {
198 auto& loc = it->first;
199 ss << loc.printToString(mgr) << ":\n" << it->second << "\n\n";
200 }
201
202 std::cerr << ss.str();
203 return ss.str();
204}
205llvm::Error cc1_main(ArrayRef<const char*> Argv, const char* Argv0, void* MainAddr)
206{
207 ensureSufficientStack();
208
209 // Initialize targets first, so that --version shows registered targets.
210 llvm::InitializeAllTargets();
211 llvm::InitializeAllTargetMCs();
212 llvm::InitializeAllAsmPrinters();
213 llvm::InitializeAllAsmParsers();
214
215 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
216#ifdef LINK_POLLY_INTO_TOOLS
217 llvm::PassRegistry& Registry = *llvm::PassRegistry::getPassRegistry();
218 polly::initializePollyPasses(Registry);
219#endif
220
221 // Buffer diagnostics from argument parsing so that we can output them using a
222 // well formed diagnostic object.
223 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
224 TextDiagnosticBuffer* DiagsBuffer = new TextDiagnosticBuffer;
225 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
226 new DiagnosticsEngine(DiagID, &*DiagOpts, DiagsBuffer));
227
228#if LLVM_VERSION_MAJOR >= 13
229 llvm::IntrusiveRefCntPtr<FileManager> Files(
230 new FileManager(FileSystemOptions(), llvm::vfs::getRealFileSystem()));
231 llvm::IntrusiveRefCntPtr<SourceManager> SrcMgr(new SourceManager(*Diags, *Files));
232#endif
233
234 // Create a Clang instance
235 std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
236
237 // Register the support for object-file-wrapped Clang modules.
238 auto PCHOps = Clang->getPCHContainerOperations();
239 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
240 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
241
242 bool Success
243 = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, *Diags);
244
245#if LLVM_VERSION_MAJOR >= 13
246 if(!Clang->hasSourceManager())
247 {
248 Diags->setSourceManager(SrcMgr.get());
249
250 Clang->setFileManager(Files.get());
251 Clang->setSourceManager(SrcMgr.get());
252 }
253#endif
254 // Infer the builtin include path if unspecified.
255 if(Clang->getHeaderSearchOpts().UseBuiltinIncludes
256 && Clang->getHeaderSearchOpts().ResourceDir.empty())
257 Clang->getHeaderSearchOpts().ResourceDir
258 = CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
259
260 Clang->setDiagnostics(Diags.get());
261 if(!Clang->hasDiagnostics())
262 {
263 return llvm::make_error<llvm::StringError>(
264 "No diagnostics", std::error_code(1, std::system_category()));
265 }
266
267 // Set an error handler, so that any LLVM backend diagnostics go through our
268 // error handler.
269 llvm::install_fatal_error_handler(
270 LLVMErrorHandler, static_cast<void*>(&Clang->getDiagnostics()));
271
272 //if(Clang && DiagsBuffer)
273 // DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
274 Clang->getDiagnostics().setSeverity(clang::diag::ext_constexpr_function_never_constant_expr, diag::Severity::Ignored, {});
275 if(!Success)
276 {
277 return llvm::make_error<llvm::StringError>(
278 printErrors(*DiagsBuffer, Clang->getSourceManager()),
279 std::error_code(1, std::system_category()));
280 }
281
282 // Execute the frontend actions.
283 {
284 llvm::TimeTraceScope TimeScope("ExecuteCompiler");
285 Success = ExecuteCompilerInvocation(Clang.get());
286 }
287
288 // If any timers were active but haven't been destroyed yet, print their
289 // results now. This happens in -disable-free mode.
290 llvm::TimerGroup::printAll(llvm::errs());
291 llvm::TimerGroup::clearAll();
292
293 auto res = Success ? llvm::Error::success()
294 : llvm::make_error<llvm::StringError>(
295 printErrors(*DiagsBuffer, Clang->getSourceManager()),
296 std::error_code(1, std::system_category()));
297
298 // Our error handler depends on the Diagnostics object, which we're
299 // potentially about to delete. Uninstall the handler now so that any
300 // later errors use the default handling behavior instead.
301 llvm::remove_fatal_error_handler();
302
303 // When running with -disable-free, don't do any destruction or shutdown.
304 if(Clang->getFrontendOpts().DisableFree)
305 {
306 llvm::BuryPointer(std::move(Clang));
307 return res;
308 }
309 return res;
310}
Definition cc1_main.cpp:58
STL namespace.