AVR.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //===--- AVR.cpp - AVR ToolChain Implementations ----------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "AVR.h"
  9. #include "CommonArgs.h"
  10. #include "InputInfo.h"
  11. #include "clang/Driver/Compilation.h"
  12. #include "clang/Driver/DriverDiagnostic.h"
  13. #include "clang/Driver/Options.h"
  14. #include "llvm/ADT/Optional.h"
  15. #include "llvm/ADT/StringSwitch.h"
  16. #include "llvm/MC/MCSubtargetInfo.h"
  17. #include "llvm/MC/SubtargetFeature.h"
  18. #include "llvm/Option/ArgList.h"
  19. #include "llvm/Support/FileSystem.h"
  20. using namespace clang::driver;
  21. using namespace clang::driver::toolchains;
  22. using namespace clang::driver::tools;
  23. using namespace clang;
  24. using namespace llvm::opt;
  25. namespace {
  26. // TODO: Consider merging this into the AVR device table
  27. // array in Targets/AVR.cpp.
  28. llvm::Optional<StringRef> GetMcuFamilyName(StringRef MCU) {
  29. return llvm::StringSwitch<llvm::Optional<StringRef>>(MCU)
  30. .Case("atmega328", Optional<StringRef>("avr5"))
  31. .Case("atmega328p", Optional<StringRef>("avr5"))
  32. .Default(Optional<StringRef>());
  33. }
  34. const StringRef PossibleAVRLibcLocations[] = {
  35. "/usr/avr",
  36. "/usr/lib/avr",
  37. };
  38. } // end anonymous namespace
  39. /// AVR Toolchain
  40. AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
  41. const ArgList &Args)
  42. : Generic_ELF(D, Triple, Args), LinkStdlib(false) {
  43. GCCInstallation.init(Triple, Args);
  44. // Only add default libraries if the user hasn't explicitly opted out.
  45. if (!Args.hasArg(options::OPT_nostdlib) &&
  46. !Args.hasArg(options::OPT_nodefaultlibs) &&
  47. !Args.hasArg(options::OPT_c /* does not apply when not linking */)) {
  48. std::string CPU = getCPUName(Args, Triple);
  49. if (CPU.empty()) {
  50. // We cannot link any standard libraries without an MCU specified.
  51. D.Diag(diag::warn_drv_avr_mcu_not_specified);
  52. } else {
  53. Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
  54. Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
  55. if (!FamilyName.hasValue()) {
  56. // We do not have an entry for this CPU in the family
  57. // mapping table yet.
  58. D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
  59. << CPU;
  60. } else if (!GCCInstallation.isValid()) {
  61. // No avr-gcc found and so no runtime linked.
  62. D.Diag(diag::warn_drv_avr_gcc_not_found);
  63. } else if (!AVRLibcRoot.hasValue()) {
  64. // No avr-libc found and so no runtime linked.
  65. D.Diag(diag::warn_drv_avr_libc_not_found);
  66. } else { // We have enough information to link stdlibs
  67. std::string GCCRoot = GCCInstallation.getInstallPath();
  68. std::string LibcRoot = AVRLibcRoot.getValue();
  69. getFilePaths().push_back(LibcRoot + std::string("/lib/") +
  70. std::string(*FamilyName));
  71. getFilePaths().push_back(LibcRoot + std::string("/lib/") +
  72. std::string(*FamilyName));
  73. getFilePaths().push_back(GCCRoot + std::string("/") +
  74. std::string(*FamilyName));
  75. LinkStdlib = true;
  76. }
  77. }
  78. if (!LinkStdlib)
  79. D.Diag(diag::warn_drv_avr_stdlib_not_linked);
  80. }
  81. }
  82. Tool *AVRToolChain::buildLinker() const {
  83. return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
  84. }
  85. void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  86. const InputInfo &Output,
  87. const InputInfoList &Inputs,
  88. const ArgList &Args,
  89. const char *LinkingOutput) const {
  90. // Compute information about the target AVR.
  91. std::string CPU = getCPUName(Args, getToolChain().getTriple());
  92. llvm::Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
  93. std::string Linker = getToolChain().GetProgramPath(getShortName());
  94. ArgStringList CmdArgs;
  95. AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  96. CmdArgs.push_back("-o");
  97. CmdArgs.push_back(Output.getFilename());
  98. // Enable garbage collection of unused sections.
  99. CmdArgs.push_back("--gc-sections");
  100. // Add library search paths before we specify libraries.
  101. Args.AddAllArgs(CmdArgs, options::OPT_L);
  102. getToolChain().AddFilePathLibArgs(Args, CmdArgs);
  103. // If the family name is known, we can link with the device-specific libgcc.
  104. // Without it, libgcc will simply not be linked. This matches avr-gcc
  105. // behavior.
  106. if (LinkStdlib) {
  107. assert(!CPU.empty() && "CPU name must be known in order to link stdlibs");
  108. // Add the object file for the CRT.
  109. std::string CrtFileName = std::string("-l:crt") + CPU + std::string(".o");
  110. CmdArgs.push_back(Args.MakeArgString(CrtFileName));
  111. CmdArgs.push_back("-lgcc");
  112. CmdArgs.push_back("-lm");
  113. CmdArgs.push_back("-lc");
  114. // Add the link library specific to the MCU.
  115. CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
  116. // Specify the family name as the emulation mode to use.
  117. // This is almost always required because otherwise avr-ld
  118. // will assume 'avr2' and warn about the program being larger
  119. // than the bare minimum supports.
  120. CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
  121. }
  122. C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
  123. CmdArgs, Inputs));
  124. }
  125. llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
  126. for (StringRef PossiblePath : PossibleAVRLibcLocations) {
  127. // Return the first avr-libc installation that exists.
  128. if (llvm::sys::fs::is_directory(PossiblePath))
  129. return Optional<std::string>(std::string(PossiblePath));
  130. }
  131. return llvm::None;
  132. }