diff --git a/clang/lib/Driver/ToolChains/AVR.h b/clang/lib/Driver/ToolChains/AVR.h --- a/clang/lib/Driver/ToolChains/AVR.h +++ b/clang/lib/Driver/ToolChains/AVR.h @@ -31,17 +31,14 @@ llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const override; + llvm::Optional findAVRLibcInstallation() const; + StringRef getGCCInstallPath() const { return GCCInstallPath; } + protected: Tool *buildLinker() const override; private: - /// Whether libgcc, libct, and friends should be linked. - /// - /// This is not done if the user does not specify a - /// microcontroller on the command line. - bool LinkStdlib; - - llvm::Optional findAVRLibcInstallation() const; + StringRef GCCInstallPath; }; } // end namespace toolchains @@ -50,9 +47,8 @@ namespace AVR { class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: - Linker(const llvm::Triple &Triple, const ToolChain &TC, bool LinkStdlib) - : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple), - LinkStdlib(LinkStdlib) {} + Linker(const llvm::Triple &Triple, const ToolChain &TC) + : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -63,7 +59,6 @@ protected: const llvm::Triple &Triple; - bool LinkStdlib; }; } // end namespace AVR } // end namespace tools diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp --- a/clang/lib/Driver/ToolChains/AVR.cpp +++ b/clang/lib/Driver/ToolChains/AVR.cpp @@ -366,49 +366,19 @@ /// AVR Toolchain AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args), LinkStdlib(false) { + : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); // Only add default libraries if the user hasn't explicitly opted out. if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nodefaultlibs) && - !Args.hasArg(options::OPT_c /* does not apply when not linking */)) { - std::string CPU = getCPUName(D, Args, Triple); - - if (CPU.empty()) { - // We cannot link any standard libraries without an MCU specified. - D.Diag(diag::warn_drv_avr_mcu_not_specified); + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (GCCInstallation.isValid()) { + GCCInstallPath = GCCInstallation.getInstallPath(); + std::string GCCParentPath(GCCInstallation.getParentLibPath()); + getProgramPaths().push_back(GCCParentPath + "/../bin"); } else { - Optional FamilyName = GetMCUFamilyName(CPU); - Optional AVRLibcRoot = findAVRLibcInstallation(); - - if (!FamilyName.hasValue()) { - // 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 (!GCCInstallation.isValid()) { - // No avr-gcc found and so no runtime linked. - D.Diag(diag::warn_drv_avr_gcc_not_found); - } else if (!AVRLibcRoot.hasValue()) { - // No avr-libc found and so no runtime linked. - D.Diag(diag::warn_drv_avr_libc_not_found); - } else { // We have enough information to link stdlibs - std::string GCCRoot(GCCInstallation.getInstallPath()); - std::string GCCParentPath(GCCInstallation.getParentLibPath()); - std::string LibcRoot = AVRLibcRoot.getValue(); - std::string SubPath = GetMCUSubPath(CPU); - - getProgramPaths().push_back(GCCParentPath + "/../bin"); - getFilePaths().push_back(LibcRoot + std::string("/lib/") + SubPath); - getFilePaths().push_back(GCCRoot + std::string("/") + SubPath); - - LinkStdlib = true; - } + D.Diag(diag::warn_drv_avr_gcc_not_found); } - - if (!LinkStdlib) - D.Diag(diag::warn_drv_avr_stdlib_not_linked); } } @@ -445,13 +415,14 @@ } Tool *AVRToolChain::buildLinker() const { - return new tools::AVR::Linker(getTriple(), *this, LinkStdlib); + return new tools::AVR::Linker(getTriple(), *this); } void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + const auto &TC = static_cast(getToolChain()); const Driver &D = getToolChain().getDriver(); // Compute information about the target AVR. @@ -473,6 +444,39 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); getToolChain().AddFilePathLibArgs(Args, CmdArgs); + // Only add default libraries if the user hasn't explicitly opted out. + bool LinkStdlib = false; + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (CPU.empty()) { + // We cannot link any standard libraries without an MCU specified. + D.Diag(diag::warn_drv_avr_mcu_not_specified); + } else { + Optional FamilyName = GetMCUFamilyName(CPU); + Optional 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 (!AVRLibcRoot) { + // No avr-libc found and so no runtime linked. + D.Diag(diag::warn_drv_avr_libc_not_found); + } else if (!TC.getGCCInstallPath().empty()) { + std::string SubPath = GetMCUSubPath(CPU); + CmdArgs.push_back( + Args.MakeArgString(Twine("-L") + *AVRLibcRoot + "/lib/" + SubPath)); + CmdArgs.push_back( + Args.MakeArgString("-L" + TC.getGCCInstallPath() + "/" + SubPath)); + LinkStdlib = true; + } + } + + if (!LinkStdlib) + D.Diag(diag::warn_drv_avr_stdlib_not_linked); + } + if (SectionAddressData.hasValue()) { std::string DataSectionArg = std::string("-Tdata=0x") + llvm::utohexstr(SectionAddressData.getValue()); diff --git a/clang/test/Driver/avr-link-no-mcu-specified.c b/clang/test/Driver/avr-link-no-mcu-specified.c deleted file mode 100644 --- a/clang/test/Driver/avr-link-no-mcu-specified.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang -### -target avr -no-canonical-prefixes -save-temps %s 2>&1 | FileCheck --check-prefix=WARN %s -// RUN: %clang -### -target avr -no-canonical-prefixes -save-temps -mmcu=atmega328 %s 2>&1 | FileCheck --check-prefix=NOWARN %s - -// WARN: warning: no target microcontroller specified on command line, cannot link standard libraries, please pass -mmcu= -// WARN: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked - -// NOWARN: main - -int main() { return 0; } - diff --git a/clang/test/Driver/avr-toolchain.c b/clang/test/Driver/avr-toolchain.c --- a/clang/test/Driver/avr-toolchain.c +++ b/clang/test/Driver/avr-toolchain.c @@ -35,3 +35,11 @@ // RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree 2>&1 -nostdinc | FileCheck --check-prefix=NOSTDINC %s // RUN: %clang %s -### -target avr --sysroot %S/Inputs/basic_avr_tree 2>&1 -nostdlibinc | FileCheck --check-prefix=NOSTDINC %s // NOSTDINC-NOT: "-internal-isystem" {{".*avr/include"}} + +// RUN: %clang -### --target=avr %s 2>&1 | FileCheck --check-prefix=WARN_STDLIB %s +// RUN: %clang -### --target=avr -mmcu=atmega328 %s 2>&1 | FileCheck --check-prefix=NOWARN_STDLIB %s +// RUN: %clang -### --target=avr -c %s 2>&1 | FileCheck --check-prefix=NOWARN_STDLIB %s + +// WARN_STDLIB: warning: no target microcontroller specified on command line, cannot link standard libraries, please pass -mmcu= +// WARN_STDLIB: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked +// NOWARN_STDLIB-NOT: warning: