Reference.h revision 360660
1254721Semaste//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===//
2254721Semaste//
3254721Semaste// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4254721Semaste// See https://llvm.org/LICENSE.txt for license information.
5254721Semaste// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#ifndef LLD_CORE_REFERENCES_H
10254721Semaste#define LLD_CORE_REFERENCES_H
11254721Semaste
12254721Semaste#include <cstdint>
13254721Semaste
14254721Semastenamespace lld {
15254721Semaste
16254721Semasteclass Atom;
17254721Semaste
18254721Semaste///
19254721Semaste/// The linker has a Graph Theory model of linking. An object file is seen
20254721Semaste/// as a set of Atoms with References to other Atoms.  Each Atom is a node
21254721Semaste/// and each Reference is an edge.
22254721Semaste///
23254721Semaste/// For example if a function contains a call site to "malloc" 40 bytes into
24254721Semaste/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
25254721Semaste/// kind=callsite, target=malloc, addend=0.
26254721Semaste///
27254721Semaste/// Besides supporting traditional "relocations", references are also used
28254721Semaste/// forcing layout (one atom must follow another), marking data-in-code
29254721Semaste/// (jump tables or ARM constants), etc.
30254721Semaste///
31254721Semaste/// The "kind" of a reference is a tuple of <namespace, arch, value>.  This
32254721Semaste/// enable us to re-use existing relocation types definded for various
33254721Semaste/// file formats and architectures.
34254721Semaste///
35254721Semaste/// References and atoms form a directed graph. The dead-stripping pass
36254721Semaste/// traverses them starting from dead-strip root atoms to garbage collect
37254721Semaste/// unreachable ones.
38254721Semaste///
39254721Semaste/// References of any kind are considered as directed edges. In addition to
40254721Semaste/// that, references of some kind is considered as bidirected edges.
41254721Semasteclass Reference {
42254721Semastepublic:
43254721Semaste  /// Which universe defines the kindValue().
44254721Semaste  enum class KindNamespace {
45254721Semaste    all     = 0,
46254721Semaste    testing = 1,
47254721Semaste    mach_o  = 2,
48254721Semaste  };
49254721Semaste
50254721Semaste  KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
51254721Semaste  void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
52254721Semaste
53254721Semaste  // Which architecture the kind value is for.
54254721Semaste  enum class KindArch { all, AArch64, ARM, x86, x86_64};
55254721Semaste
56254721Semaste  KindArch kindArch() const { return (KindArch)_kindArch; }
57254721Semaste  void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
58254721Semaste
59254721Semaste  typedef uint16_t KindValue;
60254721Semaste
61254721Semaste  KindValue kindValue() const { return _kindValue; }
62254721Semaste
63254721Semaste  /// setKindValue() is needed because during linking, some optimizations may
64254721Semaste  /// change the codegen and hence the reference kind.
65254721Semaste  void setKindValue(KindValue value) {
66254721Semaste    _kindValue = value;
67254721Semaste  }
68254721Semaste
69254721Semaste  /// KindValues used with KindNamespace::all and KindArch::all.
70254721Semaste  enum {
71254721Semaste    // kindLayoutAfter is treated as a bidirected edge by the dead-stripping
72254721Semaste    // pass.
73254721Semaste    kindLayoutAfter = 1,
74254721Semaste    kindAssociate,
75254721Semaste  };
76254721Semaste
77254721Semaste  // A value to be added to the value of a target
78254721Semaste  typedef int64_t Addend;
79254721Semaste
80254721Semaste  /// If the reference is a fixup in the Atom, then this returns the
81254721Semaste  /// byte offset into the Atom's content to do the fix up.
82254721Semaste  virtual uint64_t offsetInAtom() const = 0;
83254721Semaste
84254721Semaste  /// Returns the atom this reference refers to.
85254721Semaste  virtual const Atom *target() const = 0;
86254721Semaste
87254721Semaste  /// During linking, the linker may merge graphs which coalesces some nodes
88254721Semaste  /// (i.e. Atoms).  To switch the target of a reference, this method is called.
89254721Semaste  virtual void setTarget(const Atom *) = 0;
90254721Semaste
91254721Semaste  /// Some relocations require a symbol and a value (e.g. foo + 4).
92254721Semaste  virtual Addend addend() const = 0;
93254721Semaste
94254721Semaste  /// During linking, some optimzations may change addend value.
95254721Semaste  virtual void setAddend(Addend) = 0;
96254721Semaste
97254721Semaste  /// Returns target specific attributes of the reference.
98254721Semaste  virtual uint32_t tag() const { return 0; }
99254721Semaste
100254721Semasteprotected:
101254721Semaste  /// Reference is an abstract base class.  Only subclasses can use constructor.
102254721Semaste  Reference(KindNamespace ns, KindArch a, KindValue value)
103254721Semaste      : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {}
104254721Semaste
105254721Semaste  /// The memory for Reference objects is always managed by the owning File
106254721Semaste  /// object.  Therefore, no one but the owning File object should call
107254721Semaste  /// delete on an Reference.  In fact, some File objects may bulk allocate
108254721Semaste  /// an array of References, so they cannot be individually deleted by anyone.
109254721Semaste  virtual ~Reference() = default;
110254721Semaste
111254721Semaste  KindValue  _kindValue;
112254721Semaste  uint8_t    _kindNamespace;
113254721Semaste  uint8_t    _kindArch;
114254721Semaste};
115254721Semaste
116254721Semaste} // end namespace lld
117254721Semaste
118254721Semaste#endif // LLD_CORE_REFERENCES_H
119254721Semaste