1193323Sed//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines the MachineRelocation class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#ifndef LLVM_CODEGEN_MACHINERELOCATION_H
15193323Sed#define LLVM_CODEGEN_MACHINERELOCATION_H
16193323Sed
17218893Sdim#include "llvm/Support/DataTypes.h"
18193323Sed#include <cassert>
19193323Sed
20193323Sednamespace llvm {
21193323Sedclass GlobalValue;
22193323Sedclass MachineBasicBlock;
23193323Sed
24193323Sed/// MachineRelocation - This represents a target-specific relocation value,
25193323Sed/// produced by the code emitter.  This relocation is resolved after the has
26193323Sed/// been emitted, either to an object file or to memory, when the target of the
27193323Sed/// relocation can be resolved.
28193323Sed///
29193323Sed/// A relocation is made up of the following logical portions:
30193323Sed///   1. An offset in the machine code buffer, the location to modify.
31193323Sed///   2. A target specific relocation type (a number from 0 to 63).
32193323Sed///   3. A symbol being referenced, either as a GlobalValue* or as a string.
33193323Sed///   4. An optional constant value to be added to the reference.
34193323Sed///   5. A bit, CanRewrite, which indicates to the JIT that a function stub is
35193323Sed///      not needed for the relocation.
36193323Sed///   6. An index into the GOT, if the target uses a GOT
37193323Sed///
38193323Sedclass MachineRelocation {
39193323Sed  enum AddressType {
40193323Sed    isResult,         // Relocation has be transformed into its result pointer.
41193323Sed    isGV,             // The Target.GV field is valid.
42193323Sed    isIndirectSym,    // Relocation of an indirect symbol.
43193323Sed    isBB,             // Relocation of BB address.
44193323Sed    isExtSym,         // The Target.ExtSym field is valid.
45193323Sed    isConstPool,      // Relocation of constant pool address.
46193323Sed    isJumpTable,      // Relocation of jump table address.
47193323Sed    isGOTIndex        // The Target.GOTIndex field is valid.
48193323Sed  };
49193323Sed
50193323Sed  /// Offset - This is the offset from the start of the code buffer of the
51193323Sed  /// relocation to perform.
52193323Sed  uintptr_t Offset;
53193323Sed
54193323Sed  /// ConstantVal - A field that may be used by the target relocation type.
55193323Sed  intptr_t ConstantVal;
56193323Sed
57193323Sed  union {
58193323Sed    void *Result;           // If this has been resolved to a resolved pointer
59193323Sed    GlobalValue *GV;        // If this is a pointer to a GV or an indirect ref.
60263508Sdim    MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB
61193323Sed    const char *ExtSym;     // If this is a pointer to a named symbol
62193323Sed    unsigned Index;         // Constant pool / jump table index
63193323Sed    unsigned GOTIndex;      // Index in the GOT of this symbol/global
64193323Sed  } Target;
65193323Sed
66193323Sed  unsigned TargetReloType : 6; // The target relocation ID
67193323Sed  AddressType AddrType    : 4; // The field of Target to use
68199481Srdivacky  bool MayNeedFarStub     : 1; // True if this relocation may require a far-stub
69193323Sed  bool GOTRelative        : 1; // Should this relocation be relative to the GOT?
70193323Sed  bool TargetResolve      : 1; // True if target should resolve the address
71193323Sed
72193323Sedpublic:
73193323Sed // Relocation types used in a generic implementation.  Currently, relocation
74193323Sed // entries for all things use the generic VANILLA type until they are refined
75193323Sed // into target relocation types.
76193323Sed  enum RelocationType {
77193323Sed    VANILLA
78193323Sed  };
79193323Sed
80193323Sed  /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue.
81193323Sed  ///
82193323Sed  static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType,
83193323Sed                                 GlobalValue *GV, intptr_t cst = 0,
84199481Srdivacky                                 bool MayNeedFarStub = 0,
85193323Sed                                 bool GOTrelative = 0) {
86193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
87193323Sed    MachineRelocation Result;
88193323Sed    Result.Offset = offset;
89193323Sed    Result.ConstantVal = cst;
90193323Sed    Result.TargetReloType = RelocationType;
91193323Sed    Result.AddrType = isGV;
92199481Srdivacky    Result.MayNeedFarStub = MayNeedFarStub;
93193323Sed    Result.GOTRelative = GOTrelative;
94193323Sed    Result.TargetResolve = false;
95193323Sed    Result.Target.GV = GV;
96193323Sed    return Result;
97193323Sed  }
98193323Sed
99193323Sed  /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an
100193323Sed  /// indirect symbol.
101193323Sed  static MachineRelocation getIndirectSymbol(uintptr_t offset,
102193323Sed                                             unsigned RelocationType,
103193323Sed                                             GlobalValue *GV, intptr_t cst = 0,
104199481Srdivacky                                             bool MayNeedFarStub = 0,
105193323Sed                                             bool GOTrelative = 0) {
106193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
107193323Sed    MachineRelocation Result;
108193323Sed    Result.Offset = offset;
109193323Sed    Result.ConstantVal = cst;
110193323Sed    Result.TargetReloType = RelocationType;
111193323Sed    Result.AddrType = isIndirectSym;
112199481Srdivacky    Result.MayNeedFarStub = MayNeedFarStub;
113193323Sed    Result.GOTRelative = GOTrelative;
114193323Sed    Result.TargetResolve = false;
115193323Sed    Result.Target.GV = GV;
116193323Sed    return Result;
117193323Sed  }
118193323Sed
119193323Sed  /// MachineRelocation::getBB - Return a relocation entry for a BB.
120193323Sed  ///
121193323Sed  static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType,
122193323Sed                                 MachineBasicBlock *MBB, intptr_t cst = 0) {
123193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
124193323Sed    MachineRelocation Result;
125193323Sed    Result.Offset = offset;
126193323Sed    Result.ConstantVal = cst;
127193323Sed    Result.TargetReloType = RelocationType;
128193323Sed    Result.AddrType = isBB;
129199481Srdivacky    Result.MayNeedFarStub = false;
130193323Sed    Result.GOTRelative = false;
131193323Sed    Result.TargetResolve = false;
132193323Sed    Result.Target.MBB = MBB;
133193323Sed    return Result;
134193323Sed  }
135193323Sed
136193323Sed  /// MachineRelocation::getExtSym - Return a relocation entry for an external
137193323Sed  /// symbol, like "free".
138193323Sed  ///
139193323Sed  static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType,
140193323Sed                                     const char *ES, intptr_t cst = 0,
141203954Srdivacky                                     bool GOTrelative = 0,
142203954Srdivacky                                     bool NeedStub = true) {
143193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
144193323Sed    MachineRelocation Result;
145193323Sed    Result.Offset = offset;
146193323Sed    Result.ConstantVal = cst;
147193323Sed    Result.TargetReloType = RelocationType;
148193323Sed    Result.AddrType = isExtSym;
149203954Srdivacky    Result.MayNeedFarStub = NeedStub;
150193323Sed    Result.GOTRelative = GOTrelative;
151193323Sed    Result.TargetResolve = false;
152193323Sed    Result.Target.ExtSym = ES;
153193323Sed    return Result;
154193323Sed  }
155193323Sed
156193323Sed  /// MachineRelocation::getConstPool - Return a relocation entry for a constant
157193323Sed  /// pool entry.
158193323Sed  ///
159193323Sed  static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType,
160193323Sed                                        unsigned CPI, intptr_t cst = 0,
161193323Sed                                        bool letTargetResolve = false) {
162193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
163193323Sed    MachineRelocation Result;
164193323Sed    Result.Offset = offset;
165193323Sed    Result.ConstantVal = cst;
166193323Sed    Result.TargetReloType = RelocationType;
167193323Sed    Result.AddrType = isConstPool;
168199481Srdivacky    Result.MayNeedFarStub = false;
169193323Sed    Result.GOTRelative = false;
170193323Sed    Result.TargetResolve = letTargetResolve;
171193323Sed    Result.Target.Index = CPI;
172193323Sed    return Result;
173193323Sed  }
174193323Sed
175193323Sed  /// MachineRelocation::getJumpTable - Return a relocation entry for a jump
176193323Sed  /// table entry.
177193323Sed  ///
178193323Sed  static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType,
179193323Sed                                        unsigned JTI, intptr_t cst = 0,
180193323Sed                                        bool letTargetResolve = false) {
181193323Sed    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
182193323Sed    MachineRelocation Result;
183193323Sed    Result.Offset = offset;
184193323Sed    Result.ConstantVal = cst;
185193323Sed    Result.TargetReloType = RelocationType;
186193323Sed    Result.AddrType = isJumpTable;
187199481Srdivacky    Result.MayNeedFarStub = false;
188193323Sed    Result.GOTRelative = false;
189193323Sed    Result.TargetResolve = letTargetResolve;
190193323Sed    Result.Target.Index = JTI;
191193323Sed    return Result;
192193323Sed  }
193193323Sed
194193323Sed  /// getMachineCodeOffset - Return the offset into the code buffer that the
195193323Sed  /// relocation should be performed.
196193323Sed  intptr_t getMachineCodeOffset() const {
197193323Sed    return Offset;
198193323Sed  }
199193323Sed
200193323Sed  /// getRelocationType - Return the target-specific relocation ID for this
201193323Sed  /// relocation.
202193323Sed  unsigned getRelocationType() const {
203193323Sed    return TargetReloType;
204193323Sed  }
205193323Sed
206193323Sed  /// getConstantVal - Get the constant value associated with this relocation.
207193323Sed  /// This is often an offset from the symbol.
208193323Sed  ///
209193323Sed  intptr_t getConstantVal() const {
210193323Sed    return ConstantVal;
211193323Sed  }
212193323Sed
213193323Sed  /// setConstantVal - Set the constant value associated with this relocation.
214193323Sed  /// This is often an offset from the symbol.
215193323Sed  ///
216193323Sed  void setConstantVal(intptr_t val) {
217193323Sed    ConstantVal = val;
218193323Sed  }
219193323Sed
220193323Sed  /// isGlobalValue - Return true if this relocation is a GlobalValue, as
221193323Sed  /// opposed to a constant string.
222193323Sed  bool isGlobalValue() const {
223193323Sed    return AddrType == isGV;
224193323Sed  }
225193323Sed
226193323Sed  /// isIndirectSymbol - Return true if this relocation is the address an
227193323Sed  /// indirect symbol
228193323Sed  bool isIndirectSymbol() const {
229193323Sed    return AddrType == isIndirectSym;
230193323Sed  }
231193323Sed
232193323Sed  /// isBasicBlock - Return true if this relocation is a basic block reference.
233193323Sed  ///
234193323Sed  bool isBasicBlock() const {
235193323Sed    return AddrType == isBB;
236193323Sed  }
237193323Sed
238193323Sed  /// isExternalSymbol - Return true if this is a constant string.
239193323Sed  ///
240193323Sed  bool isExternalSymbol() const {
241193323Sed    return AddrType == isExtSym;
242193323Sed  }
243193323Sed
244193323Sed  /// isConstantPoolIndex - Return true if this is a constant pool reference.
245193323Sed  ///
246193323Sed  bool isConstantPoolIndex() const {
247193323Sed    return AddrType == isConstPool;
248193323Sed  }
249193323Sed
250193323Sed  /// isJumpTableIndex - Return true if this is a jump table reference.
251193323Sed  ///
252193323Sed  bool isJumpTableIndex() const {
253193323Sed    return AddrType == isJumpTable;
254193323Sed  }
255193323Sed
256193323Sed  /// isGOTRelative - Return true the target wants the index into the GOT of
257193323Sed  /// the symbol rather than the address of the symbol.
258193323Sed  bool isGOTRelative() const {
259193323Sed    return GOTRelative;
260193323Sed  }
261193323Sed
262199481Srdivacky  /// mayNeedFarStub - This function returns true if the JIT for this target may
263199481Srdivacky  /// need either a stub function or an indirect global-variable load to handle
264199481Srdivacky  /// the relocated GlobalValue reference.  For example, the x86-64 call
265199481Srdivacky  /// instruction can only call functions within +/-2GB of the call site.
266199481Srdivacky  /// Anything farther away needs a longer mov+call sequence, which can't just
267199481Srdivacky  /// be written on top of the existing call.
268199481Srdivacky  bool mayNeedFarStub() const {
269199481Srdivacky    return MayNeedFarStub;
270193323Sed  }
271193323Sed
272193323Sed  /// letTargetResolve - Return true if the target JITInfo is usually
273193323Sed  /// responsible for resolving the address of this relocation.
274193323Sed  bool letTargetResolve() const {
275193323Sed    return TargetResolve;
276193323Sed  }
277193323Sed
278193323Sed  /// getGlobalValue - If this is a global value reference, return the
279193323Sed  /// referenced global.
280193323Sed  GlobalValue *getGlobalValue() const {
281193323Sed    assert((isGlobalValue() || isIndirectSymbol()) &&
282193323Sed           "This is not a global value reference!");
283193323Sed    return Target.GV;
284193323Sed  }
285193323Sed
286193323Sed  MachineBasicBlock *getBasicBlock() const {
287193323Sed    assert(isBasicBlock() && "This is not a basic block reference!");
288193323Sed    return Target.MBB;
289193323Sed  }
290193323Sed
291193323Sed  /// getString - If this is a string value, return the string reference.
292193323Sed  ///
293193323Sed  const char *getExternalSymbol() const {
294193323Sed    assert(isExternalSymbol() && "This is not an external symbol reference!");
295193323Sed    return Target.ExtSym;
296193323Sed  }
297193323Sed
298193323Sed  /// getConstantPoolIndex - If this is a const pool reference, return
299193323Sed  /// the index into the constant pool.
300193323Sed  unsigned getConstantPoolIndex() const {
301193323Sed    assert(isConstantPoolIndex() && "This is not a constant pool reference!");
302193323Sed    return Target.Index;
303193323Sed  }
304193323Sed
305193323Sed  /// getJumpTableIndex - If this is a jump table reference, return
306193323Sed  /// the index into the jump table.
307193323Sed  unsigned getJumpTableIndex() const {
308193323Sed    assert(isJumpTableIndex() && "This is not a jump table reference!");
309193323Sed    return Target.Index;
310193323Sed  }
311193323Sed
312193323Sed  /// getResultPointer - Once this has been resolved to point to an actual
313193323Sed  /// address, this returns the pointer.
314193323Sed  void *getResultPointer() const {
315193323Sed    assert(AddrType == isResult && "Result pointer isn't set yet!");
316193323Sed    return Target.Result;
317193323Sed  }
318193323Sed
319193323Sed  /// setResultPointer - Set the result to the specified pointer value.
320193323Sed  ///
321193323Sed  void setResultPointer(void *Ptr) {
322193323Sed    Target.Result = Ptr;
323193323Sed    AddrType = isResult;
324193323Sed  }
325193323Sed
326193323Sed  /// setGOTIndex - Set the GOT index to a specific value.
327193323Sed  void setGOTIndex(unsigned idx) {
328193323Sed    AddrType = isGOTIndex;
329193323Sed    Target.GOTIndex = idx;
330193323Sed  }
331193323Sed
332193323Sed  /// getGOTIndex - Once this has been resolved to an entry in the GOT,
333193323Sed  /// this returns that index.  The index is from the lowest address entry
334193323Sed  /// in the GOT.
335193323Sed  unsigned getGOTIndex() const {
336193323Sed    assert(AddrType == isGOTIndex);
337193323Sed    return Target.GOTIndex;
338193323Sed  }
339193323Sed};
340193323Sed}
341193323Sed
342193323Sed#endif
343