╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ zig_clang_cc1_main.cpp ───────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
46 #include "llvm/Support/Signals.h" 47 #include "llvm/Support/TargetSelect.h" 48 #include "llvm/Support/TimeProfiler.h" 49 #include "llvm/Support/Timer.h" 50 #include "llvm/Support/VirtualFileSystem.h" 51 #include "llvm/Support/raw_ostream.h" 52 #include "llvm/Target/TargetMachine.h" 53 #include "llvm/TargetParser/AArch64TargetParser.h" 54 #include "llvm/TargetParser/ARMTargetParser.h" 55 #include "llvm/TargetParser/RISCVISAInfo.h" 56 #include <cstdio> 57 58 #ifdef CLANG_HAVE_RLIMITS 59 #include <sys/resource.h> 60 #endif 61 62 using namespace clang; 63 using namespace llvm::opt; 64 65 //===----------------------------------------------------------------------===// 66 // Main driver 67 //===----------------------------------------------------------------------===// 68 69 static void LLVMErrorHandler(void *UserData, const char *Message, 70 bool GenCrashDiag) { 71 DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData); 72 73 Diags.Report(diag::err_fe_error_backend) << Message; 74 75 // Run the interrupt handlers to make sure any special cleanups get done, in 76 // particular that we remove files registered with RemoveFileOnSignal. 77 llvm::sys::RunInterruptHandlers(); 78 79 // We cannot recover from llvm errors. When reporting a fatal error, exit 80 // with status 70 to generate crash diagnostics. For BSD systems this is 81 // defined as an internal software error. Otherwise, exit with status 1. 82 llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1); 83 } 84 85 #ifdef CLANG_HAVE_RLIMITS 86 /// Attempt to ensure that we have at least 8MiB of usable stack space. 87 static void ensureSufficientStack() { 88 struct rlimit rlim; 89 if (getrlimit(RLIMIT_STACK, &rlim) != 0) 90 return; 91 92 // Increase the soft stack limit to our desired level, if necessary and 93 // possible. 94 if (rlim.rlim_cur != RLIM_INFINITY && 95 rlim.rlim_cur < rlim_t(DesiredStackSize)) { 96 // Try to allocate sufficient stack. 97 if (rlim.rlim_max == RLIM_INFINITY || 98 rlim.rlim_max >= rlim_t(DesiredStackSize)) 99 rlim.rlim_cur = DesiredStackSize; 100 else if (rlim.rlim_cur == rlim.rlim_max) 101 return; 102 else 103 rlim.rlim_cur = rlim.rlim_max; 104 105 if (setrlimit(RLIMIT_STACK, &rlim) != 0 || 106 rlim.rlim_cur != DesiredStackSize) 107 return; 108 } 109 } 110 #else 111 static void ensureSufficientStack() {} 112 #endif 113 114 /// Print supported cpus of the given target. 115 static int PrintSupportedCPUs(std::string TargetStr) { 116 llvm::Triple Triple(TargetStr); 117 std::string Error; 118 const llvm::Target *TheTarget = 119 llvm::TargetRegistry::lookupTarget(Triple, Error); 120 if (!TheTarget) { 121 llvm::errs() << Error; 122 return 1; 123 } 124 125 // the target machine will handle the mcpu printing 126 llvm::TargetOptions Options; 127 std::unique_ptr<llvm::TargetMachine> TheTargetMachine( 128 TheTarget->createTargetMachine(Triple, "", "+cpuhelp", Options, 129 std::nullopt)); 130 return 0; 131 } 132 133 static int PrintSupportedExtensions(std::string TargetStr) { 134 llvm::Triple Triple(TargetStr); 135 std::string Error; 136 const llvm::Target *TheTarget = 137 llvm::TargetRegistry::lookupTarget(Triple, Error); 138 if (!TheTarget) { 139 llvm::errs() << Error; 140 return 1; 141 } 142 143 llvm::TargetOptions Options; 144 std::unique_ptr<llvm::TargetMachine> TheTargetMachine( 145 TheTarget->createTargetMachine(Triple, "", "", Options, std::nullopt)); 146 const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple(); 147 const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo(); 148 const llvm::ArrayRef<llvm::SubtargetFeatureKV> Features = 149 MCInfo->getAllProcessorFeatures(); 150 151 llvm::StringMap<llvm::StringRef> DescMap; 152 for (const llvm::SubtargetFeatureKV &feature : Features) 153 DescMap.insert({feature.Key, feature.Desc}); 154 155 if (MachineTriple.isRISCV()) 156 llvm::RISCVISAInfo::printSupportedExtensions(DescMap); 157 else if (MachineTriple.isAArch64()) 158 llvm::AArch64::PrintSupportedExtensions(); 159 else if (MachineTriple.isARM()) 160 llvm::ARM::PrintSupportedExtensions(DescMap); 161 else { 162 // The option was already checked in Driver::HandleImmediateArgs, 163 // so we do not expect to get here if we are not a supported architecture. 164 assert(0 && "Unhandled triple for --print-supported-extensions option."); 165 return 1; 166 } 167 168 return 0; 169 } 170 171 static int PrintEnabledExtensions(const TargetOptions& TargetOpts) { 172 llvm::Triple Triple(TargetOpts.Triple); 173 std::string Error; 174 const llvm::Target *TheTarget = 175 llvm::TargetRegistry::lookupTarget(Triple, Error); 176 if (!TheTarget) { 177 llvm::errs() << Error; 178 return 1; 179 } 180 181 // Create a target machine using the input features, the triple information 182 // and a dummy instance of llvm::TargetOptions. Note that this is _not_ the 183 // same as the `clang::TargetOptions` instance we have access to here. 184 llvm::TargetOptions BackendOptions; 185 std::string FeaturesStr = llvm::join(TargetOpts.FeaturesAsWritten, ","); 186 std::unique_ptr<llvm::TargetMachine> TheTargetMachine( 187 TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr, 188 BackendOptions, std::nullopt)); 189 const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple(); 190 const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo(); 191 192 // Extract the feature names that are enabled for the given target. 193 // We do that by capturing the key from the set of SubtargetFeatureKV entries 194 // provided by MCSubtargetInfo, which match the '-target-feature' values. 195 const std::vector<llvm::SubtargetFeatureKV> Features = 196 MCInfo->getEnabledProcessorFeatures(); 197 std::set<llvm::StringRef> EnabledFeatureNames; 198 for (const llvm::SubtargetFeatureKV &feature : Features) 199 EnabledFeatureNames.insert(feature.Key); 200 201 if (MachineTriple.isAArch64()) 202 llvm::AArch64::printEnabledExtensions(EnabledFeatureNames); 203 else if (MachineTriple.isRISCV()) { 204 llvm::StringMap<llvm::StringRef> DescMap; 205 for (const llvm::SubtargetFeatureKV &feature : Features) 206 DescMap.insert({feature.Key, feature.Desc}); 207 llvm::RISCVISAInfo::printEnabledExtensions(MachineTriple.isArch64Bit(), 208 EnabledFeatureNames, DescMap); 209 } else { 210 // The option was already checked in Driver::HandleImmediateArgs, 211 // so we do not expect to get here if we are not a supported architecture. 212 assert(0 && "Unhandled triple for --print-enabled-extensions option."); 213 return 1; 214 } 215 216 return 0; 217 } 218 219 int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { 220 ensureSufficientStack(); 221 222 IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create(); 223 224 // Register the support for object-file-wrapped Clang modules. 225 auto PCHOps = std::make_shared<PCHContainerOperations>(); 226 PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>()); 227 PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>()); 228 229 // Initialize targets first, so that --version shows registered targets. 230 llvm::InitializeAllTargets(); 231 llvm::InitializeAllTargetMCs(); 232 llvm::InitializeAllAsmPrinters(); 233 llvm::InitializeAllAsmParsers(); 234 235 // Buffer diagnostics from argument parsing so that we can output them using a 236 // well formed diagnostic object. 237 DiagnosticOptions DiagOpts; 238 TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; 239 DiagnosticsEngine Diags(DiagID, DiagOpts, DiagsBuffer); 240 241 // Setup round-trip remarks for the DiagnosticsEngine used in CreateFromArgs. 242 if (find(Argv, StringRef("-Rround-trip-cc1-args")) != Argv.end()) 243 Diags.setSeverity(diag::remark_cc1_round_trip_generated, 244 diag::Severity::Remark, {}); 245 246 auto Invocation = std::make_shared<CompilerInvocation>(); 247 bool Success = 248 CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags, Argv0); 249 250 auto Clang = std::make_unique<CompilerInstance>(std::move(Invocation), 251 std::move(PCHOps)); 252 253 if (!Clang->getFrontendOpts().TimeTracePath.empty()) { 254 llvm::timeTraceProfilerInitialize( 255 Clang->getFrontendOpts().TimeTraceGranularity, Argv0, 256 Clang->getFrontendOpts().TimeTraceVerbose); 257 } 258 // --print-supported-cpus takes priority over the actual compilation. 259 if (Clang->getFrontendOpts().PrintSupportedCPUs) 260 return PrintSupportedCPUs(Clang->getTargetOpts().Triple); 261 262 // --print-supported-extensions takes priority over the actual compilation. 263 if (Clang->getFrontendOpts().PrintSupportedExtensions) 264 return PrintSupportedExtensions(Clang->getTargetOpts().Triple); 265 266 // --print-enabled-extensions takes priority over the actual compilation. 267 if (Clang->getFrontendOpts().PrintEnabledExtensions) 268 return PrintEnabledExtensions(Clang->getTargetOpts()); 269 270 // Infer the builtin include path if unspecified. 271 if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && 272 Clang->getHeaderSearchOpts().ResourceDir.empty()) 273 Clang->getHeaderSearchOpts().ResourceDir = 274 GetResourcesPath(Argv0, MainAddr); 275 276 /// Create the actual file system. 277 auto VFS = [] { 278 auto BypassSandbox = llvm::sys::sandbox::scopedDisable(); 279 return llvm::vfs::getRealFileSystem(); 280 }(); 281 Clang->createVirtualFileSystem(std::move(VFS), DiagsBuffer); 282 283 // Create the actual diagnostics engine. 284 Clang->createDiagnostics(); 285 286 // Set an error handler, so that any LLVM backend diagnostics go through our 287 // error handler. 288 llvm::install_fatal_error_handler(LLVMErrorHandler, 289 static_cast<void*>(&Clang->getDiagnostics())); 290 291 DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics()); 292 if (!Success) { 293 Clang->getDiagnosticClient().finish(); 294 return 1; 295 } 296 297 // Execute the frontend actions. 298 { 299 llvm::TimeTraceScope TimeScope("ExecuteCompiler"); 300 bool TimePasses = Clang->getCodeGenOpts().TimePasses; 301 if (TimePasses) 302 Clang->createFrontendTimer(); 303 llvm::TimeRegion Timer(TimePasses ? &Clang->getFrontendTimer() : nullptr); 304 Success = ExecuteCompilerInvocation(Clang.get()); 305 } 306 307 // If any timers were active but haven't been destroyed yet, print their 308 // results now. This happens in -disable-free mode. 309 { 310 // This isn't a formal input or output of the compiler. 311 auto BypassSandbox = llvm::sys::sandbox::scopedDisable(); 312 std::unique_ptr<raw_ostream> IOFile = llvm::CreateInfoOutputFile(); 313 if (Clang->getCodeGenOpts().TimePassesJson) { 314 *IOFile << "{\n"; 315 llvm::TimerGroup::printAllJSONValues(*IOFile, ""); 316 *IOFile << "\n}\n"; 317 } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) { 318 llvm::TimerGroup::printAll(*IOFile); 319 } 320 llvm::TimerGroup::clearAll(); 321 } 322 323 if (llvm::timeTraceProfilerEnabled()) { 324 if (auto profilerOutput = Clang->createOutputFile( 325 Clang->getFrontendOpts().TimeTracePath, /*Binary=*/false, 326 /*RemoveFileOnSignal=*/false, 327 /*useTemporary=*/false)) { 328 llvm::timeTraceProfilerWrite(*profilerOutput); 329 profilerOutput.reset(); 330 llvm::timeTraceProfilerCleanup(); 331 Clang->clearOutputFiles(false); 332 } 333 } 334 335 // Our error handler depends on the Diagnostics object, which we're 336 // potentially about to delete. Uninstall the handler now so that any 337 // later errors use the default handling behavior instead. 338 llvm::remove_fatal_error_handler(); 339 340 // When running with -disable-free, don't do any destruction or shutdown. 341 if (Clang->getFrontendOpts().DisableFree) { 342 llvm::BuryPointer(std::move(Clang)); 343 return !Success; 344 } 345 346 return !Success; 347 } 348