Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
Line
Count
Source (jump to first uncovered line)
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"
12
#include "clang/Driver/Compilation.h"
13
#include "clang/Driver/DriverDiagnostic.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
10
llvm::Optional<StringRef> GetMcuFamilyName(StringRef MCU) {
33
10
  return llvm::StringSwitch<llvm::Optional<StringRef>>(MCU)
34
10
      .Case("atmega328", Optional<StringRef>("avr5"))
35
10
      .Case("atmega328p", Optional<StringRef>("avr5"))
36
10
      .Default(Optional<StringRef>());
37
10
}
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
7
    : Generic_ELF(D, Triple, Args), LinkStdlib(false) {
50
7
  GCCInstallation.init(Triple, Args);
51
7
52
7
  // Only add default libraries if the user hasn't explicitly opted out.
53
7
  if (!Args.hasArg(options::OPT_nostdlib) &&
54
7
      
!Args.hasArg(options::OPT_nodefaultlibs)6
&&
55
7
      
!Args.hasArg(options::OPT_c /* does not apply when not linking */)5
) {
56
5
    std::string CPU = getCPUName(Args, Triple);
57
5
58
5
    if (CPU.empty()) {
59
2
      // We cannot link any standard libraries without an MCU specified.
60
2
      D.Diag(diag::warn_drv_avr_mcu_not_specified);
61
3
    } else {
62
3
      Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
63
3
      Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
64
3
65
3
      if (!FamilyName.hasValue()) {
66
1
        // We do not have an entry for this CPU in the family
67
1
        // mapping table yet.
68
1
        D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
69
1
            << CPU;
70
2
      } else if (!GCCInstallation.isValid()) {
71
2
        // No avr-gcc found and so no runtime linked.
72
2
        D.Diag(diag::warn_drv_avr_gcc_not_found);
73
2
      } else 
if (0
!AVRLibcRoot.hasValue()0
) {
74
0
        // No avr-libc found and so no runtime linked.
75
0
        D.Diag(diag::warn_drv_avr_libc_not_found);
76
0
      } else { // We have enough information to link stdlibs
77
0
        std::string GCCRoot = std::string(GCCInstallation.getInstallPath());
78
0
        std::string LibcRoot = AVRLibcRoot.getValue();
79
0
80
0
        getFilePaths().push_back(LibcRoot + std::string("/lib/") +
81
0
                                 std::string(*FamilyName));
82
0
        getFilePaths().push_back(LibcRoot + std::string("/lib/") +
83
0
                                 std::string(*FamilyName));
84
0
        getFilePaths().push_back(GCCRoot + std::string("/") +
85
0
                                 std::string(*FamilyName));
86
0
87
0
        LinkStdlib = true;
88
0
      }
89
3
    }
90
5
91
5
    if (!LinkStdlib)
92
5
      D.Diag(diag::warn_drv_avr_stdlib_not_linked);
93
5
  }
94
7
}
95
96
7
Tool *AVRToolChain::buildLinker() const {
97
7
  return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
98
7
}
99
100
void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
101
                               const InputInfo &Output,
102
                               const InputInfoList &Inputs,
103
                               const ArgList &Args,
104
7
                               const char *LinkingOutput) const {
105
7
  // Compute information about the target AVR.
106
7
  std::string CPU = getCPUName(Args, getToolChain().getTriple());
107
7
  llvm::Optional<StringRef> FamilyName = GetMcuFamilyName(CPU);
108
7
109
7
  std::string Linker = getToolChain().GetProgramPath(getShortName());
110
7
  ArgStringList CmdArgs;
111
7
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
112
7
113
7
  CmdArgs.push_back("-o");
114
7
  CmdArgs.push_back(Output.getFilename());
115
7
116
7
  // Enable garbage collection of unused sections.
117
7
  CmdArgs.push_back("--gc-sections");
118
7
119
7
  // Add library search paths before we specify libraries.
120
7
  Args.AddAllArgs(CmdArgs, options::OPT_L);
121
7
  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
122
7
123
7
  // If the family name is known, we can link with the device-specific libgcc.
124
7
  // Without it, libgcc will simply not be linked. This matches avr-gcc
125
7
  // behavior.
126
7
  if (LinkStdlib) {
127
0
    assert(!CPU.empty() && "CPU name must be known in order to link stdlibs");
128
0
129
0
    // Add the object file for the CRT.
130
0
    std::string CrtFileName = std::string("-l:crt") + CPU + std::string(".o");
131
0
    CmdArgs.push_back(Args.MakeArgString(CrtFileName));
132
0
133
0
    CmdArgs.push_back("-lgcc");
134
0
    CmdArgs.push_back("-lm");
135
0
    CmdArgs.push_back("-lc");
136
0
137
0
    // Add the link library specific to the MCU.
138
0
    CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
139
0
140
0
    // Specify the family name as the emulation mode to use.
141
0
    // This is almost always required because otherwise avr-ld
142
0
    // will assume 'avr2' and warn about the program being larger
143
0
    // than the bare minimum supports.
144
0
    CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
145
0
  }
146
7
147
7
  C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
148
7
                                          CmdArgs, Inputs));
149
7
}
150
151
3
llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
152
6
  for (StringRef PossiblePath : PossibleAVRLibcLocations) {
153
6
    // Return the first avr-libc installation that exists.
154
6
    if (llvm::sys::fs::is_directory(PossiblePath))
155
0
      return Optional<std::string>(std::string(PossiblePath));
156
6
  }
157
3
158
3
  return llvm::None;
159
3
}