lld::COFF: better behavior when using as a library
authorRui Ueyama <ruiu@google.com>
Mon, 23 Oct 2017 20:03:32 +0000 (20:03 +0000)
committerRui Ueyama <ruiu@google.com>
Mon, 23 Oct 2017 20:03:32 +0000 (20:03 +0000)
Previously, the COFF driver would call exit(0) when called
as a library.  Now it takes `ExitEarly` option, and if it
is false, it doesn't exit.  So it is now more library-friendly.

Furthermore, link() calls freeArena() before returning, to
clean up resources.

Based on an Andrew Kelley's patch.

Differential Revision: https://reviews.llvm.org/D39202

llvm-svn: 316370

lld/COFF/Config.h
lld/COFF/Driver.cpp
lld/COFF/Error.cpp
lld/COFF/Error.h
lld/MinGW/Driver.cpp
lld/include/lld/Common/Driver.h
lld/tools/lld/lld.cpp

index 995a398a3c911e76f6ed750bfc993b7c5ea4fcc4..7a281b3fccc58bffd08f57a630658fd1a01e17c6 100644 (file)
@@ -166,6 +166,7 @@ struct Configuration {
   uint32_t MinorImageVersion = 0;
   uint32_t MajorOSVersion = 6;
   uint32_t MinorOSVersion = 0;
+  bool CanExitEarly = false;
   bool DynamicBase = true;
   bool AllowBind = true;
   bool NxCompat = true;
index 133cf40a83bffd324ca9c0441f06e063dbb44a39..168d99093c5ff471ca9a7212b0715824da348402 100644 (file)
@@ -54,18 +54,25 @@ BumpPtrAllocator BAlloc;
 StringSaver Saver{BAlloc};
 std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
 
-bool link(ArrayRef<const char *> Args, raw_ostream &Diag) {
+bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
   ErrorCount = 0;
   ErrorOS = &Diag;
 
   Config = make<Configuration>();
   Config->Argv = {Args.begin(), Args.end()};
   Config->ColorDiagnostics = ErrorOS->has_colors();
+  Config->CanExitEarly = CanExitEarly;
 
   Symtab = make<SymbolTable>();
 
   Driver = make<LinkerDriver>();
   Driver->link(Args);
+
+  // Call exit() if we can to avoid calling destructors.
+  if (CanExitEarly)
+    exitLld(ErrorCount ? 1 : 0);
+
+  freeArena();
   return !ErrorCount;
 }
 
@@ -1087,7 +1094,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   if (!Args.hasArg(OPT_INPUT)) {
     fixupExports();
     createImportLibrary(/*AsLib=*/true);
-    exit(0);
+    return;
   }
 
   // Handle /delayload
@@ -1179,7 +1186,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   // This is useful because MSVC link.exe can generate complete PDBs.
   if (Args.hasArg(OPT_msvclto)) {
     invokeMSVC(Args);
-    exit(0);
+    return;
   }
 
   // Do LTO by compiling bitcode input files to a set of native COFF files then
@@ -1273,12 +1280,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
 
   // Write the result.
   writeResult();
-
-  if (ErrorCount)
-    return;
-
-  // Call exit to avoid calling destructors.
-  exit(0);
 }
 
 } // namespace coff
index 34abc280f6bfea0de0a56e52c5da471ff7278fb9..550d9b9696721f4a841f6941942a181e7d884a67 100644 (file)
@@ -32,7 +32,7 @@ namespace coff {
 uint64_t ErrorCount;
 raw_ostream *ErrorOS;
 
-static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
+LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
   // Dealloc/destroy ManagedStatic variables before calling
   // _exit(). In a non-LTO build, this is a nop. In an LTO
   // build allows us to get the output of -time-passes.
@@ -78,7 +78,8 @@ void error(const Twine &Msg) {
     print("error: ", raw_ostream::RED);
     *ErrorOS << "too many errors emitted, stopping now"
              << " (use /ERRORLIMIT:0 to see all errors)\n";
-    exitLld(1);
+    if (Config->CanExitEarly)
+      exitLld(1);
   }
 
   ++ErrorCount;
index 1cc2dd4ed9056936511a91795f315c09c4fc2951..ac3bf81f30f4966653528ea19ce21ebd9c4bfb81 100644 (file)
@@ -27,6 +27,8 @@ LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
 LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
 LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
 
+LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
+
 template <class T> T check(ErrorOr<T> V, const Twine &Prefix) {
   if (auto EC = V.getError())
     fatal(EC, Prefix);
index ebb66125fdd7f5b5773836702af8cf8335614783..451ae2d6e461accb80a650f898f1173b202be64c 100644 (file)
@@ -217,5 +217,5 @@ bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) {
   std::vector<const char *> Vec;
   for (const std::string &S : LinkArgs)
     Vec.push_back(S.c_str());
-  return coff::link(Vec);
+  return coff::link(Vec, true);
 }
index b3fa471281693e44b3968e873cdc939e3509735d..dee46f808b10a2c8eaa63739d0fb2c820a59b3b7 100644 (file)
@@ -15,7 +15,7 @@
 
 namespace lld {
 namespace coff {
-bool link(llvm::ArrayRef<const char *> Args,
+bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,
           llvm::raw_ostream &Diag = llvm::errs());
 }
 
index bbdba4837906a83eebfc46a06d24b29e8f797645..a819c20de4470ada7481b89a4d22b0637455b79f 100644 (file)
@@ -115,7 +115,7 @@ int main(int Argc, const char **Argv) {
       return !mingw::link(Args);
     return !elf::link(Args, true);
   case WinLink:
-    return !coff::link(Args);
+    return !coff::link(Args, true);
   case Darwin:
     return !mach_o::link(Args);
   default: