clang  9.0.0svn
AVR.cpp
Go to the documentation of this file.
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 
9 #include "AVR.h"
10 #include "CommonArgs.h"
11 #include "InputInfo.h"
14 #include "clang/Driver/Options.h"
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/MC/MCSubtargetInfo.h"
18 #include "llvm/MC/SubtargetFeature.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Support/FileSystem.h"
21 
22 using namespace clang::driver;
23 using namespace clang::driver::toolchains;
24 using namespace clang::driver::tools;
25 using namespace clang;
26 using namespace llvm::opt;
27 
28 namespace {
29 
30 // TODO: Consider merging this into the AVR device table
31 // array in Targets/AVR.cpp.
32 llvm::Optional<StringRef> GetMcuFamilyName(StringRef MCU) {
33  return llvm::StringSwitch<llvm::Optional<StringRef>>(MCU)
34  .Case("atmega328", Optional<StringRef>("avr5"))
35  .Case("atmega328p", Optional<StringRef>("avr5"))
37 }
38 
39 const StringRef PossibleAVRLibcLocations[] = {
40  "/usr/avr",
41  "/usr/lib/avr",
42 };
43 
44 } // end anonymous namespace
45 
46 /// AVR Toolchain
47 AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
48  const ArgList &Args)
49  : Generic_ELF(D, Triple, Args), LinkStdlib(false) {
50  GCCInstallation.init(Triple, Args);
51 
52  // Only add default libraries if the user hasn't explicitly opted out.
53  if (!Args.hasArg(options::OPT_nostdlib) &&
54  !Args.hasArg(options::OPT_nodefaultlibs) &&
55  !Args.hasArg(options::OPT_c /* does not apply when not linking */)) {
56  std::string CPU = getCPUName(Args, Triple);
57 
58  if (CPU.empty()) {
59  // We cannot link any standard libraries without an MCU specified.
60  D.Diag(diag::warn_drv_avr_mcu_not_specified);
61  } else {
62  Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
63  Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
64 
65  if (!FamilyName.hasValue()) {
66  // We do not have an entry for this CPU in the family
67  // mapping table yet.
68  D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
69  << CPU;
70  } else if (!GCCInstallation.isValid()) {
71  // No avr-gcc found and so no runtime linked.
72  D.Diag(diag::warn_drv_avr_gcc_not_found);
73  } else if (!AVRLibcRoot.hasValue()) {
74  // No avr-libc found and so no runtime linked.
75  D.Diag(diag::warn_drv_avr_libc_not_found);
76  } else { // We have enough information to link stdlibs
77  std::string GCCRoot = GCCInstallation.getInstallPath();
78  std::string LibcRoot = AVRLibcRoot.getValue();
79 
80  getFilePaths().push_back(LibcRoot + std::string("/lib/") +
81  std::string(*FamilyName));
82  getFilePaths().push_back(LibcRoot + std::string("/lib/") +
83  std::string(*FamilyName));
84  getFilePaths().push_back(GCCRoot + std::string("/") +
85  std::string(*FamilyName));
86 
87  LinkStdlib = true;
88  }
89  }
90 
91  if (!LinkStdlib)
92  D.Diag(diag::warn_drv_avr_stdlib_not_linked);
93  }
94 }
95 
97  return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
98 }
99 
100 void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
101  const InputInfo &Output,
102  const InputInfoList &Inputs,
103  const ArgList &Args,
104  const char *LinkingOutput) const {
105  // Compute information about the target AVR.
106  std::string CPU = getCPUName(Args, getToolChain().getTriple());
107  llvm::Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
108 
109  std::string Linker = getToolChain().GetProgramPath(getShortName());
110  ArgStringList CmdArgs;
111  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
112 
113  CmdArgs.push_back("-o");
114  CmdArgs.push_back(Output.getFilename());
115 
116  // Enable garbage collection of unused sections.
117  CmdArgs.push_back("--gc-sections");
118 
119  // Add library search paths before we specify libraries.
120  Args.AddAllArgs(CmdArgs, options::OPT_L);
121  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
122 
123  // If the family name is known, we can link with the device-specific libgcc.
124  // Without it, libgcc will simply not be linked. This matches avr-gcc
125  // behavior.
126  if (LinkStdlib) {
127  assert(!CPU.empty() && "CPU name must be known in order to link stdlibs");
128 
129  // Add the object file for the CRT.
130  std::string CrtFileName = std::string("-l:crt") + CPU + std::string(".o");
131  CmdArgs.push_back(Args.MakeArgString(CrtFileName));
132 
133  CmdArgs.push_back("-lgcc");
134  CmdArgs.push_back("-lm");
135  CmdArgs.push_back("-lc");
136 
137  // Add the link library specific to the MCU.
138  CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
139 
140  // Specify the family name as the emulation mode to use.
141  // This is almost always required because otherwise avr-ld
142  // will assume 'avr2' and warn about the program being larger
143  // than the bare minimum supports.
144  CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
145  }
146 
147  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
148  CmdArgs, Inputs));
149 }
150 
151 llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
152  for (StringRef PossiblePath : PossibleAVRLibcLocations) {
153  // Return the first avr-libc installation that exists.
154  if (llvm::sys::fs::is_directory(PossiblePath))
155  return Optional<std::string>(std::string(PossiblePath));
156  }
157 
158  return llvm::None;
159 }
AVRToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
AVR Toolchain.
Definition: AVR.cpp:47
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:108
std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T, bool FromAs=false)
const char * getFilename() const
Definition: InputInfo.h:83
GCCInstallationDetector GCCInstallation
Definition: Gnu.h:279
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
path_list & getFilePaths()
Definition: ToolChain.h:231
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:57
void addCommand(std::unique_ptr< Command > C)
Definition: Compilation.h:205
#define false
Definition: stdbool.h:17
Dataflow Directional Tag Classes.
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
Tool - Information on a specific compilation tool.
Definition: Tool.h:33
Tool * buildLinker() const override
Definition: AVR.cpp:96
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
const llvm::Triple & getTriple() const
Definition: ToolChain.h:195
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args, ArrayRef< std::string > ExtraTripleAliases=None)
Initialize a GCCInstallationDetector from the driver.
Definition: Gnu.cpp:1759
StringRef getInstallPath() const
Get the detected GCC installation path.
Definition: Gnu.h:222
bool isValid() const
Check whether we detected a valid GCC install.
Definition: Gnu.h:216