xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCFixup.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_MC_MCFIXUP_H
10 #define LLVM_MC_MCFIXUP_H
11 
12 #include "llvm/Support/Compiler.h"
13 #include "llvm/Support/DataTypes.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/SMLoc.h"
16 #include <cassert>
17 
18 namespace llvm {
19 class MCExpr;
20 
21 /// Extensible enumeration to represent the type of a fixup.
22 using MCFixupKind = uint16_t;
23 enum {
24   // [0, FirstLiteralRelocationKind) encodes raw relocation types.
25 
26   // [FirstLiteralRelocationKind, FK_NONE) encodes raw relocation types coming
27   // from .reloc directives. Fixup kind
28   // FirstLiteralRelocationKind+t encodes relocation type t.
29   FirstLiteralRelocationKind = 2000,
30 
31   // Other kinds indicate the fixup may resolve to a constant, allowing the
32   // assembler to update the instruction or data directly without a relocation.
33   FK_NONE = 4000, ///< A no-op fixup.
34   FK_Data_1,      ///< A one-byte fixup.
35   FK_Data_2,      ///< A two-byte fixup.
36   FK_Data_4,      ///< A four-byte fixup.
37   FK_Data_8,      ///< A eight-byte fixup.
38   FK_Data_leb128, ///< A leb128 fixup.
39   FK_SecRel_1,    ///< A one-byte section relative fixup.
40   FK_SecRel_2,    ///< A two-byte section relative fixup.
41   FK_SecRel_4,    ///< A four-byte section relative fixup.
42   FK_SecRel_8,    ///< A eight-byte section relative fixup.
43 
44   FirstTargetFixupKind,
45 };
46 
47 /// Encode information on a single operation to perform on a byte
48 /// sequence (e.g., an encoded instruction) which requires assemble- or run-
49 /// time patching.
50 ///
51 /// Fixups are used any time the target instruction encoder needs to represent
52 /// some value in an instruction which is not yet concrete. The encoder will
53 /// encode the instruction assuming the value is 0, and emit a fixup which
54 /// communicates to the assembler backend how it should rewrite the encoded
55 /// value.
56 ///
57 /// During the process of relaxation, the assembler will apply fixups as
58 /// symbolic values become concrete. When relaxation is complete, any remaining
59 /// fixups become relocations in the object file (or errors, if the fixup cannot
60 /// be encoded on the target).
61 class MCFixup {
62   /// The value to put into the fixup location. The exact interpretation of the
63   /// expression is target dependent, usually it will be one of the operands to
64   /// an instruction or an assembler directive.
65   const MCExpr *Value = nullptr;
66 
67   /// The byte index of start of the relocation inside the MCFragment.
68   uint32_t Offset = 0;
69 
70   /// The target dependent kind of fixup item this is. The kind is used to
71   /// determine how the operand value should be encoded into the instruction.
72   MCFixupKind Kind = FK_NONE;
73 
74   /// True if this is a PC-relative fixup. The relocatable expression is
75   /// typically resolved When SymB is nullptr and SymA is a local symbol defined
76   /// within the current section.
77   bool PCRel = false;
78 
79   /// Used by RISC-V style linker relaxation. Whether the fixup is
80   /// linker-relaxable.
81   bool LinkerRelaxable = false;
82 
83   /// Consider bit fields if we need more flags.
84 
85 public:
86   static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind,
87                         bool PCRel = false) {
88     MCFixup FI;
89     FI.Value = Value;
90     FI.Offset = Offset;
91     FI.Kind = Kind;
92     FI.PCRel = PCRel;
93     return FI;
94   }
95 
getKind()96   MCFixupKind getKind() const { return Kind; }
97 
getOffset()98   uint32_t getOffset() const { return Offset; }
setOffset(uint32_t Value)99   void setOffset(uint32_t Value) { Offset = Value; }
100 
getValue()101   const MCExpr *getValue() const { return Value; }
102 
isPCRel()103   bool isPCRel() const { return PCRel; }
setPCRel()104   void setPCRel() { PCRel = true; }
isLinkerRelaxable()105   bool isLinkerRelaxable() const { return LinkerRelaxable; }
setLinkerRelaxable()106   void setLinkerRelaxable() { LinkerRelaxable = true; }
107 
108   /// Return the generic fixup kind for a value with the given size. It
109   /// is an error to pass an unsupported size.
getDataKindForSize(unsigned Size)110   static MCFixupKind getDataKindForSize(unsigned Size) {
111     switch (Size) {
112     default: llvm_unreachable("Invalid generic fixup size!");
113     case 1:
114       return FK_Data_1;
115     case 2:
116       return FK_Data_2;
117     case 4:
118       return FK_Data_4;
119     case 8:
120       return FK_Data_8;
121     }
122   }
123 
124   LLVM_ABI SMLoc getLoc() const;
125 };
126 
127 namespace mc {
128 // Check if the fixup kind is a relocation type. Return false if the fixup can
129 // be resolved without a relocation.
isRelocation(MCFixupKind FixupKind)130 inline bool isRelocation(MCFixupKind FixupKind) { return FixupKind < FK_NONE; }
131 
132 // Check if the fixup kind represents a relocation type from a .reloc directive.
133 // In ELF, this skips STT_SECTION adjustment and STT_TLS symbol type setting for
134 // TLS relocations.
isRelocRelocation(MCFixupKind FixupKind)135 inline bool isRelocRelocation(MCFixupKind FixupKind) {
136   return FirstLiteralRelocationKind <= FixupKind && FixupKind < FK_NONE;
137 }
138 } // namespace mc
139 
140 } // End llvm namespace
141 
142 #endif
143