reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
//===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLD_CORE_ATOM_H
#define LLD_CORE_ATOM_H

#include "lld/Common/LLVM.h"
#include "llvm/ADT/StringRef.h"

namespace lld {

class File;

template<typename T>
class OwningAtomPtr;

///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms.  Each Atom is a node
/// and each Reference is an edge. An Atom can be a DefinedAtom which has
/// content or a UndefinedAtom which is a placeholder and represents an
/// undefined symbol (extern declaration).
///
class Atom {
  template<typename T> friend class OwningAtomPtr;

public:
  /// Whether this atom is defined or a proxy for an undefined symbol
  enum Definition {
    definitionRegular,      ///< Normal C/C++ function or global variable.
    definitionAbsolute,     ///< Asm-only (foo = 10). Not tied to any content.
    definitionUndefined,    ///< Only in .o files to model reference to undef.
    definitionSharedLibrary ///< Only in shared libraries to model export.
  };

  /// The scope in which this atom is acessible to other atoms.
  enum Scope {
    scopeTranslationUnit,  ///< Accessible only to atoms in the same translation
                           ///  unit (e.g. a C static).
    scopeLinkageUnit,      ///< Accessible to atoms being linked but not visible
                           ///  to runtime loader (e.g. visibility=hidden).
    scopeGlobal            ///< Accessible to all atoms and visible to runtime
                           ///  loader (e.g. visibility=default).
  };

  /// file - returns the File that produced/owns this Atom
  virtual const File& file() const = 0;

  /// name - The name of the atom. For a function atom, it is the (mangled)
  /// name of the function.
  virtual StringRef name() const = 0;

  /// definition - Whether this atom is a definition or represents an undefined
  /// symbol.
  Definition definition() const { return _definition; }

  static bool classof(const Atom *a) { return true; }

protected:
  /// Atom is an abstract base class.  Only subclasses can access constructor.
  explicit Atom(Definition def) : _definition(def) {}

  /// The memory for Atom objects is always managed by the owning File
  /// object.  Therefore, no one but the owning File object should call
  /// delete on an Atom.  In fact, some File objects may bulk allocate
  /// an array of Atoms, so they cannot be individually deleted by anyone.
  virtual ~Atom() = default;

private:
  Definition _definition;
};

/// Class which owns an atom pointer and runs the atom destructor when the
/// owning pointer goes out of scope.
template<typename T>
class OwningAtomPtr {
private:
  OwningAtomPtr(const OwningAtomPtr &) = delete;
  void operator=(const OwningAtomPtr &) = delete;

public:
  OwningAtomPtr() = default;
  OwningAtomPtr(T *atom) : atom(atom) { }

  ~OwningAtomPtr() {
    if (atom)
      runDestructor(atom);
  }

  void runDestructor(Atom *atom) {
    atom->~Atom();
  }

  OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
    ptr.atom = nullptr;
  }

  void operator=(OwningAtomPtr&& ptr) {
    if (atom)
      runDestructor(atom);
    atom = ptr.atom;
    ptr.atom = nullptr;
  }

  T *const &get() const {
    return atom;
  }

  T *&get() {
    return atom;
  }

  T *release() {
    auto *v = atom;
    atom = nullptr;
    return v;
  }

private:
  T *atom = nullptr;
};

} // end namespace lld

#endif // LLD_CORE_ATOM_H