summaryrefslogtreecommitdiffstats
path: root/lld/lib/Driver/Targets.cpp
blob: 2e2bc59d3548fa78d9a425740bc01bc142c555e5 (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
//===- lib/Driver/Targets.cpp - Linker Targets ----------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Concrete instances of the Target interface.
///
//===----------------------------------------------------------------------===//

#include "lld/Driver/Target.h"

#include "lld/Core/LinkerOptions.h"
#include "lld/Core/TargetInfo.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/Writer.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"

#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"

#include <set>

using namespace lld;
using namespace std::placeholders;

class ELFTarget : public Target {
public:
  ELFTarget(std::unique_ptr<ELFTargetInfo> ti)
      : Target(std::unique_ptr<TargetInfo>(ti.get())),
        _elfTargetInfo(*ti.release()), _readerELF(createReaderELF(
            _elfTargetInfo, std::bind(&ELFTarget::getReader, this, _1))),
        _readerYAML(createReaderYAML(*_targetInfo)),
        _writer(createWriterELF(_elfTargetInfo)),
        _writerYAML(createWriterYAML(*_targetInfo)) {
  }

  virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) {
    auto kind = input.getKind();
    if (!kind)
      return error_code(kind);

    if (*kind == InputKind::YAML)
      return *_readerYAML;

    if (*kind == InputKind::Object)
      return *_readerELF;

    return llvm::make_error_code(llvm::errc::invalid_argument);
  }

  virtual ErrorOr<lld::Writer&> getWriter() {
    return _targetInfo->getLinkerOptions()._outputYAML ? *_writerYAML
                                                       : *_writer;
  }

protected:
  const ELFTargetInfo &_elfTargetInfo;
  std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
  std::unique_ptr<lld::Writer> _writer, _writerYAML;
};

class X86LinuxTarget LLVM_FINAL : public ELFTarget {
public:
  X86LinuxTarget(std::unique_ptr<ELFTargetInfo> ti)
      : ELFTarget(std::move(ti)) {}
};

class HexagonTarget LLVM_FINAL : public ELFTarget {
public:
  HexagonTarget(std::unique_ptr<ELFTargetInfo> ti)
      : ELFTarget(std::move(ti)) {}
};

std::unique_ptr<Target> Target::create(const LinkerOptions &lo) {
  llvm::Triple t(lo._target);
  // Create a TargetInfo.
  std::unique_ptr<ELFTargetInfo> ti(ELFTargetInfo::create(lo));

  // Create the Target
  if (t.getOS() == llvm::Triple::Linux && (t.getArch() == llvm::Triple::x86 ||
                                           t.getArch() == llvm::Triple::x86_64))
    return std::unique_ptr<Target>(new X86LinuxTarget(std::move(ti)));
  else if (t.getArch() == llvm::Triple::hexagon) 
    return std::unique_ptr<Target>(new HexagonTarget(std::move(ti)));
  return std::unique_ptr<Target>();
}
OpenPOWER on IntegriCloud