LCOV - code coverage report
Current view: top level - src - zig_clang_cc1_main.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 36 57 63.2 %
Date: 1970-01-01 00:00:01 Functions: 5 6 83.3 %
Branches: 10 36 27.8 %

           Branch data     Line data    Source code
       1                 :            : //===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//
       2                 :            : //
       3                 :            : //                     The LLVM Compiler Infrastructure
       4                 :            : //
       5                 :            : // This file is distributed under the University of Illinois Open Source
       6                 :            : // License. See LICENSE.TXT for details.
       7                 :            : //
       8                 :            : //===----------------------------------------------------------------------===//
       9                 :            : //
      10                 :            : // This is the entry point to the clang -cc1 functionality, which implements the
      11                 :            : // core compiler functionality along with a number of additional tools for
      12                 :            : // demonstration and testing purposes.
      13                 :            : //
      14                 :            : //===----------------------------------------------------------------------===//
      15                 :            : 
      16                 :            : #include "clang/Basic/Stack.h"
      17                 :            : #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
      18                 :            : #include "clang/Config/config.h"
      19                 :            : #include "clang/Driver/DriverDiagnostic.h"
      20                 :            : #include "clang/Driver/Options.h"
      21                 :            : #include "clang/Frontend/CompilerInstance.h"
      22                 :            : #include "clang/Frontend/CompilerInvocation.h"
      23                 :            : #include "clang/Frontend/FrontendDiagnostic.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 "llvm/ADT/Statistic.h"
      29                 :            : #include "llvm/Config/llvm-config.h"
      30                 :            : #include "llvm/LinkAllPasses.h"
      31                 :            : #include "llvm/Option/Arg.h"
      32                 :            : #include "llvm/Option/ArgList.h"
      33                 :            : #include "llvm/Option/OptTable.h"
      34                 :            : #include "llvm/Support/BuryPointer.h"
      35                 :            : #include "llvm/Support/Compiler.h"
      36                 :            : #include "llvm/Support/ErrorHandling.h"
      37                 :            : #include "llvm/Support/ManagedStatic.h"
      38                 :            : #include "llvm/Support/Signals.h"
      39                 :            : #include "llvm/Support/TargetSelect.h"
      40                 :            : #include "llvm/Support/Timer.h"
      41                 :            : #include "llvm/Support/raw_ostream.h"
      42                 :            : #include <cstdio>
      43                 :            : 
      44                 :            : #ifdef CLANG_HAVE_RLIMITS
      45                 :            : #include <sys/resource.h>
      46                 :            : #endif
      47                 :            : 
      48                 :            : using namespace clang;
      49                 :            : using namespace llvm::opt;
      50                 :            : 
      51                 :            : //===----------------------------------------------------------------------===//
      52                 :            : // Main driver
      53                 :            : //===----------------------------------------------------------------------===//
      54                 :            : 
      55                 :          0 : static void LLVMErrorHandler(void *UserData, const std::string &Message,
      56                 :            :                              bool GenCrashDiag) {
      57                 :          0 :   DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
      58                 :            : 
      59                 :          0 :   Diags.Report(diag::err_fe_error_backend) << Message;
      60                 :            : 
      61                 :            :   // Run the interrupt handlers to make sure any special cleanups get done, in
      62                 :            :   // particular that we remove files registered with RemoveFileOnSignal.
      63                 :          0 :   llvm::sys::RunInterruptHandlers();
      64                 :            : 
      65                 :            :   // We cannot recover from llvm errors.  When reporting a fatal error, exit
      66                 :            :   // with status 70 to generate crash diagnostics.  For BSD systems this is
      67                 :            :   // defined as an internal software error.  Otherwise, exit with status 1.
      68         [ #  # ]:          0 :   exit(GenCrashDiag ? 70 : 1);
      69                 :            : }
      70                 :            : 
      71                 :            : #ifdef CLANG_HAVE_RLIMITS
      72                 :            : #if defined(__linux__) && defined(__PIE__)
      73                 :            : static size_t getCurrentStackAllocation() {
      74                 :            :   // If we can't compute the current stack usage, allow for 512K of command
      75                 :            :   // line arguments and environment.
      76                 :            :   size_t Usage = 512 * 1024;
      77                 :            :   if (FILE *StatFile = fopen("/proc/self/stat", "r")) {
      78                 :            :     // We assume that the stack extends from its current address to the end of
      79                 :            :     // the environment space. In reality, there is another string literal (the
      80                 :            :     // program name) after the environment, but this is close enough (we only
      81                 :            :     // need to be within 100K or so).
      82                 :            :     unsigned long StackPtr, EnvEnd;
      83                 :            :     // Disable silly GCC -Wformat warning that complains about length
      84                 :            :     // modifiers on ignored format specifiers. We want to retain these
      85                 :            :     // for documentation purposes even though they have no effect.
      86                 :            : #if defined(__GNUC__) && !defined(__clang__)
      87                 :            : #pragma GCC diagnostic push
      88                 :            : #pragma GCC diagnostic ignored "-Wformat"
      89                 :            : #endif
      90                 :            :     if (fscanf(StatFile,
      91                 :            :                "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu "
      92                 :            :                "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu "
      93                 :            :                "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d "
      94                 :            :                "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d",
      95                 :            :                &StackPtr, &EnvEnd) == 2) {
      96                 :            : #if defined(__GNUC__) && !defined(__clang__)
      97                 :            : #pragma GCC diagnostic pop
      98                 :            : #endif
      99                 :            :       Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd;
     100                 :            :     }
     101                 :            :     fclose(StatFile);
     102                 :            :   }
     103                 :            :   return Usage;
     104                 :            : }
     105                 :            : 
     106                 :            : #include <alloca.h>
     107                 :            : 
     108                 :            : LLVM_ATTRIBUTE_NOINLINE
     109                 :            : static void ensureStackAddressSpace() {
     110                 :            :   // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
     111                 :            :   // relatively close to the stack (they are only guaranteed to be 128MiB
     112                 :            :   // apart). This results in crashes if we happen to heap-allocate more than
     113                 :            :   // 128MiB before we reach our stack high-water mark.
     114                 :            :   //
     115                 :            :   // To avoid these crashes, ensure that we have sufficient virtual memory
     116                 :            :   // pages allocated before we start running.
     117                 :            :   size_t Curr = getCurrentStackAllocation();
     118                 :            :   const int kTargetStack = DesiredStackSize - 256 * 1024;
     119                 :            :   if (Curr < kTargetStack) {
     120                 :            :     volatile char *volatile Alloc =
     121                 :            :         static_cast<volatile char *>(alloca(kTargetStack - Curr));
     122                 :            :     Alloc[0] = 0;
     123                 :            :     Alloc[kTargetStack - Curr - 1] = 0;
     124                 :            :   }
     125                 :            : }
     126                 :            : #else
     127                 :         35 : static void ensureStackAddressSpace() {}
     128                 :            : #endif
     129                 :            : 
     130                 :            : /// Attempt to ensure that we have at least 8MiB of usable stack space.
     131                 :         35 : static void ensureSufficientStack() {
     132                 :            :   struct rlimit rlim;
     133         [ -  + ]:         35 :   if (getrlimit(RLIMIT_STACK, &rlim) != 0)
     134                 :          0 :     return;
     135                 :            : 
     136                 :            :   // Increase the soft stack limit to our desired level, if necessary and
     137                 :            :   // possible.
     138 [ +  - ][ -  + ]:         35 :   if (rlim.rlim_cur != RLIM_INFINITY &&
     139                 :         35 :       rlim.rlim_cur < rlim_t(DesiredStackSize)) {
     140                 :            :     // Try to allocate sufficient stack.
     141 [ #  # ][ #  # ]:          0 :     if (rlim.rlim_max == RLIM_INFINITY ||
     142                 :          0 :         rlim.rlim_max >= rlim_t(DesiredStackSize))
     143                 :          0 :       rlim.rlim_cur = DesiredStackSize;
     144         [ #  # ]:          0 :     else if (rlim.rlim_cur == rlim.rlim_max)
     145                 :          0 :       return;
     146                 :            :     else
     147                 :          0 :       rlim.rlim_cur = rlim.rlim_max;
     148                 :            : 
     149 [ #  # ][ #  # ]:          0 :     if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
                 [ #  # ]
     150                 :          0 :         rlim.rlim_cur != DesiredStackSize)
     151                 :          0 :       return;
     152                 :            :   }
     153                 :            : 
     154                 :            :   // We should now have a stack of size at least DesiredStackSize. Ensure
     155                 :            :   // that we can actually use that much, if necessary.
     156                 :         35 :   ensureStackAddressSpace();
     157                 :            : }
     158                 :            : #else
     159                 :            : static void ensureSufficientStack() {}
     160                 :            : #endif
     161                 :            : 
     162                 :         35 : int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
     163                 :         35 :   ensureSufficientStack();
     164                 :            : 
     165                 :         70 :   std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
     166                 :         70 :   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
     167                 :            : 
     168                 :            :   // Register the support for object-file-wrapped Clang modules.
     169                 :         70 :   auto PCHOps = Clang->getPCHContainerOperations();
     170                 :         35 :   PCHOps->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>());
     171                 :         35 :   PCHOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>());
     172                 :            : 
     173                 :            :   // Initialize targets first, so that --version shows registered targets.
     174                 :         35 :   llvm::InitializeAllTargets();
     175                 :         35 :   llvm::InitializeAllTargetMCs();
     176                 :         35 :   llvm::InitializeAllAsmPrinters();
     177                 :         35 :   llvm::InitializeAllAsmParsers();
     178                 :            : 
     179                 :            :   // Buffer diagnostics from argument parsing so that we can output them using a
     180                 :            :   // well formed diagnostic object.
     181                 :         70 :   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
     182                 :         35 :   TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
     183                 :         70 :   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
     184                 :         35 :   bool Success = CompilerInvocation::CreateFromArgs(
     185                 :         35 :       Clang->getInvocation(), Argv.begin(), Argv.end(), Diags);
     186                 :            : 
     187                 :            :   // Infer the builtin include path if unspecified.
     188         [ -  + ]:         35 :   if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
           [ -  +  #  # ]
     189                 :          0 :       Clang->getHeaderSearchOpts().ResourceDir.empty())
     190                 :          0 :     Clang->getHeaderSearchOpts().ResourceDir =
     191                 :          0 :       CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
     192                 :            : 
     193                 :            :   // Create the actual diagnostics engine.
     194                 :         35 :   Clang->createDiagnostics();
     195         [ -  + ]:         35 :   if (!Clang->hasDiagnostics())
     196                 :          0 :     return 1;
     197                 :            : 
     198                 :            :   // Set an error handler, so that any LLVM backend diagnostics go through our
     199                 :            :   // error handler.
     200                 :         35 :   llvm::install_fatal_error_handler(LLVMErrorHandler,
     201                 :         35 :                                   static_cast<void*>(&Clang->getDiagnostics()));
     202                 :            : 
     203                 :         35 :   DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
     204         [ -  + ]:         35 :   if (!Success)
     205                 :          0 :     return 1;
     206                 :            : 
     207                 :            :   // Execute the frontend actions.
     208                 :         35 :   Success = ExecuteCompilerInvocation(Clang.get());
     209                 :            : 
     210                 :            :   // If any timers were active but haven't been destroyed yet, print their
     211                 :            :   // results now.  This happens in -disable-free mode.
     212                 :         35 :   llvm::TimerGroup::printAll(llvm::errs());
     213                 :            : 
     214                 :            :   // Our error handler depends on the Diagnostics object, which we're
     215                 :            :   // potentially about to delete. Uninstall the handler now so that any
     216                 :            :   // later errors use the default handling behavior instead.
     217                 :         35 :   llvm::remove_fatal_error_handler();
     218                 :            : 
     219                 :            :   // When running with -disable-free, don't do any destruction or shutdown.
     220         [ +  - ]:         35 :   if (Clang->getFrontendOpts().DisableFree) {
     221                 :         35 :     llvm::BuryPointer(std::move(Clang));
     222                 :         35 :     return !Success;
     223                 :            :   }
     224                 :            : 
     225                 :          0 :   return !Success;
     226 [ +  - ][ +  - ]:        392 : }
     227                 :            : 

Generated by: LCOV version 1.14