Index: clang/lib/Driver/ToolChains/AVR.h =================================================================== --- clang/lib/Driver/ToolChains/AVR.h +++ clang/lib/Driver/ToolChains/AVR.h @@ -33,6 +33,7 @@ llvm::Optional findAVRLibcInstallation() const; StringRef getGCCInstallPath() const { return GCCInstallPath; } + std::string getCompilerRTPath() const override; protected: Tool *buildLinker() const override; Index: clang/lib/Driver/ToolChains/AVR.cpp =================================================================== --- clang/lib/Driver/ToolChains/AVR.cpp +++ clang/lib/Driver/ToolChains/AVR.cpp @@ -19,6 +19,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" using namespace clang::driver; using namespace clang::driver::toolchains; @@ -369,8 +370,7 @@ : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); - std::string CPU = getCPUName(D, Args, Triple); - if (CPU.empty()) + if (getCPUName(D, Args, Triple).empty()) D.Diag(diag::warn_drv_avr_mcu_not_specified); // Only add default libraries if the user hasn't explicitly opted out. @@ -418,6 +418,14 @@ return new tools::AVR::Linker(getTriple(), *this); } +std::string AVRToolChain::getCompilerRTPath() const { + // Return the default path appended with '/avr', since AVR can never be a + // host environment. + SmallString<128> Path(ToolChain::getCompilerRTPath()); + llvm::sys::path::append(Path, "avr"); + return std::string(Path.str()); +} + void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, @@ -449,6 +457,12 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); getToolChain().AddFilePathLibArgs(Args, CmdArgs); + // Currently we only support libgcc and compiler-rt. + auto RtLib = TC.GetRuntimeLibType(Args); + assert( + (RtLib == ToolChain::RLT_Libgcc || RtLib == ToolChain::RLT_CompilerRT) && + "unknown runtime library"); + // Only add default libraries if the user hasn't explicitly opted out. bool LinkStdlib = false; if (!Args.hasArg(options::OPT_nostdlib) && @@ -464,10 +478,13 @@ D.Diag(diag::warn_drv_avr_libc_not_found); } else { std::string SubPath = GetMCUSubPath(CPU); + // Add path of avr-libc. CmdArgs.push_back( Args.MakeArgString(Twine("-L") + *AVRLibcRoot + "/lib/" + SubPath)); - CmdArgs.push_back( - Args.MakeArgString("-L" + TC.getGCCInstallPath() + "/" + SubPath)); + // Add path of libgcc. + if (RtLib == ToolChain::RLT_Libgcc) + CmdArgs.push_back(Args.MakeArgString("-L" + TC.getGCCInstallPath() + + "/" + SubPath)); LinkStdlib = true; } } @@ -496,7 +513,11 @@ std::string CrtFileName = std::string("-l:crt") + CPU + std::string(".o"); CmdArgs.push_back(Args.MakeArgString(CrtFileName)); - CmdArgs.push_back("-lgcc"); + // Link to libgcc. + if (RtLib == ToolChain::RLT_Libgcc) + CmdArgs.push_back("-lgcc"); + + // Link to generic libraries of avr-libc. CmdArgs.push_back("-lm"); CmdArgs.push_back("-lc"); @@ -505,6 +526,16 @@ CmdArgs.push_back("--end-group"); + // Link to compiler-rt. We directly put the libclang.builtins-avr.a + // as input file, other than '-lclang.builtins-avr'. This is a tradition + // from other platforms, such as x86 and arm. + if (RtLib == ToolChain::RLT_CompilerRT) { + std::string RtLib = + getToolChain().getCompilerRT(Args, "builtins", ToolChain::FT_Static); + if (llvm::sys::fs::exists(RtLib)) + CmdArgs.push_back(Args.MakeArgString(RtLib)); + } + // Add user specified linker script. Args.AddAllArgs(CmdArgs, options::OPT_T); Index: clang/test/Driver/avr-toolchain.c =================================================================== --- clang/test/Driver/avr-toolchain.c +++ clang/test/Driver/avr-toolchain.c @@ -72,3 +72,18 @@ // RUN: %clang -### --target=avr --sysroot=%S/Inputs/basic_avr_tree -mmcu=atmega328 %s -fuse-ld=%S/Inputs/basic_avr_tree/usr/bin/ld.lld -T avr.lds 2>&1 | FileCheck --check-prefix=LDS1 %s // LDS1: "-T" "avr.lds" // LDS1-NOT: "-mavr5" + +// RUN: %clang %s -### --target=avr -mmcu=atmega328 --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir 2>&1 | FileCheck --check-prefix=LIBGCC %s +// RUN: %clang %s -### --target=avr -mmcu=atmega328 --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir --rtlib=libgcc 2>&1 | FileCheck --check-prefix=LIBGCC %s +// LIBGCC: "-lgcc" +// LIBGCC-NOT: libclang_rt + +// RUN: %clang %s -### --target=avr -mmcu=atmega328 --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir --rtlib=compiler-rt 2>&1 | FileCheck --check-prefix=COMRT %s +// RUN: %clang %s -### --target=avr -mmcu=atmega328 --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir -fuse-ld=%S/Inputs/basic_avr_tree/usr/bin/ld.lld --rtlib=compiler-rt 2>&1 | FileCheck --check-prefix=COMRT %s +// COMRT: avr/libclang_rt.builtins-avr.a +// COMRT-NOT: "-lgcc" + +// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir --rtlib=compiler-rt 2>&1 | FileCheck --check-prefix=NOMCU %s +// RUN: %clang %s -### --target=avr --sysroot=%S/Inputs/basic_avr_tree/ -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir --rtlib=libgcc 2>&1 | FileCheck --check-prefix=NOMCU %s +// NOMCU-NOT: libclang_rt +// NOMCU-NOT: "-lgcc"