[lld] e16c0a9 - clang+lld: Improve clang+ld.darwinnew.lld interaction, pass -demangle

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 24 05:52:15 PST 2020


Author: Nico Weber
Date: 2020-11-24T08:51:58-05:00
New Revision: e16c0a9a689719f379e49d0a05cb58774cce4adb

URL: https://github.com/llvm/llvm-project/commit/e16c0a9a689719f379e49d0a05cb58774cce4adb
DIFF: https://github.com/llvm/llvm-project/commit/e16c0a9a689719f379e49d0a05cb58774cce4adb.diff

LOG: clang+lld: Improve clang+ld.darwinnew.lld interaction, pass -demangle

This patch:
- adds an ld64.lld.darwinnew symlink for lld, to go with f2710d4b576,
  so that `clang -fuse-ld=lld.darwinnew` can be used to test new
  Mach-O lld while it's in bring-up. (The expectation is that we'll
  remove this again once new Mach-O lld is the defauld and only Mach-O
  lld.)
- lets the clang driver know if the linker is lld (currently
  only triggered if `-fuse-ld=lld` or `-fuse-ld=lld.darwinnew` is
  passed). Currently only used for the next point, but could be used
  to implement other features that need close coordination between
  compiler and linker, e.g. having a diag for calling `clang++` instead
  of `clang` when link errors are caused by a missing C++ stdlib.
- lets the clang driver pass `-demangle` to Mach-O lld (both old and
  new), in addition to ld64
- implements -demangle for new Mach-O lld
- changes demangleItanium() to accept _Z, __Z, ___Z, ____Z prefixes
  (and updates one test added in D68014). Mach-O has an extra
  underscore for symbols, and the three (or, on Mach-O, four)
  underscores are used for block names.

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

Added: 
    clang/test/Driver/darwin-ld-demangle-lld.c
    lld/test/MachO/demangle.s

Modified: 
    clang/include/clang/Driver/ToolChain.h
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/ToolChains/Darwin.cpp
    clang/lib/Driver/ToolChains/Darwin.h
    lld/Common/Strings.cpp
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/MachO/Options.td
    lld/MachO/Symbols.cpp
    lld/MachO/Writer.cpp
    lld/test/ELF/undef.s
    lld/test/MachO/silent-ignore.test
    lld/tools/lld/CMakeLists.txt
    llvm/utils/gn/secondary/lld/tools/lld/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 99a5f3238865..58df4d04aea6 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -327,7 +327,11 @@ class ToolChain {
 
   /// Returns the linker path, respecting the -fuse-ld= argument to determine
   /// the linker suffix or name.
-  std::string GetLinkerPath() const;
+  /// If LinkerIsLLD is non-nullptr, it is set to true if the returned linker
+  /// is LLD. If it's set, it can be assumed that the linker is LLD built
+  /// at the same revision as clang, and clang can make assumptions about
+  /// LLD's supported flags, error output, etc.
+  std::string GetLinkerPath(bool *LinkerIsLLD = nullptr) const;
 
   /// Returns the linker path for emitting a static library.
   std::string GetStaticLibToolPath() const;

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index d2a265298007..ae1838aeb9db 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -548,7 +548,10 @@ std::string ToolChain::GetProgramPath(const char *Name) const {
   return D.GetProgramPath(Name, *this);
 }
 
-std::string ToolChain::GetLinkerPath() const {
+std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
+  if (LinkerIsLLD)
+    *LinkerIsLLD = false;
+
   // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
   // considered as the linker flavor, e.g. "bfd", "gold", or "lld".
   const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
@@ -599,8 +602,12 @@ std::string ToolChain::GetLinkerPath() const {
     LinkerName.append(UseLinker);
 
     std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
-    if (llvm::sys::fs::can_execute(LinkerPath))
+    if (llvm::sys::fs::can_execute(LinkerPath)) {
+      if (LinkerIsLLD)
+        // FIXME: Remove lld.darwinnew here once it's the only MachO lld.
+        *LinkerIsLLD = UseLinker == "lld" || UseLinker == "lld.darwinnew";
       return LinkerPath;
+    }
   }
 
   if (A)

diff  --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index c847be9ee266..ddfab0e6ab7c 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -204,15 +204,18 @@ static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
 void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
                                  ArgStringList &CmdArgs,
                                  const InputInfoList &Inputs,
-                                 unsigned Version[5]) const {
+                                 unsigned Version[5], bool LinkerIsLLD) const {
   const Driver &D = getToolChain().getDriver();
   const toolchains::MachO &MachOTC = getMachOToolChain();
 
   // Newer linkers support -demangle. Pass it if supported and not disabled by
   // the user.
-  if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+  if ((Version[0] >= 100 || LinkerIsLLD) &&
+      !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
     CmdArgs.push_back("-demangle");
 
+  // FIXME: Pass most of the flags below that check Version if LinkerIsLLD too.
+
   if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
     CmdArgs.push_back("-export_dynamic");
 
@@ -533,9 +536,13 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
           << A->getAsString(Args);
   }
 
+  bool LinkerIsLLD = false;
+  const char *Exec =
+      Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
+
   // I'm not sure why this particular decomposition exists in gcc, but
   // we follow suite for ease of comparison.
-  AddLinkArgs(C, Args, CmdArgs, Inputs, Version);
+  AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD);
 
   if (willEmitRemarks(Args) &&
       checkRemarksOptions(getToolChain().getDriver(), Args,
@@ -693,7 +700,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                        "-filelist"};
   }
 
-  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
   std::unique_ptr<Command> Cmd = std::make_unique<Command>(
       JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
   Cmd->setInputFileList(std::move(InputFileList));

diff  --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index c62c344a98da..09949db5a2bc 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -63,7 +63,8 @@ class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
   bool NeedsTempPath(const InputInfoList &Inputs) const;
   void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
                    llvm::opt::ArgStringList &CmdArgs,
-                   const InputInfoList &Inputs, unsigned Version[5]) const;
+                   const InputInfoList &Inputs, unsigned Version[5],
+                   bool LinkerIsLLD) const;
 
 public:
   Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}

diff  --git a/clang/test/Driver/darwin-ld-demangle-lld.c b/clang/test/Driver/darwin-ld-demangle-lld.c
new file mode 100644
index 000000000000..dfa48353e5a7
--- /dev/null
+++ b/clang/test/Driver/darwin-ld-demangle-lld.c
@@ -0,0 +1,6 @@
+// With -fuse-ld=lld, -demangle is always passed to the linker on Darwin.
+
+// RUN: %clang -### -fuse-ld=lld %s 2>&1 | FileCheck %s
+// FIXME: Remove ld.darwinnew once it's the default (and only) mach-o lld.
+// RUN: %clang -### -fuse-ld=lld.darwinnew %s 2>&1 | FileCheck %s
+// CHECK: -demangle

diff  --git a/lld/Common/Strings.cpp b/lld/Common/Strings.cpp
index 17c2c207491f..e3148d3d974d 100644
--- a/lld/Common/Strings.cpp
+++ b/lld/Common/Strings.cpp
@@ -21,12 +21,11 @@ using namespace lld;
 
 // Returns the demangled C++ symbol name for name.
 std::string lld::demangleItanium(StringRef name) {
-  // itaniumDemangle can be used to demangle strings other than symbol
-  // names which do not necessarily start with "_Z". Name can be
-  // either a C or C++ symbol. Don't call demangle if the name
-  // does not look like a C++ symbol name to avoid getting unexpected
-  // result for a C symbol that happens to match a mangled type name.
-  if (!name.startswith("_Z"))
+  // demangleItanium() can be called for all symbols. Only demangle C++ symbols,
+  // to avoid getting unexpected result for a C symbol that happens to match a
+  // mangled type name such as "Pi" (which would demangle to "int*").
+  if (!name.startswith("_Z") && !name.startswith("__Z") &&
+      !name.startswith("___Z") && !name.startswith("____Z"))
     return std::string(name);
 
   return demangle(std::string(name));

diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 633dbb0184fc..82c017063d44 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -43,6 +43,7 @@ struct Configuration {
   uint32_t headerPad;
   llvm::StringRef installName;
   llvm::StringRef outputFile;
+  bool demangle = false;
   llvm::MachO::Architecture arch;
   PlatformInfo platform;
   llvm::MachO::HeaderFileType outputType;

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 3b1daadf9f0a..0f5da218e80d 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -584,6 +584,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
   config->runtimePaths = args::getStrings(args, OPT_rpath);
   config->allLoad = args.hasArg(OPT_all_load);
   config->forceLoadObjC = args.hasArg(OPT_ObjC);
+  config->demangle = args.hasArg(OPT_demangle);
 
   if (const opt::Arg *arg = args.getLastArg(OPT_static, OPT_dynamic))
     config->staticLink = (arg->getOption().getID() == OPT_static);

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 3695bd1e2868..4aa999826fb6 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -1107,9 +1107,7 @@ def debug_snapshot : Flag<["-"], "debug_snapshot">,
      Flags<[HelpHidden]>,
      Group<grp_undocumented>;
 def demangle : Flag<["-"], "demangle">,
-     HelpText<"This option is undocumented in ld64">,
-     Flags<[HelpHidden]>,
-     Group<grp_undocumented>;
+     HelpText<"Demangle symbol names in diagnostics">;
 def dyld_env : Flag<["-"], "dyld_env">,
      HelpText<"This option is undocumented in ld64">,
      Flags<[HelpHidden]>,

diff  --git a/lld/MachO/Symbols.cpp b/lld/MachO/Symbols.cpp
index 75c699781a61..87bbab00901f 100644
--- a/lld/MachO/Symbols.cpp
+++ b/lld/MachO/Symbols.cpp
@@ -33,8 +33,8 @@ void LazySymbol::fetchArchiveMember() { file->fetch(sym); }
 
 // Returns a symbol for an error message.
 std::string lld::toString(const Symbol &sym) {
-  if (Optional<std::string> s = demangleItanium(sym.getName()))
-    return *s;
+  if (config->demangle)
+    return demangleItanium(sym.getName());
   return std::string(sym.getName());
 }
 

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index c5239469ff2d..fa42c1c7e61c 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -379,7 +379,7 @@ void Writer::scanRelocations() {
     for (Reloc &r : isec->relocs) {
       if (auto *s = r.referent.dyn_cast<lld::macho::Symbol *>()) {
         if (isa<Undefined>(s))
-          error("undefined symbol " + s->getName() + ", referenced from " +
+          error("undefined symbol " + toString(*s) + ", referenced from " +
                 sys::path::filename(isec->file->getName()));
         else
           target->prepareSymbolRelocation(s, isec, r);

diff  --git a/lld/test/ELF/undef.s b/lld/test/ELF/undef.s
index 4f39d20dd6a0..931a482e1810 100644
--- a/lld/test/ELF/undef.s
+++ b/lld/test/ELF/undef.s
@@ -27,9 +27,7 @@
 # CHECK-NEXT: >>>               {{.*}}:(.text+0x15)
 # CHECK-NEXT: >>> the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction)
 
-# Check that this symbol isn't demangled
-
-# CHECK:      error: undefined symbol: __Z3fooi
+# CHECK:      error: undefined symbol: foo(int)
 # CHECK-NEXT: >>> referenced by undef.s
 # CHECK-NEXT: >>>               {{.*}}:(.text+0x1A)
 

diff  --git a/lld/test/MachO/demangle.s b/lld/test/MachO/demangle.s
new file mode 100644
index 000000000000..c3ff999a468d
--- /dev/null
+++ b/lld/test/MachO/demangle.s
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+
+# RUN: not %lld %t.o -o /dev/null 2>&1 | FileCheck %s
+# RUN: not %lld -demangle %t.o -o /dev/null 2>&1 | \
+# RUN:     FileCheck --check-prefix=DEMANGLE %s
+
+# CHECK: undefined symbol __Z1fv
+# DEMANGLE: undefined symbol f()
+
+.globl _main
+_main:
+  callq __Z1fv
+  ret

diff  --git a/lld/test/MachO/silent-ignore.test b/lld/test/MachO/silent-ignore.test
index 9e997d73aa97..cac66606b0bf 100644
--- a/lld/test/MachO/silent-ignore.test
+++ b/lld/test/MachO/silent-ignore.test
@@ -1,5 +1,4 @@
 RUN: %lld -v \
-RUN:   -demangle \
 RUN:   -dynamic \
 RUN:   -no_deduplicate \
 RUN:   -lto_library /lib/foo \

diff  --git a/lld/tools/lld/CMakeLists.txt b/lld/tools/lld/CMakeLists.txt
index e6f72fcd3488..01cccab38714 100644
--- a/lld/tools/lld/CMakeLists.txt
+++ b/lld/tools/lld/CMakeLists.txt
@@ -24,7 +24,8 @@ install(TARGETS lld
   RUNTIME DESTINATION bin)
 
 if(NOT LLD_SYMLINKS_TO_CREATE)
-  set(LLD_SYMLINKS_TO_CREATE lld-link ld.lld ld64.lld wasm-ld)
+  set(LLD_SYMLINKS_TO_CREATE
+      lld-link ld.lld ld64.lld ld64.darwinnew.lld wasm-ld)
 endif()
 
 foreach(link ${LLD_SYMLINKS_TO_CREATE})

diff  --git a/llvm/utils/gn/secondary/lld/tools/lld/BUILD.gn b/llvm/utils/gn/secondary/lld/tools/lld/BUILD.gn
index f93a44fa634c..a4443c5a1c30 100644
--- a/llvm/utils/gn/secondary/lld/tools/lld/BUILD.gn
+++ b/llvm/utils/gn/secondary/lld/tools/lld/BUILD.gn
@@ -4,6 +4,7 @@ symlinks = [
   "lld-link",
   "ld.lld",
   "ld64.lld",
+  "ld64.darwinnew.lld",
   "wasm-ld",
 ]
 foreach(target, symlinks) {


        


More information about the llvm-commits mailing list