File: | build/source/llvm/lib/CodeGen/MachineOperand.cpp |
Warning: | line 1222, column 39 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- lib/CodeGen/MachineOperand.cpp -------------------------------------===// | ||||||||
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 | /// \file Methods common to all machine operands. | ||||||||
10 | // | ||||||||
11 | //===----------------------------------------------------------------------===// | ||||||||
12 | |||||||||
13 | #include "llvm/CodeGen/MachineOperand.h" | ||||||||
14 | #include "llvm/ADT/FoldingSet.h" | ||||||||
15 | #include "llvm/ADT/StringExtras.h" | ||||||||
16 | #include "llvm/Analysis/Loads.h" | ||||||||
17 | #include "llvm/CodeGen/MIRFormatter.h" | ||||||||
18 | #include "llvm/CodeGen/MachineFrameInfo.h" | ||||||||
19 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | ||||||||
20 | #include "llvm/CodeGen/MachineRegisterInfo.h" | ||||||||
21 | #include "llvm/CodeGen/StableHashing.h" | ||||||||
22 | #include "llvm/CodeGen/TargetInstrInfo.h" | ||||||||
23 | #include "llvm/CodeGen/TargetRegisterInfo.h" | ||||||||
24 | #include "llvm/Config/llvm-config.h" | ||||||||
25 | #include "llvm/IR/Constants.h" | ||||||||
26 | #include "llvm/IR/IRPrintingPasses.h" | ||||||||
27 | #include "llvm/IR/Instructions.h" | ||||||||
28 | #include "llvm/IR/ModuleSlotTracker.h" | ||||||||
29 | #include "llvm/MC/MCDwarf.h" | ||||||||
30 | #include "llvm/Target/TargetIntrinsicInfo.h" | ||||||||
31 | #include "llvm/Target/TargetMachine.h" | ||||||||
32 | #include <optional> | ||||||||
33 | |||||||||
34 | using namespace llvm; | ||||||||
35 | |||||||||
36 | static cl::opt<int> | ||||||||
37 | PrintRegMaskNumRegs("print-regmask-num-regs", | ||||||||
38 | cl::desc("Number of registers to limit to when " | ||||||||
39 | "printing regmask operands in IR dumps. " | ||||||||
40 | "unlimited = -1"), | ||||||||
41 | cl::init(32), cl::Hidden); | ||||||||
42 | |||||||||
43 | static const MachineFunction *getMFIfAvailable(const MachineOperand &MO) { | ||||||||
44 | if (const MachineInstr *MI = MO.getParent()) | ||||||||
45 | if (const MachineBasicBlock *MBB = MI->getParent()) | ||||||||
46 | if (const MachineFunction *MF = MBB->getParent()) | ||||||||
47 | return MF; | ||||||||
48 | return nullptr; | ||||||||
49 | } | ||||||||
50 | |||||||||
51 | static MachineFunction *getMFIfAvailable(MachineOperand &MO) { | ||||||||
52 | return const_cast<MachineFunction *>( | ||||||||
53 | getMFIfAvailable(const_cast<const MachineOperand &>(MO))); | ||||||||
54 | } | ||||||||
55 | |||||||||
56 | unsigned MachineOperand::getOperandNo() const { | ||||||||
57 | assert(getParent() && "Operand does not belong to any instruction!")(static_cast <bool> (getParent() && "Operand does not belong to any instruction!" ) ? void (0) : __assert_fail ("getParent() && \"Operand does not belong to any instruction!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 57, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
58 | return getParent()->getOperandNo(this); | ||||||||
59 | } | ||||||||
60 | |||||||||
61 | void MachineOperand::setReg(Register Reg) { | ||||||||
62 | if (getReg() == Reg) | ||||||||
63 | return; // No change. | ||||||||
64 | |||||||||
65 | // Clear the IsRenamable bit to keep it conservatively correct. | ||||||||
66 | IsRenamable = false; | ||||||||
67 | |||||||||
68 | // Otherwise, we have to change the register. If this operand is embedded | ||||||||
69 | // into a machine function, we need to update the old and new register's | ||||||||
70 | // use/def lists. | ||||||||
71 | if (MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
72 | MachineRegisterInfo &MRI = MF->getRegInfo(); | ||||||||
73 | MRI.removeRegOperandFromUseList(this); | ||||||||
74 | SmallContents.RegNo = Reg; | ||||||||
75 | MRI.addRegOperandToUseList(this); | ||||||||
76 | return; | ||||||||
77 | } | ||||||||
78 | |||||||||
79 | // Otherwise, just change the register, no problem. :) | ||||||||
80 | SmallContents.RegNo = Reg; | ||||||||
81 | } | ||||||||
82 | |||||||||
83 | void MachineOperand::substVirtReg(Register Reg, unsigned SubIdx, | ||||||||
84 | const TargetRegisterInfo &TRI) { | ||||||||
85 | assert(Reg.isVirtual())(static_cast <bool> (Reg.isVirtual()) ? void (0) : __assert_fail ("Reg.isVirtual()", "llvm/lib/CodeGen/MachineOperand.cpp", 85 , __extension__ __PRETTY_FUNCTION__)); | ||||||||
86 | if (SubIdx && getSubReg()) | ||||||||
87 | SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); | ||||||||
88 | setReg(Reg); | ||||||||
89 | if (SubIdx) | ||||||||
90 | setSubReg(SubIdx); | ||||||||
91 | } | ||||||||
92 | |||||||||
93 | void MachineOperand::substPhysReg(MCRegister Reg, const TargetRegisterInfo &TRI) { | ||||||||
94 | assert(Register::isPhysicalRegister(Reg))(static_cast <bool> (Register::isPhysicalRegister(Reg)) ? void (0) : __assert_fail ("Register::isPhysicalRegister(Reg)" , "llvm/lib/CodeGen/MachineOperand.cpp", 94, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
95 | if (getSubReg()) { | ||||||||
96 | Reg = TRI.getSubReg(Reg, getSubReg()); | ||||||||
97 | // Note that getSubReg() may return 0 if the sub-register doesn't exist. | ||||||||
98 | // That won't happen in legal code. | ||||||||
99 | setSubReg(0); | ||||||||
100 | if (isDef()) | ||||||||
101 | setIsUndef(false); | ||||||||
102 | } | ||||||||
103 | setReg(Reg); | ||||||||
104 | } | ||||||||
105 | |||||||||
106 | /// Change a def to a use, or a use to a def. | ||||||||
107 | void MachineOperand::setIsDef(bool Val) { | ||||||||
108 | assert(isReg() && "Wrong MachineOperand accessor")(static_cast <bool> (isReg() && "Wrong MachineOperand accessor" ) ? void (0) : __assert_fail ("isReg() && \"Wrong MachineOperand accessor\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 108, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
109 | assert((!Val || !isDebug()) && "Marking a debug operation as def")(static_cast <bool> ((!Val || !isDebug()) && "Marking a debug operation as def" ) ? void (0) : __assert_fail ("(!Val || !isDebug()) && \"Marking a debug operation as def\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 109, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
110 | if (IsDef == Val) | ||||||||
111 | return; | ||||||||
112 | assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported")(static_cast <bool> (!IsDeadOrKill && "Changing def/use with dead/kill set not supported" ) ? void (0) : __assert_fail ("!IsDeadOrKill && \"Changing def/use with dead/kill set not supported\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 112, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
113 | // MRI may keep uses and defs in different list positions. | ||||||||
114 | if (MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
115 | MachineRegisterInfo &MRI = MF->getRegInfo(); | ||||||||
116 | MRI.removeRegOperandFromUseList(this); | ||||||||
117 | IsDef = Val; | ||||||||
118 | MRI.addRegOperandToUseList(this); | ||||||||
119 | return; | ||||||||
120 | } | ||||||||
121 | IsDef = Val; | ||||||||
122 | } | ||||||||
123 | |||||||||
124 | bool MachineOperand::isRenamable() const { | ||||||||
125 | assert(isReg() && "Wrong MachineOperand accessor")(static_cast <bool> (isReg() && "Wrong MachineOperand accessor" ) ? void (0) : __assert_fail ("isReg() && \"Wrong MachineOperand accessor\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 125, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
126 | assert(getReg().isPhysical() &&(static_cast <bool> (getReg().isPhysical() && "isRenamable should only be checked on physical registers" ) ? void (0) : __assert_fail ("getReg().isPhysical() && \"isRenamable should only be checked on physical registers\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 127, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
127 | "isRenamable should only be checked on physical registers")(static_cast <bool> (getReg().isPhysical() && "isRenamable should only be checked on physical registers" ) ? void (0) : __assert_fail ("getReg().isPhysical() && \"isRenamable should only be checked on physical registers\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 127, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
128 | if (!IsRenamable) | ||||||||
129 | return false; | ||||||||
130 | |||||||||
131 | const MachineInstr *MI = getParent(); | ||||||||
132 | if (!MI) | ||||||||
133 | return true; | ||||||||
134 | |||||||||
135 | if (isDef()) | ||||||||
136 | return !MI->hasExtraDefRegAllocReq(MachineInstr::IgnoreBundle); | ||||||||
137 | |||||||||
138 | assert(isUse() && "Reg is not def or use")(static_cast <bool> (isUse() && "Reg is not def or use" ) ? void (0) : __assert_fail ("isUse() && \"Reg is not def or use\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 138, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
139 | return !MI->hasExtraSrcRegAllocReq(MachineInstr::IgnoreBundle); | ||||||||
140 | } | ||||||||
141 | |||||||||
142 | void MachineOperand::setIsRenamable(bool Val) { | ||||||||
143 | assert(isReg() && "Wrong MachineOperand accessor")(static_cast <bool> (isReg() && "Wrong MachineOperand accessor" ) ? void (0) : __assert_fail ("isReg() && \"Wrong MachineOperand accessor\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 143, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
144 | assert(getReg().isPhysical() &&(static_cast <bool> (getReg().isPhysical() && "setIsRenamable should only be called on physical registers" ) ? void (0) : __assert_fail ("getReg().isPhysical() && \"setIsRenamable should only be called on physical registers\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 145, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
145 | "setIsRenamable should only be called on physical registers")(static_cast <bool> (getReg().isPhysical() && "setIsRenamable should only be called on physical registers" ) ? void (0) : __assert_fail ("getReg().isPhysical() && \"setIsRenamable should only be called on physical registers\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 145, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
146 | IsRenamable = Val; | ||||||||
147 | } | ||||||||
148 | |||||||||
149 | // If this operand is currently a register operand, and if this is in a | ||||||||
150 | // function, deregister the operand from the register's use/def list. | ||||||||
151 | void MachineOperand::removeRegFromUses() { | ||||||||
152 | if (!isReg() || !isOnRegUseList()) | ||||||||
153 | return; | ||||||||
154 | |||||||||
155 | if (MachineFunction *MF = getMFIfAvailable(*this)) | ||||||||
156 | MF->getRegInfo().removeRegOperandFromUseList(this); | ||||||||
157 | } | ||||||||
158 | |||||||||
159 | /// ChangeToImmediate - Replace this operand with a new immediate operand of | ||||||||
160 | /// the specified value. If an operand is known to be an immediate already, | ||||||||
161 | /// the setImm method should be used. | ||||||||
162 | void MachineOperand::ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags) { | ||||||||
163 | assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an imm") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an imm\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 163, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
164 | |||||||||
165 | removeRegFromUses(); | ||||||||
166 | |||||||||
167 | OpKind = MO_Immediate; | ||||||||
168 | Contents.ImmVal = ImmVal; | ||||||||
169 | setTargetFlags(TargetFlags); | ||||||||
170 | } | ||||||||
171 | |||||||||
172 | void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm, | ||||||||
173 | unsigned TargetFlags) { | ||||||||
174 | assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an imm") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an imm\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 174, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
175 | |||||||||
176 | removeRegFromUses(); | ||||||||
177 | |||||||||
178 | OpKind = MO_FPImmediate; | ||||||||
179 | Contents.CFP = FPImm; | ||||||||
180 | setTargetFlags(TargetFlags); | ||||||||
181 | } | ||||||||
182 | |||||||||
183 | void MachineOperand::ChangeToES(const char *SymName, | ||||||||
184 | unsigned TargetFlags) { | ||||||||
185 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an external symbol") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an external symbol\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 186, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
186 | "Cannot change a tied operand into an external symbol")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an external symbol") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an external symbol\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 186, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
187 | |||||||||
188 | removeRegFromUses(); | ||||||||
189 | |||||||||
190 | OpKind = MO_ExternalSymbol; | ||||||||
191 | Contents.OffsetedInfo.Val.SymbolName = SymName; | ||||||||
192 | setOffset(0); // Offset is always 0. | ||||||||
193 | setTargetFlags(TargetFlags); | ||||||||
194 | } | ||||||||
195 | |||||||||
196 | void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset, | ||||||||
197 | unsigned TargetFlags) { | ||||||||
198 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a global address") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a global address\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 199, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
199 | "Cannot change a tied operand into a global address")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a global address") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a global address\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 199, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
200 | |||||||||
201 | removeRegFromUses(); | ||||||||
202 | |||||||||
203 | OpKind = MO_GlobalAddress; | ||||||||
204 | Contents.OffsetedInfo.Val.GV = GV; | ||||||||
205 | setOffset(Offset); | ||||||||
206 | setTargetFlags(TargetFlags); | ||||||||
207 | } | ||||||||
208 | |||||||||
209 | void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) { | ||||||||
210 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an MCSymbol") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an MCSymbol\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 211, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
211 | "Cannot change a tied operand into an MCSymbol")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into an MCSymbol") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into an MCSymbol\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 211, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
212 | |||||||||
213 | removeRegFromUses(); | ||||||||
214 | |||||||||
215 | OpKind = MO_MCSymbol; | ||||||||
216 | Contents.Sym = Sym; | ||||||||
217 | setTargetFlags(TargetFlags); | ||||||||
218 | } | ||||||||
219 | |||||||||
220 | void MachineOperand::ChangeToFrameIndex(int Idx, unsigned TargetFlags) { | ||||||||
221 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a FrameIndex") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a FrameIndex\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 222, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
222 | "Cannot change a tied operand into a FrameIndex")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a FrameIndex") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a FrameIndex\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 222, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
223 | |||||||||
224 | removeRegFromUses(); | ||||||||
225 | |||||||||
226 | OpKind = MO_FrameIndex; | ||||||||
227 | setIndex(Idx); | ||||||||
228 | setTargetFlags(TargetFlags); | ||||||||
229 | } | ||||||||
230 | |||||||||
231 | void MachineOperand::ChangeToTargetIndex(unsigned Idx, int64_t Offset, | ||||||||
232 | unsigned TargetFlags) { | ||||||||
233 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a FrameIndex") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a FrameIndex\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 234, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
234 | "Cannot change a tied operand into a FrameIndex")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a FrameIndex") ? void (0) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a FrameIndex\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 234, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
235 | |||||||||
236 | removeRegFromUses(); | ||||||||
237 | |||||||||
238 | OpKind = MO_TargetIndex; | ||||||||
239 | setIndex(Idx); | ||||||||
240 | setOffset(Offset); | ||||||||
241 | setTargetFlags(TargetFlags); | ||||||||
242 | } | ||||||||
243 | |||||||||
244 | void MachineOperand::ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx, | ||||||||
245 | unsigned TargetFlags) { | ||||||||
246 | assert((!isReg() || !isTied()) &&(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a DbgInstrRef") ? void (0 ) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a DbgInstrRef\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 247, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
247 | "Cannot change a tied operand into a DbgInstrRef")(static_cast <bool> ((!isReg() || !isTied()) && "Cannot change a tied operand into a DbgInstrRef") ? void (0 ) : __assert_fail ("(!isReg() || !isTied()) && \"Cannot change a tied operand into a DbgInstrRef\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 247, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
248 | |||||||||
249 | removeRegFromUses(); | ||||||||
250 | |||||||||
251 | OpKind = MO_DbgInstrRef; | ||||||||
252 | setInstrRefInstrIndex(InstrIdx); | ||||||||
253 | setInstrRefOpIndex(OpIdx); | ||||||||
254 | setTargetFlags(TargetFlags); | ||||||||
255 | } | ||||||||
256 | |||||||||
257 | /// ChangeToRegister - Replace this operand with a new register operand of | ||||||||
258 | /// the specified value. If an operand is known to be an register already, | ||||||||
259 | /// the setReg method should be used. | ||||||||
260 | void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp, | ||||||||
261 | bool isKill, bool isDead, bool isUndef, | ||||||||
262 | bool isDebug) { | ||||||||
263 | MachineRegisterInfo *RegInfo = nullptr; | ||||||||
264 | if (MachineFunction *MF = getMFIfAvailable(*this)) | ||||||||
265 | RegInfo = &MF->getRegInfo(); | ||||||||
266 | // If this operand is already a register operand, remove it from the | ||||||||
267 | // register's use/def lists. | ||||||||
268 | bool WasReg = isReg(); | ||||||||
269 | if (RegInfo && WasReg) | ||||||||
270 | RegInfo->removeRegOperandFromUseList(this); | ||||||||
271 | |||||||||
272 | // Ensure debug instructions set debug flag on register uses. | ||||||||
273 | const MachineInstr *MI = getParent(); | ||||||||
274 | if (!isDef && MI && MI->isDebugInstr()) | ||||||||
275 | isDebug = true; | ||||||||
276 | |||||||||
277 | // Change this to a register and set the reg#. | ||||||||
278 | assert(!(isDead && !isDef) && "Dead flag on non-def")(static_cast <bool> (!(isDead && !isDef) && "Dead flag on non-def") ? void (0) : __assert_fail ("!(isDead && !isDef) && \"Dead flag on non-def\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 278, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
279 | assert(!(isKill && isDef) && "Kill flag on def")(static_cast <bool> (!(isKill && isDef) && "Kill flag on def") ? void (0) : __assert_fail ("!(isKill && isDef) && \"Kill flag on def\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 279, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
280 | OpKind = MO_Register; | ||||||||
281 | SmallContents.RegNo = Reg; | ||||||||
282 | SubReg_TargetFlags = 0; | ||||||||
283 | IsDef = isDef; | ||||||||
284 | IsImp = isImp; | ||||||||
285 | IsDeadOrKill = isKill | isDead; | ||||||||
286 | IsRenamable = false; | ||||||||
287 | IsUndef = isUndef; | ||||||||
288 | IsInternalRead = false; | ||||||||
289 | IsEarlyClobber = false; | ||||||||
290 | IsDebug = isDebug; | ||||||||
291 | // Ensure isOnRegUseList() returns false. | ||||||||
292 | Contents.Reg.Prev = nullptr; | ||||||||
293 | // Preserve the tie when the operand was already a register. | ||||||||
294 | if (!WasReg) | ||||||||
295 | TiedTo = 0; | ||||||||
296 | |||||||||
297 | // If this operand is embedded in a function, add the operand to the | ||||||||
298 | // register's use/def list. | ||||||||
299 | if (RegInfo) | ||||||||
300 | RegInfo->addRegOperandToUseList(this); | ||||||||
301 | } | ||||||||
302 | |||||||||
303 | /// isIdenticalTo - Return true if this operand is identical to the specified | ||||||||
304 | /// operand. Note that this should stay in sync with the hash_value overload | ||||||||
305 | /// below. | ||||||||
306 | bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { | ||||||||
307 | if (getType() != Other.getType() || | ||||||||
308 | getTargetFlags() != Other.getTargetFlags()) | ||||||||
309 | return false; | ||||||||
310 | |||||||||
311 | switch (getType()) { | ||||||||
312 | case MachineOperand::MO_Register: | ||||||||
313 | return getReg() == Other.getReg() && isDef() == Other.isDef() && | ||||||||
314 | getSubReg() == Other.getSubReg(); | ||||||||
315 | case MachineOperand::MO_Immediate: | ||||||||
316 | return getImm() == Other.getImm(); | ||||||||
317 | case MachineOperand::MO_CImmediate: | ||||||||
318 | return getCImm() == Other.getCImm(); | ||||||||
319 | case MachineOperand::MO_FPImmediate: | ||||||||
320 | return getFPImm() == Other.getFPImm(); | ||||||||
321 | case MachineOperand::MO_MachineBasicBlock: | ||||||||
322 | return getMBB() == Other.getMBB(); | ||||||||
323 | case MachineOperand::MO_FrameIndex: | ||||||||
324 | return getIndex() == Other.getIndex(); | ||||||||
325 | case MachineOperand::MO_ConstantPoolIndex: | ||||||||
326 | case MachineOperand::MO_TargetIndex: | ||||||||
327 | return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); | ||||||||
328 | case MachineOperand::MO_JumpTableIndex: | ||||||||
329 | return getIndex() == Other.getIndex(); | ||||||||
330 | case MachineOperand::MO_GlobalAddress: | ||||||||
331 | return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); | ||||||||
332 | case MachineOperand::MO_ExternalSymbol: | ||||||||
333 | return strcmp(getSymbolName(), Other.getSymbolName()) == 0 && | ||||||||
334 | getOffset() == Other.getOffset(); | ||||||||
335 | case MachineOperand::MO_BlockAddress: | ||||||||
336 | return getBlockAddress() == Other.getBlockAddress() && | ||||||||
337 | getOffset() == Other.getOffset(); | ||||||||
338 | case MachineOperand::MO_RegisterMask: | ||||||||
339 | case MachineOperand::MO_RegisterLiveOut: { | ||||||||
340 | // Shallow compare of the two RegMasks | ||||||||
341 | const uint32_t *RegMask = getRegMask(); | ||||||||
342 | const uint32_t *OtherRegMask = Other.getRegMask(); | ||||||||
343 | if (RegMask == OtherRegMask) | ||||||||
344 | return true; | ||||||||
345 | |||||||||
346 | if (const MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
347 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | ||||||||
348 | unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs()); | ||||||||
349 | // Deep compare of the two RegMasks | ||||||||
350 | return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask); | ||||||||
351 | } | ||||||||
352 | // We don't know the size of the RegMask, so we can't deep compare the two | ||||||||
353 | // reg masks. | ||||||||
354 | return false; | ||||||||
355 | } | ||||||||
356 | case MachineOperand::MO_MCSymbol: | ||||||||
357 | return getMCSymbol() == Other.getMCSymbol(); | ||||||||
358 | case MachineOperand::MO_DbgInstrRef: | ||||||||
359 | return getInstrRefInstrIndex() == Other.getInstrRefInstrIndex() && | ||||||||
360 | getInstrRefOpIndex() == Other.getInstrRefOpIndex(); | ||||||||
361 | case MachineOperand::MO_CFIIndex: | ||||||||
362 | return getCFIIndex() == Other.getCFIIndex(); | ||||||||
363 | case MachineOperand::MO_Metadata: | ||||||||
364 | return getMetadata() == Other.getMetadata(); | ||||||||
365 | case MachineOperand::MO_IntrinsicID: | ||||||||
366 | return getIntrinsicID() == Other.getIntrinsicID(); | ||||||||
367 | case MachineOperand::MO_Predicate: | ||||||||
368 | return getPredicate() == Other.getPredicate(); | ||||||||
369 | case MachineOperand::MO_ShuffleMask: | ||||||||
370 | return getShuffleMask() == Other.getShuffleMask(); | ||||||||
371 | } | ||||||||
372 | llvm_unreachable("Invalid machine operand type")::llvm::llvm_unreachable_internal("Invalid machine operand type" , "llvm/lib/CodeGen/MachineOperand.cpp", 372); | ||||||||
373 | } | ||||||||
374 | |||||||||
375 | // Note: this must stay exactly in sync with isIdenticalTo above. | ||||||||
376 | hash_code llvm::hash_value(const MachineOperand &MO) { | ||||||||
377 | switch (MO.getType()) { | ||||||||
378 | case MachineOperand::MO_Register: | ||||||||
379 | // Register operands don't have target flags. | ||||||||
380 | return hash_combine(MO.getType(), (unsigned)MO.getReg(), MO.getSubReg(), MO.isDef()); | ||||||||
381 | case MachineOperand::MO_Immediate: | ||||||||
382 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); | ||||||||
383 | case MachineOperand::MO_CImmediate: | ||||||||
384 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm()); | ||||||||
385 | case MachineOperand::MO_FPImmediate: | ||||||||
386 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm()); | ||||||||
387 | case MachineOperand::MO_MachineBasicBlock: | ||||||||
388 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB()); | ||||||||
389 | case MachineOperand::MO_FrameIndex: | ||||||||
390 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); | ||||||||
391 | case MachineOperand::MO_ConstantPoolIndex: | ||||||||
392 | case MachineOperand::MO_TargetIndex: | ||||||||
393 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(), | ||||||||
394 | MO.getOffset()); | ||||||||
395 | case MachineOperand::MO_JumpTableIndex: | ||||||||
396 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); | ||||||||
397 | case MachineOperand::MO_ExternalSymbol: | ||||||||
398 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), | ||||||||
399 | StringRef(MO.getSymbolName())); | ||||||||
400 | case MachineOperand::MO_GlobalAddress: | ||||||||
401 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(), | ||||||||
402 | MO.getOffset()); | ||||||||
403 | case MachineOperand::MO_BlockAddress: | ||||||||
404 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(), | ||||||||
405 | MO.getOffset()); | ||||||||
406 | case MachineOperand::MO_RegisterMask: | ||||||||
407 | case MachineOperand::MO_RegisterLiveOut: { | ||||||||
408 | if (const MachineFunction *MF = getMFIfAvailable(MO)) { | ||||||||
409 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | ||||||||
410 | unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs()); | ||||||||
411 | const uint32_t *RegMask = MO.getRegMask(); | ||||||||
412 | std::vector<stable_hash> RegMaskHashes(RegMask, RegMask + RegMaskSize); | ||||||||
413 | return hash_combine(MO.getType(), MO.getTargetFlags(), | ||||||||
414 | stable_hash_combine_array(RegMaskHashes.data(), | ||||||||
415 | RegMaskHashes.size())); | ||||||||
416 | } | ||||||||
417 | |||||||||
418 | assert(0 && "MachineOperand not associated with any MachineFunction")(static_cast <bool> (0 && "MachineOperand not associated with any MachineFunction" ) ? void (0) : __assert_fail ("0 && \"MachineOperand not associated with any MachineFunction\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 418, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
419 | return hash_combine(MO.getType(), MO.getTargetFlags()); | ||||||||
420 | } | ||||||||
421 | case MachineOperand::MO_Metadata: | ||||||||
422 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); | ||||||||
423 | case MachineOperand::MO_MCSymbol: | ||||||||
424 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); | ||||||||
425 | case MachineOperand::MO_DbgInstrRef: | ||||||||
426 | return hash_combine(MO.getType(), MO.getTargetFlags(), | ||||||||
427 | MO.getInstrRefInstrIndex(), MO.getInstrRefOpIndex()); | ||||||||
428 | case MachineOperand::MO_CFIIndex: | ||||||||
429 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); | ||||||||
430 | case MachineOperand::MO_IntrinsicID: | ||||||||
431 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); | ||||||||
432 | case MachineOperand::MO_Predicate: | ||||||||
433 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); | ||||||||
434 | case MachineOperand::MO_ShuffleMask: | ||||||||
435 | return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask()); | ||||||||
436 | } | ||||||||
437 | llvm_unreachable("Invalid machine operand type")::llvm::llvm_unreachable_internal("Invalid machine operand type" , "llvm/lib/CodeGen/MachineOperand.cpp", 437); | ||||||||
438 | } | ||||||||
439 | |||||||||
440 | // Try to crawl up to the machine function and get TRI and IntrinsicInfo from | ||||||||
441 | // it. | ||||||||
442 | static void tryToGetTargetInfo(const MachineOperand &MO, | ||||||||
443 | const TargetRegisterInfo *&TRI, | ||||||||
444 | const TargetIntrinsicInfo *&IntrinsicInfo) { | ||||||||
445 | if (const MachineFunction *MF = getMFIfAvailable(MO)) { | ||||||||
446 | TRI = MF->getSubtarget().getRegisterInfo(); | ||||||||
447 | IntrinsicInfo = MF->getTarget().getIntrinsicInfo(); | ||||||||
448 | } | ||||||||
449 | } | ||||||||
450 | |||||||||
451 | static const char *getTargetIndexName(const MachineFunction &MF, int Index) { | ||||||||
452 | const auto *TII = MF.getSubtarget().getInstrInfo(); | ||||||||
453 | assert(TII && "expected instruction info")(static_cast <bool> (TII && "expected instruction info" ) ? void (0) : __assert_fail ("TII && \"expected instruction info\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 453, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
454 | auto Indices = TII->getSerializableTargetIndices(); | ||||||||
455 | auto Found = find_if(Indices, [&](const std::pair<int, const char *> &I) { | ||||||||
456 | return I.first == Index; | ||||||||
457 | }); | ||||||||
458 | if (Found != Indices.end()) | ||||||||
459 | return Found->second; | ||||||||
460 | return nullptr; | ||||||||
461 | } | ||||||||
462 | |||||||||
463 | const char *MachineOperand::getTargetIndexName() const { | ||||||||
464 | const MachineFunction *MF = getMFIfAvailable(*this); | ||||||||
465 | return MF ? ::getTargetIndexName(*MF, this->getIndex()) : nullptr; | ||||||||
466 | } | ||||||||
467 | |||||||||
468 | static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) { | ||||||||
469 | auto Flags = TII->getSerializableDirectMachineOperandTargetFlags(); | ||||||||
470 | for (const auto &I : Flags) { | ||||||||
471 | if (I.first == TF) { | ||||||||
472 | return I.second; | ||||||||
473 | } | ||||||||
474 | } | ||||||||
475 | return nullptr; | ||||||||
476 | } | ||||||||
477 | |||||||||
478 | static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS, | ||||||||
479 | const TargetRegisterInfo *TRI) { | ||||||||
480 | if (!TRI) { | ||||||||
481 | OS << "%dwarfreg." << DwarfReg; | ||||||||
482 | return; | ||||||||
483 | } | ||||||||
484 | |||||||||
485 | if (std::optional<unsigned> Reg = TRI->getLLVMRegNum(DwarfReg, true)) | ||||||||
486 | OS << printReg(*Reg, TRI); | ||||||||
487 | else | ||||||||
488 | OS << "<badreg>"; | ||||||||
489 | } | ||||||||
490 | |||||||||
491 | static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB, | ||||||||
492 | ModuleSlotTracker &MST) { | ||||||||
493 | OS << "%ir-block."; | ||||||||
494 | if (BB.hasName()) { | ||||||||
495 | printLLVMNameWithoutPrefix(OS, BB.getName()); | ||||||||
496 | return; | ||||||||
497 | } | ||||||||
498 | std::optional<int> Slot; | ||||||||
499 | if (const Function *F = BB.getParent()) { | ||||||||
500 | if (F == MST.getCurrentFunction()) { | ||||||||
501 | Slot = MST.getLocalSlot(&BB); | ||||||||
502 | } else if (const Module *M = F->getParent()) { | ||||||||
503 | ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false); | ||||||||
504 | CustomMST.incorporateFunction(*F); | ||||||||
505 | Slot = CustomMST.getLocalSlot(&BB); | ||||||||
506 | } | ||||||||
507 | } | ||||||||
508 | if (Slot) | ||||||||
509 | MachineOperand::printIRSlotNumber(OS, *Slot); | ||||||||
510 | else | ||||||||
511 | OS << "<unknown>"; | ||||||||
512 | } | ||||||||
513 | |||||||||
514 | static void printSyncScope(raw_ostream &OS, const LLVMContext &Context, | ||||||||
515 | SyncScope::ID SSID, | ||||||||
516 | SmallVectorImpl<StringRef> &SSNs) { | ||||||||
517 | switch (SSID) { | ||||||||
518 | case SyncScope::System: | ||||||||
519 | break; | ||||||||
520 | default: | ||||||||
521 | if (SSNs.empty()) | ||||||||
522 | Context.getSyncScopeNames(SSNs); | ||||||||
523 | |||||||||
524 | OS << "syncscope(\""; | ||||||||
525 | printEscapedString(SSNs[SSID], OS); | ||||||||
526 | OS << "\") "; | ||||||||
527 | break; | ||||||||
528 | } | ||||||||
529 | } | ||||||||
530 | |||||||||
531 | static const char *getTargetMMOFlagName(const TargetInstrInfo &TII, | ||||||||
532 | unsigned TMMOFlag) { | ||||||||
533 | auto Flags = TII.getSerializableMachineMemOperandTargetFlags(); | ||||||||
534 | for (const auto &I : Flags) { | ||||||||
535 | if (I.first == TMMOFlag) { | ||||||||
536 | return I.second; | ||||||||
537 | } | ||||||||
538 | } | ||||||||
539 | return nullptr; | ||||||||
540 | } | ||||||||
541 | |||||||||
542 | static void printFrameIndex(raw_ostream& OS, int FrameIndex, bool IsFixed, | ||||||||
543 | const MachineFrameInfo *MFI) { | ||||||||
544 | StringRef Name; | ||||||||
545 | if (MFI) { | ||||||||
546 | IsFixed = MFI->isFixedObjectIndex(FrameIndex); | ||||||||
547 | if (const AllocaInst *Alloca = MFI->getObjectAllocation(FrameIndex)) | ||||||||
548 | if (Alloca->hasName()) | ||||||||
549 | Name = Alloca->getName(); | ||||||||
550 | if (IsFixed) | ||||||||
551 | FrameIndex -= MFI->getObjectIndexBegin(); | ||||||||
552 | } | ||||||||
553 | MachineOperand::printStackObjectReference(OS, FrameIndex, IsFixed, Name); | ||||||||
554 | } | ||||||||
555 | |||||||||
556 | void MachineOperand::printSubRegIdx(raw_ostream &OS, uint64_t Index, | ||||||||
557 | const TargetRegisterInfo *TRI) { | ||||||||
558 | OS << "%subreg."; | ||||||||
559 | if (TRI && Index != 0 && Index < TRI->getNumSubRegIndices()) | ||||||||
560 | OS << TRI->getSubRegIndexName(Index); | ||||||||
561 | else | ||||||||
562 | OS << Index; | ||||||||
563 | } | ||||||||
564 | |||||||||
565 | void MachineOperand::printTargetFlags(raw_ostream &OS, | ||||||||
566 | const MachineOperand &Op) { | ||||||||
567 | if (!Op.getTargetFlags()) | ||||||||
568 | return; | ||||||||
569 | const MachineFunction *MF = getMFIfAvailable(Op); | ||||||||
570 | if (!MF) | ||||||||
571 | return; | ||||||||
572 | |||||||||
573 | const auto *TII = MF->getSubtarget().getInstrInfo(); | ||||||||
574 | assert(TII && "expected instruction info")(static_cast <bool> (TII && "expected instruction info" ) ? void (0) : __assert_fail ("TII && \"expected instruction info\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 574, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
575 | auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags()); | ||||||||
576 | OS << "target-flags("; | ||||||||
577 | const bool HasDirectFlags = Flags.first; | ||||||||
578 | const bool HasBitmaskFlags = Flags.second; | ||||||||
579 | if (!HasDirectFlags && !HasBitmaskFlags) { | ||||||||
580 | OS << "<unknown>) "; | ||||||||
581 | return; | ||||||||
582 | } | ||||||||
583 | if (HasDirectFlags) { | ||||||||
584 | if (const auto *Name = getTargetFlagName(TII, Flags.first)) | ||||||||
585 | OS << Name; | ||||||||
586 | else | ||||||||
587 | OS << "<unknown target flag>"; | ||||||||
588 | } | ||||||||
589 | if (!HasBitmaskFlags) { | ||||||||
590 | OS << ") "; | ||||||||
591 | return; | ||||||||
592 | } | ||||||||
593 | bool IsCommaNeeded = HasDirectFlags; | ||||||||
594 | unsigned BitMask = Flags.second; | ||||||||
595 | auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags(); | ||||||||
596 | for (const auto &Mask : BitMasks) { | ||||||||
597 | // Check if the flag's bitmask has the bits of the current mask set. | ||||||||
598 | if ((BitMask & Mask.first) == Mask.first) { | ||||||||
599 | if (IsCommaNeeded) | ||||||||
600 | OS << ", "; | ||||||||
601 | IsCommaNeeded = true; | ||||||||
602 | OS << Mask.second; | ||||||||
603 | // Clear the bits which were serialized from the flag's bitmask. | ||||||||
604 | BitMask &= ~(Mask.first); | ||||||||
605 | } | ||||||||
606 | } | ||||||||
607 | if (BitMask) { | ||||||||
608 | // When the resulting flag's bitmask isn't zero, we know that we didn't | ||||||||
609 | // serialize all of the bit flags. | ||||||||
610 | if (IsCommaNeeded) | ||||||||
611 | OS << ", "; | ||||||||
612 | OS << "<unknown bitmask target flag>"; | ||||||||
613 | } | ||||||||
614 | OS << ") "; | ||||||||
615 | } | ||||||||
616 | |||||||||
617 | void MachineOperand::printSymbol(raw_ostream &OS, MCSymbol &Sym) { | ||||||||
618 | OS << "<mcsymbol " << Sym << ">"; | ||||||||
619 | } | ||||||||
620 | |||||||||
621 | void MachineOperand::printStackObjectReference(raw_ostream &OS, | ||||||||
622 | unsigned FrameIndex, | ||||||||
623 | bool IsFixed, StringRef Name) { | ||||||||
624 | if (IsFixed) { | ||||||||
625 | OS << "%fixed-stack." << FrameIndex; | ||||||||
626 | return; | ||||||||
627 | } | ||||||||
628 | |||||||||
629 | OS << "%stack." << FrameIndex; | ||||||||
630 | if (!Name.empty()) | ||||||||
631 | OS << '.' << Name; | ||||||||
632 | } | ||||||||
633 | |||||||||
634 | void MachineOperand::printOperandOffset(raw_ostream &OS, int64_t Offset) { | ||||||||
635 | if (Offset == 0) | ||||||||
636 | return; | ||||||||
637 | if (Offset < 0) { | ||||||||
638 | OS << " - " << -Offset; | ||||||||
639 | return; | ||||||||
640 | } | ||||||||
641 | OS << " + " << Offset; | ||||||||
642 | } | ||||||||
643 | |||||||||
644 | void MachineOperand::printIRSlotNumber(raw_ostream &OS, int Slot) { | ||||||||
645 | if (Slot == -1) | ||||||||
646 | OS << "<badref>"; | ||||||||
647 | else | ||||||||
648 | OS << Slot; | ||||||||
649 | } | ||||||||
650 | |||||||||
651 | static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI, | ||||||||
652 | const TargetRegisterInfo *TRI) { | ||||||||
653 | switch (CFI.getOperation()) { | ||||||||
654 | case MCCFIInstruction::OpSameValue: | ||||||||
655 | OS << "same_value "; | ||||||||
656 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
657 | MachineOperand::printSymbol(OS, *Label); | ||||||||
658 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
659 | break; | ||||||||
660 | case MCCFIInstruction::OpRememberState: | ||||||||
661 | OS << "remember_state "; | ||||||||
662 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
663 | MachineOperand::printSymbol(OS, *Label); | ||||||||
664 | break; | ||||||||
665 | case MCCFIInstruction::OpRestoreState: | ||||||||
666 | OS << "restore_state "; | ||||||||
667 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
668 | MachineOperand::printSymbol(OS, *Label); | ||||||||
669 | break; | ||||||||
670 | case MCCFIInstruction::OpOffset: | ||||||||
671 | OS << "offset "; | ||||||||
672 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
673 | MachineOperand::printSymbol(OS, *Label); | ||||||||
674 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
675 | OS << ", " << CFI.getOffset(); | ||||||||
676 | break; | ||||||||
677 | case MCCFIInstruction::OpDefCfaRegister: | ||||||||
678 | OS << "def_cfa_register "; | ||||||||
679 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
680 | MachineOperand::printSymbol(OS, *Label); | ||||||||
681 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
682 | break; | ||||||||
683 | case MCCFIInstruction::OpDefCfaOffset: | ||||||||
684 | OS << "def_cfa_offset "; | ||||||||
685 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
686 | MachineOperand::printSymbol(OS, *Label); | ||||||||
687 | OS << CFI.getOffset(); | ||||||||
688 | break; | ||||||||
689 | case MCCFIInstruction::OpDefCfa: | ||||||||
690 | OS << "def_cfa "; | ||||||||
691 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
692 | MachineOperand::printSymbol(OS, *Label); | ||||||||
693 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
694 | OS << ", " << CFI.getOffset(); | ||||||||
695 | break; | ||||||||
696 | case MCCFIInstruction::OpLLVMDefAspaceCfa: | ||||||||
697 | OS << "llvm_def_aspace_cfa "; | ||||||||
698 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
699 | MachineOperand::printSymbol(OS, *Label); | ||||||||
700 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
701 | OS << ", " << CFI.getOffset(); | ||||||||
702 | OS << ", " << CFI.getAddressSpace(); | ||||||||
703 | break; | ||||||||
704 | case MCCFIInstruction::OpRelOffset: | ||||||||
705 | OS << "rel_offset "; | ||||||||
706 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
707 | MachineOperand::printSymbol(OS, *Label); | ||||||||
708 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
709 | OS << ", " << CFI.getOffset(); | ||||||||
710 | break; | ||||||||
711 | case MCCFIInstruction::OpAdjustCfaOffset: | ||||||||
712 | OS << "adjust_cfa_offset "; | ||||||||
713 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
714 | MachineOperand::printSymbol(OS, *Label); | ||||||||
715 | OS << CFI.getOffset(); | ||||||||
716 | break; | ||||||||
717 | case MCCFIInstruction::OpRestore: | ||||||||
718 | OS << "restore "; | ||||||||
719 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
720 | MachineOperand::printSymbol(OS, *Label); | ||||||||
721 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
722 | break; | ||||||||
723 | case MCCFIInstruction::OpEscape: { | ||||||||
724 | OS << "escape "; | ||||||||
725 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
726 | MachineOperand::printSymbol(OS, *Label); | ||||||||
727 | if (!CFI.getValues().empty()) { | ||||||||
728 | size_t e = CFI.getValues().size() - 1; | ||||||||
729 | for (size_t i = 0; i < e; ++i) | ||||||||
730 | OS << format("0x%02x", uint8_t(CFI.getValues()[i])) << ", "; | ||||||||
731 | OS << format("0x%02x", uint8_t(CFI.getValues()[e])); | ||||||||
732 | } | ||||||||
733 | break; | ||||||||
734 | } | ||||||||
735 | case MCCFIInstruction::OpUndefined: | ||||||||
736 | OS << "undefined "; | ||||||||
737 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
738 | MachineOperand::printSymbol(OS, *Label); | ||||||||
739 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
740 | break; | ||||||||
741 | case MCCFIInstruction::OpRegister: | ||||||||
742 | OS << "register "; | ||||||||
743 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
744 | MachineOperand::printSymbol(OS, *Label); | ||||||||
745 | printCFIRegister(CFI.getRegister(), OS, TRI); | ||||||||
746 | OS << ", "; | ||||||||
747 | printCFIRegister(CFI.getRegister2(), OS, TRI); | ||||||||
748 | break; | ||||||||
749 | case MCCFIInstruction::OpWindowSave: | ||||||||
750 | OS << "window_save "; | ||||||||
751 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
752 | MachineOperand::printSymbol(OS, *Label); | ||||||||
753 | break; | ||||||||
754 | case MCCFIInstruction::OpNegateRAState: | ||||||||
755 | OS << "negate_ra_sign_state "; | ||||||||
756 | if (MCSymbol *Label = CFI.getLabel()) | ||||||||
757 | MachineOperand::printSymbol(OS, *Label); | ||||||||
758 | break; | ||||||||
759 | default: | ||||||||
760 | // TODO: Print the other CFI Operations. | ||||||||
761 | OS << "<unserializable cfi directive>"; | ||||||||
762 | break; | ||||||||
763 | } | ||||||||
764 | } | ||||||||
765 | |||||||||
766 | void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, | ||||||||
767 | const TargetIntrinsicInfo *IntrinsicInfo) const { | ||||||||
768 | print(OS, LLT{}, TRI, IntrinsicInfo); | ||||||||
769 | } | ||||||||
770 | |||||||||
771 | void MachineOperand::print(raw_ostream &OS, LLT TypeToPrint, | ||||||||
772 | const TargetRegisterInfo *TRI, | ||||||||
773 | const TargetIntrinsicInfo *IntrinsicInfo) const { | ||||||||
774 | tryToGetTargetInfo(*this, TRI, IntrinsicInfo); | ||||||||
775 | ModuleSlotTracker DummyMST(nullptr); | ||||||||
776 | print(OS, DummyMST, TypeToPrint, std::nullopt, /*PrintDef=*/false, | ||||||||
777 | /*IsStandalone=*/true, | ||||||||
778 | /*ShouldPrintRegisterTies=*/true, | ||||||||
779 | /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); | ||||||||
780 | } | ||||||||
781 | |||||||||
782 | void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, | ||||||||
783 | LLT TypeToPrint, std::optional<unsigned> OpIdx, | ||||||||
784 | bool PrintDef, bool IsStandalone, | ||||||||
785 | bool ShouldPrintRegisterTies, | ||||||||
786 | unsigned TiedOperandIdx, | ||||||||
787 | const TargetRegisterInfo *TRI, | ||||||||
788 | const TargetIntrinsicInfo *IntrinsicInfo) const { | ||||||||
789 | printTargetFlags(OS, *this); | ||||||||
790 | switch (getType()) { | ||||||||
791 | case MachineOperand::MO_Register: { | ||||||||
792 | Register Reg = getReg(); | ||||||||
793 | if (isImplicit()) | ||||||||
794 | OS << (isDef() ? "implicit-def " : "implicit "); | ||||||||
795 | else if (PrintDef && isDef()) | ||||||||
796 | // Print the 'def' flag only when the operand is defined after '='. | ||||||||
797 | OS << "def "; | ||||||||
798 | if (isInternalRead()) | ||||||||
799 | OS << "internal "; | ||||||||
800 | if (isDead()) | ||||||||
801 | OS << "dead "; | ||||||||
802 | if (isKill()) | ||||||||
803 | OS << "killed "; | ||||||||
804 | if (isUndef()) | ||||||||
805 | OS << "undef "; | ||||||||
806 | if (isEarlyClobber()) | ||||||||
807 | OS << "early-clobber "; | ||||||||
808 | if (getReg().isPhysical() && isRenamable()) | ||||||||
809 | OS << "renamable "; | ||||||||
810 | // isDebug() is exactly true for register operands of a DBG_VALUE. So we | ||||||||
811 | // simply infer it when parsing and do not need to print it. | ||||||||
812 | |||||||||
813 | const MachineRegisterInfo *MRI = nullptr; | ||||||||
814 | if (Reg.isVirtual()) { | ||||||||
815 | if (const MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
816 | MRI = &MF->getRegInfo(); | ||||||||
817 | } | ||||||||
818 | } | ||||||||
819 | |||||||||
820 | OS << printReg(Reg, TRI, 0, MRI); | ||||||||
821 | // Print the sub register. | ||||||||
822 | if (unsigned SubReg = getSubReg()) { | ||||||||
823 | if (TRI) | ||||||||
824 | OS << '.' << TRI->getSubRegIndexName(SubReg); | ||||||||
825 | else | ||||||||
826 | OS << ".subreg" << SubReg; | ||||||||
827 | } | ||||||||
828 | // Print the register class / bank. | ||||||||
829 | if (Reg.isVirtual()) { | ||||||||
830 | if (const MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
831 | const MachineRegisterInfo &MRI = MF->getRegInfo(); | ||||||||
832 | if (IsStandalone || !PrintDef || MRI.def_empty(Reg)) { | ||||||||
833 | OS << ':'; | ||||||||
834 | OS << printRegClassOrBank(Reg, MRI, TRI); | ||||||||
835 | } | ||||||||
836 | } | ||||||||
837 | } | ||||||||
838 | // Print ties. | ||||||||
839 | if (ShouldPrintRegisterTies && isTied() && !isDef()) | ||||||||
840 | OS << "(tied-def " << TiedOperandIdx << ")"; | ||||||||
841 | // Print types. | ||||||||
842 | if (TypeToPrint.isValid()) | ||||||||
843 | OS << '(' << TypeToPrint << ')'; | ||||||||
844 | break; | ||||||||
845 | } | ||||||||
846 | case MachineOperand::MO_Immediate: { | ||||||||
847 | const MIRFormatter *Formatter = nullptr; | ||||||||
848 | if (const MachineFunction *MF = getMFIfAvailable(*this)) { | ||||||||
849 | const auto *TII = MF->getSubtarget().getInstrInfo(); | ||||||||
850 | assert(TII && "expected instruction info")(static_cast <bool> (TII && "expected instruction info" ) ? void (0) : __assert_fail ("TII && \"expected instruction info\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 850, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
851 | Formatter = TII->getMIRFormatter(); | ||||||||
852 | } | ||||||||
853 | if (Formatter) | ||||||||
854 | Formatter->printImm(OS, *getParent(), OpIdx, getImm()); | ||||||||
855 | else | ||||||||
856 | OS << getImm(); | ||||||||
857 | break; | ||||||||
858 | } | ||||||||
859 | case MachineOperand::MO_CImmediate: | ||||||||
860 | getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); | ||||||||
861 | break; | ||||||||
862 | case MachineOperand::MO_FPImmediate: | ||||||||
863 | getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); | ||||||||
864 | break; | ||||||||
865 | case MachineOperand::MO_MachineBasicBlock: | ||||||||
866 | OS << printMBBReference(*getMBB()); | ||||||||
867 | break; | ||||||||
868 | case MachineOperand::MO_FrameIndex: { | ||||||||
869 | int FrameIndex = getIndex(); | ||||||||
870 | bool IsFixed = false; | ||||||||
871 | const MachineFrameInfo *MFI = nullptr; | ||||||||
872 | if (const MachineFunction *MF = getMFIfAvailable(*this)) | ||||||||
873 | MFI = &MF->getFrameInfo(); | ||||||||
874 | printFrameIndex(OS, FrameIndex, IsFixed, MFI); | ||||||||
875 | break; | ||||||||
876 | } | ||||||||
877 | case MachineOperand::MO_ConstantPoolIndex: | ||||||||
878 | OS << "%const." << getIndex(); | ||||||||
879 | printOperandOffset(OS, getOffset()); | ||||||||
880 | break; | ||||||||
881 | case MachineOperand::MO_TargetIndex: { | ||||||||
882 | OS << "target-index("; | ||||||||
883 | const char *Name = "<unknown>"; | ||||||||
884 | if (const MachineFunction *MF = getMFIfAvailable(*this)) | ||||||||
885 | if (const auto *TargetIndexName = ::getTargetIndexName(*MF, getIndex())) | ||||||||
886 | Name = TargetIndexName; | ||||||||
887 | OS << Name << ')'; | ||||||||
888 | printOperandOffset(OS, getOffset()); | ||||||||
889 | break; | ||||||||
890 | } | ||||||||
891 | case MachineOperand::MO_JumpTableIndex: | ||||||||
892 | OS << printJumpTableEntryReference(getIndex()); | ||||||||
893 | break; | ||||||||
894 | case MachineOperand::MO_GlobalAddress: | ||||||||
895 | getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); | ||||||||
896 | printOperandOffset(OS, getOffset()); | ||||||||
897 | break; | ||||||||
898 | case MachineOperand::MO_ExternalSymbol: { | ||||||||
899 | StringRef Name = getSymbolName(); | ||||||||
900 | OS << '&'; | ||||||||
901 | if (Name.empty()) { | ||||||||
902 | OS << "\"\""; | ||||||||
903 | } else { | ||||||||
904 | printLLVMNameWithoutPrefix(OS, Name); | ||||||||
905 | } | ||||||||
906 | printOperandOffset(OS, getOffset()); | ||||||||
907 | break; | ||||||||
908 | } | ||||||||
909 | case MachineOperand::MO_BlockAddress: { | ||||||||
910 | OS << "blockaddress("; | ||||||||
911 | getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, | ||||||||
912 | MST); | ||||||||
913 | OS << ", "; | ||||||||
914 | printIRBlockReference(OS, *getBlockAddress()->getBasicBlock(), MST); | ||||||||
915 | OS << ')'; | ||||||||
916 | MachineOperand::printOperandOffset(OS, getOffset()); | ||||||||
917 | break; | ||||||||
918 | } | ||||||||
919 | case MachineOperand::MO_RegisterMask: { | ||||||||
920 | OS << "<regmask"; | ||||||||
921 | if (TRI) { | ||||||||
922 | unsigned NumRegsInMask = 0; | ||||||||
923 | unsigned NumRegsEmitted = 0; | ||||||||
924 | for (unsigned i = 0; i < TRI->getNumRegs(); ++i) { | ||||||||
925 | unsigned MaskWord = i / 32; | ||||||||
926 | unsigned MaskBit = i % 32; | ||||||||
927 | if (getRegMask()[MaskWord] & (1 << MaskBit)) { | ||||||||
928 | if (PrintRegMaskNumRegs < 0 || | ||||||||
929 | NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) { | ||||||||
930 | OS << " " << printReg(i, TRI); | ||||||||
931 | NumRegsEmitted++; | ||||||||
932 | } | ||||||||
933 | NumRegsInMask++; | ||||||||
934 | } | ||||||||
935 | } | ||||||||
936 | if (NumRegsEmitted != NumRegsInMask) | ||||||||
937 | OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; | ||||||||
938 | } else { | ||||||||
939 | OS << " ..."; | ||||||||
940 | } | ||||||||
941 | OS << ">"; | ||||||||
942 | break; | ||||||||
943 | } | ||||||||
944 | case MachineOperand::MO_RegisterLiveOut: { | ||||||||
945 | const uint32_t *RegMask = getRegLiveOut(); | ||||||||
946 | OS << "liveout("; | ||||||||
947 | if (!TRI) { | ||||||||
948 | OS << "<unknown>"; | ||||||||
949 | } else { | ||||||||
950 | bool IsCommaNeeded = false; | ||||||||
951 | for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) { | ||||||||
952 | if (RegMask[Reg / 32] & (1U << (Reg % 32))) { | ||||||||
953 | if (IsCommaNeeded) | ||||||||
954 | OS << ", "; | ||||||||
955 | OS << printReg(Reg, TRI); | ||||||||
956 | IsCommaNeeded = true; | ||||||||
957 | } | ||||||||
958 | } | ||||||||
959 | } | ||||||||
960 | OS << ")"; | ||||||||
961 | break; | ||||||||
962 | } | ||||||||
963 | case MachineOperand::MO_Metadata: | ||||||||
964 | getMetadata()->printAsOperand(OS, MST); | ||||||||
965 | break; | ||||||||
966 | case MachineOperand::MO_MCSymbol: | ||||||||
967 | printSymbol(OS, *getMCSymbol()); | ||||||||
968 | break; | ||||||||
969 | case MachineOperand::MO_DbgInstrRef: { | ||||||||
970 | OS << "dbg-instr-ref(" << getInstrRefInstrIndex() << ", " | ||||||||
971 | << getInstrRefOpIndex() << ')'; | ||||||||
972 | break; | ||||||||
973 | } | ||||||||
974 | case MachineOperand::MO_CFIIndex: { | ||||||||
975 | if (const MachineFunction *MF = getMFIfAvailable(*this)) | ||||||||
976 | printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI); | ||||||||
977 | else | ||||||||
978 | OS << "<cfi directive>"; | ||||||||
979 | break; | ||||||||
980 | } | ||||||||
981 | case MachineOperand::MO_IntrinsicID: { | ||||||||
982 | Intrinsic::ID ID = getIntrinsicID(); | ||||||||
983 | if (ID < Intrinsic::num_intrinsics) | ||||||||
984 | OS << "intrinsic(@" << Intrinsic::getBaseName(ID) << ')'; | ||||||||
985 | else if (IntrinsicInfo) | ||||||||
986 | OS << "intrinsic(@" << IntrinsicInfo->getName(ID) << ')'; | ||||||||
987 | else | ||||||||
988 | OS << "intrinsic(" << ID << ')'; | ||||||||
989 | break; | ||||||||
990 | } | ||||||||
991 | case MachineOperand::MO_Predicate: { | ||||||||
992 | auto Pred = static_cast<CmpInst::Predicate>(getPredicate()); | ||||||||
993 | OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" | ||||||||
994 | << Pred << ')'; | ||||||||
995 | break; | ||||||||
996 | } | ||||||||
997 | case MachineOperand::MO_ShuffleMask: | ||||||||
998 | OS << "shufflemask("; | ||||||||
999 | ArrayRef<int> Mask = getShuffleMask(); | ||||||||
1000 | StringRef Separator; | ||||||||
1001 | for (int Elt : Mask) { | ||||||||
1002 | if (Elt == -1) | ||||||||
1003 | OS << Separator << "undef"; | ||||||||
1004 | else | ||||||||
1005 | OS << Separator << Elt; | ||||||||
1006 | Separator = ", "; | ||||||||
1007 | } | ||||||||
1008 | |||||||||
1009 | OS << ')'; | ||||||||
1010 | break; | ||||||||
1011 | } | ||||||||
1012 | } | ||||||||
1013 | |||||||||
1014 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||||
1015 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void MachineOperand::dump() const { dbgs() << *this << '\n'; } | ||||||||
1016 | #endif | ||||||||
1017 | |||||||||
1018 | //===----------------------------------------------------------------------===// | ||||||||
1019 | // MachineMemOperand Implementation | ||||||||
1020 | //===----------------------------------------------------------------------===// | ||||||||
1021 | |||||||||
1022 | /// getAddrSpace - Return the LLVM IR address space number that this pointer | ||||||||
1023 | /// points into. | ||||||||
1024 | unsigned MachinePointerInfo::getAddrSpace() const { return AddrSpace; } | ||||||||
1025 | |||||||||
1026 | /// isDereferenceable - Return true if V is always dereferenceable for | ||||||||
1027 | /// Offset + Size byte. | ||||||||
1028 | bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C, | ||||||||
1029 | const DataLayout &DL) const { | ||||||||
1030 | if (!isa<const Value *>(V)) | ||||||||
1031 | return false; | ||||||||
1032 | |||||||||
1033 | const Value *BasePtr = cast<const Value *>(V); | ||||||||
1034 | if (BasePtr == nullptr) | ||||||||
1035 | return false; | ||||||||
1036 | |||||||||
1037 | return isDereferenceableAndAlignedPointer( | ||||||||
1038 | BasePtr, Align(1), APInt(DL.getPointerSizeInBits(), Offset + Size), DL); | ||||||||
1039 | } | ||||||||
1040 | |||||||||
1041 | /// getConstantPool - Return a MachinePointerInfo record that refers to the | ||||||||
1042 | /// constant pool. | ||||||||
1043 | MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) { | ||||||||
1044 | return MachinePointerInfo(MF.getPSVManager().getConstantPool()); | ||||||||
1045 | } | ||||||||
1046 | |||||||||
1047 | /// getFixedStack - Return a MachinePointerInfo record that refers to the | ||||||||
1048 | /// the specified FrameIndex. | ||||||||
1049 | MachinePointerInfo MachinePointerInfo::getFixedStack(MachineFunction &MF, | ||||||||
1050 | int FI, int64_t Offset) { | ||||||||
1051 | return MachinePointerInfo(MF.getPSVManager().getFixedStack(FI), Offset); | ||||||||
1052 | } | ||||||||
1053 | |||||||||
1054 | MachinePointerInfo MachinePointerInfo::getJumpTable(MachineFunction &MF) { | ||||||||
1055 | return MachinePointerInfo(MF.getPSVManager().getJumpTable()); | ||||||||
1056 | } | ||||||||
1057 | |||||||||
1058 | MachinePointerInfo MachinePointerInfo::getGOT(MachineFunction &MF) { | ||||||||
1059 | return MachinePointerInfo(MF.getPSVManager().getGOT()); | ||||||||
1060 | } | ||||||||
1061 | |||||||||
1062 | MachinePointerInfo MachinePointerInfo::getStack(MachineFunction &MF, | ||||||||
1063 | int64_t Offset, uint8_t ID) { | ||||||||
1064 | return MachinePointerInfo(MF.getPSVManager().getStack(), Offset, ID); | ||||||||
1065 | } | ||||||||
1066 | |||||||||
1067 | MachinePointerInfo MachinePointerInfo::getUnknownStack(MachineFunction &MF) { | ||||||||
1068 | return MachinePointerInfo(MF.getDataLayout().getAllocaAddrSpace()); | ||||||||
1069 | } | ||||||||
1070 | |||||||||
1071 | MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, | ||||||||
1072 | LLT type, Align a, const AAMDNodes &AAInfo, | ||||||||
1073 | const MDNode *Ranges, SyncScope::ID SSID, | ||||||||
1074 | AtomicOrdering Ordering, | ||||||||
1075 | AtomicOrdering FailureOrdering) | ||||||||
1076 | : PtrInfo(ptrinfo), MemoryType(type), FlagVals(f), BaseAlign(a), | ||||||||
1077 | AAInfo(AAInfo), Ranges(Ranges) { | ||||||||
1078 | assert((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) ||(static_cast <bool> ((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType> (cast<const Value *>(PtrInfo.V)->getType())) && "invalid pointer value") ? void (0) : __assert_fail ("(PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) && \"invalid pointer value\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1080, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
1079 | isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) &&(static_cast <bool> ((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType> (cast<const Value *>(PtrInfo.V)->getType())) && "invalid pointer value") ? void (0) : __assert_fail ("(PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) && \"invalid pointer value\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1080, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
1080 | "invalid pointer value")(static_cast <bool> ((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType> (cast<const Value *>(PtrInfo.V)->getType())) && "invalid pointer value") ? void (0) : __assert_fail ("(PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) && \"invalid pointer value\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1080, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1081 | assert((isLoad() || isStore()) && "Not a load/store!")(static_cast <bool> ((isLoad() || isStore()) && "Not a load/store!") ? void (0) : __assert_fail ("(isLoad() || isStore()) && \"Not a load/store!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1081, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1082 | |||||||||
1083 | AtomicInfo.SSID = static_cast<unsigned>(SSID); | ||||||||
1084 | assert(getSyncScopeID() == SSID && "Value truncated")(static_cast <bool> (getSyncScopeID() == SSID && "Value truncated") ? void (0) : __assert_fail ("getSyncScopeID() == SSID && \"Value truncated\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1084, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1085 | AtomicInfo.Ordering = static_cast<unsigned>(Ordering); | ||||||||
1086 | assert(getSuccessOrdering() == Ordering && "Value truncated")(static_cast <bool> (getSuccessOrdering() == Ordering && "Value truncated") ? void (0) : __assert_fail ("getSuccessOrdering() == Ordering && \"Value truncated\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1086, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1087 | AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering); | ||||||||
1088 | assert(getFailureOrdering() == FailureOrdering && "Value truncated")(static_cast <bool> (getFailureOrdering() == FailureOrdering && "Value truncated") ? void (0) : __assert_fail ("getFailureOrdering() == FailureOrdering && \"Value truncated\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1088, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1089 | } | ||||||||
1090 | |||||||||
1091 | MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, | ||||||||
1092 | uint64_t s, Align a, | ||||||||
1093 | const AAMDNodes &AAInfo, | ||||||||
1094 | const MDNode *Ranges, SyncScope::ID SSID, | ||||||||
1095 | AtomicOrdering Ordering, | ||||||||
1096 | AtomicOrdering FailureOrdering) | ||||||||
1097 | : MachineMemOperand(ptrinfo, f, | ||||||||
1098 | s == ~UINT64_C(0)0UL ? LLT() : LLT::scalar(8 * s), a, | ||||||||
1099 | AAInfo, Ranges, SSID, Ordering, FailureOrdering) {} | ||||||||
1100 | |||||||||
1101 | /// Profile - Gather unique data for the object. | ||||||||
1102 | /// | ||||||||
1103 | void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { | ||||||||
1104 | ID.AddInteger(getOffset()); | ||||||||
1105 | ID.AddInteger(getMemoryType().getUniqueRAWLLTData()); | ||||||||
1106 | ID.AddPointer(getOpaqueValue()); | ||||||||
1107 | ID.AddInteger(getFlags()); | ||||||||
1108 | ID.AddInteger(getBaseAlign().value()); | ||||||||
1109 | } | ||||||||
1110 | |||||||||
1111 | void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { | ||||||||
1112 | // The Value and Offset may differ due to CSE. But the flags and size | ||||||||
1113 | // should be the same. | ||||||||
1114 | assert(MMO->getFlags() == getFlags() && "Flags mismatch!")(static_cast <bool> (MMO->getFlags() == getFlags() && "Flags mismatch!") ? void (0) : __assert_fail ("MMO->getFlags() == getFlags() && \"Flags mismatch!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1114, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1115 | assert((MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) ||(static_cast <bool> ((MMO->getSize() == ~0UL || getSize () == ~0UL || MMO->getSize() == getSize()) && "Size mismatch!" ) ? void (0) : __assert_fail ("(MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || MMO->getSize() == getSize()) && \"Size mismatch!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1117, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
1116 | MMO->getSize() == getSize()) &&(static_cast <bool> ((MMO->getSize() == ~0UL || getSize () == ~0UL || MMO->getSize() == getSize()) && "Size mismatch!" ) ? void (0) : __assert_fail ("(MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || MMO->getSize() == getSize()) && \"Size mismatch!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1117, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
1117 | "Size mismatch!")(static_cast <bool> ((MMO->getSize() == ~0UL || getSize () == ~0UL || MMO->getSize() == getSize()) && "Size mismatch!" ) ? void (0) : __assert_fail ("(MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || MMO->getSize() == getSize()) && \"Size mismatch!\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1117, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1118 | |||||||||
1119 | if (MMO->getBaseAlign() >= getBaseAlign()) { | ||||||||
1120 | // Update the alignment value. | ||||||||
1121 | BaseAlign = MMO->getBaseAlign(); | ||||||||
1122 | // Also update the base and offset, because the new alignment may | ||||||||
1123 | // not be applicable with the old ones. | ||||||||
1124 | PtrInfo = MMO->PtrInfo; | ||||||||
1125 | } | ||||||||
1126 | } | ||||||||
1127 | |||||||||
1128 | /// getAlign - Return the minimum known alignment in bytes of the | ||||||||
1129 | /// actual memory reference. | ||||||||
1130 | Align MachineMemOperand::getAlign() const { | ||||||||
1131 | return commonAlignment(getBaseAlign(), getOffset()); | ||||||||
1132 | } | ||||||||
1133 | |||||||||
1134 | void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, | ||||||||
1135 | SmallVectorImpl<StringRef> &SSNs, | ||||||||
1136 | const LLVMContext &Context, | ||||||||
1137 | const MachineFrameInfo *MFI, | ||||||||
1138 | const TargetInstrInfo *TII) const { | ||||||||
1139 | OS << '('; | ||||||||
1140 | if (isVolatile()) | ||||||||
| |||||||||
1141 | OS << "volatile "; | ||||||||
1142 | if (isNonTemporal()) | ||||||||
1143 | OS << "non-temporal "; | ||||||||
1144 | if (isDereferenceable()) | ||||||||
1145 | OS << "dereferenceable "; | ||||||||
1146 | if (isInvariant()) | ||||||||
1147 | OS << "invariant "; | ||||||||
1148 | if (TII) { | ||||||||
1149 | if (getFlags() & MachineMemOperand::MOTargetFlag1) | ||||||||
1150 | OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag1) | ||||||||
1151 | << "\" "; | ||||||||
1152 | if (getFlags() & MachineMemOperand::MOTargetFlag2) | ||||||||
1153 | OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag2) | ||||||||
1154 | << "\" "; | ||||||||
1155 | if (getFlags() & MachineMemOperand::MOTargetFlag3) | ||||||||
1156 | OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag3) | ||||||||
1157 | << "\" "; | ||||||||
1158 | } else { | ||||||||
1159 | if (getFlags() & MachineMemOperand::MOTargetFlag1) | ||||||||
1160 | OS << "\"MOTargetFlag1\" "; | ||||||||
1161 | if (getFlags() & MachineMemOperand::MOTargetFlag2) | ||||||||
1162 | OS << "\"MOTargetFlag2\" "; | ||||||||
1163 | if (getFlags() & MachineMemOperand::MOTargetFlag3) | ||||||||
1164 | OS << "\"MOTargetFlag3\" "; | ||||||||
1165 | } | ||||||||
1166 | |||||||||
1167 | assert((isLoad() || isStore()) &&(static_cast <bool> ((isLoad() || isStore()) && "machine memory operand must be a load or store (or both)") ? void (0) : __assert_fail ("(isLoad() || isStore()) && \"machine memory operand must be a load or store (or both)\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1168, __extension__ __PRETTY_FUNCTION__ )) | ||||||||
1168 | "machine memory operand must be a load or store (or both)")(static_cast <bool> ((isLoad() || isStore()) && "machine memory operand must be a load or store (or both)") ? void (0) : __assert_fail ("(isLoad() || isStore()) && \"machine memory operand must be a load or store (or both)\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1168, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1169 | if (isLoad()) | ||||||||
1170 | OS << "load "; | ||||||||
1171 | if (isStore()) | ||||||||
1172 | OS << "store "; | ||||||||
1173 | |||||||||
1174 | printSyncScope(OS, Context, getSyncScopeID(), SSNs); | ||||||||
1175 | |||||||||
1176 | if (getSuccessOrdering() != AtomicOrdering::NotAtomic) | ||||||||
1177 | OS << toIRString(getSuccessOrdering()) << ' '; | ||||||||
1178 | if (getFailureOrdering() != AtomicOrdering::NotAtomic) | ||||||||
1179 | OS << toIRString(getFailureOrdering()) << ' '; | ||||||||
1180 | |||||||||
1181 | if (getMemoryType().isValid()) | ||||||||
1182 | OS << '(' << getMemoryType() << ')'; | ||||||||
1183 | else | ||||||||
1184 | OS << "unknown-size"; | ||||||||
1185 | |||||||||
1186 | if (const Value *Val
| ||||||||
1187 | OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); | ||||||||
1188 | MIRFormatter::printIRValue(OS, *Val, MST); | ||||||||
1189 | } else if (const PseudoSourceValue *PVal = getPseudoValue()) { | ||||||||
1190 | OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); | ||||||||
1191 | assert(PVal && "Expected a pseudo source value")(static_cast <bool> (PVal && "Expected a pseudo source value" ) ? void (0) : __assert_fail ("PVal && \"Expected a pseudo source value\"" , "llvm/lib/CodeGen/MachineOperand.cpp", 1191, __extension__ __PRETTY_FUNCTION__ )); | ||||||||
1192 | switch (PVal->kind()) { | ||||||||
1193 | case PseudoSourceValue::Stack: | ||||||||
1194 | OS << "stack"; | ||||||||
1195 | break; | ||||||||
1196 | case PseudoSourceValue::GOT: | ||||||||
1197 | OS << "got"; | ||||||||
1198 | break; | ||||||||
1199 | case PseudoSourceValue::JumpTable: | ||||||||
1200 | OS << "jump-table"; | ||||||||
1201 | break; | ||||||||
1202 | case PseudoSourceValue::ConstantPool: | ||||||||
1203 | OS << "constant-pool"; | ||||||||
1204 | break; | ||||||||
1205 | case PseudoSourceValue::FixedStack: { | ||||||||
1206 | int FrameIndex = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex(); | ||||||||
1207 | bool IsFixed = true; | ||||||||
1208 | printFrameIndex(OS, FrameIndex, IsFixed, MFI); | ||||||||
1209 | break; | ||||||||
1210 | } | ||||||||
1211 | case PseudoSourceValue::GlobalValueCallEntry: | ||||||||
1212 | OS << "call-entry "; | ||||||||
1213 | cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand( | ||||||||
1214 | OS, /*PrintType=*/false, MST); | ||||||||
1215 | break; | ||||||||
1216 | case PseudoSourceValue::ExternalSymbolCallEntry: | ||||||||
1217 | OS << "call-entry &"; | ||||||||
1218 | printLLVMNameWithoutPrefix( | ||||||||
1219 | OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol()); | ||||||||
1220 | break; | ||||||||
1221 | default: { | ||||||||
1222 | const MIRFormatter *Formatter = TII->getMIRFormatter(); | ||||||||
| |||||||||
1223 | // FIXME: This is not necessarily the correct MIR serialization format for | ||||||||
1224 | // a custom pseudo source value, but at least it allows | ||||||||
1225 | // MIR printing to work on a target with custom pseudo source | ||||||||
1226 | // values. | ||||||||
1227 | OS << "custom \""; | ||||||||
1228 | Formatter->printCustomPseudoSourceValue(OS, MST, *PVal); | ||||||||
1229 | OS << '\"'; | ||||||||
1230 | break; | ||||||||
1231 | } | ||||||||
1232 | } | ||||||||
1233 | } else if (getOpaqueValue() == nullptr && getOffset() != 0) { | ||||||||
1234 | OS << ((isLoad() && isStore()) ? " on " | ||||||||
1235 | : isLoad() ? " from " | ||||||||
1236 | : " into ") | ||||||||
1237 | << "unknown-address"; | ||||||||
1238 | } | ||||||||
1239 | MachineOperand::printOperandOffset(OS, getOffset()); | ||||||||
1240 | if (getSize() > 0 && getAlign() != getSize()) | ||||||||
1241 | OS << ", align " << getAlign().value(); | ||||||||
1242 | if (getAlign() != getBaseAlign()) | ||||||||
1243 | OS << ", basealign " << getBaseAlign().value(); | ||||||||
1244 | auto AAInfo = getAAInfo(); | ||||||||
1245 | if (AAInfo.TBAA) { | ||||||||
1246 | OS << ", !tbaa "; | ||||||||
1247 | AAInfo.TBAA->printAsOperand(OS, MST); | ||||||||
1248 | } | ||||||||
1249 | if (AAInfo.Scope) { | ||||||||
1250 | OS << ", !alias.scope "; | ||||||||
1251 | AAInfo.Scope->printAsOperand(OS, MST); | ||||||||
1252 | } | ||||||||
1253 | if (AAInfo.NoAlias) { | ||||||||
1254 | OS << ", !noalias "; | ||||||||
1255 | AAInfo.NoAlias->printAsOperand(OS, MST); | ||||||||
1256 | } | ||||||||
1257 | if (getRanges()) { | ||||||||
1258 | OS << ", !range "; | ||||||||
1259 | getRanges()->printAsOperand(OS, MST); | ||||||||
1260 | } | ||||||||
1261 | // FIXME: Implement addrspace printing/parsing in MIR. | ||||||||
1262 | // For now, print this even though parsing it is not available in MIR. | ||||||||
1263 | if (unsigned AS = getAddrSpace()) | ||||||||
1264 | OS << ", addrspace " << AS; | ||||||||
1265 | |||||||||
1266 | OS << ')'; | ||||||||
1267 | } |
1 | //==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- 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 contains the declaration of the MachineMemOperand class, which is a |
10 | // description of a memory reference. It is used to help track dependencies |
11 | // in the backend. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H |
16 | #define LLVM_CODEGEN_MACHINEMEMOPERAND_H |
17 | |
18 | #include "llvm/ADT/BitmaskEnum.h" |
19 | #include "llvm/ADT/PointerUnion.h" |
20 | #include "llvm/CodeGen/LowLevelType.h" |
21 | #include "llvm/CodeGen/PseudoSourceValue.h" |
22 | #include "llvm/IR/DerivedTypes.h" |
23 | #include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*> |
24 | #include "llvm/Support/AtomicOrdering.h" |
25 | #include "llvm/Support/DataTypes.h" |
26 | |
27 | namespace llvm { |
28 | |
29 | class FoldingSetNodeID; |
30 | class MDNode; |
31 | class raw_ostream; |
32 | class MachineFunction; |
33 | class ModuleSlotTracker; |
34 | class TargetInstrInfo; |
35 | |
36 | /// This class contains a discriminated union of information about pointers in |
37 | /// memory operands, relating them back to LLVM IR or to virtual locations (such |
38 | /// as frame indices) that are exposed during codegen. |
39 | struct MachinePointerInfo { |
40 | /// This is the IR pointer value for the access, or it is null if unknown. |
41 | PointerUnion<const Value *, const PseudoSourceValue *> V; |
42 | |
43 | /// Offset - This is an offset from the base Value*. |
44 | int64_t Offset; |
45 | |
46 | unsigned AddrSpace = 0; |
47 | |
48 | uint8_t StackID; |
49 | |
50 | explicit MachinePointerInfo(const Value *v, int64_t offset = 0, |
51 | uint8_t ID = 0) |
52 | : V(v), Offset(offset), StackID(ID) { |
53 | AddrSpace = v ? v->getType()->getPointerAddressSpace() : 0; |
54 | } |
55 | |
56 | explicit MachinePointerInfo(const PseudoSourceValue *v, int64_t offset = 0, |
57 | uint8_t ID = 0) |
58 | : V(v), Offset(offset), StackID(ID) { |
59 | AddrSpace = v ? v->getAddressSpace() : 0; |
60 | } |
61 | |
62 | explicit MachinePointerInfo(unsigned AddressSpace = 0, int64_t offset = 0) |
63 | : V((const Value *)nullptr), Offset(offset), AddrSpace(AddressSpace), |
64 | StackID(0) {} |
65 | |
66 | explicit MachinePointerInfo( |
67 | PointerUnion<const Value *, const PseudoSourceValue *> v, |
68 | int64_t offset = 0, |
69 | uint8_t ID = 0) |
70 | : V(v), Offset(offset), StackID(ID) { |
71 | if (V) { |
72 | if (const auto *ValPtr = dyn_cast_if_present<const Value *>(V)) |
73 | AddrSpace = ValPtr->getType()->getPointerAddressSpace(); |
74 | else |
75 | AddrSpace = cast<const PseudoSourceValue *>(V)->getAddressSpace(); |
76 | } |
77 | } |
78 | |
79 | MachinePointerInfo getWithOffset(int64_t O) const { |
80 | if (V.isNull()) |
81 | return MachinePointerInfo(AddrSpace, Offset + O); |
82 | if (isa<const Value *>(V)) |
83 | return MachinePointerInfo(cast<const Value *>(V), Offset + O, StackID); |
84 | return MachinePointerInfo(cast<const PseudoSourceValue *>(V), Offset + O, |
85 | StackID); |
86 | } |
87 | |
88 | /// Return true if memory region [V, V+Offset+Size) is known to be |
89 | /// dereferenceable. |
90 | bool isDereferenceable(unsigned Size, LLVMContext &C, |
91 | const DataLayout &DL) const; |
92 | |
93 | /// Return the LLVM IR address space number that this pointer points into. |
94 | unsigned getAddrSpace() const; |
95 | |
96 | /// Return a MachinePointerInfo record that refers to the constant pool. |
97 | static MachinePointerInfo getConstantPool(MachineFunction &MF); |
98 | |
99 | /// Return a MachinePointerInfo record that refers to the specified |
100 | /// FrameIndex. |
101 | static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, |
102 | int64_t Offset = 0); |
103 | |
104 | /// Return a MachinePointerInfo record that refers to a jump table entry. |
105 | static MachinePointerInfo getJumpTable(MachineFunction &MF); |
106 | |
107 | /// Return a MachinePointerInfo record that refers to a GOT entry. |
108 | static MachinePointerInfo getGOT(MachineFunction &MF); |
109 | |
110 | /// Stack pointer relative access. |
111 | static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, |
112 | uint8_t ID = 0); |
113 | |
114 | /// Stack memory without other information. |
115 | static MachinePointerInfo getUnknownStack(MachineFunction &MF); |
116 | }; |
117 | |
118 | |
119 | //===----------------------------------------------------------------------===// |
120 | /// A description of a memory reference used in the backend. |
121 | /// Instead of holding a StoreInst or LoadInst, this class holds the address |
122 | /// Value of the reference along with a byte size and offset. This allows it |
123 | /// to describe lowered loads and stores. Also, the special PseudoSourceValue |
124 | /// objects can be used to represent loads and stores to memory locations |
125 | /// that aren't explicit in the regular LLVM IR. |
126 | /// |
127 | class MachineMemOperand { |
128 | public: |
129 | /// Flags values. These may be or'd together. |
130 | enum Flags : uint16_t { |
131 | // No flags set. |
132 | MONone = 0, |
133 | /// The memory access reads data. |
134 | MOLoad = 1u << 0, |
135 | /// The memory access writes data. |
136 | MOStore = 1u << 1, |
137 | /// The memory access is volatile. |
138 | MOVolatile = 1u << 2, |
139 | /// The memory access is non-temporal. |
140 | MONonTemporal = 1u << 3, |
141 | /// The memory access is dereferenceable (i.e., doesn't trap). |
142 | MODereferenceable = 1u << 4, |
143 | /// The memory access always returns the same value (or traps). |
144 | MOInvariant = 1u << 5, |
145 | |
146 | // Reserved for use by target-specific passes. |
147 | // Targets may override getSerializableMachineMemOperandTargetFlags() to |
148 | // enable MIR serialization/parsing of these flags. If more of these flags |
149 | // are added, the MIR printing/parsing code will need to be updated as well. |
150 | MOTargetFlag1 = 1u << 6, |
151 | MOTargetFlag2 = 1u << 7, |
152 | MOTargetFlag3 = 1u << 8, |
153 | |
154 | LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ MOTargetFlag3)LLVM_BITMASK_LARGEST_ENUMERATOR = MOTargetFlag3 |
155 | }; |
156 | |
157 | private: |
158 | /// Atomic information for this memory operation. |
159 | struct MachineAtomicInfo { |
160 | /// Synchronization scope ID for this memory operation. |
161 | unsigned SSID : 8; // SyncScope::ID |
162 | /// Atomic ordering requirements for this memory operation. For cmpxchg |
163 | /// atomic operations, atomic ordering requirements when store occurs. |
164 | unsigned Ordering : 4; // enum AtomicOrdering |
165 | /// For cmpxchg atomic operations, atomic ordering requirements when store |
166 | /// does not occur. |
167 | unsigned FailureOrdering : 4; // enum AtomicOrdering |
168 | }; |
169 | |
170 | MachinePointerInfo PtrInfo; |
171 | |
172 | /// Track the memory type of the access. An access size which is unknown or |
173 | /// too large to be represented by LLT should use the invalid LLT. |
174 | LLT MemoryType; |
175 | |
176 | Flags FlagVals; |
177 | Align BaseAlign; |
178 | MachineAtomicInfo AtomicInfo; |
179 | AAMDNodes AAInfo; |
180 | const MDNode *Ranges; |
181 | |
182 | public: |
183 | /// Construct a MachineMemOperand object with the specified PtrInfo, flags, |
184 | /// size, and base alignment. For atomic operations the synchronization scope |
185 | /// and atomic ordering requirements must also be specified. For cmpxchg |
186 | /// atomic operations the atomic ordering requirements when store does not |
187 | /// occur must also be specified. |
188 | MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s, |
189 | Align a, const AAMDNodes &AAInfo = AAMDNodes(), |
190 | const MDNode *Ranges = nullptr, |
191 | SyncScope::ID SSID = SyncScope::System, |
192 | AtomicOrdering Ordering = AtomicOrdering::NotAtomic, |
193 | AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); |
194 | MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, LLT type, Align a, |
195 | const AAMDNodes &AAInfo = AAMDNodes(), |
196 | const MDNode *Ranges = nullptr, |
197 | SyncScope::ID SSID = SyncScope::System, |
198 | AtomicOrdering Ordering = AtomicOrdering::NotAtomic, |
199 | AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); |
200 | |
201 | const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } |
202 | |
203 | /// Return the base address of the memory access. This may either be a normal |
204 | /// LLVM IR Value, or one of the special values used in CodeGen. |
205 | /// Special values are those obtained via |
206 | /// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and |
207 | /// other PseudoSourceValue member functions which return objects which stand |
208 | /// for frame/stack pointer relative references and other special references |
209 | /// which are not representable in the high-level IR. |
210 | const Value *getValue() const { |
211 | return dyn_cast_if_present<const Value *>(PtrInfo.V); |
212 | } |
213 | |
214 | const PseudoSourceValue *getPseudoValue() const { |
215 | return dyn_cast_if_present<const PseudoSourceValue *>(PtrInfo.V); |
216 | } |
217 | |
218 | const void *getOpaqueValue() const { return PtrInfo.V.getOpaqueValue(); } |
219 | |
220 | /// Return the raw flags of the source value, \see Flags. |
221 | Flags getFlags() const { return FlagVals; } |
222 | |
223 | /// Bitwise OR the current flags with the given flags. |
224 | void setFlags(Flags f) { FlagVals |= f; } |
225 | |
226 | /// For normal values, this is a byte offset added to the base address. |
227 | /// For PseudoSourceValue::FPRel values, this is the FrameIndex number. |
228 | int64_t getOffset() const { return PtrInfo.Offset; } |
229 | |
230 | unsigned getAddrSpace() const { return PtrInfo.getAddrSpace(); } |
231 | |
232 | /// Return the memory type of the memory reference. This should only be relied |
233 | /// on for GlobalISel G_* operation legalization. |
234 | LLT getMemoryType() const { return MemoryType; } |
235 | |
236 | /// Return the size in bytes of the memory reference. |
237 | uint64_t getSize() const { |
238 | return MemoryType.isValid() ? MemoryType.getSizeInBytes() : ~UINT64_C(0)0UL; |
239 | } |
240 | |
241 | /// Return the size in bits of the memory reference. |
242 | uint64_t getSizeInBits() const { |
243 | return MemoryType.isValid() ? MemoryType.getSizeInBits() : ~UINT64_C(0)0UL; |
244 | } |
245 | |
246 | LLT getType() const { |
247 | return MemoryType; |
248 | } |
249 | |
250 | /// Return the minimum known alignment in bytes of the actual memory |
251 | /// reference. |
252 | Align getAlign() const; |
253 | |
254 | /// Return the minimum known alignment in bytes of the base address, without |
255 | /// the offset. |
256 | Align getBaseAlign() const { return BaseAlign; } |
257 | |
258 | /// Return the AA tags for the memory reference. |
259 | AAMDNodes getAAInfo() const { return AAInfo; } |
260 | |
261 | /// Return the range tag for the memory reference. |
262 | const MDNode *getRanges() const { return Ranges; } |
263 | |
264 | /// Returns the synchronization scope ID for this memory operation. |
265 | SyncScope::ID getSyncScopeID() const { |
266 | return static_cast<SyncScope::ID>(AtomicInfo.SSID); |
267 | } |
268 | |
269 | /// Return the atomic ordering requirements for this memory operation. For |
270 | /// cmpxchg atomic operations, return the atomic ordering requirements when |
271 | /// store occurs. |
272 | AtomicOrdering getSuccessOrdering() const { |
273 | return static_cast<AtomicOrdering>(AtomicInfo.Ordering); |
274 | } |
275 | |
276 | /// For cmpxchg atomic operations, return the atomic ordering requirements |
277 | /// when store does not occur. |
278 | AtomicOrdering getFailureOrdering() const { |
279 | return static_cast<AtomicOrdering>(AtomicInfo.FailureOrdering); |
280 | } |
281 | |
282 | /// Return a single atomic ordering that is at least as strong as both the |
283 | /// success and failure orderings for an atomic operation. (For operations |
284 | /// other than cmpxchg, this is equivalent to getSuccessOrdering().) |
285 | AtomicOrdering getMergedOrdering() const { |
286 | return getMergedAtomicOrdering(getSuccessOrdering(), getFailureOrdering()); |
287 | } |
288 | |
289 | bool isLoad() const { return FlagVals & MOLoad; } |
290 | bool isStore() const { return FlagVals & MOStore; } |
291 | bool isVolatile() const { return FlagVals & MOVolatile; } |
292 | bool isNonTemporal() const { return FlagVals & MONonTemporal; } |
293 | bool isDereferenceable() const { return FlagVals & MODereferenceable; } |
294 | bool isInvariant() const { return FlagVals & MOInvariant; } |
295 | |
296 | /// Returns true if this operation has an atomic ordering requirement of |
297 | /// unordered or higher, false otherwise. |
298 | bool isAtomic() const { |
299 | return getSuccessOrdering() != AtomicOrdering::NotAtomic; |
300 | } |
301 | |
302 | /// Returns true if this memory operation doesn't have any ordering |
303 | /// constraints other than normal aliasing. Volatile and (ordered) atomic |
304 | /// memory operations can't be reordered. |
305 | bool isUnordered() const { |
306 | return (getSuccessOrdering() == AtomicOrdering::NotAtomic || |
307 | getSuccessOrdering() == AtomicOrdering::Unordered) && |
308 | !isVolatile(); |
309 | } |
310 | |
311 | /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a |
312 | /// greater alignment. This must only be used when the new alignment applies |
313 | /// to all users of this MachineMemOperand. |
314 | void refineAlignment(const MachineMemOperand *MMO); |
315 | |
316 | /// Change the SourceValue for this MachineMemOperand. This should only be |
317 | /// used when an object is being relocated and all references to it are being |
318 | /// updated. |
319 | void setValue(const Value *NewSV) { PtrInfo.V = NewSV; } |
320 | void setValue(const PseudoSourceValue *NewSV) { PtrInfo.V = NewSV; } |
321 | void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; } |
322 | |
323 | /// Reset the tracked memory type. |
324 | void setType(LLT NewTy) { |
325 | MemoryType = NewTy; |
326 | } |
327 | |
328 | /// Profile - Gather unique data for the object. |
329 | /// |
330 | void Profile(FoldingSetNodeID &ID) const; |
331 | |
332 | /// Support for operator<<. |
333 | /// @{ |
334 | void print(raw_ostream &OS, ModuleSlotTracker &MST, |
335 | SmallVectorImpl<StringRef> &SSNs, const LLVMContext &Context, |
336 | const MachineFrameInfo *MFI, const TargetInstrInfo *TII) const; |
337 | /// @} |
338 | |
339 | friend bool operator==(const MachineMemOperand &LHS, |
340 | const MachineMemOperand &RHS) { |
341 | return LHS.getValue() == RHS.getValue() && |
342 | LHS.getPseudoValue() == RHS.getPseudoValue() && |
343 | LHS.getSize() == RHS.getSize() && |
344 | LHS.getOffset() == RHS.getOffset() && |
345 | LHS.getFlags() == RHS.getFlags() && |
346 | LHS.getAAInfo() == RHS.getAAInfo() && |
347 | LHS.getRanges() == RHS.getRanges() && |
348 | LHS.getAlign() == RHS.getAlign() && |
349 | LHS.getAddrSpace() == RHS.getAddrSpace(); |
350 | } |
351 | |
352 | friend bool operator!=(const MachineMemOperand &LHS, |
353 | const MachineMemOperand &RHS) { |
354 | return !(LHS == RHS); |
355 | } |
356 | }; |
357 | |
358 | } // End llvm namespace |
359 | |
360 | #endif |
1 | //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- 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 isa<X>(), cast<X>(), dyn_cast<X>(), |
10 | // cast_if_present<X>(), and dyn_cast_if_present<X>() templates. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_CASTING_H |
15 | #define LLVM_SUPPORT_CASTING_H |
16 | |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/type_traits.h" |
19 | #include <cassert> |
20 | #include <memory> |
21 | #include <optional> |
22 | #include <type_traits> |
23 | |
24 | namespace llvm { |
25 | |
26 | //===----------------------------------------------------------------------===// |
27 | // simplify_type |
28 | //===----------------------------------------------------------------------===// |
29 | |
30 | /// Define a template that can be specialized by smart pointers to reflect the |
31 | /// fact that they are automatically dereferenced, and are not involved with the |
32 | /// template selection process... the default implementation is a noop. |
33 | // TODO: rename this and/or replace it with other cast traits. |
34 | template <typename From> struct simplify_type { |
35 | using SimpleType = From; // The real type this represents... |
36 | |
37 | // An accessor to get the real value... |
38 | static SimpleType &getSimplifiedValue(From &Val) { return Val; } |
39 | }; |
40 | |
41 | template <typename From> struct simplify_type<const From> { |
42 | using NonConstSimpleType = typename simplify_type<From>::SimpleType; |
43 | using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type; |
44 | using RetType = |
45 | typename add_lvalue_reference_if_not_pointer<SimpleType>::type; |
46 | |
47 | static RetType getSimplifiedValue(const From &Val) { |
48 | return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)); |
49 | } |
50 | }; |
51 | |
52 | // TODO: add this namespace once everyone is switched to using the new |
53 | // interface. |
54 | // namespace detail { |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // isa_impl |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | // The core of the implementation of isa<X> is here; To and From should be |
61 | // the names of classes. This template can be specialized to customize the |
62 | // implementation of isa<> without rewriting it from scratch. |
63 | template <typename To, typename From, typename Enabler = void> struct isa_impl { |
64 | static inline bool doit(const From &Val) { return To::classof(&Val); } |
65 | }; |
66 | |
67 | // Always allow upcasts, and perform no dynamic check for them. |
68 | template <typename To, typename From> |
69 | struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> { |
70 | static inline bool doit(const From &) { return true; } |
71 | }; |
72 | |
73 | template <typename To, typename From> struct isa_impl_cl { |
74 | static inline bool doit(const From &Val) { |
75 | return isa_impl<To, From>::doit(Val); |
76 | } |
77 | }; |
78 | |
79 | template <typename To, typename From> struct isa_impl_cl<To, const From> { |
80 | static inline bool doit(const From &Val) { |
81 | return isa_impl<To, From>::doit(Val); |
82 | } |
83 | }; |
84 | |
85 | template <typename To, typename From> |
86 | struct isa_impl_cl<To, const std::unique_ptr<From>> { |
87 | static inline bool doit(const std::unique_ptr<From> &Val) { |
88 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 88, __extension__ __PRETTY_FUNCTION__ )); |
89 | return isa_impl_cl<To, From>::doit(*Val); |
90 | } |
91 | }; |
92 | |
93 | template <typename To, typename From> struct isa_impl_cl<To, From *> { |
94 | static inline bool doit(const From *Val) { |
95 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 95, __extension__ __PRETTY_FUNCTION__ )); |
96 | return isa_impl<To, From>::doit(*Val); |
97 | } |
98 | }; |
99 | |
100 | template <typename To, typename From> struct isa_impl_cl<To, From *const> { |
101 | static inline bool doit(const From *Val) { |
102 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 102, __extension__ __PRETTY_FUNCTION__ )); |
103 | return isa_impl<To, From>::doit(*Val); |
104 | } |
105 | }; |
106 | |
107 | template <typename To, typename From> struct isa_impl_cl<To, const From *> { |
108 | static inline bool doit(const From *Val) { |
109 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 109, __extension__ __PRETTY_FUNCTION__ )); |
110 | return isa_impl<To, From>::doit(*Val); |
111 | } |
112 | }; |
113 | |
114 | template <typename To, typename From> |
115 | struct isa_impl_cl<To, const From *const> { |
116 | static inline bool doit(const From *Val) { |
117 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 117, __extension__ __PRETTY_FUNCTION__ )); |
118 | return isa_impl<To, From>::doit(*Val); |
119 | } |
120 | }; |
121 | |
122 | template <typename To, typename From, typename SimpleFrom> |
123 | struct isa_impl_wrap { |
124 | // When From != SimplifiedType, we can simplify the type some more by using |
125 | // the simplify_type template. |
126 | static bool doit(const From &Val) { |
127 | return isa_impl_wrap<To, SimpleFrom, |
128 | typename simplify_type<SimpleFrom>::SimpleType>:: |
129 | doit(simplify_type<const From>::getSimplifiedValue(Val)); |
130 | } |
131 | }; |
132 | |
133 | template <typename To, typename FromTy> |
134 | struct isa_impl_wrap<To, FromTy, FromTy> { |
135 | // When From == SimpleType, we are as simple as we are going to get. |
136 | static bool doit(const FromTy &Val) { |
137 | return isa_impl_cl<To, FromTy>::doit(Val); |
138 | } |
139 | }; |
140 | |
141 | //===----------------------------------------------------------------------===// |
142 | // cast_retty + cast_retty_impl |
143 | //===----------------------------------------------------------------------===// |
144 | |
145 | template <class To, class From> struct cast_retty; |
146 | |
147 | // Calculate what type the 'cast' function should return, based on a requested |
148 | // type of To and a source type of From. |
149 | template <class To, class From> struct cast_retty_impl { |
150 | using ret_type = To &; // Normal case, return Ty& |
151 | }; |
152 | template <class To, class From> struct cast_retty_impl<To, const From> { |
153 | using ret_type = const To &; // Normal case, return Ty& |
154 | }; |
155 | |
156 | template <class To, class From> struct cast_retty_impl<To, From *> { |
157 | using ret_type = To *; // Pointer arg case, return Ty* |
158 | }; |
159 | |
160 | template <class To, class From> struct cast_retty_impl<To, const From *> { |
161 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
162 | }; |
163 | |
164 | template <class To, class From> struct cast_retty_impl<To, const From *const> { |
165 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
166 | }; |
167 | |
168 | template <class To, class From> |
169 | struct cast_retty_impl<To, std::unique_ptr<From>> { |
170 | private: |
171 | using PointerType = typename cast_retty_impl<To, From *>::ret_type; |
172 | using ResultType = std::remove_pointer_t<PointerType>; |
173 | |
174 | public: |
175 | using ret_type = std::unique_ptr<ResultType>; |
176 | }; |
177 | |
178 | template <class To, class From, class SimpleFrom> struct cast_retty_wrap { |
179 | // When the simplified type and the from type are not the same, use the type |
180 | // simplifier to reduce the type, then reuse cast_retty_impl to get the |
181 | // resultant type. |
182 | using ret_type = typename cast_retty<To, SimpleFrom>::ret_type; |
183 | }; |
184 | |
185 | template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> { |
186 | // When the simplified type is equal to the from type, use it directly. |
187 | using ret_type = typename cast_retty_impl<To, FromTy>::ret_type; |
188 | }; |
189 | |
190 | template <class To, class From> struct cast_retty { |
191 | using ret_type = typename cast_retty_wrap< |
192 | To, From, typename simplify_type<From>::SimpleType>::ret_type; |
193 | }; |
194 | |
195 | //===----------------------------------------------------------------------===// |
196 | // cast_convert_val |
197 | //===----------------------------------------------------------------------===// |
198 | |
199 | // Ensure the non-simple values are converted using the simplify_type template |
200 | // that may be specialized by smart pointers... |
201 | // |
202 | template <class To, class From, class SimpleFrom> struct cast_convert_val { |
203 | // This is not a simple type, use the template to simplify it... |
204 | static typename cast_retty<To, From>::ret_type doit(const From &Val) { |
205 | return cast_convert_val<To, SimpleFrom, |
206 | typename simplify_type<SimpleFrom>::SimpleType>:: |
207 | doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val))); |
208 | } |
209 | }; |
210 | |
211 | template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> { |
212 | // If it's a reference, switch to a pointer to do the cast and then deref it. |
213 | static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { |
214 | return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type> |
215 | *)&const_cast<FromTy &>(Val); |
216 | } |
217 | }; |
218 | |
219 | template <class To, class FromTy> |
220 | struct cast_convert_val<To, FromTy *, FromTy *> { |
221 | // If it's a pointer, we can use c-style casting directly. |
222 | static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) { |
223 | return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>( |
224 | Val); |
225 | } |
226 | }; |
227 | |
228 | //===----------------------------------------------------------------------===// |
229 | // is_simple_type |
230 | //===----------------------------------------------------------------------===// |
231 | |
232 | template <class X> struct is_simple_type { |
233 | static const bool value = |
234 | std::is_same_v<X, typename simplify_type<X>::SimpleType>; |
235 | }; |
236 | |
237 | // } // namespace detail |
238 | |
239 | //===----------------------------------------------------------------------===// |
240 | // CastIsPossible |
241 | //===----------------------------------------------------------------------===// |
242 | |
243 | /// This struct provides a way to check if a given cast is possible. It provides |
244 | /// a static function called isPossible that is used to check if a cast can be |
245 | /// performed. It should be overridden like this: |
246 | /// |
247 | /// template<> struct CastIsPossible<foo, bar> { |
248 | /// static inline bool isPossible(const bar &b) { |
249 | /// return bar.isFoo(); |
250 | /// } |
251 | /// }; |
252 | template <typename To, typename From, typename Enable = void> |
253 | struct CastIsPossible { |
254 | static inline bool isPossible(const From &f) { |
255 | return isa_impl_wrap< |
256 | To, const From, |
257 | typename simplify_type<const From>::SimpleType>::doit(f); |
258 | } |
259 | }; |
260 | |
261 | // Needed for optional unwrapping. This could be implemented with isa_impl, but |
262 | // we want to implement things in the new method and move old implementations |
263 | // over. In fact, some of the isa_impl templates should be moved over to |
264 | // CastIsPossible. |
265 | template <typename To, typename From> |
266 | struct CastIsPossible<To, std::optional<From>> { |
267 | static inline bool isPossible(const std::optional<From> &f) { |
268 | assert(f && "CastIsPossible::isPossible called on a nullopt!")(static_cast <bool> (f && "CastIsPossible::isPossible called on a nullopt!" ) ? void (0) : __assert_fail ("f && \"CastIsPossible::isPossible called on a nullopt!\"" , "llvm/include/llvm/Support/Casting.h", 268, __extension__ __PRETTY_FUNCTION__ )); |
269 | return isa_impl_wrap< |
270 | To, const From, |
271 | typename simplify_type<const From>::SimpleType>::doit(*f); |
272 | } |
273 | }; |
274 | |
275 | /// Upcasting (from derived to base) and casting from a type to itself should |
276 | /// always be possible. |
277 | template <typename To, typename From> |
278 | struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> { |
279 | static inline bool isPossible(const From &f) { return true; } |
280 | }; |
281 | |
282 | //===----------------------------------------------------------------------===// |
283 | // Cast traits |
284 | //===----------------------------------------------------------------------===// |
285 | |
286 | /// All of these cast traits are meant to be implementations for useful casts |
287 | /// that users may want to use that are outside the standard behavior. An |
288 | /// example of how to use a special cast called `CastTrait` is: |
289 | /// |
290 | /// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {}; |
291 | /// |
292 | /// Essentially, if your use case falls directly into one of the use cases |
293 | /// supported by a given cast trait, simply inherit your special CastInfo |
294 | /// directly from one of these to avoid having to reimplement the boilerplate |
295 | /// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also |
296 | /// provide a subset of those functions. |
297 | |
298 | /// This cast trait just provides castFailed for the specified `To` type to make |
299 | /// CastInfo specializations more declarative. In order to use this, the target |
300 | /// result type must be `To` and `To` must be constructible from `nullptr`. |
301 | template <typename To> struct NullableValueCastFailed { |
302 | static To castFailed() { return To(nullptr); } |
303 | }; |
304 | |
305 | /// This cast trait just provides the default implementation of doCastIfPossible |
306 | /// to make CastInfo specializations more declarative. The `Derived` template |
307 | /// parameter *must* be provided for forwarding castFailed and doCast. |
308 | template <typename To, typename From, typename Derived> |
309 | struct DefaultDoCastIfPossible { |
310 | static To doCastIfPossible(From f) { |
311 | if (!Derived::isPossible(f)) |
312 | return Derived::castFailed(); |
313 | return Derived::doCast(f); |
314 | } |
315 | }; |
316 | |
317 | namespace detail { |
318 | /// A helper to derive the type to use with `Self` for cast traits, when the |
319 | /// provided CRTP derived type is allowed to be void. |
320 | template <typename OptionalDerived, typename Default> |
321 | using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>, |
322 | Default, OptionalDerived>; |
323 | } // namespace detail |
324 | |
325 | /// This cast trait provides casting for the specific case of casting to a |
326 | /// value-typed object from a pointer-typed object. Note that `To` must be |
327 | /// nullable/constructible from a pointer to `From` to use this cast. |
328 | template <typename To, typename From, typename Derived = void> |
329 | struct ValueFromPointerCast |
330 | : public CastIsPossible<To, From *>, |
331 | public NullableValueCastFailed<To>, |
332 | public DefaultDoCastIfPossible< |
333 | To, From *, |
334 | detail::SelfType<Derived, ValueFromPointerCast<To, From>>> { |
335 | static inline To doCast(From *f) { return To(f); } |
336 | }; |
337 | |
338 | /// This cast trait provides std::unique_ptr casting. It has the semantics of |
339 | /// moving the contents of the input unique_ptr into the output unique_ptr |
340 | /// during the cast. It's also a good example of how to implement a move-only |
341 | /// cast. |
342 | template <typename To, typename From, typename Derived = void> |
343 | struct UniquePtrCast : public CastIsPossible<To, From *> { |
344 | using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>; |
345 | using CastResultType = std::unique_ptr< |
346 | std::remove_reference_t<typename cast_retty<To, From>::ret_type>>; |
347 | |
348 | static inline CastResultType doCast(std::unique_ptr<From> &&f) { |
349 | return CastResultType((typename CastResultType::element_type *)f.release()); |
350 | } |
351 | |
352 | static inline CastResultType castFailed() { return CastResultType(nullptr); } |
353 | |
354 | static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) { |
355 | if (!Self::isPossible(f)) |
356 | return castFailed(); |
357 | return doCast(f); |
358 | } |
359 | }; |
360 | |
361 | /// This cast trait provides std::optional<T> casting. This means that if you |
362 | /// have a value type, you can cast it to another value type and have dyn_cast |
363 | /// return an std::optional<T>. |
364 | template <typename To, typename From, typename Derived = void> |
365 | struct OptionalValueCast |
366 | : public CastIsPossible<To, From>, |
367 | public DefaultDoCastIfPossible< |
368 | std::optional<To>, From, |
369 | detail::SelfType<Derived, OptionalValueCast<To, From>>> { |
370 | static inline std::optional<To> castFailed() { return std::optional<To>{}; } |
371 | |
372 | static inline std::optional<To> doCast(const From &f) { return To(f); } |
373 | }; |
374 | |
375 | /// Provides a cast trait that strips `const` from types to make it easier to |
376 | /// implement a const-version of a non-const cast. It just removes boilerplate |
377 | /// and reduces the amount of code you as the user need to implement. You can |
378 | /// use it like this: |
379 | /// |
380 | /// template<> struct CastInfo<foo, bar> { |
381 | /// ...verbose implementation... |
382 | /// }; |
383 | /// |
384 | /// template<> struct CastInfo<foo, const bar> : public |
385 | /// ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {}; |
386 | /// |
387 | template <typename To, typename From, typename ForwardTo> |
388 | struct ConstStrippingForwardingCast { |
389 | // Remove the pointer if it exists, then we can get rid of consts/volatiles. |
390 | using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>; |
391 | // Now if it's a pointer, add it back. Otherwise, we want a ref. |
392 | using NonConstFrom = |
393 | std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>; |
394 | |
395 | static inline bool isPossible(const From &f) { |
396 | return ForwardTo::isPossible(const_cast<NonConstFrom>(f)); |
397 | } |
398 | |
399 | static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); } |
400 | |
401 | static inline decltype(auto) doCast(const From &f) { |
402 | return ForwardTo::doCast(const_cast<NonConstFrom>(f)); |
403 | } |
404 | |
405 | static inline decltype(auto) doCastIfPossible(const From &f) { |
406 | return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f)); |
407 | } |
408 | }; |
409 | |
410 | /// Provides a cast trait that uses a defined pointer to pointer cast as a base |
411 | /// for reference-to-reference casts. Note that it does not provide castFailed |
412 | /// and doCastIfPossible because a pointer-to-pointer cast would likely just |
413 | /// return `nullptr` which could cause nullptr dereference. You can use it like |
414 | /// this: |
415 | /// |
416 | /// template <> struct CastInfo<foo, bar *> { ... verbose implementation... }; |
417 | /// |
418 | /// template <> |
419 | /// struct CastInfo<foo, bar> |
420 | /// : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {}; |
421 | /// |
422 | template <typename To, typename From, typename ForwardTo> |
423 | struct ForwardToPointerCast { |
424 | static inline bool isPossible(const From &f) { |
425 | return ForwardTo::isPossible(&f); |
426 | } |
427 | |
428 | static inline decltype(auto) doCast(const From &f) { |
429 | return *ForwardTo::doCast(&f); |
430 | } |
431 | }; |
432 | |
433 | //===----------------------------------------------------------------------===// |
434 | // CastInfo |
435 | //===----------------------------------------------------------------------===// |
436 | |
437 | /// This struct provides a method for customizing the way a cast is performed. |
438 | /// It inherits from CastIsPossible, to support the case of declaring many |
439 | /// CastIsPossible specializations without having to specialize the full |
440 | /// CastInfo. |
441 | /// |
442 | /// In order to specialize different behaviors, specify different functions in |
443 | /// your CastInfo specialization. |
444 | /// For isa<> customization, provide: |
445 | /// |
446 | /// `static bool isPossible(const From &f)` |
447 | /// |
448 | /// For cast<> customization, provide: |
449 | /// |
450 | /// `static To doCast(const From &f)` |
451 | /// |
452 | /// For dyn_cast<> and the *_if_present<> variants' customization, provide: |
453 | /// |
454 | /// `static To castFailed()` and `static To doCastIfPossible(const From &f)` |
455 | /// |
456 | /// Your specialization might look something like this: |
457 | /// |
458 | /// template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> { |
459 | /// static inline foo doCast(const bar &b) { |
460 | /// return foo(const_cast<bar &>(b)); |
461 | /// } |
462 | /// static inline foo castFailed() { return foo(); } |
463 | /// static inline foo doCastIfPossible(const bar &b) { |
464 | /// if (!CastInfo<foo, bar>::isPossible(b)) |
465 | /// return castFailed(); |
466 | /// return doCast(b); |
467 | /// } |
468 | /// }; |
469 | |
470 | // The default implementations of CastInfo don't use cast traits for now because |
471 | // we need to specify types all over the place due to the current expected |
472 | // casting behavior and the way cast_retty works. New use cases can and should |
473 | // take advantage of the cast traits whenever possible! |
474 | |
475 | template <typename To, typename From, typename Enable = void> |
476 | struct CastInfo : public CastIsPossible<To, From> { |
477 | using Self = CastInfo<To, From, Enable>; |
478 | |
479 | using CastReturnType = typename cast_retty<To, From>::ret_type; |
480 | |
481 | static inline CastReturnType doCast(const From &f) { |
482 | return cast_convert_val< |
483 | To, From, |
484 | typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f)); |
485 | } |
486 | |
487 | // This assumes that you can construct the cast return type from `nullptr`. |
488 | // This is largely to support legacy use cases - if you don't want this |
489 | // behavior you should specialize CastInfo for your use case. |
490 | static inline CastReturnType castFailed() { return CastReturnType(nullptr); } |
491 | |
492 | static inline CastReturnType doCastIfPossible(const From &f) { |
493 | if (!Self::isPossible(f)) |
494 | return castFailed(); |
495 | return doCast(f); |
496 | } |
497 | }; |
498 | |
499 | /// This struct provides an overload for CastInfo where From has simplify_type |
500 | /// defined. This simply forwards to the appropriate CastInfo with the |
501 | /// simplified type/value, so you don't have to implement both. |
502 | template <typename To, typename From> |
503 | struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> { |
504 | using Self = CastInfo<To, From>; |
505 | using SimpleFrom = typename simplify_type<From>::SimpleType; |
506 | using SimplifiedSelf = CastInfo<To, SimpleFrom>; |
507 | |
508 | static inline bool isPossible(From &f) { |
509 | return SimplifiedSelf::isPossible( |
510 | simplify_type<From>::getSimplifiedValue(f)); |
511 | } |
512 | |
513 | static inline decltype(auto) doCast(From &f) { |
514 | return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f)); |
515 | } |
516 | |
517 | static inline decltype(auto) castFailed() { |
518 | return SimplifiedSelf::castFailed(); |
519 | } |
520 | |
521 | static inline decltype(auto) doCastIfPossible(From &f) { |
522 | return SimplifiedSelf::doCastIfPossible( |
523 | simplify_type<From>::getSimplifiedValue(f)); |
524 | } |
525 | }; |
526 | |
527 | //===----------------------------------------------------------------------===// |
528 | // Pre-specialized CastInfo |
529 | //===----------------------------------------------------------------------===// |
530 | |
531 | /// Provide a CastInfo specialized for std::unique_ptr. |
532 | template <typename To, typename From> |
533 | struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {}; |
534 | |
535 | /// Provide a CastInfo specialized for std::optional<From>. It's assumed that if |
536 | /// the input is std::optional<From> that the output can be std::optional<To>. |
537 | /// If that's not the case, specialize CastInfo for your use case. |
538 | template <typename To, typename From> |
539 | struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> { |
540 | }; |
541 | |
542 | /// isa<X> - Return true if the parameter to the template is an instance of one |
543 | /// of the template type arguments. Used like this: |
544 | /// |
545 | /// if (isa<Type>(myVal)) { ... } |
546 | /// if (isa<Type0, Type1, Type2>(myVal)) { ... } |
547 | template <typename To, typename From> |
548 | [[nodiscard]] inline bool isa(const From &Val) { |
549 | return CastInfo<To, const From>::isPossible(Val); |
550 | } |
551 | |
552 | template <typename First, typename Second, typename... Rest, typename From> |
553 | [[nodiscard]] inline bool isa(const From &Val) { |
554 | return isa<First>(Val) || isa<Second, Rest...>(Val); |
555 | } |
556 | |
557 | /// cast<X> - Return the argument parameter cast to the specified type. This |
558 | /// casting operator asserts that the type is correct, so it does not return |
559 | /// null on failure. It does not allow a null argument (use cast_if_present for |
560 | /// that). It is typically used like this: |
561 | /// |
562 | /// cast<Instruction>(myVal)->getParent() |
563 | |
564 | template <typename To, typename From> |
565 | [[nodiscard]] inline decltype(auto) cast(const From &Val) { |
566 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 566, __extension__ __PRETTY_FUNCTION__ )); |
567 | return CastInfo<To, const From>::doCast(Val); |
568 | } |
569 | |
570 | template <typename To, typename From> |
571 | [[nodiscard]] inline decltype(auto) cast(From &Val) { |
572 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 572, __extension__ __PRETTY_FUNCTION__ )); |
573 | return CastInfo<To, From>::doCast(Val); |
574 | } |
575 | |
576 | template <typename To, typename From> |
577 | [[nodiscard]] inline decltype(auto) cast(From *Val) { |
578 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 578, __extension__ __PRETTY_FUNCTION__ )); |
579 | return CastInfo<To, From *>::doCast(Val); |
580 | } |
581 | |
582 | template <typename To, typename From> |
583 | [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) { |
584 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 584, __extension__ __PRETTY_FUNCTION__ )); |
585 | return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val)); |
586 | } |
587 | |
588 | //===----------------------------------------------------------------------===// |
589 | // ValueIsPresent |
590 | //===----------------------------------------------------------------------===// |
591 | |
592 | template <typename T> |
593 | constexpr bool IsNullable = |
594 | std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>; |
595 | |
596 | /// ValueIsPresent provides a way to check if a value is, well, present. For |
597 | /// pointers, this is the equivalent of checking against nullptr, for Optionals |
598 | /// this is the equivalent of checking hasValue(). It also provides a method for |
599 | /// unwrapping a value (think calling .value() on an optional). |
600 | |
601 | // Generic values can't *not* be present. |
602 | template <typename T, typename Enable = void> struct ValueIsPresent { |
603 | using UnwrappedType = T; |
604 | static inline bool isPresent(const T &t) { return true; } |
605 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
606 | }; |
607 | |
608 | // Optional provides its own way to check if something is present. |
609 | template <typename T> struct ValueIsPresent<std::optional<T>> { |
610 | using UnwrappedType = T; |
611 | static inline bool isPresent(const std::optional<T> &t) { |
612 | return t.has_value(); |
613 | } |
614 | static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; } |
615 | }; |
616 | |
617 | // If something is "nullable" then we just compare it to nullptr to see if it |
618 | // exists. |
619 | template <typename T> |
620 | struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> { |
621 | using UnwrappedType = T; |
622 | static inline bool isPresent(const T &t) { return t != T(nullptr); } |
623 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
624 | }; |
625 | |
626 | namespace detail { |
627 | // Convenience function we can use to check if a value is present. Because of |
628 | // simplify_type, we have to call it on the simplified type for now. |
629 | template <typename T> inline bool isPresent(const T &t) { |
630 | return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent( |
631 | simplify_type<T>::getSimplifiedValue(const_cast<T &>(t))); |
632 | } |
633 | |
634 | // Convenience function we can use to unwrap a value. |
635 | template <typename T> inline decltype(auto) unwrapValue(T &t) { |
636 | return ValueIsPresent<T>::unwrapValue(t); |
637 | } |
638 | } // namespace detail |
639 | |
640 | /// dyn_cast<X> - Return the argument parameter cast to the specified type. This |
641 | /// casting operator returns null if the argument is of the wrong type, so it |
642 | /// can be used to test for a type as well as cast if successful. The value |
643 | /// passed in must be present, if not, use dyn_cast_if_present. This should be |
644 | /// used in the context of an if statement like this: |
645 | /// |
646 | /// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } |
647 | |
648 | template <typename To, typename From> |
649 | [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) { |
650 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 650, __extension__ __PRETTY_FUNCTION__ )); |
651 | return CastInfo<To, const From>::doCastIfPossible(Val); |
652 | } |
653 | |
654 | template <typename To, typename From> |
655 | [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) { |
656 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 656, __extension__ __PRETTY_FUNCTION__ )); |
657 | return CastInfo<To, From>::doCastIfPossible(Val); |
658 | } |
659 | |
660 | template <typename To, typename From> |
661 | [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) { |
662 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 662, __extension__ __PRETTY_FUNCTION__ )); |
663 | return CastInfo<To, From *>::doCastIfPossible(Val); |
664 | } |
665 | |
666 | template <typename To, typename From> |
667 | [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) { |
668 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 668, __extension__ __PRETTY_FUNCTION__ )); |
669 | return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible( |
670 | std::forward<std::unique_ptr<From> &&>(Val)); |
671 | } |
672 | |
673 | /// isa_and_present<X> - Functionally identical to isa, except that a null value |
674 | /// is accepted. |
675 | template <typename... X, class Y> |
676 | [[nodiscard]] inline bool isa_and_present(const Y &Val) { |
677 | if (!detail::isPresent(Val)) |
678 | return false; |
679 | return isa<X...>(Val); |
680 | } |
681 | |
682 | template <typename... X, class Y> |
683 | [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) { |
684 | return isa_and_present<X...>(Val); |
685 | } |
686 | |
687 | /// cast_if_present<X> - Functionally identical to cast, except that a null |
688 | /// value is accepted. |
689 | template <class X, class Y> |
690 | [[nodiscard]] inline auto cast_if_present(const Y &Val) { |
691 | if (!detail::isPresent(Val)) |
692 | return CastInfo<X, const Y>::castFailed(); |
693 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 693, __extension__ __PRETTY_FUNCTION__ )); |
694 | return cast<X>(detail::unwrapValue(Val)); |
695 | } |
696 | |
697 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) { |
698 | if (!detail::isPresent(Val)) |
699 | return CastInfo<X, Y>::castFailed(); |
700 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 700, __extension__ __PRETTY_FUNCTION__ )); |
701 | return cast<X>(detail::unwrapValue(Val)); |
702 | } |
703 | |
704 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) { |
705 | if (!detail::isPresent(Val)) |
706 | return CastInfo<X, Y *>::castFailed(); |
707 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 707, __extension__ __PRETTY_FUNCTION__ )); |
708 | return cast<X>(detail::unwrapValue(Val)); |
709 | } |
710 | |
711 | template <class X, class Y> |
712 | [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) { |
713 | if (!detail::isPresent(Val)) |
714 | return UniquePtrCast<X, Y>::castFailed(); |
715 | return UniquePtrCast<X, Y>::doCast(std::move(Val)); |
716 | } |
717 | |
718 | // Provide a forwarding from cast_or_null to cast_if_present for current |
719 | // users. This is deprecated and will be removed in a future patch, use |
720 | // cast_if_present instead. |
721 | template <class X, class Y> auto cast_or_null(const Y &Val) { |
722 | return cast_if_present<X>(Val); |
723 | } |
724 | |
725 | template <class X, class Y> auto cast_or_null(Y &Val) { |
726 | return cast_if_present<X>(Val); |
727 | } |
728 | |
729 | template <class X, class Y> auto cast_or_null(Y *Val) { |
730 | return cast_if_present<X>(Val); |
731 | } |
732 | |
733 | template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) { |
734 | return cast_if_present<X>(std::move(Val)); |
735 | } |
736 | |
737 | /// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a |
738 | /// null (or none in the case of optionals) value is accepted. |
739 | template <class X, class Y> auto dyn_cast_if_present(const Y &Val) { |
740 | if (!detail::isPresent(Val)) |
741 | return CastInfo<X, const Y>::castFailed(); |
742 | return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val)); |
743 | } |
744 | |
745 | template <class X, class Y> auto dyn_cast_if_present(Y &Val) { |
746 | if (!detail::isPresent(Val)) |
747 | return CastInfo<X, Y>::castFailed(); |
748 | return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val)); |
749 | } |
750 | |
751 | template <class X, class Y> auto dyn_cast_if_present(Y *Val) { |
752 | if (!detail::isPresent(Val)) |
753 | return CastInfo<X, Y *>::castFailed(); |
754 | return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val)); |
755 | } |
756 | |
757 | // Forwards to dyn_cast_if_present to avoid breaking current users. This is |
758 | // deprecated and will be removed in a future patch, use |
759 | // cast_if_present instead. |
760 | template <class X, class Y> auto dyn_cast_or_null(const Y &Val) { |
761 | return dyn_cast_if_present<X>(Val); |
762 | } |
763 | |
764 | template <class X, class Y> auto dyn_cast_or_null(Y &Val) { |
765 | return dyn_cast_if_present<X>(Val); |
766 | } |
767 | |
768 | template <class X, class Y> auto dyn_cast_or_null(Y *Val) { |
769 | return dyn_cast_if_present<X>(Val); |
770 | } |
771 | |
772 | /// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>, |
773 | /// taking ownership of the input pointer iff isa<X>(Val) is true. If the |
774 | /// cast is successful, From refers to nullptr on exit and the casted value |
775 | /// is returned. If the cast is unsuccessful, the function returns nullptr |
776 | /// and From is unchanged. |
777 | template <class X, class Y> |
778 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
779 | unique_dyn_cast(std::unique_ptr<Y> &Val) { |
780 | if (!isa<X>(Val)) |
781 | return nullptr; |
782 | return cast<X>(std::move(Val)); |
783 | } |
784 | |
785 | template <class X, class Y> |
786 | [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) { |
787 | return unique_dyn_cast<X, Y>(Val); |
788 | } |
789 | |
790 | // unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, |
791 | // except that a null value is accepted. |
792 | template <class X, class Y> |
793 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
794 | unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) { |
795 | if (!Val) |
796 | return nullptr; |
797 | return unique_dyn_cast<X, Y>(Val); |
798 | } |
799 | |
800 | template <class X, class Y> |
801 | [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) { |
802 | return unique_dyn_cast_or_null<X, Y>(Val); |
803 | } |
804 | |
805 | } // end namespace llvm |
806 | |
807 | #endif // LLVM_SUPPORT_CASTING_H |
1 | //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- 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 | /// \file |
10 | /// This file defines the PointerUnion class, which is a discriminated union of |
11 | /// pointer types. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_ADT_POINTERUNION_H |
16 | #define LLVM_ADT_POINTERUNION_H |
17 | |
18 | #include "llvm/ADT/DenseMapInfo.h" |
19 | #include "llvm/ADT/PointerIntPair.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/PointerLikeTypeTraits.h" |
23 | #include <algorithm> |
24 | #include <cassert> |
25 | #include <cstddef> |
26 | #include <cstdint> |
27 | |
28 | namespace llvm { |
29 | |
30 | namespace pointer_union_detail { |
31 | /// Determine the number of bits required to store integers with values < n. |
32 | /// This is ceil(log2(n)). |
33 | constexpr int bitsRequired(unsigned n) { |
34 | return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0; |
35 | } |
36 | |
37 | template <typename... Ts> constexpr int lowBitsAvailable() { |
38 | return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}); |
39 | } |
40 | |
41 | /// Find the first type in a list of types. |
42 | template <typename T, typename...> struct GetFirstType { |
43 | using type = T; |
44 | }; |
45 | |
46 | /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion |
47 | /// for the template arguments. |
48 | template <typename ...PTs> class PointerUnionUIntTraits { |
49 | public: |
50 | static inline void *getAsVoidPointer(void *P) { return P; } |
51 | static inline void *getFromVoidPointer(void *P) { return P; } |
52 | static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>(); |
53 | }; |
54 | |
55 | template <typename Derived, typename ValTy, int I, typename ...Types> |
56 | class PointerUnionMembers; |
57 | |
58 | template <typename Derived, typename ValTy, int I> |
59 | class PointerUnionMembers<Derived, ValTy, I> { |
60 | protected: |
61 | ValTy Val; |
62 | PointerUnionMembers() = default; |
63 | PointerUnionMembers(ValTy Val) : Val(Val) {} |
64 | |
65 | friend struct PointerLikeTypeTraits<Derived>; |
66 | }; |
67 | |
68 | template <typename Derived, typename ValTy, int I, typename Type, |
69 | typename ...Types> |
70 | class PointerUnionMembers<Derived, ValTy, I, Type, Types...> |
71 | : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> { |
72 | using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>; |
73 | public: |
74 | using Base::Base; |
75 | PointerUnionMembers() = default; |
76 | PointerUnionMembers(Type V) |
77 | : Base(ValTy(const_cast<void *>( |
78 | PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
79 | I)) {} |
80 | |
81 | using Base::operator=; |
82 | Derived &operator=(Type V) { |
83 | this->Val = ValTy( |
84 | const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
85 | I); |
86 | return static_cast<Derived &>(*this); |
87 | }; |
88 | }; |
89 | } |
90 | |
91 | // This is a forward declaration of CastInfoPointerUnionImpl |
92 | // Refer to its definition below for further details |
93 | template <typename... PTs> struct CastInfoPointerUnionImpl; |
94 | /// A discriminated union of two or more pointer types, with the discriminator |
95 | /// in the low bit of the pointer. |
96 | /// |
97 | /// This implementation is extremely efficient in space due to leveraging the |
98 | /// low bits of the pointer, while exposing a natural and type-safe API. |
99 | /// |
100 | /// Common use patterns would be something like this: |
101 | /// PointerUnion<int*, float*> P; |
102 | /// P = (int*)0; |
103 | /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" |
104 | /// X = P.get<int*>(); // ok. |
105 | /// Y = P.get<float*>(); // runtime assertion failure. |
106 | /// Z = P.get<double*>(); // compile time failure. |
107 | /// P = (float*)0; |
108 | /// Y = P.get<float*>(); // ok. |
109 | /// X = P.get<int*>(); // runtime assertion failure. |
110 | /// PointerUnion<int*, int*> Q; // compile time failure. |
111 | template <typename... PTs> |
112 | class PointerUnion |
113 | : public pointer_union_detail::PointerUnionMembers< |
114 | PointerUnion<PTs...>, |
115 | PointerIntPair< |
116 | void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int, |
117 | pointer_union_detail::PointerUnionUIntTraits<PTs...>>, |
118 | 0, PTs...> { |
119 | static_assert(TypesAreDistinct<PTs...>::value, |
120 | "PointerUnion alternative types cannot be repeated"); |
121 | // The first type is special because we want to directly cast a pointer to a |
122 | // default-initialized union to a pointer to the first type. But we don't |
123 | // want PointerUnion to be a 'template <typename First, typename ...Rest>' |
124 | // because it's much more convenient to have a name for the whole pack. So |
125 | // split off the first type here. |
126 | using First = TypeAtIndex<0, PTs...>; |
127 | using Base = typename PointerUnion::PointerUnionMembers; |
128 | |
129 | /// This is needed to give the CastInfo implementation below access |
130 | /// to protected members. |
131 | /// Refer to its definition for further details. |
132 | friend struct CastInfoPointerUnionImpl<PTs...>; |
133 | |
134 | public: |
135 | PointerUnion() = default; |
136 | |
137 | PointerUnion(std::nullptr_t) : PointerUnion() {} |
138 | using Base::Base; |
139 | |
140 | /// Test if the pointer held in the union is null, regardless of |
141 | /// which type it is. |
142 | bool isNull() const { return !this->Val.getPointer(); } |
143 | |
144 | explicit operator bool() const { return !isNull(); } |
145 | |
146 | // FIXME: Replace the uses of is(), get() and dyn_cast() with |
147 | // isa<T>, cast<T> and the llvm::dyn_cast<T> |
148 | |
149 | /// Test if the Union currently holds the type matching T. |
150 | template <typename T> inline bool is() const { return isa<T>(*this); } |
151 | |
152 | /// Returns the value of the specified pointer type. |
153 | /// |
154 | /// If the specified pointer type is incorrect, assert. |
155 | template <typename T> inline T get() const { |
156 | assert(isa<T>(*this) && "Invalid accessor called")(static_cast <bool> (isa<T>(*this) && "Invalid accessor called" ) ? void (0) : __assert_fail ("isa<T>(*this) && \"Invalid accessor called\"" , "llvm/include/llvm/ADT/PointerUnion.h", 156, __extension__ __PRETTY_FUNCTION__ )); |
157 | return cast<T>(*this); |
158 | } |
159 | |
160 | /// Returns the current pointer if it is of the specified pointer type, |
161 | /// otherwise returns null. |
162 | template <typename T> inline T dyn_cast() const { |
163 | return llvm::dyn_cast_if_present<T>(*this); |
164 | } |
165 | |
166 | /// If the union is set to the first pointer type get an address pointing to |
167 | /// it. |
168 | First const *getAddrOfPtr1() const { |
169 | return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); |
170 | } |
171 | |
172 | /// If the union is set to the first pointer type get an address pointing to |
173 | /// it. |
174 | First *getAddrOfPtr1() { |
175 | assert(isa<First>(*this) && "Val is not the first pointer")(static_cast <bool> (isa<First>(*this) && "Val is not the first pointer") ? void (0) : __assert_fail ( "isa<First>(*this) && \"Val is not the first pointer\"" , "llvm/include/llvm/ADT/PointerUnion.h", 175, __extension__ __PRETTY_FUNCTION__ )); |
176 | assert((static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(cast<First>(*this)) == this->Val. getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
177 | PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) ==(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(cast<First>(*this)) == this->Val. getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
178 | this->Val.getPointer() &&(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(cast<First>(*this)) == this->Val. getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
179 | "Can't get the address because PointerLikeTypeTraits changes the ptr")(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(cast<First>(*this)) == this->Val. getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )); |
180 | return const_cast<First *>( |
181 | reinterpret_cast<const First *>(this->Val.getAddrOfPointer())); |
182 | } |
183 | |
184 | /// Assignment from nullptr which just clears the union. |
185 | const PointerUnion &operator=(std::nullptr_t) { |
186 | this->Val.initWithPointer(nullptr); |
187 | return *this; |
188 | } |
189 | |
190 | /// Assignment from elements of the union. |
191 | using Base::operator=; |
192 | |
193 | void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } |
194 | static inline PointerUnion getFromOpaqueValue(void *VP) { |
195 | PointerUnion V; |
196 | V.Val = decltype(V.Val)::getFromOpaqueValue(VP); |
197 | return V; |
198 | } |
199 | }; |
200 | |
201 | template <typename ...PTs> |
202 | bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
203 | return lhs.getOpaqueValue() == rhs.getOpaqueValue(); |
204 | } |
205 | |
206 | template <typename ...PTs> |
207 | bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
208 | return lhs.getOpaqueValue() != rhs.getOpaqueValue(); |
209 | } |
210 | |
211 | template <typename ...PTs> |
212 | bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
213 | return lhs.getOpaqueValue() < rhs.getOpaqueValue(); |
214 | } |
215 | |
216 | /// We can't (at least, at this moment with C++14) declare CastInfo |
217 | /// as a friend of PointerUnion like this: |
218 | /// ``` |
219 | /// template<typename To> |
220 | /// friend struct CastInfo<To, PointerUnion<PTs...>>; |
221 | /// ``` |
222 | /// The compiler complains 'Partial specialization cannot be declared as a |
223 | /// friend'. |
224 | /// So we define this struct to be a bridge between CastInfo and |
225 | /// PointerUnion. |
226 | template <typename... PTs> struct CastInfoPointerUnionImpl { |
227 | using From = PointerUnion<PTs...>; |
228 | |
229 | template <typename To> static inline bool isPossible(From &F) { |
230 | return F.Val.getInt() == FirstIndexOfType<To, PTs...>::value; |
231 | } |
232 | |
233 | template <typename To> static To doCast(From &F) { |
234 | assert(isPossible<To>(F) && "cast to an incompatible type !")(static_cast <bool> (isPossible<To>(F) && "cast to an incompatible type !") ? void (0) : __assert_fail ("isPossible<To>(F) && \"cast to an incompatible type !\"" , "llvm/include/llvm/ADT/PointerUnion.h", 234, __extension__ __PRETTY_FUNCTION__ )); |
235 | return PointerLikeTypeTraits<To>::getFromVoidPointer(F.Val.getPointer()); |
236 | } |
237 | }; |
238 | |
239 | // Specialization of CastInfo for PointerUnion |
240 | template <typename To, typename... PTs> |
241 | struct CastInfo<To, PointerUnion<PTs...>> |
242 | : public DefaultDoCastIfPossible<To, PointerUnion<PTs...>, |
243 | CastInfo<To, PointerUnion<PTs...>>> { |
244 | using From = PointerUnion<PTs...>; |
245 | using Impl = CastInfoPointerUnionImpl<PTs...>; |
246 | |
247 | static inline bool isPossible(From &f) { |
248 | return Impl::template isPossible<To>(f); |
249 | } |
250 | |
251 | static To doCast(From &f) { return Impl::template doCast<To>(f); } |
252 | |
253 | static inline To castFailed() { return To(); } |
254 | }; |
255 | |
256 | template <typename To, typename... PTs> |
257 | struct CastInfo<To, const PointerUnion<PTs...>> |
258 | : public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>, |
259 | CastInfo<To, PointerUnion<PTs...>>> { |
260 | }; |
261 | |
262 | // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has |
263 | // # low bits available = min(PT1bits,PT2bits)-1. |
264 | template <typename ...PTs> |
265 | struct PointerLikeTypeTraits<PointerUnion<PTs...>> { |
266 | static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { |
267 | return P.getOpaqueValue(); |
268 | } |
269 | |
270 | static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { |
271 | return PointerUnion<PTs...>::getFromOpaqueValue(P); |
272 | } |
273 | |
274 | // The number of bits available are the min of the pointer types minus the |
275 | // bits needed for the discriminator. |
276 | static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype( |
277 | PointerUnion<PTs...>::Val)>::NumLowBitsAvailable; |
278 | }; |
279 | |
280 | // Teach DenseMap how to use PointerUnions as keys. |
281 | template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { |
282 | using Union = PointerUnion<PTs...>; |
283 | using FirstInfo = |
284 | DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; |
285 | |
286 | static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } |
287 | |
288 | static inline Union getTombstoneKey() { |
289 | return Union(FirstInfo::getTombstoneKey()); |
290 | } |
291 | |
292 | static unsigned getHashValue(const Union &UnionVal) { |
293 | intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); |
294 | return DenseMapInfo<intptr_t>::getHashValue(key); |
295 | } |
296 | |
297 | static bool isEqual(const Union &LHS, const Union &RHS) { |
298 | return LHS == RHS; |
299 | } |
300 | }; |
301 | |
302 | } // end namespace llvm |
303 | |
304 | #endif // LLVM_ADT_POINTERUNION_H |