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