1 1.1 joerg //===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===// 2 1.1 joerg // 3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 joerg // 7 1.1 joerg //===----------------------------------------------------------------------===// 8 1.1 joerg // 9 1.1 joerg // This is the entry point to the clang -cc1 functionality, which implements the 10 1.1 joerg // core compiler functionality along with a number of additional tools for 11 1.1 joerg // demonstration and testing purposes. 12 1.1 joerg // 13 1.1 joerg //===----------------------------------------------------------------------===// 14 1.1 joerg 15 1.1 joerg #include "clang/Basic/Stack.h" 16 1.1 joerg #include "clang/Basic/TargetOptions.h" 17 1.1 joerg #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 18 1.1 joerg #include "clang/Config/config.h" 19 1.1 joerg #include "clang/Driver/DriverDiagnostic.h" 20 1.1 joerg #include "clang/Driver/Options.h" 21 1.1 joerg #include "clang/Frontend/CompilerInstance.h" 22 1.1 joerg #include "clang/Frontend/CompilerInvocation.h" 23 1.1 joerg #include "clang/Frontend/FrontendDiagnostic.h" 24 1.1 joerg #include "clang/Frontend/TextDiagnosticBuffer.h" 25 1.1 joerg #include "clang/Frontend/TextDiagnosticPrinter.h" 26 1.1 joerg #include "clang/Frontend/Utils.h" 27 1.1 joerg #include "clang/FrontendTool/Utils.h" 28 1.1 joerg #include "llvm/ADT/Statistic.h" 29 1.1 joerg #include "llvm/Config/llvm-config.h" 30 1.1 joerg #include "llvm/LinkAllPasses.h" 31 1.1 joerg #include "llvm/Option/Arg.h" 32 1.1 joerg #include "llvm/Option/ArgList.h" 33 1.1 joerg #include "llvm/Option/OptTable.h" 34 1.1 joerg #include "llvm/Support/BuryPointer.h" 35 1.1 joerg #include "llvm/Support/Compiler.h" 36 1.1 joerg #include "llvm/Support/ErrorHandling.h" 37 1.1 joerg #include "llvm/Support/ManagedStatic.h" 38 1.1 joerg #include "llvm/Support/Path.h" 39 1.1.1.2 joerg #include "llvm/Support/Process.h" 40 1.1 joerg #include "llvm/Support/Signals.h" 41 1.1 joerg #include "llvm/Support/TargetRegistry.h" 42 1.1 joerg #include "llvm/Support/TargetSelect.h" 43 1.1 joerg #include "llvm/Support/TimeProfiler.h" 44 1.1 joerg #include "llvm/Support/Timer.h" 45 1.1 joerg #include "llvm/Support/raw_ostream.h" 46 1.1 joerg #include "llvm/Target/TargetMachine.h" 47 1.1 joerg #include <cstdio> 48 1.1 joerg 49 1.1 joerg #ifdef CLANG_HAVE_RLIMITS 50 1.1 joerg #include <sys/resource.h> 51 1.1 joerg #endif 52 1.1 joerg 53 1.1 joerg using namespace clang; 54 1.1 joerg using namespace llvm::opt; 55 1.1 joerg 56 1.1 joerg //===----------------------------------------------------------------------===// 57 1.1 joerg // Main driver 58 1.1 joerg //===----------------------------------------------------------------------===// 59 1.1 joerg 60 1.1 joerg static void LLVMErrorHandler(void *UserData, const std::string &Message, 61 1.1 joerg bool GenCrashDiag) { 62 1.1 joerg DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); 63 1.1 joerg 64 1.1 joerg Diags.Report(diag::err_fe_error_backend) << Message; 65 1.1 joerg 66 1.1 joerg // Run the interrupt handlers to make sure any special cleanups get done, in 67 1.1 joerg // particular that we remove files registered with RemoveFileOnSignal. 68 1.1 joerg llvm::sys::RunInterruptHandlers(); 69 1.1 joerg 70 1.1 joerg // We cannot recover from llvm errors. When reporting a fatal error, exit 71 1.1 joerg // with status 70 to generate crash diagnostics. For BSD systems this is 72 1.1 joerg // defined as an internal software error. Otherwise, exit with status 1. 73 1.1.1.2 joerg llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1); 74 1.1 joerg } 75 1.1 joerg 76 1.1 joerg #ifdef CLANG_HAVE_RLIMITS 77 1.1 joerg #if defined(__linux__) && defined(__PIE__) 78 1.1 joerg static size_t getCurrentStackAllocation() { 79 1.1 joerg // If we can't compute the current stack usage, allow for 512K of command 80 1.1 joerg // line arguments and environment. 81 1.1 joerg size_t Usage = 512 * 1024; 82 1.1 joerg if (FILE *StatFile = fopen("/proc/self/stat", "r")) { 83 1.1 joerg // We assume that the stack extends from its current address to the end of 84 1.1 joerg // the environment space. In reality, there is another string literal (the 85 1.1 joerg // program name) after the environment, but this is close enough (we only 86 1.1 joerg // need to be within 100K or so). 87 1.1 joerg unsigned long StackPtr, EnvEnd; 88 1.1 joerg // Disable silly GCC -Wformat warning that complains about length 89 1.1 joerg // modifiers on ignored format specifiers. We want to retain these 90 1.1 joerg // for documentation purposes even though they have no effect. 91 1.1 joerg #if defined(__GNUC__) && !defined(__clang__) 92 1.1 joerg #pragma GCC diagnostic push 93 1.1 joerg #pragma GCC diagnostic ignored "-Wformat" 94 1.1 joerg #endif 95 1.1 joerg if (fscanf(StatFile, 96 1.1 joerg "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu " 97 1.1 joerg "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu " 98 1.1 joerg "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d " 99 1.1 joerg "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d", 100 1.1 joerg &StackPtr, &EnvEnd) == 2) { 101 1.1 joerg #if defined(__GNUC__) && !defined(__clang__) 102 1.1 joerg #pragma GCC diagnostic pop 103 1.1 joerg #endif 104 1.1 joerg Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd; 105 1.1 joerg } 106 1.1 joerg fclose(StatFile); 107 1.1 joerg } 108 1.1 joerg return Usage; 109 1.1 joerg } 110 1.1 joerg 111 1.1 joerg #include <alloca.h> 112 1.1 joerg 113 1.1 joerg LLVM_ATTRIBUTE_NOINLINE 114 1.1 joerg static void ensureStackAddressSpace() { 115 1.1 joerg // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary 116 1.1 joerg // relatively close to the stack (they are only guaranteed to be 128MiB 117 1.1 joerg // apart). This results in crashes if we happen to heap-allocate more than 118 1.1 joerg // 128MiB before we reach our stack high-water mark. 119 1.1 joerg // 120 1.1 joerg // To avoid these crashes, ensure that we have sufficient virtual memory 121 1.1 joerg // pages allocated before we start running. 122 1.1 joerg size_t Curr = getCurrentStackAllocation(); 123 1.1 joerg const int kTargetStack = DesiredStackSize - 256 * 1024; 124 1.1 joerg if (Curr < kTargetStack) { 125 1.1 joerg volatile char *volatile Alloc = 126 1.1 joerg static_cast<volatile char *>(alloca(kTargetStack - Curr)); 127 1.1 joerg Alloc[0] = 0; 128 1.1 joerg Alloc[kTargetStack - Curr - 1] = 0; 129 1.1 joerg } 130 1.1 joerg } 131 1.1 joerg #else 132 1.1 joerg static void ensureStackAddressSpace() {} 133 1.1 joerg #endif 134 1.1 joerg 135 1.1 joerg /// Attempt to ensure that we have at least 8MiB of usable stack space. 136 1.1 joerg static void ensureSufficientStack() { 137 1.1 joerg struct rlimit rlim; 138 1.1 joerg if (getrlimit(RLIMIT_STACK, &rlim) != 0) 139 1.1 joerg return; 140 1.1 joerg 141 1.1 joerg // Increase the soft stack limit to our desired level, if necessary and 142 1.1 joerg // possible. 143 1.1 joerg if (rlim.rlim_cur != RLIM_INFINITY && 144 1.1 joerg rlim.rlim_cur < rlim_t(DesiredStackSize)) { 145 1.1 joerg // Try to allocate sufficient stack. 146 1.1 joerg if (rlim.rlim_max == RLIM_INFINITY || 147 1.1 joerg rlim.rlim_max >= rlim_t(DesiredStackSize)) 148 1.1 joerg rlim.rlim_cur = DesiredStackSize; 149 1.1 joerg else if (rlim.rlim_cur == rlim.rlim_max) 150 1.1 joerg return; 151 1.1 joerg else 152 1.1 joerg rlim.rlim_cur = rlim.rlim_max; 153 1.1 joerg 154 1.1 joerg if (setrlimit(RLIMIT_STACK, &rlim) != 0 || 155 1.1 joerg rlim.rlim_cur != DesiredStackSize) 156 1.1 joerg return; 157 1.1 joerg } 158 1.1 joerg 159 1.1 joerg // We should now have a stack of size at least DesiredStackSize. Ensure 160 1.1 joerg // that we can actually use that much, if necessary. 161 1.1 joerg ensureStackAddressSpace(); 162 1.1 joerg } 163 1.1 joerg #else 164 1.1 joerg static void ensureSufficientStack() {} 165 1.1 joerg #endif 166 1.1 joerg 167 1.1 joerg /// Print supported cpus of the given target. 168 1.1 joerg static int PrintSupportedCPUs(std::string TargetStr) { 169 1.1 joerg std::string Error; 170 1.1 joerg const llvm::Target *TheTarget = 171 1.1 joerg llvm::TargetRegistry::lookupTarget(TargetStr, Error); 172 1.1 joerg if (!TheTarget) { 173 1.1 joerg llvm::errs() << Error; 174 1.1 joerg return 1; 175 1.1 joerg } 176 1.1 joerg 177 1.1 joerg // the target machine will handle the mcpu printing 178 1.1 joerg llvm::TargetOptions Options; 179 1.1 joerg std::unique_ptr<llvm::TargetMachine> TheTargetMachine( 180 1.1.1.2 joerg TheTarget->createTargetMachine(TargetStr, "", "+cpuhelp", Options, None)); 181 1.1 joerg return 0; 182 1.1 joerg } 183 1.1 joerg 184 1.1 joerg int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { 185 1.1 joerg ensureSufficientStack(); 186 1.1 joerg 187 1.1 joerg std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); 188 1.1 joerg IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 189 1.1 joerg 190 1.1 joerg // Register the support for object-file-wrapped Clang modules. 191 1.1 joerg auto PCHOps = Clang->getPCHContainerOperations(); 192 1.1 joerg PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 193 1.1 joerg PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 194 1.1 joerg 195 1.1 joerg // Initialize targets first, so that --version shows registered targets. 196 1.1 joerg llvm::InitializeAllTargets(); 197 1.1 joerg llvm::InitializeAllTargetMCs(); 198 1.1 joerg llvm::InitializeAllAsmPrinters(); 199 1.1 joerg llvm::InitializeAllAsmParsers(); 200 1.1 joerg 201 1.1 joerg // Buffer diagnostics from argument parsing so that we can output them using a 202 1.1 joerg // well formed diagnostic object. 203 1.1 joerg IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 204 1.1 joerg TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 205 1.1 joerg DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); 206 1.1.1.2 joerg 207 1.1.1.2 joerg // Setup round-trip remarks for the DiagnosticsEngine used in CreateFromArgs. 208 1.1.1.2 joerg if (find(Argv, StringRef("-Rround-trip-cc1-args")) != Argv.end()) 209 1.1.1.2 joerg Diags.setSeverity(diag::remark_cc1_round_trip_generated, 210 1.1.1.2 joerg diag::Severity::Remark, {}); 211 1.1.1.2 joerg 212 1.1.1.2 joerg bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), 213 1.1.1.2 joerg Argv, Diags, Argv0); 214 1.1 joerg 215 1.1 joerg if (Clang->getFrontendOpts().TimeTrace) { 216 1.1 joerg llvm::timeTraceProfilerInitialize( 217 1.1.1.2 joerg Clang->getFrontendOpts().TimeTraceGranularity, Argv0); 218 1.1 joerg } 219 1.1 joerg // --print-supported-cpus takes priority over the actual compilation. 220 1.1 joerg if (Clang->getFrontendOpts().PrintSupportedCPUs) 221 1.1 joerg return PrintSupportedCPUs(Clang->getTargetOpts().Triple); 222 1.1 joerg 223 1.1 joerg // Infer the builtin include path if unspecified. 224 1.1 joerg if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 225 1.1 joerg Clang->getHeaderSearchOpts().ResourceDir.empty()) 226 1.1 joerg Clang->getHeaderSearchOpts().ResourceDir = 227 1.1 joerg CompilerInvocation::GetResourcesPath(Argv0, MainAddr); 228 1.1 joerg 229 1.1 joerg // Create the actual diagnostics engine. 230 1.1 joerg Clang->createDiagnostics(); 231 1.1 joerg if (!Clang->hasDiagnostics()) 232 1.1 joerg return 1; 233 1.1 joerg 234 1.1 joerg // Set an error handler, so that any LLVM backend diagnostics go through our 235 1.1 joerg // error handler. 236 1.1 joerg llvm::install_fatal_error_handler(LLVMErrorHandler, 237 1.1 joerg static_cast<void*>(&Clang->getDiagnostics())); 238 1.1 joerg 239 1.1 joerg DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 240 1.1 joerg if (!Success) 241 1.1 joerg return 1; 242 1.1 joerg 243 1.1 joerg // Execute the frontend actions. 244 1.1 joerg { 245 1.1.1.2 joerg llvm::TimeTraceScope TimeScope("ExecuteCompiler"); 246 1.1 joerg Success = ExecuteCompilerInvocation(Clang.get()); 247 1.1 joerg } 248 1.1 joerg 249 1.1 joerg // If any timers were active but haven't been destroyed yet, print their 250 1.1 joerg // results now. This happens in -disable-free mode. 251 1.1 joerg llvm::TimerGroup::printAll(llvm::errs()); 252 1.1 joerg llvm::TimerGroup::clearAll(); 253 1.1 joerg 254 1.1 joerg if (llvm::timeTraceProfilerEnabled()) { 255 1.1 joerg SmallString<128> Path(Clang->getFrontendOpts().OutputFile); 256 1.1 joerg llvm::sys::path::replace_extension(Path, "json"); 257 1.1.1.2 joerg if (auto profilerOutput = Clang->createOutputFile( 258 1.1.1.2 joerg Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false, 259 1.1.1.2 joerg /*useTemporary=*/false)) { 260 1.1 joerg llvm::timeTraceProfilerWrite(*profilerOutput); 261 1.1 joerg // FIXME(ibiryukov): make profilerOutput flush in destructor instead. 262 1.1 joerg profilerOutput->flush(); 263 1.1 joerg llvm::timeTraceProfilerCleanup(); 264 1.1.1.2 joerg Clang->clearOutputFiles(false); 265 1.1 joerg } 266 1.1 joerg } 267 1.1 joerg 268 1.1 joerg // Our error handler depends on the Diagnostics object, which we're 269 1.1 joerg // potentially about to delete. Uninstall the handler now so that any 270 1.1 joerg // later errors use the default handling behavior instead. 271 1.1 joerg llvm::remove_fatal_error_handler(); 272 1.1 joerg 273 1.1 joerg // When running with -disable-free, don't do any destruction or shutdown. 274 1.1 joerg if (Clang->getFrontendOpts().DisableFree) { 275 1.1 joerg llvm::BuryPointer(std::move(Clang)); 276 1.1 joerg return !Success; 277 1.1 joerg } 278 1.1 joerg 279 1.1 joerg return !Success; 280 1.1 joerg } 281