Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- clang-linker-wrapper/ClangLinkerWrapper.cpp - wrapper over linker-===//
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
// This tool works as a wrapper over a linking job. This tool is used to create
10
// linked device images for offloading. It scans the linker's input for embedded
11
// device offloading data stored in sections `.llvm.offloading` and extracts it
12
// as a temporary file. The extracted device files will then be passed to a
13
// device linking job to create a final device image.
14
//
15
//===---------------------------------------------------------------------===//
16
17
#include "OffloadWrapper.h"
18
#include "clang/Basic/Version.h"
19
#include "llvm/BinaryFormat/Magic.h"
20
#include "llvm/Bitcode/BitcodeWriter.h"
21
#include "llvm/CodeGen/CommandFlags.h"
22
#include "llvm/IR/Constants.h"
23
#include "llvm/IR/DiagnosticPrinter.h"
24
#include "llvm/IR/Module.h"
25
#include "llvm/IRReader/IRReader.h"
26
#include "llvm/LTO/LTO.h"
27
#include "llvm/MC/TargetRegistry.h"
28
#include "llvm/Object/Archive.h"
29
#include "llvm/Object/ArchiveWriter.h"
30
#include "llvm/Object/Binary.h"
31
#include "llvm/Object/ELFObjectFile.h"
32
#include "llvm/Object/IRObjectFile.h"
33
#include "llvm/Object/ObjectFile.h"
34
#include "llvm/Object/OffloadBinary.h"
35
#include "llvm/Option/ArgList.h"
36
#include "llvm/Option/OptTable.h"
37
#include "llvm/Option/Option.h"
38
#include "llvm/Support/CommandLine.h"
39
#include "llvm/Support/Errc.h"
40
#include "llvm/Support/FileOutputBuffer.h"
41
#include "llvm/Support/FileSystem.h"
42
#include "llvm/Support/Host.h"
43
#include "llvm/Support/InitLLVM.h"
44
#include "llvm/Support/MemoryBuffer.h"
45
#include "llvm/Support/Path.h"
46
#include "llvm/Support/Program.h"
47
#include "llvm/Support/Signals.h"
48
#include "llvm/Support/SourceMgr.h"
49
#include "llvm/Support/StringSaver.h"
50
#include "llvm/Support/TargetSelect.h"
51
#include "llvm/Support/WithColor.h"
52
#include "llvm/Support/raw_ostream.h"
53
#include "llvm/Target/TargetMachine.h"
54
55
using namespace llvm;
56
using namespace llvm::opt;
57
using namespace llvm::object;
58
59
/// We use the command line parser only to forward options like `-pass-remarks`
60
/// to the LLVM tools.
61
static cl::OptionCategory
62
    ClangLinkerWrapperCategory("clang-linker-wrapper options");
63
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden,
64
                          cl::cat(ClangLinkerWrapperCategory));
65
static cl::list<std::string>
66
    DummyArguments(cl::Sink, cl::Hidden, cl::cat(ClangLinkerWrapperCategory));
67
68
/// Path of the current binary.
69
static const char *LinkerExecutable;
70
71
/// Ssave intermediary results.
72
static bool SaveTemps = false;
73
74
/// Print arguments without executing.
75
static bool DryRun = false;
76
77
/// Print verbose output.
78
static bool Verbose = false;
79
80
/// Filename of the executable being created.
81
static StringRef ExecutableName;
82
83
/// Binary path for the CUDA installation.
84
static std::string CudaBinaryPath;
85
86
/// Temporary files created by the linker wrapper.
87
static std::list<SmallString<128>> TempFiles;
88
89
/// Codegen flags for LTO backend.
90
static codegen::RegisterCodeGenFlags CodeGenFlags;
91
92
/// Global flag to indicate that the LTO pipeline threw an error.
93
static std::atomic<bool> LTOError;
94
95
using OffloadingImage = OffloadBinary::OffloadingImage;
96
97
/// A class to contain the binary information for a single OffloadBinary.
98
class OffloadFile : public OwningBinary<OffloadBinary> {
99
public:
100
  using TargetID = std::pair<StringRef, StringRef>;
101
102
  OffloadFile(std::unique_ptr<OffloadBinary> Binary,
103
              std::unique_ptr<MemoryBuffer> Buffer)
104
0
      : OwningBinary<OffloadBinary>(std::move(Binary), std::move(Buffer)) {}
105
106
  /// We use the Triple and Architecture pair to group linker inputs together.
107
  /// This conversion function lets us use these files in a hash-map.
108
0
  operator TargetID() const {
109
0
    return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
110
0
  }
111
};
112
113
namespace llvm {
114
// Provide DenseMapInfo so that OffloadKind can be used in a DenseMap.
115
template <> struct DenseMapInfo<OffloadKind> {
116
0
  static inline OffloadKind getEmptyKey() { return OFK_LAST; }
117
0
  static inline OffloadKind getTombstoneKey() {
118
0
    return static_cast<OffloadKind>(OFK_LAST + 1);
119
0
  }
120
0
  static unsigned getHashValue(const OffloadKind &Val) { return Val; }
121
122
0
  static bool isEqual(const OffloadKind &LHS, const OffloadKind &RHS) {
123
0
    return LHS == RHS;
124
0
  }
125
};
126
} // namespace llvm
127
128
namespace {
129
using std::error_code;
130
131
/// Must not overlap with llvm::opt::DriverFlag.
132
enum WrapperFlags {
133
  WrapperOnlyOption = (1 << 4), // Options only used by the linker wrapper.
134
  DeviceOnlyOption = (1 << 5),  // Options only used for device linking.
135
};
136
137
enum ID {
138
  OPT_INVALID = 0, // This is not an option ID.
139
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
140
               HELPTEXT, METAVAR, VALUES)                                      \
141
  OPT_##ID,
142
#include "LinkerWrapperOpts.inc"
143
  LastOption
144
#undef OPTION
145
};
146
147
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
148
#include "LinkerWrapperOpts.inc"
149
#undef PREFIX
150
151
static const OptTable::Info InfoTable[] = {
152
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
153
               HELPTEXT, METAVAR, VALUES)                                      \
154
  {PREFIX, NAME,  HELPTEXT,    METAVAR,     OPT_##ID,  Option::KIND##Class,    \
155
   PARAM,  FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES},
156
#include "LinkerWrapperOpts.inc"
157
#undef OPTION
158
};
159
160
class WrapperOptTable : public opt::OptTable {
161
public:
162
0
  WrapperOptTable() : OptTable(InfoTable) {}
163
};
164
165
0
const OptTable &getOptTable() {
166
0
  static const WrapperOptTable *Table = []() {
167
0
    auto Result = std::make_unique<WrapperOptTable>();
168
0
    return Result.release();
169
0
  }();
170
0
  return *Table;
171
0
}
172
173
Error extractFromBuffer(std::unique_ptr<MemoryBuffer> Buffer,
174
                        SmallVectorImpl<OffloadFile> &DeviceFiles);
175
176
0
void printCommands(ArrayRef<StringRef> CmdArgs) {
177
0
  if (CmdArgs.empty())
178
0
    return;
179
180
0
  llvm::errs() << " \"" << CmdArgs.front() << "\" ";
181
0
  for (auto IC = std::next(CmdArgs.begin()), IE = CmdArgs.end(); IC != IE; ++IC)
182
0
    llvm::errs() << *IC << (std::next(IC) != IE ? " " : "\n");
183
0
}
184
185
0
[[noreturn]] void reportError(Error E) {
186
0
  outs().flush();
187
0
  logAllUnhandledErrors(std::move(E),
188
0
                        WithColor::error(errs(), LinkerExecutable));
189
0
  exit(EXIT_FAILURE);
190
0
}
191
192
/// Create an extra user-specified \p OffloadFile.
193
/// TODO: We should find a way to wrap these as libraries instead.
194
0
Expected<OffloadFile> getInputBitcodeLibrary(StringRef Input) {
195
0
  auto DeviceAndPath = StringRef(Input).split('=');
196
0
  auto StringAndArch = DeviceAndPath.first.rsplit('-');
197
0
  auto KindAndTriple = StringAndArch.first.split('-');
198
199
0
  llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> ImageOrError =
200
0
      llvm::MemoryBuffer::getFileOrSTDIN(DeviceAndPath.second);
201
0
  if (std::error_code EC = ImageOrError.getError())
202
0
    return createFileError(DeviceAndPath.second, EC);
203
204
0
  OffloadingImage Image{};
205
0
  Image.TheImageKind = IMG_Bitcode;
206
0
  Image.TheOffloadKind = getOffloadKind(KindAndTriple.first);
207
0
  Image.StringData = {{"triple", KindAndTriple.second},
208
0
                      {"arch", StringAndArch.second}};
209
0
  Image.Image = std::move(*ImageOrError);
210
211
0
  std::unique_ptr<MemoryBuffer> Binary = OffloadBinary::write(Image);
212
0
  auto NewBinaryOrErr = OffloadBinary::create(*Binary);
213
0
  if (!NewBinaryOrErr)
214
0
    return NewBinaryOrErr.takeError();
215
0
  return OffloadFile(std::move(*NewBinaryOrErr), std::move(Binary));
216
0
}
217
218
0
std::string getMainExecutable(const char *Name) {
219
0
  void *Ptr = (void *)(intptr_t)&getMainExecutable;
220
0
  auto COWPath = sys::fs::getMainExecutable(Name, Ptr);
221
0
  return sys::path::parent_path(COWPath).str();
222
0
}
223
224
/// Get a temporary filename suitable for output.
225
0
Expected<StringRef> createOutputFile(const Twine &Prefix, StringRef Extension) {
226
0
  SmallString<128> OutputFile;
227
0
  if (SaveTemps) {
228
0
    (Prefix + "." + Extension).toNullTerminatedStringRef(OutputFile);
229
0
  } else {
230
0
    if (std::error_code EC =
231
0
            sys::fs::createTemporaryFile(Prefix, Extension, OutputFile))
232
0
      return createFileError(OutputFile, EC);
233
0
  }
234
235
0
  TempFiles.emplace_back(std::move(OutputFile));
236
0
  return TempFiles.back();
237
0
}
238
239
/// Execute the command \p ExecutablePath with the arguments \p Args.
240
0
Error executeCommands(StringRef ExecutablePath, ArrayRef<StringRef> Args) {
241
0
  if (Verbose || DryRun)
242
0
    printCommands(Args);
243
244
0
  if (!DryRun)
245
0
    if (sys::ExecuteAndWait(ExecutablePath, Args))
246
0
      return createStringError(inconvertibleErrorCode(),
247
0
                               "'" + sys::path::filename(ExecutablePath) + "'" +
248
0
                                   " failed");
249
0
  return Error::success();
250
0
}
251
252
0
Expected<std::string> findProgram(StringRef Name, ArrayRef<StringRef> Paths) {
253
254
0
  ErrorOr<std::string> Path = sys::findProgramByName(Name, Paths);
255
0
  if (!Path)
256
0
    Path = sys::findProgramByName(Name);
257
0
  if (!Path && DryRun)
258
0
    return Name.str();
259
0
  if (!Path)
260
0
    return createStringError(Path.getError(),
261
0
                             "Unable to find '" + Name + "' in path");
262
0
  return *Path;
263
0
}
264
265
/// Runs the wrapped linker job with the newly created input.
266
0
Error runLinker(ArrayRef<StringRef> Files, const ArgList &Args) {
267
0
  llvm::TimeTraceScope TimeScope("Execute host linker");
268
269
  // Render the linker arguments and add the newly created image. We add it
270
  // after the output file to ensure it is linked with the correct libraries.
271
0
  StringRef LinkerPath = Args.getLastArgValue(OPT_linker_path_EQ);
272
0
  ArgStringList NewLinkerArgs;
273
0
  for (const opt::Arg *Arg : Args) {
274
    // Do not forward arguments only intended for the linker wrapper.
275
0
    if (Arg->getOption().hasFlag(WrapperOnlyOption))
276
0
      continue;
277
278
0
    Arg->render(Args, NewLinkerArgs);
279
0
    if (Arg->getOption().matches(OPT_o))
280
0
      llvm::transform(Files, std::back_inserter(NewLinkerArgs),
281
0
                      [&](StringRef Arg) { return Args.MakeArgString(Arg); });
282
0
  }
283
284
0
  SmallVector<StringRef> LinkerArgs({LinkerPath});
285
0
  for (StringRef Arg : NewLinkerArgs)
286
0
    LinkerArgs.push_back(Arg);
287
0
  if (Error Err = executeCommands(LinkerPath, LinkerArgs))
288
0
    return Err;
289
0
  return Error::success();
290
0
}
291
292
0
void printVersion(raw_ostream &OS) {
293
0
  OS << clang::getClangToolFullVersion("clang-linker-wrapper") << '\n';
294
0
}
295
296
/// Attempts to extract all the embedded device images contained inside the
297
/// buffer \p Contents. The buffer is expected to contain a valid offloading
298
/// binary format.
299
Error extractOffloadFiles(MemoryBufferRef Contents,
300
0
                          SmallVectorImpl<OffloadFile> &DeviceFiles) {
301
0
  uint64_t Offset = 0;
302
  // There could be multiple offloading binaries stored at this section.
303
0
  while (Offset < Contents.getBuffer().size()) {
304
0
    std::unique_ptr<MemoryBuffer> Buffer =
305
0
        MemoryBuffer::getMemBuffer(Contents.getBuffer().drop_front(Offset), "",
306
0
                                   /*RequiresNullTerminator*/ false);
307
0
    auto BinaryOrErr = OffloadBinary::create(*Buffer);
308
0
    if (!BinaryOrErr)
309
0
      return BinaryOrErr.takeError();
310
0
    OffloadBinary &Binary = **BinaryOrErr;
311
312
    // Create a new owned binary with a copy of the original memory.
313
0
    std::unique_ptr<MemoryBuffer> BufferCopy = MemoryBuffer::getMemBufferCopy(
314
0
        Binary.getData().take_front(Binary.getSize()),
315
0
        Contents.getBufferIdentifier());
316
0
    auto NewBinaryOrErr = OffloadBinary::create(*BufferCopy);
317
0
    if (!NewBinaryOrErr)
318
0
      return NewBinaryOrErr.takeError();
319
0
    DeviceFiles.emplace_back(std::move(*NewBinaryOrErr), std::move(BufferCopy));
320
321
0
    Offset += Binary.getSize();
322
0
  }
323
324
0
  return Error::success();
325
0
}
326
327
// Extract offloading binaries from an Object file \p Obj.
328
Error extractFromBinary(const ObjectFile &Obj,
329
0
                        SmallVectorImpl<OffloadFile> &DeviceFiles) {
330
0
  for (ELFSectionRef Sec : Obj.sections()) {
331
0
    if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING)
332
0
      continue;
333
334
0
    Expected<StringRef> Buffer = Sec.getContents();
335
0
    if (!Buffer)
336
0
      return Buffer.takeError();
337
338
0
    MemoryBufferRef Contents(*Buffer, Obj.getFileName());
339
0
    if (Error Err = extractOffloadFiles(Contents, DeviceFiles))
340
0
      return Err;
341
0
  }
342
343
0
  return Error::success();
344
0
}
345
346
Error extractFromBitcode(std::unique_ptr<MemoryBuffer> Buffer,
347
0
                         SmallVectorImpl<OffloadFile> &DeviceFiles) {
348
0
  LLVMContext Context;
349
0
  SMDiagnostic Err;
350
0
  std::unique_ptr<Module> M = getLazyIRModule(std::move(Buffer), Err, Context);
351
0
  if (!M)
352
0
    return createStringError(inconvertibleErrorCode(),
353
0
                             "Failed to create module");
354
355
  // Extract offloading data from globals referenced by the
356
  // `llvm.embedded.object` metadata with the `.llvm.offloading` section.
357
0
  auto *MD = M->getNamedMetadata("llvm.embedded.objects");
358
0
  if (!MD)
359
0
    return Error::success();
360
361
0
  for (const MDNode *Op : MD->operands()) {
362
0
    if (Op->getNumOperands() < 2)
363
0
      continue;
364
365
0
    MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1));
366
0
    if (!SectionID || SectionID->getString() != ".llvm.offloading")
367
0
      continue;
368
369
0
    GlobalVariable *GV =
370
0
        mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0));
371
0
    if (!GV)
372
0
      continue;
373
374
0
    auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer());
375
0
    if (!CDS)
376
0
      continue;
377
378
0
    MemoryBufferRef Contents(CDS->getAsString(), M->getName());
379
0
    if (Error Err = extractOffloadFiles(Contents, DeviceFiles))
380
0
      return Err;
381
0
  }
382
383
0
  return Error::success();
384
0
}
385
386
Error extractFromArchive(const Archive &Library,
387
0
                         SmallVectorImpl<OffloadFile> &DeviceFiles) {
388
  // Try to extract device code from each file stored in the static archive.
389
0
  Error Err = Error::success();
390
0
  for (auto Child : Library.children(Err)) {
391
0
    auto ChildBufferOrErr = Child.getMemoryBufferRef();
392
0
    if (!ChildBufferOrErr)
393
0
      return ChildBufferOrErr.takeError();
394
0
    std::unique_ptr<MemoryBuffer> ChildBuffer =
395
0
        MemoryBuffer::getMemBuffer(*ChildBufferOrErr, false);
396
397
    // Check if the buffer has the required alignment.
398
0
    if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
399
0
                       ChildBuffer->getBufferStart()))
400
0
      ChildBuffer = MemoryBuffer::getMemBufferCopy(
401
0
          ChildBufferOrErr->getBuffer(),
402
0
          ChildBufferOrErr->getBufferIdentifier());
403
404
0
    if (Error Err = extractFromBuffer(std::move(ChildBuffer), DeviceFiles))
405
0
      return Err;
406
0
  }
407
408
0
  if (Err)
409
0
    return Err;
410
0
  return Error::success();
411
0
}
412
413
/// Extracts embedded device offloading code from a memory \p Buffer to a list
414
/// of \p DeviceFiles.
415
Error extractFromBuffer(std::unique_ptr<MemoryBuffer> Buffer,
416
0
                        SmallVectorImpl<OffloadFile> &DeviceFiles) {
417
0
  file_magic Type = identify_magic(Buffer->getBuffer());
418
0
  switch (Type) {
419
0
  case file_magic::bitcode:
420
0
    return extractFromBitcode(std::move(Buffer), DeviceFiles);
421
0
  case file_magic::elf_relocatable: {
422
0
    Expected<std::unique_ptr<ObjectFile>> ObjFile =
423
0
        ObjectFile::createObjectFile(*Buffer, Type);
424
0
    if (!ObjFile)
425
0
      return ObjFile.takeError();
426
0
    return extractFromBinary(*ObjFile->get(), DeviceFiles);
427
0
  }
428
0
  case file_magic::archive: {
429
0
    Expected<std::unique_ptr<llvm::object::Archive>> LibFile =
430
0
        object::Archive::create(*Buffer);
431
0
    if (!LibFile)
432
0
      return LibFile.takeError();
433
0
    return extractFromArchive(*LibFile->get(), DeviceFiles);
434
0
  }
435
0
  default:
436
0
    return Error::success();
437
0
  }
438
0
}
439
440
namespace nvptx {
441
Expected<StringRef> assemble(StringRef InputFile, const ArgList &Args,
442
0
                             bool RDC = true) {
443
0
  llvm::TimeTraceScope TimeScope("NVPTX Assembler");
444
  // NVPTX uses the ptxas binary to create device object files.
445
0
  Expected<std::string> PtxasPath = findProgram("ptxas", {CudaBinaryPath});
446
0
  if (!PtxasPath)
447
0
    return PtxasPath.takeError();
448
449
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
450
0
  StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
451
  // Create a new file to write the linked device image to. Assume that the
452
  // input filename already has the device and architecture.
453
0
  auto TempFileOrErr = createOutputFile(sys::path::stem(InputFile), "cubin");
454
0
  if (!TempFileOrErr)
455
0
    return TempFileOrErr.takeError();
456
457
0
  SmallVector<StringRef, 16> CmdArgs;
458
0
  StringRef OptLevel = Args.getLastArgValue(OPT_opt_level, "O2");
459
0
  CmdArgs.push_back(*PtxasPath);
460
0
  CmdArgs.push_back(Triple.isArch64Bit() ? "-m64" : "-m32");
461
0
  if (Verbose)
462
0
    CmdArgs.push_back("-v");
463
0
  for (StringRef Arg : Args.getAllArgValues(OPT_ptxas_arg))
464
0
    CmdArgs.push_back(Args.MakeArgString(Arg));
465
0
  CmdArgs.push_back("-o");
466
0
  CmdArgs.push_back(*TempFileOrErr);
467
0
  CmdArgs.push_back(Args.MakeArgString("-" + OptLevel));
468
0
  CmdArgs.push_back("--gpu-name");
469
0
  CmdArgs.push_back(Arch);
470
0
  if (Args.hasArg(OPT_debug))
471
0
    CmdArgs.push_back("-g");
472
0
  if (RDC)
473
0
    CmdArgs.push_back("-c");
474
475
0
  CmdArgs.push_back(InputFile);
476
477
0
  if (Error Err = executeCommands(*PtxasPath, CmdArgs))
478
0
    return std::move(Err);
479
480
0
  return *TempFileOrErr;
481
0
}
482
483
0
Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
484
0
  llvm::TimeTraceScope TimeScope("NVPTX linker");
485
  // NVPTX uses the nvlink binary to link device object files.
486
0
  Expected<std::string> NvlinkPath = findProgram("nvlink", {CudaBinaryPath});
487
0
  if (!NvlinkPath)
488
0
    return NvlinkPath.takeError();
489
490
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
491
0
  StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
492
493
  // Create a new file to write the linked device image to.
494
0
  auto TempFileOrErr =
495
0
      createOutputFile(sys::path::filename(ExecutableName) + "-device-" +
496
0
                           Triple.getArchName() + "-" + Arch,
497
0
                       "out");
498
0
  if (!TempFileOrErr)
499
0
    return TempFileOrErr.takeError();
500
501
0
  SmallVector<StringRef, 16> CmdArgs;
502
0
  CmdArgs.push_back(*NvlinkPath);
503
0
  CmdArgs.push_back(Triple.isArch64Bit() ? "-m64" : "-m32");
504
0
  if (Args.hasArg(OPT_debug))
505
0
    CmdArgs.push_back("-g");
506
0
  if (Verbose)
507
0
    CmdArgs.push_back("-v");
508
0
  CmdArgs.push_back("-o");
509
0
  CmdArgs.push_back(*TempFileOrErr);
510
0
  CmdArgs.push_back("-arch");
511
0
  CmdArgs.push_back(Arch);
512
513
  // Add extracted input files.
514
0
  for (StringRef Input : InputFiles)
515
0
    CmdArgs.push_back(Input);
516
517
0
  for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
518
0
    CmdArgs.push_back(Args.MakeArgString(Arg));
519
0
  if (Error Err = executeCommands(*NvlinkPath, CmdArgs))
520
0
    return std::move(Err);
521
522
0
  return *TempFileOrErr;
523
0
}
524
525
Expected<StringRef>
526
fatbinary(ArrayRef<std::pair<StringRef, StringRef>> InputFiles,
527
0
          const ArgList &Args) {
528
0
  llvm::TimeTraceScope TimeScope("NVPTX fatbinary");
529
  // NVPTX uses the fatbinary program to bundle the linked images.
530
0
  Expected<std::string> FatBinaryPath =
531
0
      findProgram("fatbinary", {CudaBinaryPath});
532
0
  if (!FatBinaryPath)
533
0
    return FatBinaryPath.takeError();
534
535
0
  llvm::Triple Triple(
536
0
      Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
537
538
  // Create a new file to write the linked device image to.
539
0
  auto TempFileOrErr = createOutputFile(
540
0
      sys::path::filename(ExecutableName) + "-device", "fatbin");
541
0
  if (!TempFileOrErr)
542
0
    return TempFileOrErr.takeError();
543
544
0
  SmallVector<StringRef, 16> CmdArgs;
545
0
  CmdArgs.push_back(*FatBinaryPath);
546
0
  CmdArgs.push_back(Triple.isArch64Bit() ? "-64" : "-32");
547
0
  CmdArgs.push_back("--create");
548
0
  CmdArgs.push_back(*TempFileOrErr);
549
0
  for (const auto &FileAndArch : InputFiles)
550
0
    CmdArgs.push_back(
551
0
        Args.MakeArgString("--image=profile=" + std::get<1>(FileAndArch) +
552
0
                           ",file=" + std::get<0>(FileAndArch)));
553
554
0
  if (Error Err = executeCommands(*FatBinaryPath, CmdArgs))
555
0
    return std::move(Err);
556
557
0
  return *TempFileOrErr;
558
0
}
559
} // namespace nvptx
560
561
namespace amdgcn {
562
0
Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
563
0
  llvm::TimeTraceScope TimeScope("AMDGPU linker");
564
  // AMDGPU uses lld to link device object files.
565
0
  Expected<std::string> LLDPath =
566
0
      findProgram("lld", {getMainExecutable("lld")});
567
0
  if (!LLDPath)
568
0
    return LLDPath.takeError();
569
570
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
571
0
  StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
572
573
  // Create a new file to write the linked device image to.
574
0
  auto TempFileOrErr =
575
0
      createOutputFile(sys::path::filename(ExecutableName) + "-" +
576
0
                           Triple.getArchName() + "-" + Arch,
577
0
                       "out");
578
0
  if (!TempFileOrErr)
579
0
    return TempFileOrErr.takeError();
580
0
  std::string ArchArg = ("-plugin-opt=mcpu=" + Arch).str();
581
582
0
  SmallVector<StringRef, 16> CmdArgs;
583
0
  CmdArgs.push_back(*LLDPath);
584
0
  CmdArgs.push_back("-flavor");
585
0
  CmdArgs.push_back("gnu");
586
0
  CmdArgs.push_back("--no-undefined");
587
0
  CmdArgs.push_back("-shared");
588
0
  CmdArgs.push_back("-plugin-opt=-amdgpu-internalize-symbols");
589
0
  CmdArgs.push_back(ArchArg);
590
0
  CmdArgs.push_back("-o");
591
0
  CmdArgs.push_back(*TempFileOrErr);
592
593
  // Add extracted input files.
594
0
  for (StringRef Input : InputFiles)
595
0
    CmdArgs.push_back(Input);
596
597
0
  for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
598
0
    CmdArgs.push_back(Args.MakeArgString(Arg));
599
0
  if (Error Err = executeCommands(*LLDPath, CmdArgs))
600
0
    return std::move(Err);
601
602
0
  return *TempFileOrErr;
603
0
}
604
605
Expected<StringRef>
606
fatbinary(ArrayRef<std::pair<StringRef, StringRef>> InputFiles,
607
0
          const ArgList &Args) {
608
0
  llvm::TimeTraceScope TimeScope("AMDGPU Fatbinary");
609
610
  // AMDGPU uses the clang-offload-bundler to bundle the linked images.
611
0
  Expected<std::string> OffloadBundlerPath = findProgram(
612
0
      "clang-offload-bundler", {getMainExecutable("clang-offload-bundler")});
613
0
  if (!OffloadBundlerPath)
614
0
    return OffloadBundlerPath.takeError();
615
616
0
  llvm::Triple Triple(
617
0
      Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
618
619
  // Create a new file to write the linked device image to.
620
0
  auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
621
0
                                            "-device-" + Triple.getArchName(),
622
0
                                        "hipfb");
623
0
  if (!TempFileOrErr)
624
0
    return TempFileOrErr.takeError();
625
626
0
  BumpPtrAllocator Alloc;
627
0
  StringSaver Saver(Alloc);
628
629
0
  SmallVector<StringRef, 16> CmdArgs;
630
0
  CmdArgs.push_back(*OffloadBundlerPath);
631
0
  CmdArgs.push_back("-type=o");
632
0
  CmdArgs.push_back("-bundle-align=4096");
633
634
0
  SmallVector<StringRef> Targets = {"-targets=host-x86_64-unknown-linux"};
635
0
  for (const auto &FileAndArch : InputFiles)
636
0
    Targets.push_back(
637
0
        Saver.save("hipv4-amdgcn-amd-amdhsa--" + std::get<1>(FileAndArch)));
638
0
  CmdArgs.push_back(Saver.save(llvm::join(Targets, ",")));
639
640
0
  CmdArgs.push_back("-input=/dev/null");
641
0
  for (const auto &FileAndArch : InputFiles)
642
0
    CmdArgs.push_back(Saver.save("-input=" + std::get<0>(FileAndArch)));
643
644
0
  CmdArgs.push_back(Saver.save("-output=" + *TempFileOrErr));
645
646
0
  if (Error Err = executeCommands(*OffloadBundlerPath, CmdArgs))
647
0
    return std::move(Err);
648
649
0
  return *TempFileOrErr;
650
0
}
651
} // namespace amdgcn
652
653
namespace generic {
654
655
0
const char *getLDMOption(const llvm::Triple &T) {
656
0
  switch (T.getArch()) {
657
0
  case llvm::Triple::x86:
658
0
    if (T.isOSIAMCU())
659
0
      return "elf_iamcu";
660
0
    return "elf_i386";
661
0
  case llvm::Triple::aarch64:
662
0
    return "aarch64linux";
663
0
  case llvm::Triple::aarch64_be:
664
0
    return "aarch64linuxb";
665
0
  case llvm::Triple::ppc64:
666
0
    return "elf64ppc";
667
0
  case llvm::Triple::ppc64le:
668
0
    return "elf64lppc";
669
0
  case llvm::Triple::x86_64:
670
0
    if (T.isX32())
671
0
      return "elf32_x86_64";
672
0
    return "elf_x86_64";
673
0
  case llvm::Triple::ve:
674
0
    return "elf64ve";
675
0
  default:
676
0
    return nullptr;
677
0
  }
678
0
}
679
680
0
Expected<StringRef> link(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
681
0
  llvm::TimeTraceScope TimeScope("Generic linker");
682
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
683
0
  StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
684
685
  // Create a new file to write the linked device image to.
686
0
  auto TempFileOrErr =
687
0
      createOutputFile(sys::path::filename(ExecutableName) + "-" +
688
0
                           Triple.getArchName() + "-" + Arch,
689
0
                       "out");
690
0
  if (!TempFileOrErr)
691
0
    return TempFileOrErr.takeError();
692
693
  // Use the host linker to perform generic offloading. Use the same libraries
694
  // and paths as the host application does.
695
0
  SmallVector<StringRef, 16> CmdArgs;
696
0
  CmdArgs.push_back(Args.getLastArgValue(OPT_linker_path_EQ));
697
0
  CmdArgs.push_back("-m");
698
0
  CmdArgs.push_back(getLDMOption(Triple));
699
0
  CmdArgs.push_back("-shared");
700
701
0
  ArgStringList LinkerArgs;
702
0
  for (const opt::Arg *Arg : Args) {
703
0
    auto Op = Arg->getOption();
704
0
    if (Op.matches(OPT_library) || Op.matches(OPT_library_path) ||
705
0
        Op.matches(OPT_as_needed) || Op.matches(OPT_no_as_needed) ||
706
0
        Op.matches(OPT_rpath) || Op.matches(OPT_dynamic_linker))
707
0
      Arg->render(Args, LinkerArgs);
708
0
  }
709
0
  for (StringRef Arg : LinkerArgs)
710
0
    CmdArgs.push_back(Arg);
711
712
0
  CmdArgs.push_back("-Bsymbolic");
713
0
  CmdArgs.push_back("-o");
714
0
  CmdArgs.push_back(*TempFileOrErr);
715
716
  // Add extracted input files.
717
0
  for (StringRef Input : InputFiles)
718
0
    CmdArgs.push_back(Input);
719
720
0
  for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
721
0
    CmdArgs.push_back(Args.MakeArgString(Arg));
722
0
  if (Error Err =
723
0
          executeCommands(Args.getLastArgValue(OPT_linker_path_EQ), CmdArgs))
724
0
    return std::move(Err);
725
726
0
  return *TempFileOrErr;
727
0
}
728
} // namespace generic
729
730
Expected<StringRef> linkDevice(ArrayRef<StringRef> InputFiles,
731
0
                               const ArgList &Args) {
732
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
733
0
  switch (Triple.getArch()) {
734
0
  case Triple::nvptx:
735
0
  case Triple::nvptx64:
736
0
    return nvptx::link(InputFiles, Args);
737
0
  case Triple::amdgcn:
738
0
    return amdgcn::link(InputFiles, Args);
739
0
  case Triple::x86:
740
0
  case Triple::x86_64:
741
0
  case Triple::aarch64:
742
0
  case Triple::aarch64_be:
743
0
  case Triple::ppc64:
744
0
  case Triple::ppc64le:
745
0
    return generic::link(InputFiles, Args);
746
0
  default:
747
0
    return createStringError(inconvertibleErrorCode(),
748
0
                             Triple.getArchName() +
749
0
                                 " linking is not supported");
750
0
  }
751
0
}
752
753
0
void diagnosticHandler(const DiagnosticInfo &DI) {
754
0
  std::string ErrStorage;
755
0
  raw_string_ostream OS(ErrStorage);
756
0
  DiagnosticPrinterRawOStream DP(OS);
757
0
  DI.print(DP);
758
759
0
  switch (DI.getSeverity()) {
760
0
  case DS_Error:
761
0
    WithColor::error(errs(), LinkerExecutable) << ErrStorage << "\n";
762
0
    LTOError = true;
763
0
    break;
764
0
  case DS_Warning:
765
0
    WithColor::warning(errs(), LinkerExecutable) << ErrStorage << "\n";
766
0
    break;
767
0
  case DS_Note:
768
0
    WithColor::note(errs(), LinkerExecutable) << ErrStorage << "\n";
769
0
    break;
770
0
  case DS_Remark:
771
0
    WithColor::remark(errs()) << ErrStorage << "\n";
772
0
    break;
773
0
  }
774
0
}
775
776
// Get the list of target features from the input file and unify them such that
777
// if there are multiple +xxx or -xxx features we only keep the last one.
778
0
std::vector<std::string> getTargetFeatures(ArrayRef<OffloadFile> InputFiles) {
779
0
  SmallVector<StringRef> Features;
780
0
  for (const OffloadFile &File : InputFiles) {
781
0
    for (auto Arg : llvm::split(File.getBinary()->getString("feature"), ","))
782
0
      Features.emplace_back(Arg);
783
0
  }
784
785
  // Only add a feature if it hasn't been seen before starting from the end.
786
0
  std::vector<std::string> UnifiedFeatures;
787
0
  DenseSet<StringRef> UsedFeatures;
788
0
  for (StringRef Feature : llvm::reverse(Features)) {
789
0
    if (UsedFeatures.insert(Feature.drop_front()).second)
790
0
      UnifiedFeatures.push_back(Feature.str());
791
0
  }
792
793
0
  return UnifiedFeatures;
794
0
}
795
796
0
CodeGenOpt::Level getCGOptLevel(unsigned OptLevel) {
797
0
  switch (OptLevel) {
798
0
  case 0:
799
0
    return CodeGenOpt::None;
800
0
  case 1:
801
0
    return CodeGenOpt::Less;
802
0
  case 2:
803
0
    return CodeGenOpt::Default;
804
0
  case 3:
805
0
    return CodeGenOpt::Aggressive;
806
0
  }
807
0
  llvm_unreachable("Invalid optimization level");
808
0
}
809
810
template <typename ModuleHook = function_ref<bool(size_t, const Module &)>>
811
std::unique_ptr<lto::LTO> createLTO(
812
    const ArgList &Args, const std::vector<std::string> &Features,
813
0
    ModuleHook Hook = [](size_t, const Module &) { return true; }) {
814
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
815
0
  StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
816
0
  lto::Config Conf;
817
0
  lto::ThinBackend Backend;
818
  // TODO: Handle index-only thin-LTO
819
0
  Backend =
820
0
      lto::createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
821
822
0
  Conf.CPU = Arch.str();
823
0
  Conf.Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple);
824
825
0
  StringRef OptLevel = Args.getLastArgValue(OPT_opt_level, "O2");
826
0
  Conf.MAttrs = Features;
827
0
  Conf.CGOptLevel = getCGOptLevel(OptLevel[1] - '0');
828
0
  Conf.OptLevel = OptLevel[1] - '0';
829
0
  if (Conf.OptLevel > 0)
830
0
    Conf.UseDefaultPipeline = true;
831
0
  Conf.DefaultTriple = Triple.getTriple();
832
833
0
  LTOError = false;
834
0
  Conf.DiagHandler = diagnosticHandler;
835
836
0
  Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
837
0
  Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
838
839
0
  if (SaveTemps) {
840
0
    std::string TempName = (sys::path::filename(ExecutableName) + "-device-" +
841
0
                            Triple.getTriple() + "-" + Arch)
842
0
                               .str();
843
0
    Conf.PostInternalizeModuleHook = [=](size_t Task, const Module &M) {
844
0
      std::string File = !Task ? TempName + ".bc"
845
0
                               : TempName + "." + std::to_string(Task) + ".bc";
846
0
      error_code EC;
847
0
      raw_fd_ostream LinkedBitcode(File, EC, sys::fs::OF_None);
848
0
      if (EC)
849
0
        reportError(errorCodeToError(EC));
850
0
      WriteBitcodeToFile(M, LinkedBitcode);
851
0
      return true;
852
0
    };
Unexecuted instantiation: ClangLinkerWrapper.cpp:std::__1::unique_ptr<llvm::lto::LTO, std::__1::default_delete<llvm::lto::LTO> > (anonymous namespace)::createLTO<(anonymous namespace)::linkBitcodeFiles(llvm::SmallVectorImpl<OffloadFile>&, llvm::SmallVectorImpl<llvm::StringRef>&, llvm::opt::ArgList const&)::$_4>(llvm::opt::ArgList const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, (anonymous namespace)::linkBitcodeFiles(llvm::SmallVectorImpl<OffloadFile>&, llvm::SmallVectorImpl<llvm::StringRef>&, llvm::opt::ArgList const&)::$_4)::'lambda'(unsigned long, llvm::Module const&)::operator()(unsigned long, llvm::Module const&) const
Unexecuted instantiation: ClangLinkerWrapper.cpp:std::__1::unique_ptr<llvm::lto::LTO, std::__1::default_delete<llvm::lto::LTO> > (anonymous namespace)::createLTO<llvm::function_ref<bool (unsigned long, llvm::Module const&)> >(llvm::opt::ArgList const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, llvm::function_ref<bool (unsigned long, llvm::Module const&)>)::'lambda'(unsigned long, llvm::Module const&)::operator()(unsigned long, llvm::Module const&) const
853
0
  }
854
0
  Conf.PostOptModuleHook = Hook;
855
0
  Conf.CGFileType = Triple.isNVPTX() ? CGFT_AssemblyFile : CGFT_ObjectFile;
856
857
  // TODO: Handle remark files
858
0
  Conf.HasWholeProgramVisibility = Args.hasArg(OPT_whole_program);
859
860
0
  return std::make_unique<lto::LTO>(std::move(Conf), Backend);
861
0
}
Unexecuted instantiation: ClangLinkerWrapper.cpp:std::__1::unique_ptr<llvm::lto::LTO, std::__1::default_delete<llvm::lto::LTO> > (anonymous namespace)::createLTO<(anonymous namespace)::linkBitcodeFiles(llvm::SmallVectorImpl<OffloadFile>&, llvm::SmallVectorImpl<llvm::StringRef>&, llvm::opt::ArgList const&)::$_4>(llvm::opt::ArgList const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, (anonymous namespace)::linkBitcodeFiles(llvm::SmallVectorImpl<OffloadFile>&, llvm::SmallVectorImpl<llvm::StringRef>&, llvm::opt::ArgList const&)::$_4)
Unexecuted instantiation: ClangLinkerWrapper.cpp:std::__1::unique_ptr<llvm::lto::LTO, std::__1::default_delete<llvm::lto::LTO> > (anonymous namespace)::createLTO<llvm::function_ref<bool (unsigned long, llvm::Module const&)> >(llvm::opt::ArgList const&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, llvm::function_ref<bool (unsigned long, llvm::Module const&)>)
862
863
// Returns true if \p S is valid as a C language identifier and will be given
864
// `__start_` and `__stop_` symbols.
865
0
bool isValidCIdentifier(StringRef S) {
866
0
  return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
867
0
         std::all_of(S.begin() + 1, S.end(),
868
0
                     [](char C) { return C == '_' || isAlnum(C); });
869
0
}
870
871
Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
872
                       SmallVectorImpl<StringRef> &OutputFiles,
873
0
                       const ArgList &Args) {
874
0
  llvm::TimeTraceScope TimeScope("Link bitcode files");
875
0
  const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
876
877
0
  SmallVector<OffloadFile, 4> BitcodeInputFiles;
878
0
  DenseSet<StringRef> UsedInRegularObj;
879
0
  DenseSet<StringRef> UsedInSharedLib;
880
0
  BumpPtrAllocator Alloc;
881
0
  StringSaver Saver(Alloc);
882
883
  // Search for bitcode files in the input and create an LTO input file. If it
884
  // is not a bitcode file, scan its symbol table for symbols we need to save.
885
0
  for (OffloadFile &File : InputFiles) {
886
0
    MemoryBufferRef Buffer = MemoryBufferRef(File.getBinary()->getImage(), "");
887
888
0
    file_magic Type = identify_magic(Buffer.getBuffer());
889
0
    switch (Type) {
890
0
    case file_magic::bitcode: {
891
0
      BitcodeInputFiles.emplace_back(std::move(File));
892
0
      continue;
893
0
    }
894
0
    case file_magic::elf_relocatable:
895
0
    case file_magic::elf_shared_object: {
896
0
      Expected<std::unique_ptr<ObjectFile>> ObjFile =
897
0
          ObjectFile::createObjectFile(Buffer);
898
0
      if (!ObjFile)
899
0
        continue;
900
901
0
      for (SymbolRef Sym : (*ObjFile)->symbols()) {
902
0
        Expected<StringRef> Name = Sym.getName();
903
0
        if (!Name)
904
0
          return Name.takeError();
905
906
        // Record if we've seen these symbols in any object or shared libraries.
907
0
        if ((*ObjFile)->isRelocatableObject())
908
0
          UsedInRegularObj.insert(Saver.save(*Name));
909
0
        else
910
0
          UsedInSharedLib.insert(Saver.save(*Name));
911
0
      }
912
0
      continue;
913
0
    }
914
0
    default:
915
0
      continue;
916
0
    }
917
0
  }
918
919
0
  if (BitcodeInputFiles.empty())
920
0
    return Error::success();
921
922
  // Remove all the bitcode files that we moved from the original input.
923
0
  llvm::erase_if(InputFiles, [](OffloadFile &F) { return !F.getBinary(); });
924
925
  // LTO Module hook to output bitcode without running the backend.
926
0
  SmallVector<StringRef, 4> BitcodeOutput;
927
0
  auto OutputBitcode = [&](size_t, const Module &M) {
928
0
    auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
929
0
                                              "-jit-" + Triple.getTriple(),
930
0
                                          "bc");
931
0
    if (!TempFileOrErr)
932
0
      reportError(TempFileOrErr.takeError());
933
934
0
    std::error_code EC;
935
0
    raw_fd_ostream LinkedBitcode(*TempFileOrErr, EC, sys::fs::OF_None);
936
0
    if (EC)
937
0
      reportError(errorCodeToError(EC));
938
0
    WriteBitcodeToFile(M, LinkedBitcode);
939
0
    BitcodeOutput.push_back(*TempFileOrErr);
940
0
    return false;
941
0
  };
942
943
  // We assume visibility of the whole program if every input file was bitcode.
944
0
  auto Features = getTargetFeatures(BitcodeInputFiles);
945
0
  auto LTOBackend = Args.hasArg(OPT_embed_bitcode)
946
0
                        ? createLTO(Args, Features, OutputBitcode)
947
0
                        : createLTO(Args, Features);
948
949
  // We need to resolve the symbols so the LTO backend knows which symbols need
950
  // to be kept or can be internalized. This is a simplified symbol resolution
951
  // scheme to approximate the full resolution a linker would do.
952
0
  uint64_t Idx = 0;
953
0
  DenseSet<StringRef> PrevailingSymbols;
954
0
  for (auto &BitcodeInput : BitcodeInputFiles) {
955
    // Get a semi-unique buffer identifier for Thin-LTO.
956
0
    StringRef Identifier = Saver.save(
957
0
        std::to_string(Idx++) + "." +
958
0
        BitcodeInput.getBinary()->getMemoryBufferRef().getBufferIdentifier());
959
0
    MemoryBufferRef Buffer =
960
0
        MemoryBufferRef(BitcodeInput.getBinary()->getImage(), Identifier);
961
0
    Expected<std::unique_ptr<lto::InputFile>> BitcodeFileOrErr =
962
0
        llvm::lto::InputFile::create(Buffer);
963
0
    if (!BitcodeFileOrErr)
964
0
      return BitcodeFileOrErr.takeError();
965
966
    // Save the input file and the buffer associated with its memory.
967
0
    const auto Symbols = (*BitcodeFileOrErr)->symbols();
968
0
    SmallVector<lto::SymbolResolution, 16> Resolutions(Symbols.size());
969
0
    size_t Idx = 0;
970
0
    for (auto &Sym : Symbols) {
971
0
      lto::SymbolResolution &Res = Resolutions[Idx++];
972
973
      // We will use this as the prevailing symbol definition in LTO unless
974
      // it is undefined or another definition has already been used.
975
0
      Res.Prevailing =
976
0
          !Sym.isUndefined() &&
977
0
          PrevailingSymbols.insert(Saver.save(Sym.getName())).second;
978
979
      // We need LTO to preseve the following global symbols:
980
      // 1) Symbols used in regular objects.
981
      // 2) Sections that will be given a __start/__stop symbol.
982
      // 3) Prevailing symbols that are needed visible to external libraries.
983
0
      Res.VisibleToRegularObj =
984
0
          UsedInRegularObj.contains(Sym.getName()) ||
985
0
          isValidCIdentifier(Sym.getSectionName()) ||
986
0
          (Res.Prevailing &&
987
0
           (Sym.getVisibility() != GlobalValue::HiddenVisibility &&
988
0
            !Sym.canBeOmittedFromSymbolTable()));
989
990
      // Identify symbols that must be exported dynamically and can be
991
      // referenced by other files.
992
0
      Res.ExportDynamic =
993
0
          Sym.getVisibility() != GlobalValue::HiddenVisibility &&
994
0
          (UsedInSharedLib.contains(Sym.getName()) ||
995
0
           !Sym.canBeOmittedFromSymbolTable());
996
997
      // The final definition will reside in this linkage unit if the symbol is
998
      // defined and local to the module. This only checks for bitcode files,
999
      // full assertion will require complete symbol resolution.
1000
0
      Res.FinalDefinitionInLinkageUnit =
1001
0
          Sym.getVisibility() != GlobalValue::DefaultVisibility &&
1002
0
          (!Sym.isUndefined() && !Sym.isCommon());
1003
1004
      // We do not support linker redefined symbols (e.g. --wrap) for device
1005
      // image linking, so the symbols will not be changed after LTO.
1006
0
      Res.LinkerRedefined = false;
1007
0
    }
1008
1009
    // Add the bitcode file with its resolved symbols to the LTO job.
1010
0
    if (Error Err = LTOBackend->add(std::move(*BitcodeFileOrErr), Resolutions))
1011
0
      return Err;
1012
0
  }
1013
1014
  // Run the LTO job to compile the bitcode.
1015
0
  size_t MaxTasks = LTOBackend->getMaxTasks();
1016
0
  SmallVector<StringRef> Files(MaxTasks);
1017
0
  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
1018
0
    int FD = -1;
1019
0
    auto &TempFile = Files[Task];
1020
0
    StringRef Extension = (Triple.isNVPTX()) ? "s" : "o";
1021
0
    std::string TaskStr = Task ? "." + std::to_string(Task) : "";
1022
0
    auto TempFileOrErr =
1023
0
        createOutputFile(sys::path::filename(ExecutableName) + "-device-" +
1024
0
                             Triple.getTriple() + TaskStr,
1025
0
                         Extension);
1026
0
    if (!TempFileOrErr)
1027
0
      reportError(TempFileOrErr.takeError());
1028
0
    TempFile = *TempFileOrErr;
1029
0
    if (std::error_code EC = sys::fs::openFileForWrite(TempFile, FD))
1030
0
      reportError(errorCodeToError(EC));
1031
0
    return std::make_unique<CachedFileStream>(
1032
0
        std::make_unique<llvm::raw_fd_ostream>(FD, true));
1033
0
  };
1034
1035
0
  if (Error Err = LTOBackend->run(AddStream))
1036
0
    return Err;
1037
1038
0
  if (LTOError)
1039
0
    return createStringError(inconvertibleErrorCode(),
1040
0
                             "Errors encountered inside the LTO pipeline.");
1041
1042
  // If we are embedding bitcode we only need the intermediate output.
1043
0
  bool SingleOutput = Files.size() == 1;
1044
0
  if (Args.hasArg(OPT_embed_bitcode)) {
1045
0
    if (BitcodeOutput.size() != 1 || !SingleOutput)
1046
0
      return createStringError(inconvertibleErrorCode(),
1047
0
                               "Cannot embed bitcode with multiple files.");
1048
0
    OutputFiles.push_back(static_cast<std::string>(BitcodeOutput.front()));
1049
0
    return Error::success();
1050
0
  }
1051
1052
  // Is we are compiling for NVPTX we need to run the assembler first.
1053
0
  if (Triple.isNVPTX()) {
1054
0
    for (StringRef &File : Files) {
1055
0
      auto FileOrErr = nvptx::assemble(File, Args, !SingleOutput);
1056
0
      if (!FileOrErr)
1057
0
        return FileOrErr.takeError();
1058
0
      File = *FileOrErr;
1059
0
    }
1060
0
  }
1061
1062
  // Append the new inputs to the device linker input.
1063
0
  for (StringRef File : Files)
1064
0
    OutputFiles.push_back(File);
1065
1066
0
  return Error::success();
1067
0
}
1068
1069
0
Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
1070
0
  const OffloadBinary &Binary = *File.getBinary();
1071
1072
0
  StringRef Prefix =
1073
0
      sys::path::stem(Binary.getMemoryBufferRef().getBufferIdentifier());
1074
0
  StringRef Suffix = getImageKindName(Binary.getImageKind());
1075
1076
0
  auto TempFileOrErr = createOutputFile(
1077
0
      Prefix + "-" + Binary.getTriple() + "-" + Binary.getArch(), Suffix);
1078
0
  if (!TempFileOrErr)
1079
0
    return TempFileOrErr.takeError();
1080
1081
0
  Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr =
1082
0
      FileOutputBuffer::create(*TempFileOrErr, Binary.getImage().size());
1083
0
  if (!OutputOrErr)
1084
0
    return OutputOrErr.takeError();
1085
0
  std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr);
1086
0
  std::copy(Binary.getImage().bytes_begin(), Binary.getImage().bytes_end(),
1087
0
            Output->getBufferStart());
1088
0
  if (Error E = Output->commit())
1089
0
    return std::move(E);
1090
1091
0
  return *TempFileOrErr;
1092
0
}
1093
1094
// Compile the module to an object file using the appropriate target machine for
1095
// the host triple.
1096
0
Expected<StringRef> compileModule(Module &M) {
1097
0
  llvm::TimeTraceScope TimeScope("Compile module");
1098
0
  std::string Msg;
1099
0
  const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
1100
0
  if (!T)
1101
0
    return createStringError(inconvertibleErrorCode(), Msg);
1102
1103
0
  auto Options =
1104
0
      codegen::InitTargetOptionsFromCodeGenFlags(Triple(M.getTargetTriple()));
1105
0
  StringRef CPU = "";
1106
0
  StringRef Features = "";
1107
0
  std::unique_ptr<TargetMachine> TM(
1108
0
      T->createTargetMachine(M.getTargetTriple(), CPU, Features, Options,
1109
0
                             Reloc::PIC_, M.getCodeModel()));
1110
1111
0
  if (M.getDataLayout().isDefault())
1112
0
    M.setDataLayout(TM->createDataLayout());
1113
1114
0
  int FD = -1;
1115
0
  auto TempFileOrErr =
1116
0
      createOutputFile(sys::path::filename(ExecutableName) + "-wrapper", "o");
1117
0
  if (!TempFileOrErr)
1118
0
    return TempFileOrErr.takeError();
1119
0
  if (std::error_code EC = sys::fs::openFileForWrite(*TempFileOrErr, FD))
1120
0
    return errorCodeToError(EC);
1121
1122
0
  auto OS = std::make_unique<llvm::raw_fd_ostream>(FD, true);
1123
1124
0
  legacy::PassManager CodeGenPasses;
1125
0
  TargetLibraryInfoImpl TLII(Triple(M.getTargetTriple()));
1126
0
  CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII));
1127
0
  if (TM->addPassesToEmitFile(CodeGenPasses, *OS, nullptr, CGFT_ObjectFile))
1128
0
    return createStringError(inconvertibleErrorCode(),
1129
0
                             "Failed to execute host backend");
1130
0
  CodeGenPasses.run(M);
1131
1132
0
  return *TempFileOrErr;
1133
0
}
1134
1135
/// Creates the object file containing the device image and runtime
1136
/// registration code from the device images stored in \p Images.
1137
Expected<StringRef>
1138
wrapDeviceImages(ArrayRef<std::unique_ptr<MemoryBuffer>> Buffers,
1139
0
                 const ArgList &Args, OffloadKind Kind) {
1140
0
  llvm::TimeTraceScope TimeScope("Wrap bundled images");
1141
1142
0
  SmallVector<ArrayRef<char>, 4> BuffersToWrap;
1143
0
  for (const auto &Buffer : Buffers)
1144
0
    BuffersToWrap.emplace_back(
1145
0
        ArrayRef<char>(Buffer->getBufferStart(), Buffer->getBufferSize()));
1146
1147
0
  LLVMContext Context;
1148
0
  Module M("offload.wrapper.module", Context);
1149
0
  M.setTargetTriple(
1150
0
      Args.getLastArgValue(OPT_host_triple_EQ, sys::getDefaultTargetTriple()));
1151
1152
0
  switch (Kind) {
1153
0
  case OFK_OpenMP:
1154
0
    if (Error Err = wrapOpenMPBinaries(M, BuffersToWrap))
1155
0
      return std::move(Err);
1156
0
    break;
1157
0
  case OFK_Cuda:
1158
0
    if (Error Err = wrapCudaBinary(M, BuffersToWrap.front()))
1159
0
      return std::move(Err);
1160
0
    break;
1161
0
  case OFK_HIP:
1162
0
    if (Error Err = wrapHIPBinary(M, BuffersToWrap.front()))
1163
0
      return std::move(Err);
1164
0
    break;
1165
0
  default:
1166
0
    return createStringError(inconvertibleErrorCode(),
1167
0
                             getOffloadKindName(Kind) +
1168
0
                                 " wrapping is not supported");
1169
0
  }
1170
1171
0
  if (Args.hasArg(OPT_print_wrapped_module))
1172
0
    errs() << M;
1173
1174
0
  auto FileOrErr = compileModule(M);
1175
0
  if (!FileOrErr)
1176
0
    return FileOrErr.takeError();
1177
0
  return *FileOrErr;
1178
0
}
1179
1180
Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1181
0
bundleOpenMP(ArrayRef<OffloadingImage> Images) {
1182
0
  SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1183
0
  for (const OffloadingImage &Image : Images)
1184
0
    Buffers.emplace_back(
1185
0
        MemoryBuffer::getMemBufferCopy(Image.Image->getBuffer()));
1186
1187
0
  return std::move(Buffers);
1188
0
}
1189
1190
Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1191
0
bundleCuda(ArrayRef<OffloadingImage> Images, const ArgList &Args) {
1192
0
  SmallVector<std::pair<StringRef, StringRef>, 4> InputFiles;
1193
0
  for (const OffloadingImage &Image : Images)
1194
0
    InputFiles.emplace_back(std::make_pair(Image.Image->getBufferIdentifier(),
1195
0
                                           Image.StringData.lookup("arch")));
1196
1197
0
  Triple TheTriple = Triple(Images.front().StringData.lookup("triple"));
1198
0
  auto FileOrErr = nvptx::fatbinary(InputFiles, Args);
1199
0
  if (!FileOrErr)
1200
0
    return FileOrErr.takeError();
1201
1202
0
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ImageOrError =
1203
0
      llvm::MemoryBuffer::getFileOrSTDIN(*FileOrErr);
1204
1205
0
  SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1206
0
  if (std::error_code EC = ImageOrError.getError())
1207
0
    return createFileError(*FileOrErr, EC);
1208
0
  Buffers.emplace_back(std::move(*ImageOrError));
1209
1210
0
  return std::move(Buffers);
1211
0
}
1212
1213
Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1214
0
bundleHIP(ArrayRef<OffloadingImage> Images, const ArgList &Args) {
1215
0
  SmallVector<std::pair<StringRef, StringRef>, 4> InputFiles;
1216
0
  for (const OffloadingImage &Image : Images)
1217
0
    InputFiles.emplace_back(std::make_pair(Image.Image->getBufferIdentifier(),
1218
0
                                           Image.StringData.lookup("arch")));
1219
1220
0
  Triple TheTriple = Triple(Images.front().StringData.lookup("triple"));
1221
0
  auto FileOrErr = amdgcn::fatbinary(InputFiles, Args);
1222
0
  if (!FileOrErr)
1223
0
    return FileOrErr.takeError();
1224
1225
0
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ImageOrError =
1226
0
      llvm::MemoryBuffer::getFileOrSTDIN(*FileOrErr);
1227
1228
0
  SmallVector<std::unique_ptr<MemoryBuffer>> Buffers;
1229
0
  if (std::error_code EC = ImageOrError.getError())
1230
0
    return createFileError(*FileOrErr, EC);
1231
0
  Buffers.emplace_back(std::move(*ImageOrError));
1232
1233
0
  return std::move(Buffers);
1234
0
}
1235
1236
/// Transforms the input \p Images into the binary format the runtime expects
1237
/// for the given \p Kind.
1238
Expected<SmallVector<std::unique_ptr<MemoryBuffer>>>
1239
bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args,
1240
0
                   OffloadKind Kind) {
1241
0
  llvm::TimeTraceScope TimeScope("Bundle linked output");
1242
0
  switch (Kind) {
1243
0
  case OFK_OpenMP:
1244
0
    return bundleOpenMP(Images);
1245
0
  case OFK_Cuda:
1246
0
    return bundleCuda(Images, Args);
1247
0
  case OFK_HIP:
1248
0
    return bundleHIP(Images, Args);
1249
0
  default:
1250
0
    return createStringError(inconvertibleErrorCode(),
1251
0
                             getOffloadKindName(Kind) +
1252
0
                                 " bundling is not supported");
1253
0
  }
1254
0
}
1255
1256
/// Returns a new ArgList containg arguments used for the device linking phase.
1257
DerivedArgList getLinkerArgs(ArrayRef<OffloadFile> Input,
1258
0
                             const InputArgList &Args) {
1259
0
  DerivedArgList DAL = DerivedArgList(DerivedArgList(Args));
1260
0
  for (Arg *A : Args)
1261
0
    DAL.append(A);
1262
1263
  // Set the subarchitecture and target triple for this compilation.
1264
0
  const OptTable &Tbl = getOptTable();
1265
0
  DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_arch_EQ),
1266
0
                   Args.MakeArgString(Input.front().getBinary()->getArch()));
1267
0
  DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_triple_EQ),
1268
0
                   Args.MakeArgString(Input.front().getBinary()->getTriple()));
1269
1270
  // If every input file is bitcode we have whole program visibility as we do
1271
  // only support static linking with bitcode.
1272
0
  auto ContainsBitcode = [](const OffloadFile &F) {
1273
0
    return identify_magic(F.getBinary()->getImage()) == file_magic::bitcode;
1274
0
  };
1275
0
  if (llvm::all_of(Input, ContainsBitcode))
1276
0
    DAL.AddFlagArg(nullptr, Tbl.getOption(OPT_whole_program));
1277
1278
  // Forward '-Xoffload-linker' options to the appropriate backend.
1279
0
  for (StringRef Arg : Args.getAllArgValues(OPT_device_linker_args_EQ)) {
1280
0
    auto TripleAndValue = Arg.split('=');
1281
0
    if (TripleAndValue.second.empty())
1282
0
      DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
1283
0
                       Args.MakeArgString(TripleAndValue.first));
1284
0
    else if (TripleAndValue.first == DAL.getLastArgValue(OPT_triple_EQ))
1285
0
      DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
1286
0
                       Args.MakeArgString(TripleAndValue.second));
1287
0
  }
1288
1289
0
  return DAL;
1290
0
}
1291
1292
/// Transforms all the extracted offloading input files into an image that can
1293
/// be registered by the runtime.
1294
Expected<SmallVector<StringRef>>
1295
linkAndWrapDeviceFiles(SmallVectorImpl<OffloadFile> &LinkerInputFiles,
1296
0
                       const InputArgList &Args) {
1297
0
  llvm::TimeTraceScope TimeScope("Handle all device input");
1298
1299
0
  DenseMap<OffloadFile::TargetID, SmallVector<OffloadFile, 4>> InputsForTarget;
1300
0
  for (auto &File : LinkerInputFiles)
1301
0
    InputsForTarget[File].emplace_back(std::move(File));
1302
0
  LinkerInputFiles.clear();
1303
1304
0
  DenseMap<OffloadKind, SmallVector<OffloadingImage, 2>> Images;
1305
0
  for (auto &InputForTarget : InputsForTarget) {
1306
0
    llvm::TimeTraceScope TimeScope("Link device input");
1307
1308
0
    SmallVector<OffloadFile, 4> &Input = InputForTarget.getSecond();
1309
0
    auto LinkerArgs = getLinkerArgs(Input, Args);
1310
1311
0
    DenseSet<OffloadKind> ActiveOffloadKinds;
1312
0
    for (const auto &File : Input)
1313
0
      ActiveOffloadKinds.insert(File.getBinary()->getOffloadKind());
1314
1315
    // First link and remove all the input files containing bitcode.
1316
0
    SmallVector<StringRef> InputFiles;
1317
0
    if (Error Err = linkBitcodeFiles(Input, InputFiles, LinkerArgs))
1318
0
      return std::move(Err);
1319
1320
    // Write any remaining device inputs to an output file for the linker job.
1321
0
    for (const OffloadFile &File : Input) {
1322
0
      auto FileNameOrErr = writeOffloadFile(File);
1323
0
      if (!FileNameOrErr)
1324
0
        return FileNameOrErr.takeError();
1325
0
      InputFiles.emplace_back(*FileNameOrErr);
1326
0
    }
1327
1328
    // Link the remaining device files, if necessary, using the device linker.
1329
0
    llvm::Triple Triple(LinkerArgs.getLastArgValue(OPT_triple_EQ));
1330
0
    bool RequiresLinking =
1331
0
        !Args.hasArg(OPT_embed_bitcode) &&
1332
0
        !(Input.empty() && InputFiles.size() == 1 && Triple.isNVPTX());
1333
0
    auto OutputOrErr = RequiresLinking ? linkDevice(InputFiles, LinkerArgs)
1334
0
                                       : InputFiles.front();
1335
0
    if (!OutputOrErr)
1336
0
      return OutputOrErr.takeError();
1337
1338
    // Store the offloading image for each linked output file.
1339
0
    for (OffloadKind Kind : ActiveOffloadKinds) {
1340
0
      llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
1341
0
          llvm::MemoryBuffer::getFileOrSTDIN(*OutputOrErr);
1342
0
      if (std::error_code EC = FileOrErr.getError())
1343
0
        return createFileError(*OutputOrErr, EC);
1344
1345
0
      OffloadingImage TheImage{};
1346
0
      TheImage.TheImageKind = IMG_Object;
1347
0
      TheImage.TheOffloadKind = Kind;
1348
0
      TheImage.StringData = {
1349
0
          {"triple", LinkerArgs.getLastArgValue(OPT_triple_EQ)},
1350
0
          {"arch", LinkerArgs.getLastArgValue(OPT_arch_EQ)}};
1351
0
      TheImage.Image = std::move(*FileOrErr);
1352
0
      Images[Kind].emplace_back(std::move(TheImage));
1353
0
    }
1354
0
  }
1355
1356
  // Create a binary image of each offloading image and embed it into a new
1357
  // object file.
1358
0
  SmallVector<StringRef> WrappedOutput;
1359
0
  for (const auto &KindAndImages : Images) {
1360
0
    OffloadKind Kind = KindAndImages.first;
1361
0
    auto BundledImagesOrErr =
1362
0
        bundleLinkedOutput(KindAndImages.second, Args, Kind);
1363
0
    if (!BundledImagesOrErr)
1364
0
      return BundledImagesOrErr.takeError();
1365
0
    auto OutputOrErr = wrapDeviceImages(*BundledImagesOrErr, Args, Kind);
1366
0
    if (!OutputOrErr)
1367
0
      return OutputOrErr.takeError();
1368
0
    WrappedOutput.push_back(*OutputOrErr);
1369
0
  }
1370
1371
0
  return WrappedOutput;
1372
0
}
1373
1374
Optional<std::string> findFile(StringRef Dir, StringRef Root,
1375
0
                               const Twine &Name) {
1376
0
  SmallString<128> Path;
1377
0
  if (Dir.startswith("="))
1378
0
    sys::path::append(Path, Root, Dir.substr(1), Name);
1379
0
  else
1380
0
    sys::path::append(Path, Dir, Name);
1381
1382
0
  if (sys::fs::exists(Path))
1383
0
    return static_cast<std::string>(Path);
1384
0
  return None;
1385
0
}
1386
1387
Optional<std::string> findFromSearchPaths(StringRef Name, StringRef Root,
1388
0
                                          ArrayRef<StringRef> SearchPaths) {
1389
0
  for (StringRef Dir : SearchPaths)
1390
0
    if (Optional<std::string> File = findFile(Dir, Root, Name))
1391
0
      return File;
1392
0
  return None;
1393
0
}
1394
1395
Optional<std::string> searchLibraryBaseName(StringRef Name, StringRef Root,
1396
0
                                            ArrayRef<StringRef> SearchPaths) {
1397
0
  for (StringRef Dir : SearchPaths) {
1398
0
    if (Optional<std::string> File = findFile(Dir, Root, "lib" + Name + ".so"))
1399
0
      return None;
1400
0
    if (Optional<std::string> File = findFile(Dir, Root, "lib" + Name + ".a"))
1401
0
      return File;
1402
0
  }
1403
0
  return None;
1404
0
}
1405
1406
/// Search for static libraries in the linker's library path given input like
1407
/// `-lfoo` or `-l:libfoo.a`.
1408
Optional<std::string> searchLibrary(StringRef Input, StringRef Root,
1409
0
                                    ArrayRef<StringRef> SearchPaths) {
1410
0
  if (Input.startswith(":"))
1411
0
    return findFromSearchPaths(Input.drop_front(), Root, SearchPaths);
1412
0
  return searchLibraryBaseName(Input, Root, SearchPaths);
1413
0
}
1414
1415
/// Search the input files and libraries for embedded device offloading code and
1416
/// add it to the list of files to be linked. Files coming from static libraries
1417
/// are only added to the input if they are used by an existing input file.
1418
0
Expected<SmallVector<OffloadFile>> getDeviceInput(const ArgList &Args) {
1419
0
  llvm::TimeTraceScope TimeScope("ExtractDeviceCode");
1420
1421
0
  StringRef Root = Args.getLastArgValue(OPT_sysroot_EQ);
1422
0
  SmallVector<StringRef> LibraryPaths;
1423
0
  for (const opt::Arg *Arg : Args.filtered(OPT_library_path))
1424
0
    LibraryPaths.push_back(Arg->getValue());
1425
1426
  // Try to extract device code from the linker input files.
1427
0
  SmallVector<OffloadFile> InputFiles;
1428
0
  SmallVector<OffloadFile> LazyInputFiles;
1429
0
  for (const opt::Arg *Arg : Args.filtered(OPT_INPUT)) {
1430
0
    StringRef Filename = Arg->getValue();
1431
0
    if (!sys::fs::exists(Filename) || sys::fs::is_directory(Filename))
1432
0
      continue;
1433
1434
0
    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
1435
0
        MemoryBuffer::getFileOrSTDIN(Filename);
1436
0
    if (std::error_code EC = BufferOrErr.getError())
1437
0
      reportError(createFileError(Filename, EC));
1438
1439
0
    bool IsLazy =
1440
0
        identify_magic((*BufferOrErr)->getBuffer()) == file_magic::archive;
1441
0
    if (Error Err = extractFromBuffer(std::move(*BufferOrErr),
1442
0
                                      IsLazy ? LazyInputFiles : InputFiles))
1443
0
      reportError(std::move(Err));
1444
0
  }
1445
1446
  // Try to extract input from input libraries.
1447
0
  for (const opt::Arg *Arg : Args.filtered(OPT_library)) {
1448
0
    if (auto Library = searchLibrary(Arg->getValue(), Root, LibraryPaths)) {
1449
0
      ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
1450
0
          MemoryBuffer::getFileOrSTDIN(*Library);
1451
0
      if (std::error_code EC = BufferOrErr.getError())
1452
0
        reportError(createFileError(*Library, EC));
1453
1454
0
      if (Error Err =
1455
0
              extractFromBuffer(std::move(*BufferOrErr), LazyInputFiles))
1456
0
        reportError(std::move(Err));
1457
0
    }
1458
0
  }
1459
1460
0
  for (StringRef Library : Args.getAllArgValues(OPT_bitcode_library_EQ)) {
1461
0
    auto FileOrErr = getInputBitcodeLibrary(Library);
1462
0
    if (!FileOrErr)
1463
0
      reportError(FileOrErr.takeError());
1464
0
    InputFiles.push_back(std::move(*FileOrErr));
1465
0
  }
1466
1467
0
  DenseSet<OffloadFile::TargetID> IsTargetUsed;
1468
0
  for (const auto &File : InputFiles)
1469
0
    IsTargetUsed.insert(File);
1470
1471
  // We should only include input files that are used.
1472
  // TODO: Only load a library if it defined undefined symbols in the input.
1473
0
  for (auto &LazyFile : LazyInputFiles)
1474
0
    if (IsTargetUsed.contains(LazyFile))
1475
0
      InputFiles.emplace_back(std::move(LazyFile));
1476
1477
0
  return std::move(InputFiles);
1478
0
}
1479
1480
} // namespace
1481
1482
int main(int Argc, char **Argv) {
1483
  InitLLVM X(Argc, Argv);
1484
  InitializeAllTargetInfos();
1485
  InitializeAllTargets();
1486
  InitializeAllTargetMCs();
1487
  InitializeAllAsmParsers();
1488
  InitializeAllAsmPrinters();
1489
1490
  LinkerExecutable = Argv[0];
1491
  sys::PrintStackTraceOnErrorSignal(Argv[0]);
1492
1493
  const OptTable &Tbl = getOptTable();
1494
  BumpPtrAllocator Alloc;
1495
  StringSaver Saver(Alloc);
1496
0
  auto Args = Tbl.parseArgs(Argc, Argv, OPT_INVALID, Saver, [&](StringRef Err) {
1497
0
    reportError(createStringError(inconvertibleErrorCode(), Err));
1498
0
  });
1499
1500
  if (Args.hasArg(OPT_help) || Args.hasArg(OPT_help_hidden)) {
1501
    Tbl.printHelp(
1502
        outs(),
1503
        "clang-linker-wrapper [options] -- <options to passed to the linker>",
1504
        "\nA wrapper utility over the host linker. It scans the input files\n"
1505
        "for sections that require additional processing prior to linking.\n"
1506
        "The will then transparently pass all arguments and input to the\n"
1507
        "specified host linker to create the final binary.\n",
1508
        Args.hasArg(OPT_help_hidden), Args.hasArg(OPT_help_hidden));
1509
    return EXIT_SUCCESS;
1510
  }
1511
  if (Args.hasArg(OPT_v)) {
1512
    printVersion(outs());
1513
    return EXIT_SUCCESS;
1514
  }
1515
1516
  // This forwards '-pass-remarks=' to the LTO backend if present.
1517
  cl::HideUnrelatedOptions(ClangLinkerWrapperCategory);
1518
  cl::ParseCommandLineOptions(Argc, Argv);
1519
1520
  Verbose = Args.hasArg(OPT_verbose);
1521
  DryRun = Args.hasArg(OPT_dry_run);
1522
  SaveTemps = Args.hasArg(OPT_save_temps);
1523
  ExecutableName = Args.getLastArgValue(OPT_o, "a.out");
1524
  CudaBinaryPath = Args.getLastArgValue(OPT_cuda_path_EQ).str();
1525
  if (!CudaBinaryPath.empty())
1526
    CudaBinaryPath = CudaBinaryPath + "/bin";
1527
1528
  if (Args.hasArg(OPT_wrapper_time_trace_eq)) {
1529
    unsigned Granularity;
1530
    Args.getLastArgValue(OPT_wrapper_time_trace_granularity, "500")
1531
        .getAsInteger(10, Granularity);
1532
    timeTraceProfilerInitialize(Granularity, Argv[0]);
1533
  }
1534
1535
  {
1536
    llvm::TimeTraceScope TimeScope("Execute linker wrapper");
1537
1538
    // Extract the device input files stored in the host fat binary.
1539
    auto DeviceInputFiles = getDeviceInput(Args);
1540
    if (!DeviceInputFiles)
1541
      reportError(DeviceInputFiles.takeError());
1542
1543
    // Link and wrap the device images extracted from the linker input.
1544
    auto FilesOrErr = linkAndWrapDeviceFiles(*DeviceInputFiles, Args);
1545
    if (!FilesOrErr)
1546
      reportError(FilesOrErr.takeError());
1547
1548
    // Run the host linking job with the rendered arguments.
1549
    if (Error Err = runLinker(*FilesOrErr, Args))
1550
      reportError(std::move(Err));
1551
  }
1552
1553
  if (const opt::Arg *Arg = Args.getLastArg(OPT_wrapper_time_trace_eq)) {
1554
    if (Error Err = timeTraceProfilerWrite(Arg->getValue(), ExecutableName))
1555
      reportError(std::move(Err));
1556
    timeTraceProfilerCleanup();
1557
  }
1558
1559
  // Remove the temporary files created.
1560
  if (!SaveTemps)
1561
    for (const auto &TempFile : TempFiles)
1562
      if (std::error_code EC = sys::fs::remove(TempFile))
1563
        reportError(createFileError(TempFile, EC));
1564
1565
  return EXIT_SUCCESS;
1566
}