Path: blob/main/contrib/llvm-project/clang/tools/driver/cc1_main.cpp
35236 views
//===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This is the entry point to the clang -cc1 functionality, which implements the9// core compiler functionality along with a number of additional tools for10// demonstration and testing purposes.11//12//===----------------------------------------------------------------------===//1314#include "clang/Basic/Stack.h"15#include "clang/Basic/TargetOptions.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/ADT/StringExtras.h"29#include "llvm/Config/llvm-config.h"30#include "llvm/LinkAllPasses.h"31#include "llvm/MC/MCSubtargetInfo.h"32#include "llvm/MC/TargetRegistry.h"33#include "llvm/Option/Arg.h"34#include "llvm/Option/ArgList.h"35#include "llvm/Option/OptTable.h"36#include "llvm/Support/BuryPointer.h"37#include "llvm/Support/Compiler.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/ManagedStatic.h"40#include "llvm/Support/Path.h"41#include "llvm/Support/Process.h"42#include "llvm/Support/Signals.h"43#include "llvm/Support/TargetSelect.h"44#include "llvm/Support/TimeProfiler.h"45#include "llvm/Support/Timer.h"46#include "llvm/Support/raw_ostream.h"47#include "llvm/Target/TargetMachine.h"48#include "llvm/TargetParser/AArch64TargetParser.h"49#include "llvm/TargetParser/ARMTargetParser.h"50#include "llvm/TargetParser/RISCVISAInfo.h"51#include <cstdio>5253#ifdef CLANG_HAVE_RLIMITS54#include <sys/resource.h>55#endif5657using namespace clang;58using namespace llvm::opt;5960//===----------------------------------------------------------------------===//61// Main driver62//===----------------------------------------------------------------------===//6364static void LLVMErrorHandler(void *UserData, const char *Message,65bool GenCrashDiag) {66DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);6768Diags.Report(diag::err_fe_error_backend) << Message;6970// Run the interrupt handlers to make sure any special cleanups get done, in71// particular that we remove files registered with RemoveFileOnSignal.72llvm::sys::RunInterruptHandlers();7374// We cannot recover from llvm errors. When reporting a fatal error, exit75// with status 70 to generate crash diagnostics. For BSD systems this is76// defined as an internal software error. Otherwise, exit with status 1.77llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);78}7980#ifdef CLANG_HAVE_RLIMITS81/// Attempt to ensure that we have at least 8MiB of usable stack space.82static void ensureSufficientStack() {83struct rlimit rlim;84if (getrlimit(RLIMIT_STACK, &rlim) != 0)85return;8687// Increase the soft stack limit to our desired level, if necessary and88// possible.89if (rlim.rlim_cur != RLIM_INFINITY &&90rlim.rlim_cur < rlim_t(DesiredStackSize)) {91// Try to allocate sufficient stack.92if (rlim.rlim_max == RLIM_INFINITY ||93rlim.rlim_max >= rlim_t(DesiredStackSize))94rlim.rlim_cur = DesiredStackSize;95else if (rlim.rlim_cur == rlim.rlim_max)96return;97else98rlim.rlim_cur = rlim.rlim_max;99100if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||101rlim.rlim_cur != DesiredStackSize)102return;103}104}105#else106static void ensureSufficientStack() {}107#endif108109/// Print supported cpus of the given target.110static int PrintSupportedCPUs(std::string TargetStr) {111std::string Error;112const llvm::Target *TheTarget =113llvm::TargetRegistry::lookupTarget(TargetStr, Error);114if (!TheTarget) {115llvm::errs() << Error;116return 1;117}118119// the target machine will handle the mcpu printing120llvm::TargetOptions Options;121std::unique_ptr<llvm::TargetMachine> TheTargetMachine(122TheTarget->createTargetMachine(TargetStr, "", "+cpuhelp", Options,123std::nullopt));124return 0;125}126127static int PrintSupportedExtensions(std::string TargetStr) {128std::string Error;129const llvm::Target *TheTarget =130llvm::TargetRegistry::lookupTarget(TargetStr, Error);131if (!TheTarget) {132llvm::errs() << Error;133return 1;134}135136llvm::TargetOptions Options;137std::unique_ptr<llvm::TargetMachine> TheTargetMachine(138TheTarget->createTargetMachine(TargetStr, "", "", Options, std::nullopt));139const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple();140const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo();141const llvm::ArrayRef<llvm::SubtargetFeatureKV> Features =142MCInfo->getAllProcessorFeatures();143144llvm::StringMap<llvm::StringRef> DescMap;145for (const llvm::SubtargetFeatureKV &feature : Features)146DescMap.insert({feature.Key, feature.Desc});147148if (MachineTriple.isRISCV())149llvm::RISCVISAInfo::printSupportedExtensions(DescMap);150else if (MachineTriple.isAArch64())151llvm::AArch64::PrintSupportedExtensions();152else if (MachineTriple.isARM())153llvm::ARM::PrintSupportedExtensions(DescMap);154else {155// The option was already checked in Driver::HandleImmediateArgs,156// so we do not expect to get here if we are not a supported architecture.157assert(0 && "Unhandled triple for --print-supported-extensions option.");158return 1;159}160161return 0;162}163164static int PrintEnabledExtensions(const TargetOptions& TargetOpts) {165std::string Error;166const llvm::Target *TheTarget =167llvm::TargetRegistry::lookupTarget(TargetOpts.Triple, Error);168if (!TheTarget) {169llvm::errs() << Error;170return 1;171}172173// Create a target machine using the input features, the triple information174// and a dummy instance of llvm::TargetOptions. Note that this is _not_ the175// same as the `clang::TargetOptions` instance we have access to here.176llvm::TargetOptions BackendOptions;177std::string FeaturesStr = llvm::join(TargetOpts.FeaturesAsWritten, ",");178std::unique_ptr<llvm::TargetMachine> TheTargetMachine(179TheTarget->createTargetMachine(TargetOpts.Triple, TargetOpts.CPU, FeaturesStr, BackendOptions, std::nullopt));180const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple();181const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo();182183// Extract the feature names that are enabled for the given target.184// We do that by capturing the key from the set of SubtargetFeatureKV entries185// provided by MCSubtargetInfo, which match the '-target-feature' values.186const std::vector<llvm::SubtargetFeatureKV> Features =187MCInfo->getEnabledProcessorFeatures();188std::set<llvm::StringRef> EnabledFeatureNames;189for (const llvm::SubtargetFeatureKV &feature : Features)190EnabledFeatureNames.insert(feature.Key);191192if (MachineTriple.isAArch64())193llvm::AArch64::printEnabledExtensions(EnabledFeatureNames);194else if (MachineTriple.isRISCV()) {195llvm::StringMap<llvm::StringRef> DescMap;196for (const llvm::SubtargetFeatureKV &feature : Features)197DescMap.insert({feature.Key, feature.Desc});198llvm::RISCVISAInfo::printEnabledExtensions(MachineTriple.isArch64Bit(),199EnabledFeatureNames, DescMap);200} else {201// The option was already checked in Driver::HandleImmediateArgs,202// so we do not expect to get here if we are not a supported architecture.203assert(0 && "Unhandled triple for --print-enabled-extensions option.");204return 1;205}206207return 0;208}209210int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {211ensureSufficientStack();212213std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());214IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());215216// Register the support for object-file-wrapped Clang modules.217auto PCHOps = Clang->getPCHContainerOperations();218PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());219PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());220221// Initialize targets first, so that --version shows registered targets.222llvm::InitializeAllTargets();223llvm::InitializeAllTargetMCs();224llvm::InitializeAllAsmPrinters();225llvm::InitializeAllAsmParsers();226227// Buffer diagnostics from argument parsing so that we can output them using a228// well formed diagnostic object.229IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();230TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;231DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);232233// Setup round-trip remarks for the DiagnosticsEngine used in CreateFromArgs.234if (find(Argv, StringRef("-Rround-trip-cc1-args")) != Argv.end())235Diags.setSeverity(diag::remark_cc1_round_trip_generated,236diag::Severity::Remark, {});237238bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),239Argv, Diags, Argv0);240241if (!Clang->getFrontendOpts().TimeTracePath.empty()) {242llvm::timeTraceProfilerInitialize(243Clang->getFrontendOpts().TimeTraceGranularity, Argv0,244Clang->getFrontendOpts().TimeTraceVerbose);245}246// --print-supported-cpus takes priority over the actual compilation.247if (Clang->getFrontendOpts().PrintSupportedCPUs)248return PrintSupportedCPUs(Clang->getTargetOpts().Triple);249250// --print-supported-extensions takes priority over the actual compilation.251if (Clang->getFrontendOpts().PrintSupportedExtensions)252return PrintSupportedExtensions(Clang->getTargetOpts().Triple);253254// --print-enabled-extensions takes priority over the actual compilation.255if (Clang->getFrontendOpts().PrintEnabledExtensions)256return PrintEnabledExtensions(Clang->getTargetOpts());257258// Infer the builtin include path if unspecified.259if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&260Clang->getHeaderSearchOpts().ResourceDir.empty())261Clang->getHeaderSearchOpts().ResourceDir =262CompilerInvocation::GetResourcesPath(Argv0, MainAddr);263264// Create the actual diagnostics engine.265Clang->createDiagnostics();266if (!Clang->hasDiagnostics())267return 1;268269// Set an error handler, so that any LLVM backend diagnostics go through our270// error handler.271llvm::install_fatal_error_handler(LLVMErrorHandler,272static_cast<void*>(&Clang->getDiagnostics()));273274DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());275if (!Success) {276Clang->getDiagnosticClient().finish();277return 1;278}279280// Execute the frontend actions.281{282llvm::TimeTraceScope TimeScope("ExecuteCompiler");283Success = ExecuteCompilerInvocation(Clang.get());284}285286// If any timers were active but haven't been destroyed yet, print their287// results now. This happens in -disable-free mode.288llvm::TimerGroup::printAll(llvm::errs());289llvm::TimerGroup::clearAll();290291if (llvm::timeTraceProfilerEnabled()) {292// It is possible that the compiler instance doesn't own a file manager here293// if we're compiling a module unit. Since the file manager are owned by AST294// when we're compiling a module unit. So the file manager may be invalid295// here.296//297// It should be fine to create file manager here since the file system298// options are stored in the compiler invocation and we can recreate the VFS299// from the compiler invocation.300if (!Clang->hasFileManager())301Clang->createFileManager(createVFSFromCompilerInvocation(302Clang->getInvocation(), Clang->getDiagnostics()));303304if (auto profilerOutput = Clang->createOutputFile(305Clang->getFrontendOpts().TimeTracePath, /*Binary=*/false,306/*RemoveFileOnSignal=*/false,307/*useTemporary=*/false)) {308llvm::timeTraceProfilerWrite(*profilerOutput);309profilerOutput.reset();310llvm::timeTraceProfilerCleanup();311Clang->clearOutputFiles(false);312}313}314315// Our error handler depends on the Diagnostics object, which we're316// potentially about to delete. Uninstall the handler now so that any317// later errors use the default handling behavior instead.318llvm::remove_fatal_error_handler();319320// When running with -disable-free, don't do any destruction or shutdown.321if (Clang->getFrontendOpts().DisableFree) {322llvm::BuryPointer(std::move(Clang));323return !Success;324}325326return !Success;327}328329330