1 | //===- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks -------*- 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 | // This file defines the MCInstrAnalysis class which the MCTargetDescs can |
10 | // derive from to give additional information to MC. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_MC_MCINSTRANALYSIS_H |
15 | #define LLVM_MC_MCINSTRANALYSIS_H |
16 | |
17 | #include "llvm/ADT/ArrayRef.h" |
18 | #include "llvm/MC/MCInst.h" |
19 | #include "llvm/MC/MCInstrDesc.h" |
20 | #include "llvm/MC/MCInstrInfo.h" |
21 | #include "llvm/MC/MCRegisterInfo.h" |
22 | #include <cstdint> |
23 | #include <vector> |
24 | |
25 | namespace llvm { |
26 | |
27 | class MCRegisterInfo; |
28 | class Triple; |
29 | |
30 | class MCInstrAnalysis { |
31 | protected: |
32 | friend class Target; |
33 | |
34 | const MCInstrInfo *Info; |
35 | |
36 | public: |
37 | MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {} |
38 | virtual ~MCInstrAnalysis() = default; |
39 | |
40 | /// Clear the internal state. See updateState for more information. |
41 | virtual void resetState() {} |
42 | |
43 | /// Update internal state with \p Inst at \p Addr. |
44 | /// |
45 | /// For some types of analyses, inspecting a single instruction is not |
46 | /// sufficient. Some examples are auipc/jalr pairs on RISC-V or adrp/ldr pairs |
47 | /// on AArch64. To support inspecting multiple instructions, targets may keep |
48 | /// track of an internal state while analysing instructions. Clients should |
49 | /// call updateState for every instruction which allows later calls to one of |
50 | /// the analysis functions to take previous instructions into account. |
51 | /// Whenever state becomes irrelevant (e.g., when starting to disassemble a |
52 | /// new function), clients should call resetState to clear it. |
53 | virtual void updateState(const MCInst &Inst, uint64_t Addr) {} |
54 | |
55 | virtual bool isBranch(const MCInst &Inst) const { |
56 | return Info->get(Opcode: Inst.getOpcode()).isBranch(); |
57 | } |
58 | |
59 | virtual bool isConditionalBranch(const MCInst &Inst) const { |
60 | return Info->get(Opcode: Inst.getOpcode()).isConditionalBranch(); |
61 | } |
62 | |
63 | virtual bool isUnconditionalBranch(const MCInst &Inst) const { |
64 | return Info->get(Opcode: Inst.getOpcode()).isUnconditionalBranch(); |
65 | } |
66 | |
67 | virtual bool isIndirectBranch(const MCInst &Inst) const { |
68 | return Info->get(Opcode: Inst.getOpcode()).isIndirectBranch(); |
69 | } |
70 | |
71 | virtual bool isCall(const MCInst &Inst) const { |
72 | return Info->get(Opcode: Inst.getOpcode()).isCall(); |
73 | } |
74 | |
75 | virtual bool isReturn(const MCInst &Inst) const { |
76 | return Info->get(Opcode: Inst.getOpcode()).isReturn(); |
77 | } |
78 | |
79 | virtual bool isTerminator(const MCInst &Inst) const { |
80 | return Info->get(Opcode: Inst.getOpcode()).isTerminator(); |
81 | } |
82 | |
83 | virtual bool mayAffectControlFlow(const MCInst &Inst, |
84 | const MCRegisterInfo &MCRI) const { |
85 | if (isBranch(Inst) || isCall(Inst) || isReturn(Inst) || |
86 | isIndirectBranch(Inst)) |
87 | return true; |
88 | unsigned PC = MCRI.getProgramCounter(); |
89 | if (PC == 0) |
90 | return false; |
91 | return Info->get(Opcode: Inst.getOpcode()).hasDefOfPhysReg(MI: Inst, Reg: PC, RI: MCRI); |
92 | } |
93 | |
94 | /// Returns true if at least one of the register writes performed by |
95 | /// \param Inst implicitly clears the upper portion of all super-registers. |
96 | /// |
97 | /// Example: on X86-64, a write to EAX implicitly clears the upper half of |
98 | /// RAX. Also (still on x86) an XMM write perfomed by an AVX 128-bit |
99 | /// instruction implicitly clears the upper portion of the correspondent |
100 | /// YMM register. |
101 | /// |
102 | /// This method also updates an APInt which is used as mask of register |
103 | /// writes. There is one bit for every explicit/implicit write performed by |
104 | /// the instruction. If a write implicitly clears its super-registers, then |
105 | /// the corresponding bit is set (vic. the corresponding bit is cleared). |
106 | /// |
107 | /// The first bits in the APint are related to explicit writes. The remaining |
108 | /// bits are related to implicit writes. The sequence of writes follows the |
109 | /// machine operand sequence. For implicit writes, the sequence is defined by |
110 | /// the MCInstrDesc. |
111 | /// |
112 | /// The assumption is that the bit-width of the APInt is correctly set by |
113 | /// the caller. The default implementation conservatively assumes that none of |
114 | /// the writes clears the upper portion of a super-register. |
115 | virtual bool (const MCRegisterInfo &MRI, |
116 | const MCInst &Inst, |
117 | APInt &Writes) const; |
118 | |
119 | /// Returns true if MI is a dependency breaking zero-idiom for the given |
120 | /// subtarget. |
121 | /// |
122 | /// Mask is used to identify input operands that have their dependency |
123 | /// broken. Each bit of the mask is associated with a specific input operand. |
124 | /// Bits associated with explicit input operands are laid out first in the |
125 | /// mask; implicit operands come after explicit operands. |
126 | /// |
127 | /// Dependencies are broken only for operands that have their corresponding bit |
128 | /// set. Operands that have their bit cleared, or that don't have a |
129 | /// corresponding bit in the mask don't have their dependency broken. Note |
130 | /// that Mask may not be big enough to describe all operands. The assumption |
131 | /// for operands that don't have a correspondent bit in the mask is that those |
132 | /// are still data dependent. |
133 | /// |
134 | /// The only exception to the rule is for when Mask has all zeroes. |
135 | /// A zero mask means: dependencies are broken for all explicit register |
136 | /// operands. |
137 | virtual bool isZeroIdiom(const MCInst &MI, APInt &Mask, |
138 | unsigned CPUID) const { |
139 | return false; |
140 | } |
141 | |
142 | /// Returns true if MI is a dependency breaking instruction for the |
143 | /// subtarget associated with CPUID . |
144 | /// |
145 | /// The value computed by a dependency breaking instruction is not dependent |
146 | /// on the inputs. An example of dependency breaking instruction on X86 is |
147 | /// `XOR %eax, %eax`. |
148 | /// |
149 | /// If MI is a dependency breaking instruction for subtarget CPUID, then Mask |
150 | /// can be inspected to identify independent operands. |
151 | /// |
152 | /// Essentially, each bit of the mask corresponds to an input operand. |
153 | /// Explicit operands are laid out first in the mask; implicit operands follow |
154 | /// explicit operands. Bits are set for operands that are independent. |
155 | /// |
156 | /// Note that the number of bits in Mask may not be equivalent to the sum of |
157 | /// explicit and implicit operands in MI. Operands that don't have a |
158 | /// corresponding bit in Mask are assumed "not independente". |
159 | /// |
160 | /// The only exception is for when Mask is all zeroes. That means: explicit |
161 | /// input operands of MI are independent. |
162 | virtual bool isDependencyBreaking(const MCInst &MI, APInt &Mask, |
163 | unsigned CPUID) const { |
164 | return isZeroIdiom(MI, Mask, CPUID); |
165 | } |
166 | |
167 | /// Returns true if MI is a candidate for move elimination. |
168 | /// |
169 | /// Different subtargets may apply different constraints to optimizable |
170 | /// register moves. For example, on most X86 subtargets, a candidate for move |
171 | /// elimination cannot specify the same register for both source and |
172 | /// destination. |
173 | virtual bool isOptimizableRegisterMove(const MCInst &MI, |
174 | unsigned CPUID) const { |
175 | return false; |
176 | } |
177 | |
178 | /// Given a branch instruction try to get the address the branch |
179 | /// targets. Return true on success, and the address in Target. |
180 | virtual bool |
181 | evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, |
182 | uint64_t &Target) const; |
183 | |
184 | /// Given an instruction tries to get the address of a memory operand. Returns |
185 | /// the address on success. |
186 | virtual std::optional<uint64_t> |
187 | evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI, |
188 | uint64_t Addr, uint64_t Size) const; |
189 | |
190 | /// Given an instruction with a memory operand that could require relocation, |
191 | /// returns the offset within the instruction of that relocation. |
192 | virtual std::optional<uint64_t> |
193 | getMemoryOperandRelocationOffset(const MCInst &Inst, uint64_t Size) const; |
194 | |
195 | /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries. |
196 | virtual std::vector<std::pair<uint64_t, uint64_t>> |
197 | findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents, |
198 | const Triple &TargetTriple) const { |
199 | return {}; |
200 | } |
201 | }; |
202 | |
203 | } // end namespace llvm |
204 | |
205 | #endif // LLVM_MC_MCINSTRANALYSIS_H |
206 | |