Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/LTO.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- LTO.cpp ------------------------------------------------------------===//
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 "LTO.h"
10
#include "Config.h"
11
#include "InputFiles.h"
12
#include "Symbols.h"
13
#include "lld/Common/Args.h"
14
#include "lld/Common/ErrorHandler.h"
15
#include "lld/Common/Strings.h"
16
#include "lld/Common/TargetOptionsCommandFlags.h"
17
#include "llvm/ADT/STLExtras.h"
18
#include "llvm/ADT/SmallString.h"
19
#include "llvm/ADT/StringRef.h"
20
#include "llvm/ADT/Twine.h"
21
#include "llvm/Bitcode/BitcodeWriter.h"
22
#include "llvm/IR/DiagnosticPrinter.h"
23
#include "llvm/LTO/Caching.h"
24
#include "llvm/LTO/Config.h"
25
#include "llvm/LTO/LTO.h"
26
#include "llvm/Object/SymbolicFile.h"
27
#include "llvm/Support/CodeGen.h"
28
#include "llvm/Support/Error.h"
29
#include "llvm/Support/FileSystem.h"
30
#include "llvm/Support/MemoryBuffer.h"
31
#include "llvm/Support/raw_ostream.h"
32
#include <algorithm>
33
#include <cstddef>
34
#include <memory>
35
#include <string>
36
#include <system_error>
37
#include <vector>
38
39
using namespace llvm;
40
using namespace llvm::object;
41
42
using namespace lld;
43
using namespace lld::coff;
44
45
// Creates an empty file to and returns a raw_fd_ostream to write to it.
46
13
static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
47
13
  std::error_code ec;
48
13
  auto ret =
49
13
      llvm::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::F_None);
50
13
  if (ec) {
51
3
    error("cannot open " + file + ": " + ec.message());
52
3
    return nullptr;
53
3
  }
54
10
  return ret;
55
10
}
56
57
7
static std::string getThinLTOOutputFile(StringRef path) {
58
7
  return lto::getThinLTOOutputFile(path,
59
7
                                   config->thinLTOPrefixReplace.first,
60
7
                                   config->thinLTOPrefixReplace.second);
61
7
}
62
63
52
static lto::Config createConfig() {
64
52
  lto::Config c;
65
52
  c.Options = initTargetOptionsFromCodeGenFlags();
66
52
67
52
  // Always emit a section per function/datum with LTO. LLVM LTO should get most
68
52
  // of the benefit of linker GC, but there are still opportunities for ICF.
69
52
  c.Options.FunctionSections = true;
70
52
  c.Options.DataSections = true;
71
52
72
52
  // Use static reloc model on 32-bit x86 because it usually results in more
73
52
  // compact code, and because there are also known code generation bugs when
74
52
  // using the PIC model (see PR34306).
75
52
  if (config->machine == COFF::IMAGE_FILE_MACHINE_I386)
76
2
    c.RelocModel = Reloc::Static;
77
50
  else
78
50
    c.RelocModel = Reloc::PIC_;
79
52
  c.DisableVerify = true;
80
52
  c.DiagHandler = diagnosticHandler;
81
52
  c.OptLevel = config->ltoo;
82
52
  c.CPU = getCPUStr();
83
52
  c.MAttrs = getMAttrs();
84
52
  c.CGOptLevel = args::getCGOptLevel(config->ltoo);
85
52
86
52
  if (config->saveTemps)
87
4
    checkError(c.addSaveTemps(std::string(config->outputFile) + ".",
88
4
                              /*UseInputModulePath*/ true));
89
52
  return c;
90
52
}
91
92
52
BitcodeCompiler::BitcodeCompiler() {
93
52
  // Initialize indexFile.
94
52
  if (!config->thinLTOIndexOnlyArg.empty())
95
0
    indexFile = openFile(config->thinLTOIndexOnlyArg);
96
52
97
52
  // Initialize ltoObj.
98
52
  lto::ThinBackend backend;
99
52
  if (config->thinLTOIndexOnly) {
100
11
    auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
101
7
    backend = lto::createWriteIndexesThinBackend(
102
7
        config->thinLTOPrefixReplace.first, config->thinLTOPrefixReplace.second,
103
7
        config->thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);
104
45
  } else if (config->thinLTOJobs != 0) {
105
0
    backend = lto::createInProcessThinBackend(config->thinLTOJobs);
106
0
  }
107
52
108
52
  ltoObj = llvm::make_unique<lto::LTO>(createConfig(), backend,
109
52
                                       config->ltoPartitions);
110
52
}
111
112
52
BitcodeCompiler::~BitcodeCompiler() = default;
113
114
103
static void undefine(Symbol *s) { replaceSymbol<Undefined>(s, s->getName()); }
115
116
74
void BitcodeCompiler::add(BitcodeFile &f) {
117
74
  lto::InputFile &obj = *f.obj;
118
74
  unsigned symNum = 0;
119
74
  std::vector<Symbol *> symBodies = f.getSymbols();
120
74
  std::vector<lto::SymbolResolution> resols(symBodies.size());
121
74
122
74
  if (config->thinLTOIndexOnly)
123
12
    thinIndices.insert(obj.getName());
124
74
125
74
  // Provide a resolution to the LTO API for each symbol.
126
142
  for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
127
142
    Symbol *sym = symBodies[symNum];
128
142
    lto::SymbolResolution &r = resols[symNum];
129
142
    ++symNum;
130
142
131
142
    // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
132
142
    // reports two symbols for module ASM defined. Without this check, lld
133
142
    // flags an undefined in IR with a definition in ASM as prevailing.
134
142
    // Once IRObjectFile is fixed to report only one symbol this hack can
135
142
    // be removed.
136
142
    r.Prevailing = !objSym.isUndefined() && 
sym->getFile() == &f113
;
137
142
    r.VisibleToRegularObj = sym->isUsedInRegularObj;
138
142
    if (r.Prevailing)
139
103
      undefine(sym);
140
142
  }
141
74
  checkError(ltoObj->add(std::move(f.obj), resols));
142
74
}
143
144
// Merge all the bitcode files we have seen, codegen the result
145
// and return the resulting objects.
146
52
std::vector<StringRef> BitcodeCompiler::compile() {
147
52
  unsigned maxTasks = ltoObj->getMaxTasks();
148
52
  buf.resize(maxTasks);
149
52
  files.resize(maxTasks);
150
52
151
52
  // The /lldltocache option specifies the path to a directory in which to cache
152
52
  // native object files for ThinLTO incremental builds. If a path was
153
52
  // specified, configure LTO to use it as the cache directory.
154
52
  lto::NativeObjectCache cache;
155
52
  if (!config->ltoCache.empty())
156
1
    cache = check(lto::localCache(
157
2
        config->ltoCache, [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
158
2
          files[task] = std::move(mb);
159
2
        }));
160
52
161
52
  checkError(ltoObj->run(
162
66
      [&](size_t task) {
163
66
        return llvm::make_unique<lto::NativeObjectStream>(
164
66
            llvm::make_unique<raw_svector_ostream>(buf[task]));
165
66
      },
166
52
      cache));
167
52
168
52
  // Emit empty index files for non-indexed files
169
52
  for (StringRef s : thinIndices) {
170
1
    std::string path = getThinLTOOutputFile(s);
171
1
    openFile(path + ".thinlto.bc");
172
1
    if (config->thinLTOEmitImportsFiles)
173
1
      openFile(path + ".imports");
174
1
  }
175
52
176
52
  // ThinLTO with index only option is required to generate only the index
177
52
  // files. After that, we exit from linker and ThinLTO backend runs in a
178
52
  // distributed environment.
179
52
  if (config->thinLTOIndexOnly) {
180
7
    if (indexFile)
181
0
      indexFile->close();
182
7
    return {};
183
7
  }
184
45
185
45
  if (!config->ltoCache.empty())
186
1
    pruneCache(config->ltoCache, config->ltoCachePolicy);
187
45
188
45
  std::vector<StringRef> ret;
189
106
  for (unsigned i = 0; i != maxTasks; 
++i61
) {
190
61
    if (buf[i].empty())
191
2
      continue;
192
59
    if (config->saveTemps) {
193
12
      if (i == 0)
194
4
        saveBuffer(buf[i], config->outputFile + ".lto.obj");
195
8
      else
196
8
        saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.obj");
197
12
    }
198
59
    ret.emplace_back(buf[i].data(), buf[i].size());
199
59
  }
200
45
201
45
  for (std::unique_ptr<MemoryBuffer> &file : files)
202
61
    if (file)
203
2
      ret.push_back(file->getBuffer());
204
45
205
45
  return ret;
206
45
}