summaryrefslogtreecommitdiffstats
path: root/lld/lib/Driver/UniversalDriver.cpp
blob: 5164f9da69c90c368d8a481fe41edb4794d691d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//===- lib/Driver/UniversalDriver.cpp -------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Concrete instance of the Driver for darwin's ld.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Driver.h"
#include "lld/ReaderWriter/MachOTargetInfo.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

#include <memory>

namespace lld {


bool UniversalDriver::link(int argc, const char *argv[]) {
  // Convert argv[] C-array to vector.
  std::vector<const char *> args;
  args.assign(&argv[0], &argv[argc]);
  
  // Determine flavor of link based on command name or -flavor argument.
  // Note: 'args' is modified to remove -flavor option.
  Flavor flavor = selectFlavor(args);
  
  // Switch to appropriate driver.
  switch (flavor) {
  case Flavor::gnu_ld:
    return GnuLdDriver::linkELF(args.size(), &args[0]);
  case Flavor::darwin_ld:
    return DarwinLdDriver::linkMachO(args.size(), &args[0]);
  case Flavor::core:
    return CoreDriver::link(args.size(), &args[0]);
  case Flavor::win_link:
    llvm_unreachable("Unsupported flavor");
  case Flavor::invalid:
    return true;
  }
}





/// Pick the flavor of driver to use based on the command line and
/// host environment.
UniversalDriver::Flavor UniversalDriver::selectFlavor(
                                              std::vector<const char*> &args) {
  // -core as first arg is shorthand for -flavor core.
  if (args.size() >= 1 && StringRef(args[1]) == "-core") {
    args.erase(args.begin() + 1);
    return Flavor::core;
  }
  // Handle -flavor as first arg.
  if (args.size() >= 2 && StringRef(args[1]) == "-flavor") {
    Flavor flavor = strToFlavor(args[2]);
    args.erase(args.begin() + 1);
    args.erase(args.begin() + 1);
    if (flavor == Flavor::invalid)
      llvm::errs() << "error: '" << args[2] << "' invalid value for -flavor.\n";
    return flavor;
  }

  // Check if flavor is at end of program name (e.g. "lld-gnu");
  SmallVector<StringRef, 3> components;
  llvm::SplitString(args[0], components, "-");
  Flavor flavor = strToFlavor(components.back());
  
  // If flavor still undetermined, then error out.
  if (flavor == Flavor::invalid)
    llvm::errs() << "error: failed to determine driver flavor from program name"
                    " '" << args[0] << "'.\n";
  return flavor;
}

/// Maps flavor strings to Flavor enum values.
UniversalDriver::Flavor UniversalDriver::strToFlavor(StringRef str) {
  return llvm::StringSwitch<Flavor>(str)
           .Case("gnu",    Flavor::gnu_ld)
           .Case("darwin", Flavor::darwin_ld)
           .Case("link",   Flavor::win_link)
           .Case("core",   Flavor::core)
           .Case("ld",     Flavor::gnu_ld) // deprecated
           .Default(Flavor::invalid);
}


} // namespace lld
OpenPOWER on IntegriCloud