brintos

brintos / llvm-project-archived public Read only

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