Call _exit.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 26 Oct 2016 18:59:00 +0000 (18:59 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 26 Oct 2016 18:59:00 +0000 (18:59 +0000)
As the state of lld gets more complicated, shutting down gets more
expensive.

In a normal lld run we can just call _exit immediately after renaming
the temporary output file. We still want the ability to run a full
shutdown since that is useful for detecting memory leaks.

This patch adds a --full-shutdown flag and changes lit to use it.

llvm-svn: 285224

lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/Driver.h
lld/ELF/Options.td
lld/ELF/Writer.cpp
lld/include/lld/Driver/Driver.h
lld/test/ELF/amdgpu-globals.s
lld/test/lit.cfg
lld/tools/lld/lld.cpp

index 88dee03..96eebac 100644 (file)
@@ -128,6 +128,7 @@ struct Configuration {
   bool ZNow;
   bool ZOrigin;
   bool ZRelro;
+  bool ExitEarly;
   bool ZWxneeded;
   DiscardPolicy Discard;
   SortSectionPolicy SortSection;
index 207a2e5..d491592 100644 (file)
@@ -39,7 +39,8 @@ using namespace lld::elf;
 Configuration *elf::Config;
 LinkerDriver *elf::Driver;
 
-bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
+bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
+               raw_ostream &Error) {
   HasError = false;
   ErrorOS = &Error;
   Argv0 = Args[0];
@@ -51,7 +52,7 @@ bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
   Driver = &D;
   ScriptConfig = &SC;
 
-  Driver->main(Args);
+  Driver->main(Args, CanExitEarly);
   InputFile::freePool();
   return !HasError;
 }
@@ -281,7 +282,7 @@ static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key,
   return Default;
 }
 
-void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
+void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
   ELFOptTable Parser;
   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
   if (Args.hasArg(OPT_help)) {
@@ -290,6 +291,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
   }
   if (Args.hasArg(OPT_version))
     outs() << getLLDVersion() << "\n";
+  Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
 
   if (const char *Path = getReproduceOption(Args)) {
     // Note that --reproduce is a debug option so you can ignore it
index 5cd0bc1..faa61a5 100644 (file)
@@ -27,7 +27,7 @@ extern class LinkerDriver *Driver;
 
 class LinkerDriver {
 public:
-  void main(ArrayRef<const char *> Args);
+  void main(ArrayRef<const char *> Args, bool CanExitEarly);
   void addFile(StringRef Path);
   void addLibrary(StringRef Name);
   llvm::LLVMContext Context;      // to parse bitcode files
index 0e13cdb..0174d21 100644 (file)
@@ -80,6 +80,9 @@ def fatal_warnings: F<"fatal-warnings">,
 def fini: S<"fini">, MetaVarName<"<symbol>">,
   HelpText<"Specify a finalizer function">;
 
+def full_shutdown : F<"full-shutdown">,
+  HelpText<"Perform a full shutdown instead of calling _exit">;
+
 def format: J<"format=">, MetaVarName<"<input-format>">,
   HelpText<"Change the input format of the inputs following this option">;
 
index 7728941..e156f3c 100644 (file)
 #include "llvm/Support/raw_ostream.h"
 #include <climits>
 
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#endif
+
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
@@ -316,6 +320,14 @@ template <class ELFT> void Writer<ELFT>::run() {
     return;
   if (auto EC = Buffer->commit())
     error(EC, "failed to write to the output file");
+  if (Config->ExitEarly) {
+    // Flush the output streams and exit immediately.  A full shutdown is a good
+    // test that we are keeping track of all allocated memory, but actually
+    // freeing it is a wast of time in a regular linker run.
+    outs().flush();
+    errs().flush();
+    _exit(0);
+  }
 }
 
 template <class ELFT>
index 312f4f8..a3265c8 100644 (file)
@@ -19,7 +19,7 @@ bool link(llvm::ArrayRef<const char *> Args);
 }
 
 namespace elf {
-bool link(llvm::ArrayRef<const char *> Args,
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
           llvm::raw_ostream &Diag = llvm::errs());
 }
 
index 7f46b98..f30c0ed 100644 (file)
@@ -1,5 +1,5 @@
 # RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
-# RUN: lld -flavor gnu %t.o -o %t
+# RUN: ld.lld %t.o -o %t
 # RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
 
 # REQUIRES: amdgpu
index 3c7fa5d..91813a7 100644 (file)
@@ -150,6 +150,8 @@ if config.test_exec_root is None:
 NoPreJunk = r"(?<!(-|\.|/))"
 NoPostJunk = r"(?!(-|\.))"
 
+config.substitutions.append( (r"\bld.lld\b", 'ld.lld --full-shutdown') )
+
 tool_patterns = [r"\bFileCheck\b",
                  r"\bnot\b",
                  NoPreJunk + r"\blld\b" + NoPostJunk,
index 99f3d2d..0c32ff1 100644 (file)
@@ -101,7 +101,7 @@ int main(int Argc, const char **Argv) {
   std::vector<const char *> Args(Argv, Argv + Argc);
   switch (parseFlavor(Args)) {
   case Gnu:
-    return !elf::link(Args);
+    return !elf::link(Args, true);
   case WinLink:
     return !coff::link(Args);
   case Darwin: