benshi001 created this revision.
benshi001 added reviewers: aykevl, MaskRay.
Herald added subscribers: StephenFan, Jim, dylanmckay.
Herald added a project: All.
benshi001 requested review of this revision.
Herald added subscribers: cfe-commits, jacquesguan.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126192

Files:
  clang/lib/Driver/ToolChains/AVR.cpp
  clang/test/Driver/Inputs/basic_avr_tree/usr/bin/ld.lld
  clang/test/Driver/Inputs/basic_avr_tree/usr/lib/avr/lib/ldscripts/avr5.xn
  clang/test/Driver/avr-toolchain.c

Index: clang/test/Driver/avr-toolchain.c
===================================================================
--- clang/test/Driver/avr-toolchain.c
+++ clang/test/Driver/avr-toolchain.c
@@ -53,8 +53,15 @@
 // LINKA-NOT: warning: {{.*}} data section address
 
 // RUN: %clang -### --target=avr --sysroot=%S/Inputs/ -mmcu=atmega328 %s 2>&1 | FileCheck --check-prefixes=NOGCC %s
-// NOGCC: warning: no avr-gcc installation can be found on the system, cannot link standard libraries
+// NOGCC: error: invalid linker
 // NOGCC: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked
 // NOGCC-NOT: warning: {{.*}} microcontroller
 // NOGCC-NOT: warning: {{.*}} avr-libc
 // NOGCC-NOT: warning: {{.*}} data section address
+
+// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=avrld 2>&1 | FileCheck --check-prefix=NOLD %s
+// NOLD: error: invalid linker
+
+// RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=lld 2>&1 | FileCheck --check-prefix=LLD %s
+// LLD: {{".*lld"}} {{.*}} "-e" "__vectors" "-T" {{".*avr5.xn"}}
+// LLD-NOT: "-mavr5"
Index: clang/lib/Driver/ToolChains/AVR.cpp
===================================================================
--- clang/lib/Driver/ToolChains/AVR.cpp
+++ clang/lib/Driver/ToolChains/AVR.cpp
@@ -429,9 +429,24 @@
   // Compute information about the target AVR.
   std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
   llvm::Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
+  llvm::Optional<std::string> AVRLibcRoot = TC.findAVRLibcInstallation();
   llvm::Optional<unsigned> SectionAddressData = GetMCUSectionAddressData(CPU);
 
+  // Compute the linker program path, and use GNU "avr-ld" as default.
   std::string Linker = getToolChain().GetProgramPath(getShortName());
+  const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+  if (A) {
+    std::string UseLinker = A->getValue();
+    // Compute full path of ld.lld.
+    if (UseLinker == "lld")
+      Linker = getToolChain().GetProgramPath("ld.lld");
+    else
+      Linker = UseLinker;
+  }
+  // Check if the linker program is valid.
+  if (!llvm::sys::fs::can_execute(Linker))
+    D.Diag(diag::err_drv_invalid_linker_name) << Linker;
+
   ArgStringList CmdArgs;
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
 
@@ -450,17 +465,11 @@
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
     if (!CPU.empty()) {
-        Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
-        Optional<std::string> AVRLibcRoot = TC.findAVRLibcInstallation();
-
       if (!FamilyName) {
         // We do not have an entry for this CPU in the family
         // mapping table yet.
         D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
             << CPU;
-      } else if (TC.getGCCInstallPath().empty()) {
-        // We can not link since there is no avr-ld.
-        D.Diag(diag::warn_drv_avr_gcc_not_found);
       } else if (!AVRLibcRoot) {
         // No avr-libc found and so no runtime linked.
         D.Diag(diag::warn_drv_avr_libc_not_found);
@@ -473,7 +482,6 @@
         LinkStdlib = true;
       }
     }
-
     if (!LinkStdlib)
       D.Diag(diag::warn_drv_avr_stdlib_not_linked);
   }
@@ -508,11 +516,28 @@
 
     CmdArgs.push_back("--end-group");
 
-    // Specify the family name as the emulation mode to use.
-    // This is almost always required because otherwise avr-ld
-    // will assume 'avr2' and warn about the program being larger
-    // than the bare minimum supports.
-    CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
+    // Add specific options for different linkers.
+    if (Linker.find("avr-ld") != std::string::npos) {
+      // Specify the family name as the emulation mode to use.
+      // This is almost always required because otherwise avr-ld
+      // will assume 'avr2' and warn about the program being larger
+      // than the bare minimum supports.
+      CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
+    } else if (Linker.find("ld.lld") != std::string::npos) {
+      // We must explicitly specify `__vectors` as the entry for lld.
+      CmdArgs.push_back(Args.MakeArgString("-e"));
+      CmdArgs.push_back(Args.MakeArgString("__vectors"));
+      // We must explicitly spefify the linker script (for lld), which has
+      // already been integrated into avr-libc, and whose full path is
+      // expected to be $AVR-LIBC/lib/ldscripts/$FamilyName.xn .
+      if (AVRLibcRoot && FamilyName) {
+        std::string Prefix(*AVRLibcRoot + "/lib/ldscripts/");
+        if (llvm::sys::fs::is_directory(Prefix)) {
+          CmdArgs.push_back(Args.MakeArgString("-T"));
+          CmdArgs.push_back(Args.MakeArgString(Prefix + *FamilyName + ".xn"));
+        }
+      }
+    }
   }
 
   C.addCommand(std::make_unique<Command>(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to