Line data Source code
1 : //===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_MC_MCFIXUP_H
11 : #define LLVM_MC_MCFIXUP_H
12 :
13 : #include "llvm/MC/MCExpr.h"
14 : #include "llvm/Support/DataTypes.h"
15 : #include "llvm/Support/ErrorHandling.h"
16 : #include "llvm/Support/SMLoc.h"
17 : #include <cassert>
18 :
19 : namespace llvm {
20 : class MCExpr;
21 :
22 : /// Extensible enumeration to represent the type of a fixup.
23 : enum MCFixupKind {
24 : FK_Data_1 = 0, ///< A one-byte fixup.
25 : FK_Data_2, ///< A two-byte fixup.
26 : FK_Data_4, ///< A four-byte fixup.
27 : FK_Data_8, ///< A eight-byte fixup.
28 : FK_PCRel_1, ///< A one-byte pc relative fixup.
29 : FK_PCRel_2, ///< A two-byte pc relative fixup.
30 : FK_PCRel_4, ///< A four-byte pc relative fixup.
31 : FK_PCRel_8, ///< A eight-byte pc relative fixup.
32 : FK_GPRel_1, ///< A one-byte gp relative fixup.
33 : FK_GPRel_2, ///< A two-byte gp relative fixup.
34 : FK_GPRel_4, ///< A four-byte gp relative fixup.
35 : FK_GPRel_8, ///< A eight-byte gp relative fixup.
36 : FK_DTPRel_4, ///< A four-byte dtp relative fixup.
37 : FK_DTPRel_8, ///< A eight-byte dtp relative fixup.
38 : FK_TPRel_4, ///< A four-byte tp relative fixup.
39 : FK_TPRel_8, ///< A eight-byte tp relative fixup.
40 : FK_SecRel_1, ///< A one-byte section relative fixup.
41 : FK_SecRel_2, ///< A two-byte section relative fixup.
42 : FK_SecRel_4, ///< A four-byte section relative fixup.
43 : FK_SecRel_8, ///< A eight-byte section relative fixup.
44 : FK_Data_Add_1, ///< A one-byte add fixup.
45 : FK_Data_Add_2, ///< A two-byte add fixup.
46 : FK_Data_Add_4, ///< A four-byte add fixup.
47 : FK_Data_Add_8, ///< A eight-byte add fixup.
48 : FK_Data_Sub_1, ///< A one-byte sub fixup.
49 : FK_Data_Sub_2, ///< A two-byte sub fixup.
50 : FK_Data_Sub_4, ///< A four-byte sub fixup.
51 : FK_Data_Sub_8, ///< A eight-byte sub fixup.
52 :
53 : FirstTargetFixupKind = 128,
54 :
55 : // Limit range of target fixups, in case we want to pack more efficiently
56 : // later.
57 : MaxTargetFixupKind = (1 << 8)
58 : };
59 :
60 : /// Encode information on a single operation to perform on a byte
61 : /// sequence (e.g., an encoded instruction) which requires assemble- or run-
62 : /// time patching.
63 : ///
64 : /// Fixups are used any time the target instruction encoder needs to represent
65 : /// some value in an instruction which is not yet concrete. The encoder will
66 : /// encode the instruction assuming the value is 0, and emit a fixup which
67 : /// communicates to the assembler backend how it should rewrite the encoded
68 : /// value.
69 : ///
70 : /// During the process of relaxation, the assembler will apply fixups as
71 : /// symbolic values become concrete. When relaxation is complete, any remaining
72 : /// fixups become relocations in the object file (or errors, if the fixup cannot
73 : /// be encoded on the target).
74 : class MCFixup {
75 : /// The value to put into the fixup location. The exact interpretation of the
76 : /// expression is target dependent, usually it will be one of the operands to
77 : /// an instruction or an assembler directive.
78 : const MCExpr *Value;
79 :
80 : /// The byte index of start of the relocation inside the MCFragment.
81 : uint32_t Offset;
82 :
83 : /// The target dependent kind of fixup item this is. The kind is used to
84 : /// determine how the operand value should be encoded into the instruction.
85 : unsigned Kind;
86 :
87 : /// The source location which gave rise to the fixup, if any.
88 : SMLoc Loc;
89 : public:
90 : static MCFixup create(uint32_t Offset, const MCExpr *Value,
91 : MCFixupKind Kind, SMLoc Loc = SMLoc()) {
92 : assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!");
93 : MCFixup FI;
94 2253037 : FI.Value = Value;
95 2253037 : FI.Offset = Offset;
96 2253037 : FI.Kind = unsigned(Kind);
97 2253037 : FI.Loc = Loc;
98 : return FI;
99 : }
100 :
101 : /// Return a fixup corresponding to the add half of a add/sub fixup pair for
102 : /// the given Fixup.
103 : static MCFixup createAddFor(const MCFixup &Fixup) {
104 : MCFixup FI;
105 0 : FI.Value = Fixup.getValue();
106 0 : FI.Offset = Fixup.getOffset();
107 0 : FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind());
108 0 : FI.Loc = Fixup.getLoc();
109 : return FI;
110 : }
111 :
112 : /// Return a fixup corresponding to the sub half of a add/sub fixup pair for
113 : /// the given Fixup.
114 : static MCFixup createSubFor(const MCFixup &Fixup) {
115 : MCFixup FI;
116 0 : FI.Value = Fixup.getValue();
117 0 : FI.Offset = Fixup.getOffset();
118 0 : FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind());
119 0 : FI.Loc = Fixup.getLoc();
120 : return FI;
121 : }
122 :
123 0 : MCFixupKind getKind() const { return MCFixupKind(Kind); }
124 :
125 0 : uint32_t getOffset() const { return Offset; }
126 5498117 : void setOffset(uint32_t Value) { Offset = Value; }
127 :
128 0 : const MCExpr *getValue() const { return Value; }
129 :
130 : /// Return the generic fixup kind for a value with the given size. It
131 : /// is an error to pass an unsupported size.
132 : static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) {
133 9561395 : switch (Size) {
134 0 : default: llvm_unreachable("Invalid generic fixup size!");
135 1958343 : case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1;
136 3929 : case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2;
137 4877064 : case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4;
138 486472 : case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8;
139 : }
140 : }
141 :
142 : /// Return the generic fixup kind for an addition with a given size. It
143 : /// is an error to pass an unsupported size.
144 : static MCFixupKind getAddKindForKind(unsigned Kind) {
145 : switch (Kind) {
146 0 : default: llvm_unreachable("Unknown type to convert!");
147 : case FK_Data_1: return FK_Data_Add_1;
148 : case FK_Data_2: return FK_Data_Add_2;
149 : case FK_Data_4: return FK_Data_Add_4;
150 : case FK_Data_8: return FK_Data_Add_8;
151 : }
152 : }
153 :
154 : /// Return the generic fixup kind for an subtraction with a given size. It
155 : /// is an error to pass an unsupported size.
156 : static MCFixupKind getSubKindForKind(unsigned Kind) {
157 : switch (Kind) {
158 0 : default: llvm_unreachable("Unknown type to convert!");
159 : case FK_Data_1: return FK_Data_Sub_1;
160 : case FK_Data_2: return FK_Data_Sub_2;
161 : case FK_Data_4: return FK_Data_Sub_4;
162 : case FK_Data_8: return FK_Data_Sub_8;
163 : }
164 : }
165 :
166 0 : SMLoc getLoc() const { return Loc; }
167 : };
168 :
169 : } // End llvm namespace
170 :
171 : #endif
|