1044eb2f6SDimitry Andric //===- lib/CodeGen/MachineOperand.cpp -------------------------------------===//
2044eb2f6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6044eb2f6SDimitry Andric //
7044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
8044eb2f6SDimitry Andric //
9044eb2f6SDimitry Andric /// \file Methods common to all machine operands.
10044eb2f6SDimitry Andric //
11044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
12044eb2f6SDimitry Andric
13044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
14b1c73532SDimitry Andric #include "llvm/ADT/StableHashing.h"
15eb11fae6SDimitry Andric #include "llvm/ADT/StringExtras.h"
16044eb2f6SDimitry Andric #include "llvm/Analysis/Loads.h"
17706b4fc4SDimitry Andric #include "llvm/CodeGen/MIRFormatter.h"
18044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
20044eb2f6SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21b1c73532SDimitry Andric #include "llvm/CodeGen/PseudoSourceValueManager.h"
22044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
23044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
24eb11fae6SDimitry Andric #include "llvm/Config/llvm-config.h"
25044eb2f6SDimitry Andric #include "llvm/IR/Constants.h"
26044eb2f6SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
27cfca06d7SDimitry Andric #include "llvm/IR/Instructions.h"
28044eb2f6SDimitry Andric #include "llvm/IR/ModuleSlotTracker.h"
29e6d15924SDimitry Andric #include "llvm/MC/MCDwarf.h"
30044eb2f6SDimitry Andric #include "llvm/Target/TargetIntrinsicInfo.h"
31044eb2f6SDimitry Andric #include "llvm/Target/TargetMachine.h"
32e3b55780SDimitry Andric #include <optional>
33044eb2f6SDimitry Andric
34044eb2f6SDimitry Andric using namespace llvm;
35044eb2f6SDimitry Andric
36044eb2f6SDimitry Andric static cl::opt<int>
37044eb2f6SDimitry Andric PrintRegMaskNumRegs("print-regmask-num-regs",
38044eb2f6SDimitry Andric cl::desc("Number of registers to limit to when "
39044eb2f6SDimitry Andric "printing regmask operands in IR dumps. "
40044eb2f6SDimitry Andric "unlimited = -1"),
41044eb2f6SDimitry Andric cl::init(32), cl::Hidden);
42044eb2f6SDimitry Andric
getMFIfAvailable(const MachineOperand & MO)43044eb2f6SDimitry Andric static const MachineFunction *getMFIfAvailable(const MachineOperand &MO) {
44044eb2f6SDimitry Andric if (const MachineInstr *MI = MO.getParent())
45044eb2f6SDimitry Andric if (const MachineBasicBlock *MBB = MI->getParent())
46044eb2f6SDimitry Andric if (const MachineFunction *MF = MBB->getParent())
47044eb2f6SDimitry Andric return MF;
48044eb2f6SDimitry Andric return nullptr;
49044eb2f6SDimitry Andric }
50e3b55780SDimitry Andric
getMFIfAvailable(MachineOperand & MO)51044eb2f6SDimitry Andric static MachineFunction *getMFIfAvailable(MachineOperand &MO) {
52044eb2f6SDimitry Andric return const_cast<MachineFunction *>(
53044eb2f6SDimitry Andric getMFIfAvailable(const_cast<const MachineOperand &>(MO)));
54044eb2f6SDimitry Andric }
55044eb2f6SDimitry Andric
getOperandNo() const567fa27ce4SDimitry Andric unsigned MachineOperand::getOperandNo() const {
577fa27ce4SDimitry Andric assert(getParent() && "Operand does not belong to any instruction!");
587fa27ce4SDimitry Andric return getParent()->getOperandNo(this);
597fa27ce4SDimitry Andric }
607fa27ce4SDimitry Andric
setReg(Register Reg)611d5ae102SDimitry Andric void MachineOperand::setReg(Register Reg) {
62044eb2f6SDimitry Andric if (getReg() == Reg)
63044eb2f6SDimitry Andric return; // No change.
64044eb2f6SDimitry Andric
65eb11fae6SDimitry Andric // Clear the IsRenamable bit to keep it conservatively correct.
66eb11fae6SDimitry Andric IsRenamable = false;
67eb11fae6SDimitry Andric
68044eb2f6SDimitry Andric // Otherwise, we have to change the register. If this operand is embedded
69044eb2f6SDimitry Andric // into a machine function, we need to update the old and new register's
70044eb2f6SDimitry Andric // use/def lists.
71044eb2f6SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) {
72044eb2f6SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo();
73044eb2f6SDimitry Andric MRI.removeRegOperandFromUseList(this);
74044eb2f6SDimitry Andric SmallContents.RegNo = Reg;
75044eb2f6SDimitry Andric MRI.addRegOperandToUseList(this);
76044eb2f6SDimitry Andric return;
77044eb2f6SDimitry Andric }
78044eb2f6SDimitry Andric
79044eb2f6SDimitry Andric // Otherwise, just change the register, no problem. :)
80044eb2f6SDimitry Andric SmallContents.RegNo = Reg;
81044eb2f6SDimitry Andric }
82044eb2f6SDimitry Andric
substVirtReg(Register Reg,unsigned SubIdx,const TargetRegisterInfo & TRI)831d5ae102SDimitry Andric void MachineOperand::substVirtReg(Register Reg, unsigned SubIdx,
84044eb2f6SDimitry Andric const TargetRegisterInfo &TRI) {
851d5ae102SDimitry Andric assert(Reg.isVirtual());
86044eb2f6SDimitry Andric if (SubIdx && getSubReg())
87044eb2f6SDimitry Andric SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg());
88044eb2f6SDimitry Andric setReg(Reg);
89044eb2f6SDimitry Andric if (SubIdx)
90044eb2f6SDimitry Andric setSubReg(SubIdx);
91044eb2f6SDimitry Andric }
92044eb2f6SDimitry Andric
substPhysReg(MCRegister Reg,const TargetRegisterInfo & TRI)931d5ae102SDimitry Andric void MachineOperand::substPhysReg(MCRegister Reg, const TargetRegisterInfo &TRI) {
94b60736ecSDimitry Andric assert(Register::isPhysicalRegister(Reg));
95044eb2f6SDimitry Andric if (getSubReg()) {
96044eb2f6SDimitry Andric Reg = TRI.getSubReg(Reg, getSubReg());
97044eb2f6SDimitry Andric // Note that getSubReg() may return 0 if the sub-register doesn't exist.
98044eb2f6SDimitry Andric // That won't happen in legal code.
99044eb2f6SDimitry Andric setSubReg(0);
100044eb2f6SDimitry Andric if (isDef())
101044eb2f6SDimitry Andric setIsUndef(false);
102044eb2f6SDimitry Andric }
103044eb2f6SDimitry Andric setReg(Reg);
104044eb2f6SDimitry Andric }
105044eb2f6SDimitry Andric
106044eb2f6SDimitry Andric /// Change a def to a use, or a use to a def.
setIsDef(bool Val)107044eb2f6SDimitry Andric void MachineOperand::setIsDef(bool Val) {
108044eb2f6SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor");
109044eb2f6SDimitry Andric assert((!Val || !isDebug()) && "Marking a debug operation as def");
110044eb2f6SDimitry Andric if (IsDef == Val)
111044eb2f6SDimitry Andric return;
112044eb2f6SDimitry Andric assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported");
113044eb2f6SDimitry Andric // MRI may keep uses and defs in different list positions.
114044eb2f6SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) {
115044eb2f6SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo();
116044eb2f6SDimitry Andric MRI.removeRegOperandFromUseList(this);
117044eb2f6SDimitry Andric IsDef = Val;
118044eb2f6SDimitry Andric MRI.addRegOperandToUseList(this);
119044eb2f6SDimitry Andric return;
120044eb2f6SDimitry Andric }
121044eb2f6SDimitry Andric IsDef = Val;
122044eb2f6SDimitry Andric }
123044eb2f6SDimitry Andric
isRenamable() const124044eb2f6SDimitry Andric bool MachineOperand::isRenamable() const {
125044eb2f6SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor");
126e3b55780SDimitry Andric assert(getReg().isPhysical() &&
127044eb2f6SDimitry Andric "isRenamable should only be checked on physical registers");
128eb11fae6SDimitry Andric if (!IsRenamable)
129eb11fae6SDimitry Andric return false;
130eb11fae6SDimitry Andric
131eb11fae6SDimitry Andric const MachineInstr *MI = getParent();
132eb11fae6SDimitry Andric if (!MI)
133eb11fae6SDimitry Andric return true;
134eb11fae6SDimitry Andric
135eb11fae6SDimitry Andric if (isDef())
136eb11fae6SDimitry Andric return !MI->hasExtraDefRegAllocReq(MachineInstr::IgnoreBundle);
137eb11fae6SDimitry Andric
138eb11fae6SDimitry Andric assert(isUse() && "Reg is not def or use");
139eb11fae6SDimitry Andric return !MI->hasExtraSrcRegAllocReq(MachineInstr::IgnoreBundle);
140044eb2f6SDimitry Andric }
141044eb2f6SDimitry Andric
setIsRenamable(bool Val)142044eb2f6SDimitry Andric void MachineOperand::setIsRenamable(bool Val) {
143044eb2f6SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor");
144e3b55780SDimitry Andric assert(getReg().isPhysical() &&
145044eb2f6SDimitry Andric "setIsRenamable should only be called on physical registers");
146044eb2f6SDimitry Andric IsRenamable = Val;
147044eb2f6SDimitry Andric }
148044eb2f6SDimitry Andric
149044eb2f6SDimitry Andric // If this operand is currently a register operand, and if this is in a
150044eb2f6SDimitry Andric // function, deregister the operand from the register's use/def list.
removeRegFromUses()151044eb2f6SDimitry Andric void MachineOperand::removeRegFromUses() {
152044eb2f6SDimitry Andric if (!isReg() || !isOnRegUseList())
153044eb2f6SDimitry Andric return;
154044eb2f6SDimitry Andric
155044eb2f6SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this))
156044eb2f6SDimitry Andric MF->getRegInfo().removeRegOperandFromUseList(this);
157044eb2f6SDimitry Andric }
158044eb2f6SDimitry Andric
159044eb2f6SDimitry Andric /// ChangeToImmediate - Replace this operand with a new immediate operand of
160044eb2f6SDimitry Andric /// the specified value. If an operand is known to be an immediate already,
161044eb2f6SDimitry Andric /// the setImm method should be used.
ChangeToImmediate(int64_t ImmVal,unsigned TargetFlags)162b60736ecSDimitry Andric void MachineOperand::ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags) {
163044eb2f6SDimitry Andric assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm");
164044eb2f6SDimitry Andric
165044eb2f6SDimitry Andric removeRegFromUses();
166044eb2f6SDimitry Andric
167044eb2f6SDimitry Andric OpKind = MO_Immediate;
168044eb2f6SDimitry Andric Contents.ImmVal = ImmVal;
169b60736ecSDimitry Andric setTargetFlags(TargetFlags);
170044eb2f6SDimitry Andric }
171044eb2f6SDimitry Andric
ChangeToFPImmediate(const ConstantFP * FPImm,unsigned TargetFlags)172b60736ecSDimitry Andric void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm,
173b60736ecSDimitry Andric unsigned TargetFlags) {
174044eb2f6SDimitry Andric assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm");
175044eb2f6SDimitry Andric
176044eb2f6SDimitry Andric removeRegFromUses();
177044eb2f6SDimitry Andric
178044eb2f6SDimitry Andric OpKind = MO_FPImmediate;
179044eb2f6SDimitry Andric Contents.CFP = FPImm;
180b60736ecSDimitry Andric setTargetFlags(TargetFlags);
181044eb2f6SDimitry Andric }
182044eb2f6SDimitry Andric
ChangeToES(const char * SymName,unsigned TargetFlags)183044eb2f6SDimitry Andric void MachineOperand::ChangeToES(const char *SymName,
1841d5ae102SDimitry Andric unsigned TargetFlags) {
185044eb2f6SDimitry Andric assert((!isReg() || !isTied()) &&
186044eb2f6SDimitry Andric "Cannot change a tied operand into an external symbol");
187044eb2f6SDimitry Andric
188044eb2f6SDimitry Andric removeRegFromUses();
189044eb2f6SDimitry Andric
190044eb2f6SDimitry Andric OpKind = MO_ExternalSymbol;
191044eb2f6SDimitry Andric Contents.OffsetedInfo.Val.SymbolName = SymName;
192044eb2f6SDimitry Andric setOffset(0); // Offset is always 0.
193044eb2f6SDimitry Andric setTargetFlags(TargetFlags);
194044eb2f6SDimitry Andric }
195044eb2f6SDimitry Andric
ChangeToGA(const GlobalValue * GV,int64_t Offset,unsigned TargetFlags)196e6d15924SDimitry Andric void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset,
1971d5ae102SDimitry Andric unsigned TargetFlags) {
198e6d15924SDimitry Andric assert((!isReg() || !isTied()) &&
199e6d15924SDimitry Andric "Cannot change a tied operand into a global address");
200e6d15924SDimitry Andric
201e6d15924SDimitry Andric removeRegFromUses();
202e6d15924SDimitry Andric
203e6d15924SDimitry Andric OpKind = MO_GlobalAddress;
204e6d15924SDimitry Andric Contents.OffsetedInfo.Val.GV = GV;
205e6d15924SDimitry Andric setOffset(Offset);
206e6d15924SDimitry Andric setTargetFlags(TargetFlags);
207e6d15924SDimitry Andric }
208e6d15924SDimitry Andric
ChangeToBA(const BlockAddress * BA,int64_t Offset,unsigned TargetFlags)2094df029ccSDimitry Andric void MachineOperand::ChangeToBA(const BlockAddress *BA, int64_t Offset,
2104df029ccSDimitry Andric unsigned TargetFlags) {
2114df029ccSDimitry Andric assert((!isReg() || !isTied()) &&
2124df029ccSDimitry Andric "Cannot change a tied operand into a block address");
2134df029ccSDimitry Andric
2144df029ccSDimitry Andric removeRegFromUses();
2154df029ccSDimitry Andric
2164df029ccSDimitry Andric OpKind = MO_BlockAddress;
2174df029ccSDimitry Andric Contents.OffsetedInfo.Val.BA = BA;
2184df029ccSDimitry Andric setOffset(Offset);
2194df029ccSDimitry Andric setTargetFlags(TargetFlags);
2204df029ccSDimitry Andric }
2214df029ccSDimitry Andric
ChangeToMCSymbol(MCSymbol * Sym,unsigned TargetFlags)222b60736ecSDimitry Andric void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) {
223044eb2f6SDimitry Andric assert((!isReg() || !isTied()) &&
224044eb2f6SDimitry Andric "Cannot change a tied operand into an MCSymbol");
225044eb2f6SDimitry Andric
226044eb2f6SDimitry Andric removeRegFromUses();
227044eb2f6SDimitry Andric
228044eb2f6SDimitry Andric OpKind = MO_MCSymbol;
229044eb2f6SDimitry Andric Contents.Sym = Sym;
230b60736ecSDimitry Andric setTargetFlags(TargetFlags);
231044eb2f6SDimitry Andric }
232044eb2f6SDimitry Andric
ChangeToFrameIndex(int Idx,unsigned TargetFlags)233b60736ecSDimitry Andric void MachineOperand::ChangeToFrameIndex(int Idx, unsigned TargetFlags) {
234044eb2f6SDimitry Andric assert((!isReg() || !isTied()) &&
235044eb2f6SDimitry Andric "Cannot change a tied operand into a FrameIndex");
236044eb2f6SDimitry Andric
237044eb2f6SDimitry Andric removeRegFromUses();
238044eb2f6SDimitry Andric
239044eb2f6SDimitry Andric OpKind = MO_FrameIndex;
240044eb2f6SDimitry Andric setIndex(Idx);
241b60736ecSDimitry Andric setTargetFlags(TargetFlags);
242044eb2f6SDimitry Andric }
243044eb2f6SDimitry Andric
ChangeToTargetIndex(unsigned Idx,int64_t Offset,unsigned TargetFlags)244044eb2f6SDimitry Andric void MachineOperand::ChangeToTargetIndex(unsigned Idx, int64_t Offset,
2451d5ae102SDimitry Andric unsigned TargetFlags) {
246044eb2f6SDimitry Andric assert((!isReg() || !isTied()) &&
247044eb2f6SDimitry Andric "Cannot change a tied operand into a FrameIndex");
248044eb2f6SDimitry Andric
249044eb2f6SDimitry Andric removeRegFromUses();
250044eb2f6SDimitry Andric
251044eb2f6SDimitry Andric OpKind = MO_TargetIndex;
252044eb2f6SDimitry Andric setIndex(Idx);
253044eb2f6SDimitry Andric setOffset(Offset);
254044eb2f6SDimitry Andric setTargetFlags(TargetFlags);
255044eb2f6SDimitry Andric }
256044eb2f6SDimitry Andric
ChangeToDbgInstrRef(unsigned InstrIdx,unsigned OpIdx,unsigned TargetFlags)257e3b55780SDimitry Andric void MachineOperand::ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx,
258e3b55780SDimitry Andric unsigned TargetFlags) {
259e3b55780SDimitry Andric assert((!isReg() || !isTied()) &&
260e3b55780SDimitry Andric "Cannot change a tied operand into a DbgInstrRef");
261e3b55780SDimitry Andric
262e3b55780SDimitry Andric removeRegFromUses();
263e3b55780SDimitry Andric
264e3b55780SDimitry Andric OpKind = MO_DbgInstrRef;
265e3b55780SDimitry Andric setInstrRefInstrIndex(InstrIdx);
266e3b55780SDimitry Andric setInstrRefOpIndex(OpIdx);
267e3b55780SDimitry Andric setTargetFlags(TargetFlags);
268e3b55780SDimitry Andric }
269e3b55780SDimitry Andric
270044eb2f6SDimitry Andric /// ChangeToRegister - Replace this operand with a new register operand of
271044eb2f6SDimitry Andric /// the specified value. If an operand is known to be an register already,
272044eb2f6SDimitry Andric /// the setReg method should be used.
ChangeToRegister(Register Reg,bool isDef,bool isImp,bool isKill,bool isDead,bool isUndef,bool isDebug)2731d5ae102SDimitry Andric void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp,
274044eb2f6SDimitry Andric bool isKill, bool isDead, bool isUndef,
275044eb2f6SDimitry Andric bool isDebug) {
276044eb2f6SDimitry Andric MachineRegisterInfo *RegInfo = nullptr;
277044eb2f6SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this))
278044eb2f6SDimitry Andric RegInfo = &MF->getRegInfo();
279044eb2f6SDimitry Andric // If this operand is already a register operand, remove it from the
280044eb2f6SDimitry Andric // register's use/def lists.
281044eb2f6SDimitry Andric bool WasReg = isReg();
282044eb2f6SDimitry Andric if (RegInfo && WasReg)
283044eb2f6SDimitry Andric RegInfo->removeRegOperandFromUseList(this);
284044eb2f6SDimitry Andric
285c0981da4SDimitry Andric // Ensure debug instructions set debug flag on register uses.
286c0981da4SDimitry Andric const MachineInstr *MI = getParent();
287c0981da4SDimitry Andric if (!isDef && MI && MI->isDebugInstr())
288c0981da4SDimitry Andric isDebug = true;
289c0981da4SDimitry Andric
290044eb2f6SDimitry Andric // Change this to a register and set the reg#.
291044eb2f6SDimitry Andric assert(!(isDead && !isDef) && "Dead flag on non-def");
292044eb2f6SDimitry Andric assert(!(isKill && isDef) && "Kill flag on def");
293044eb2f6SDimitry Andric OpKind = MO_Register;
294044eb2f6SDimitry Andric SmallContents.RegNo = Reg;
295044eb2f6SDimitry Andric SubReg_TargetFlags = 0;
296044eb2f6SDimitry Andric IsDef = isDef;
297044eb2f6SDimitry Andric IsImp = isImp;
298044eb2f6SDimitry Andric IsDeadOrKill = isKill | isDead;
299044eb2f6SDimitry Andric IsRenamable = false;
300044eb2f6SDimitry Andric IsUndef = isUndef;
301044eb2f6SDimitry Andric IsInternalRead = false;
302044eb2f6SDimitry Andric IsEarlyClobber = false;
303044eb2f6SDimitry Andric IsDebug = isDebug;
304044eb2f6SDimitry Andric // Ensure isOnRegUseList() returns false.
305044eb2f6SDimitry Andric Contents.Reg.Prev = nullptr;
306044eb2f6SDimitry Andric // Preserve the tie when the operand was already a register.
307044eb2f6SDimitry Andric if (!WasReg)
308044eb2f6SDimitry Andric TiedTo = 0;
309044eb2f6SDimitry Andric
310044eb2f6SDimitry Andric // If this operand is embedded in a function, add the operand to the
311044eb2f6SDimitry Andric // register's use/def list.
312044eb2f6SDimitry Andric if (RegInfo)
313044eb2f6SDimitry Andric RegInfo->addRegOperandToUseList(this);
314044eb2f6SDimitry Andric }
315044eb2f6SDimitry Andric
316044eb2f6SDimitry Andric /// isIdenticalTo - Return true if this operand is identical to the specified
317044eb2f6SDimitry Andric /// operand. Note that this should stay in sync with the hash_value overload
318044eb2f6SDimitry Andric /// below.
isIdenticalTo(const MachineOperand & Other) const319044eb2f6SDimitry Andric bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
320044eb2f6SDimitry Andric if (getType() != Other.getType() ||
321044eb2f6SDimitry Andric getTargetFlags() != Other.getTargetFlags())
322044eb2f6SDimitry Andric return false;
323044eb2f6SDimitry Andric
324044eb2f6SDimitry Andric switch (getType()) {
325044eb2f6SDimitry Andric case MachineOperand::MO_Register:
326044eb2f6SDimitry Andric return getReg() == Other.getReg() && isDef() == Other.isDef() &&
327044eb2f6SDimitry Andric getSubReg() == Other.getSubReg();
328044eb2f6SDimitry Andric case MachineOperand::MO_Immediate:
329044eb2f6SDimitry Andric return getImm() == Other.getImm();
330044eb2f6SDimitry Andric case MachineOperand::MO_CImmediate:
331044eb2f6SDimitry Andric return getCImm() == Other.getCImm();
332044eb2f6SDimitry Andric case MachineOperand::MO_FPImmediate:
333044eb2f6SDimitry Andric return getFPImm() == Other.getFPImm();
334044eb2f6SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
335044eb2f6SDimitry Andric return getMBB() == Other.getMBB();
336044eb2f6SDimitry Andric case MachineOperand::MO_FrameIndex:
337044eb2f6SDimitry Andric return getIndex() == Other.getIndex();
338044eb2f6SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
339044eb2f6SDimitry Andric case MachineOperand::MO_TargetIndex:
340044eb2f6SDimitry Andric return getIndex() == Other.getIndex() && getOffset() == Other.getOffset();
341044eb2f6SDimitry Andric case MachineOperand::MO_JumpTableIndex:
342044eb2f6SDimitry Andric return getIndex() == Other.getIndex();
343044eb2f6SDimitry Andric case MachineOperand::MO_GlobalAddress:
344044eb2f6SDimitry Andric return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset();
345044eb2f6SDimitry Andric case MachineOperand::MO_ExternalSymbol:
346044eb2f6SDimitry Andric return strcmp(getSymbolName(), Other.getSymbolName()) == 0 &&
347044eb2f6SDimitry Andric getOffset() == Other.getOffset();
348044eb2f6SDimitry Andric case MachineOperand::MO_BlockAddress:
349044eb2f6SDimitry Andric return getBlockAddress() == Other.getBlockAddress() &&
350044eb2f6SDimitry Andric getOffset() == Other.getOffset();
351044eb2f6SDimitry Andric case MachineOperand::MO_RegisterMask:
352044eb2f6SDimitry Andric case MachineOperand::MO_RegisterLiveOut: {
353044eb2f6SDimitry Andric // Shallow compare of the two RegMasks
354044eb2f6SDimitry Andric const uint32_t *RegMask = getRegMask();
355044eb2f6SDimitry Andric const uint32_t *OtherRegMask = Other.getRegMask();
356044eb2f6SDimitry Andric if (RegMask == OtherRegMask)
357044eb2f6SDimitry Andric return true;
358044eb2f6SDimitry Andric
359044eb2f6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
360044eb2f6SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
361e3b55780SDimitry Andric unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs());
362044eb2f6SDimitry Andric // Deep compare of the two RegMasks
363044eb2f6SDimitry Andric return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask);
364044eb2f6SDimitry Andric }
365044eb2f6SDimitry Andric // We don't know the size of the RegMask, so we can't deep compare the two
366044eb2f6SDimitry Andric // reg masks.
367044eb2f6SDimitry Andric return false;
368044eb2f6SDimitry Andric }
369044eb2f6SDimitry Andric case MachineOperand::MO_MCSymbol:
370044eb2f6SDimitry Andric return getMCSymbol() == Other.getMCSymbol();
371e3b55780SDimitry Andric case MachineOperand::MO_DbgInstrRef:
372e3b55780SDimitry Andric return getInstrRefInstrIndex() == Other.getInstrRefInstrIndex() &&
373e3b55780SDimitry Andric getInstrRefOpIndex() == Other.getInstrRefOpIndex();
374044eb2f6SDimitry Andric case MachineOperand::MO_CFIIndex:
375044eb2f6SDimitry Andric return getCFIIndex() == Other.getCFIIndex();
376044eb2f6SDimitry Andric case MachineOperand::MO_Metadata:
377044eb2f6SDimitry Andric return getMetadata() == Other.getMetadata();
378044eb2f6SDimitry Andric case MachineOperand::MO_IntrinsicID:
379044eb2f6SDimitry Andric return getIntrinsicID() == Other.getIntrinsicID();
380044eb2f6SDimitry Andric case MachineOperand::MO_Predicate:
381044eb2f6SDimitry Andric return getPredicate() == Other.getPredicate();
3821d5ae102SDimitry Andric case MachineOperand::MO_ShuffleMask:
3831d5ae102SDimitry Andric return getShuffleMask() == Other.getShuffleMask();
384044eb2f6SDimitry Andric }
385044eb2f6SDimitry Andric llvm_unreachable("Invalid machine operand type");
386044eb2f6SDimitry Andric }
387044eb2f6SDimitry Andric
388044eb2f6SDimitry Andric // Note: this must stay exactly in sync with isIdenticalTo above.
hash_value(const MachineOperand & MO)389044eb2f6SDimitry Andric hash_code llvm::hash_value(const MachineOperand &MO) {
390044eb2f6SDimitry Andric switch (MO.getType()) {
391044eb2f6SDimitry Andric case MachineOperand::MO_Register:
392044eb2f6SDimitry Andric // Register operands don't have target flags.
393e6d15924SDimitry Andric return hash_combine(MO.getType(), (unsigned)MO.getReg(), MO.getSubReg(), MO.isDef());
394044eb2f6SDimitry Andric case MachineOperand::MO_Immediate:
395044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm());
396044eb2f6SDimitry Andric case MachineOperand::MO_CImmediate:
397044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm());
398044eb2f6SDimitry Andric case MachineOperand::MO_FPImmediate:
399044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm());
400044eb2f6SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
401044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB());
402044eb2f6SDimitry Andric case MachineOperand::MO_FrameIndex:
403044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
404044eb2f6SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
405044eb2f6SDimitry Andric case MachineOperand::MO_TargetIndex:
406044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(),
407044eb2f6SDimitry Andric MO.getOffset());
408044eb2f6SDimitry Andric case MachineOperand::MO_JumpTableIndex:
409044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
410044eb2f6SDimitry Andric case MachineOperand::MO_ExternalSymbol:
411044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(),
412e6d15924SDimitry Andric StringRef(MO.getSymbolName()));
413044eb2f6SDimitry Andric case MachineOperand::MO_GlobalAddress:
414044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(),
415044eb2f6SDimitry Andric MO.getOffset());
416044eb2f6SDimitry Andric case MachineOperand::MO_BlockAddress:
417044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(),
418044eb2f6SDimitry Andric MO.getOffset());
419044eb2f6SDimitry Andric case MachineOperand::MO_RegisterMask:
420e3b55780SDimitry Andric case MachineOperand::MO_RegisterLiveOut: {
421e3b55780SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(MO)) {
422e3b55780SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
423e3b55780SDimitry Andric unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs());
424e3b55780SDimitry Andric const uint32_t *RegMask = MO.getRegMask();
425e3b55780SDimitry Andric std::vector<stable_hash> RegMaskHashes(RegMask, RegMask + RegMaskSize);
426e3b55780SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(),
427e3b55780SDimitry Andric stable_hash_combine_array(RegMaskHashes.data(),
428e3b55780SDimitry Andric RegMaskHashes.size()));
429e3b55780SDimitry Andric }
430e3b55780SDimitry Andric
431e3b55780SDimitry Andric assert(0 && "MachineOperand not associated with any MachineFunction");
432e3b55780SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags());
433e3b55780SDimitry Andric }
434044eb2f6SDimitry Andric case MachineOperand::MO_Metadata:
435044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata());
436044eb2f6SDimitry Andric case MachineOperand::MO_MCSymbol:
437044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol());
438e3b55780SDimitry Andric case MachineOperand::MO_DbgInstrRef:
439e3b55780SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(),
440e3b55780SDimitry Andric MO.getInstrRefInstrIndex(), MO.getInstrRefOpIndex());
441044eb2f6SDimitry Andric case MachineOperand::MO_CFIIndex:
442044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex());
443044eb2f6SDimitry Andric case MachineOperand::MO_IntrinsicID:
444044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
445044eb2f6SDimitry Andric case MachineOperand::MO_Predicate:
446044eb2f6SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
4471d5ae102SDimitry Andric case MachineOperand::MO_ShuffleMask:
4481d5ae102SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask());
449044eb2f6SDimitry Andric }
450044eb2f6SDimitry Andric llvm_unreachable("Invalid machine operand type");
451044eb2f6SDimitry Andric }
452044eb2f6SDimitry Andric
453044eb2f6SDimitry Andric // Try to crawl up to the machine function and get TRI and IntrinsicInfo from
454044eb2f6SDimitry Andric // it.
tryToGetTargetInfo(const MachineOperand & MO,const TargetRegisterInfo * & TRI,const TargetIntrinsicInfo * & IntrinsicInfo)455044eb2f6SDimitry Andric static void tryToGetTargetInfo(const MachineOperand &MO,
456044eb2f6SDimitry Andric const TargetRegisterInfo *&TRI,
457044eb2f6SDimitry Andric const TargetIntrinsicInfo *&IntrinsicInfo) {
458044eb2f6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(MO)) {
459044eb2f6SDimitry Andric TRI = MF->getSubtarget().getRegisterInfo();
460044eb2f6SDimitry Andric IntrinsicInfo = MF->getTarget().getIntrinsicInfo();
461044eb2f6SDimitry Andric }
462044eb2f6SDimitry Andric }
463044eb2f6SDimitry Andric
getTargetIndexName(const MachineFunction & MF,int Index)464044eb2f6SDimitry Andric static const char *getTargetIndexName(const MachineFunction &MF, int Index) {
465044eb2f6SDimitry Andric const auto *TII = MF.getSubtarget().getInstrInfo();
466044eb2f6SDimitry Andric assert(TII && "expected instruction info");
467044eb2f6SDimitry Andric auto Indices = TII->getSerializableTargetIndices();
468044eb2f6SDimitry Andric auto Found = find_if(Indices, [&](const std::pair<int, const char *> &I) {
469044eb2f6SDimitry Andric return I.first == Index;
470044eb2f6SDimitry Andric });
471044eb2f6SDimitry Andric if (Found != Indices.end())
472044eb2f6SDimitry Andric return Found->second;
473044eb2f6SDimitry Andric return nullptr;
474044eb2f6SDimitry Andric }
475044eb2f6SDimitry Andric
getTargetIndexName() const476b60736ecSDimitry Andric const char *MachineOperand::getTargetIndexName() const {
477b60736ecSDimitry Andric const MachineFunction *MF = getMFIfAvailable(*this);
478b60736ecSDimitry Andric return MF ? ::getTargetIndexName(*MF, this->getIndex()) : nullptr;
479b60736ecSDimitry Andric }
480b60736ecSDimitry Andric
getTargetFlagName(const TargetInstrInfo * TII,unsigned TF)481044eb2f6SDimitry Andric static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) {
482044eb2f6SDimitry Andric auto Flags = TII->getSerializableDirectMachineOperandTargetFlags();
483044eb2f6SDimitry Andric for (const auto &I : Flags) {
484044eb2f6SDimitry Andric if (I.first == TF) {
485044eb2f6SDimitry Andric return I.second;
486044eb2f6SDimitry Andric }
487044eb2f6SDimitry Andric }
488044eb2f6SDimitry Andric return nullptr;
489044eb2f6SDimitry Andric }
490044eb2f6SDimitry Andric
printCFIRegister(unsigned DwarfReg,raw_ostream & OS,const TargetRegisterInfo * TRI)491c7dac04cSDimitry Andric static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS,
492c7dac04cSDimitry Andric const TargetRegisterInfo *TRI) {
493c7dac04cSDimitry Andric if (!TRI) {
494c7dac04cSDimitry Andric OS << "%dwarfreg." << DwarfReg;
495c7dac04cSDimitry Andric return;
496c7dac04cSDimitry Andric }
497c7dac04cSDimitry Andric
498e3b55780SDimitry Andric if (std::optional<unsigned> Reg = TRI->getLLVMRegNum(DwarfReg, true))
4991d5ae102SDimitry Andric OS << printReg(*Reg, TRI);
5001d5ae102SDimitry Andric else
501c7dac04cSDimitry Andric OS << "<badreg>";
502c7dac04cSDimitry Andric }
503c7dac04cSDimitry Andric
printIRBlockReference(raw_ostream & OS,const BasicBlock & BB,ModuleSlotTracker & MST)504c7dac04cSDimitry Andric static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB,
505c7dac04cSDimitry Andric ModuleSlotTracker &MST) {
506c7dac04cSDimitry Andric OS << "%ir-block.";
507c7dac04cSDimitry Andric if (BB.hasName()) {
508c7dac04cSDimitry Andric printLLVMNameWithoutPrefix(OS, BB.getName());
509c7dac04cSDimitry Andric return;
510c7dac04cSDimitry Andric }
511e3b55780SDimitry Andric std::optional<int> Slot;
512c7dac04cSDimitry Andric if (const Function *F = BB.getParent()) {
513c7dac04cSDimitry Andric if (F == MST.getCurrentFunction()) {
514c7dac04cSDimitry Andric Slot = MST.getLocalSlot(&BB);
515c7dac04cSDimitry Andric } else if (const Module *M = F->getParent()) {
516c7dac04cSDimitry Andric ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false);
517c7dac04cSDimitry Andric CustomMST.incorporateFunction(*F);
518c7dac04cSDimitry Andric Slot = CustomMST.getLocalSlot(&BB);
519c7dac04cSDimitry Andric }
520c7dac04cSDimitry Andric }
521c7dac04cSDimitry Andric if (Slot)
522c7dac04cSDimitry Andric MachineOperand::printIRSlotNumber(OS, *Slot);
523c7dac04cSDimitry Andric else
524c7dac04cSDimitry Andric OS << "<unknown>";
525c7dac04cSDimitry Andric }
526c7dac04cSDimitry Andric
printSyncScope(raw_ostream & OS,const LLVMContext & Context,SyncScope::ID SSID,SmallVectorImpl<StringRef> & SSNs)527eb11fae6SDimitry Andric static void printSyncScope(raw_ostream &OS, const LLVMContext &Context,
528eb11fae6SDimitry Andric SyncScope::ID SSID,
529eb11fae6SDimitry Andric SmallVectorImpl<StringRef> &SSNs) {
530eb11fae6SDimitry Andric switch (SSID) {
531eb11fae6SDimitry Andric case SyncScope::System:
532eb11fae6SDimitry Andric break;
533eb11fae6SDimitry Andric default:
534eb11fae6SDimitry Andric if (SSNs.empty())
535eb11fae6SDimitry Andric Context.getSyncScopeNames(SSNs);
536eb11fae6SDimitry Andric
537eb11fae6SDimitry Andric OS << "syncscope(\"";
538eb11fae6SDimitry Andric printEscapedString(SSNs[SSID], OS);
539eb11fae6SDimitry Andric OS << "\") ";
540eb11fae6SDimitry Andric break;
541eb11fae6SDimitry Andric }
542eb11fae6SDimitry Andric }
543eb11fae6SDimitry Andric
getTargetMMOFlagName(const TargetInstrInfo & TII,unsigned TMMOFlag)544eb11fae6SDimitry Andric static const char *getTargetMMOFlagName(const TargetInstrInfo &TII,
545eb11fae6SDimitry Andric unsigned TMMOFlag) {
546eb11fae6SDimitry Andric auto Flags = TII.getSerializableMachineMemOperandTargetFlags();
547eb11fae6SDimitry Andric for (const auto &I : Flags) {
548eb11fae6SDimitry Andric if (I.first == TMMOFlag) {
549eb11fae6SDimitry Andric return I.second;
550eb11fae6SDimitry Andric }
551eb11fae6SDimitry Andric }
552eb11fae6SDimitry Andric return nullptr;
553eb11fae6SDimitry Andric }
554eb11fae6SDimitry Andric
printFrameIndex(raw_ostream & OS,int FrameIndex,bool IsFixed,const MachineFrameInfo * MFI)555eb11fae6SDimitry Andric static void printFrameIndex(raw_ostream& OS, int FrameIndex, bool IsFixed,
556eb11fae6SDimitry Andric const MachineFrameInfo *MFI) {
557eb11fae6SDimitry Andric StringRef Name;
558eb11fae6SDimitry Andric if (MFI) {
559eb11fae6SDimitry Andric IsFixed = MFI->isFixedObjectIndex(FrameIndex);
560eb11fae6SDimitry Andric if (const AllocaInst *Alloca = MFI->getObjectAllocation(FrameIndex))
561eb11fae6SDimitry Andric if (Alloca->hasName())
562eb11fae6SDimitry Andric Name = Alloca->getName();
563eb11fae6SDimitry Andric if (IsFixed)
564eb11fae6SDimitry Andric FrameIndex -= MFI->getObjectIndexBegin();
565eb11fae6SDimitry Andric }
566eb11fae6SDimitry Andric MachineOperand::printStackObjectReference(OS, FrameIndex, IsFixed, Name);
567eb11fae6SDimitry Andric }
568eb11fae6SDimitry Andric
printSubRegIdx(raw_ostream & OS,uint64_t Index,const TargetRegisterInfo * TRI)569eb11fae6SDimitry Andric void MachineOperand::printSubRegIdx(raw_ostream &OS, uint64_t Index,
570044eb2f6SDimitry Andric const TargetRegisterInfo *TRI) {
571044eb2f6SDimitry Andric OS << "%subreg.";
572e3b55780SDimitry Andric if (TRI && Index != 0 && Index < TRI->getNumSubRegIndices())
573044eb2f6SDimitry Andric OS << TRI->getSubRegIndexName(Index);
574044eb2f6SDimitry Andric else
575044eb2f6SDimitry Andric OS << Index;
576044eb2f6SDimitry Andric }
577044eb2f6SDimitry Andric
printTargetFlags(raw_ostream & OS,const MachineOperand & Op)578044eb2f6SDimitry Andric void MachineOperand::printTargetFlags(raw_ostream &OS,
579044eb2f6SDimitry Andric const MachineOperand &Op) {
580044eb2f6SDimitry Andric if (!Op.getTargetFlags())
581044eb2f6SDimitry Andric return;
582044eb2f6SDimitry Andric const MachineFunction *MF = getMFIfAvailable(Op);
583044eb2f6SDimitry Andric if (!MF)
584044eb2f6SDimitry Andric return;
585044eb2f6SDimitry Andric
586044eb2f6SDimitry Andric const auto *TII = MF->getSubtarget().getInstrInfo();
587044eb2f6SDimitry Andric assert(TII && "expected instruction info");
588044eb2f6SDimitry Andric auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags());
589044eb2f6SDimitry Andric OS << "target-flags(";
590044eb2f6SDimitry Andric const bool HasDirectFlags = Flags.first;
591044eb2f6SDimitry Andric const bool HasBitmaskFlags = Flags.second;
592044eb2f6SDimitry Andric if (!HasDirectFlags && !HasBitmaskFlags) {
593044eb2f6SDimitry Andric OS << "<unknown>) ";
594044eb2f6SDimitry Andric return;
595044eb2f6SDimitry Andric }
596044eb2f6SDimitry Andric if (HasDirectFlags) {
597044eb2f6SDimitry Andric if (const auto *Name = getTargetFlagName(TII, Flags.first))
598044eb2f6SDimitry Andric OS << Name;
599044eb2f6SDimitry Andric else
600044eb2f6SDimitry Andric OS << "<unknown target flag>";
601044eb2f6SDimitry Andric }
602044eb2f6SDimitry Andric if (!HasBitmaskFlags) {
603044eb2f6SDimitry Andric OS << ") ";
604044eb2f6SDimitry Andric return;
605044eb2f6SDimitry Andric }
606044eb2f6SDimitry Andric bool IsCommaNeeded = HasDirectFlags;
607044eb2f6SDimitry Andric unsigned BitMask = Flags.second;
608044eb2f6SDimitry Andric auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags();
609044eb2f6SDimitry Andric for (const auto &Mask : BitMasks) {
610044eb2f6SDimitry Andric // Check if the flag's bitmask has the bits of the current mask set.
611044eb2f6SDimitry Andric if ((BitMask & Mask.first) == Mask.first) {
612044eb2f6SDimitry Andric if (IsCommaNeeded)
613044eb2f6SDimitry Andric OS << ", ";
614044eb2f6SDimitry Andric IsCommaNeeded = true;
615044eb2f6SDimitry Andric OS << Mask.second;
616044eb2f6SDimitry Andric // Clear the bits which were serialized from the flag's bitmask.
617044eb2f6SDimitry Andric BitMask &= ~(Mask.first);
618044eb2f6SDimitry Andric }
619044eb2f6SDimitry Andric }
620044eb2f6SDimitry Andric if (BitMask) {
621044eb2f6SDimitry Andric // When the resulting flag's bitmask isn't zero, we know that we didn't
622044eb2f6SDimitry Andric // serialize all of the bit flags.
623044eb2f6SDimitry Andric if (IsCommaNeeded)
624044eb2f6SDimitry Andric OS << ", ";
625044eb2f6SDimitry Andric OS << "<unknown bitmask target flag>";
626044eb2f6SDimitry Andric }
627044eb2f6SDimitry Andric OS << ") ";
628044eb2f6SDimitry Andric }
629044eb2f6SDimitry Andric
printSymbol(raw_ostream & OS,MCSymbol & Sym)630044eb2f6SDimitry Andric void MachineOperand::printSymbol(raw_ostream &OS, MCSymbol &Sym) {
631044eb2f6SDimitry Andric OS << "<mcsymbol " << Sym << ">";
632044eb2f6SDimitry Andric }
633044eb2f6SDimitry Andric
printStackObjectReference(raw_ostream & OS,unsigned FrameIndex,bool IsFixed,StringRef Name)634044eb2f6SDimitry Andric void MachineOperand::printStackObjectReference(raw_ostream &OS,
635044eb2f6SDimitry Andric unsigned FrameIndex,
636044eb2f6SDimitry Andric bool IsFixed, StringRef Name) {
637044eb2f6SDimitry Andric if (IsFixed) {
638044eb2f6SDimitry Andric OS << "%fixed-stack." << FrameIndex;
639044eb2f6SDimitry Andric return;
640044eb2f6SDimitry Andric }
641044eb2f6SDimitry Andric
642044eb2f6SDimitry Andric OS << "%stack." << FrameIndex;
643044eb2f6SDimitry Andric if (!Name.empty())
644044eb2f6SDimitry Andric OS << '.' << Name;
645044eb2f6SDimitry Andric }
646044eb2f6SDimitry Andric
printOperandOffset(raw_ostream & OS,int64_t Offset)647c7dac04cSDimitry Andric void MachineOperand::printOperandOffset(raw_ostream &OS, int64_t Offset) {
648c7dac04cSDimitry Andric if (Offset == 0)
649c7dac04cSDimitry Andric return;
650c7dac04cSDimitry Andric if (Offset < 0) {
651c7dac04cSDimitry Andric OS << " - " << -Offset;
652c7dac04cSDimitry Andric return;
653c7dac04cSDimitry Andric }
654c7dac04cSDimitry Andric OS << " + " << Offset;
655c7dac04cSDimitry Andric }
656c7dac04cSDimitry Andric
printIRSlotNumber(raw_ostream & OS,int Slot)657c7dac04cSDimitry Andric void MachineOperand::printIRSlotNumber(raw_ostream &OS, int Slot) {
658c7dac04cSDimitry Andric if (Slot == -1)
659c7dac04cSDimitry Andric OS << "<badref>";
660c7dac04cSDimitry Andric else
661c7dac04cSDimitry Andric OS << Slot;
662c7dac04cSDimitry Andric }
663c7dac04cSDimitry Andric
printCFI(raw_ostream & OS,const MCCFIInstruction & CFI,const TargetRegisterInfo * TRI)664c7dac04cSDimitry Andric static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI,
665c7dac04cSDimitry Andric const TargetRegisterInfo *TRI) {
666c7dac04cSDimitry Andric switch (CFI.getOperation()) {
667c7dac04cSDimitry Andric case MCCFIInstruction::OpSameValue:
668c7dac04cSDimitry Andric OS << "same_value ";
669c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
670c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
671c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
672c7dac04cSDimitry Andric break;
673c7dac04cSDimitry Andric case MCCFIInstruction::OpRememberState:
674c7dac04cSDimitry Andric OS << "remember_state ";
675c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
676c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
677c7dac04cSDimitry Andric break;
678c7dac04cSDimitry Andric case MCCFIInstruction::OpRestoreState:
679c7dac04cSDimitry Andric OS << "restore_state ";
680c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
681c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
682c7dac04cSDimitry Andric break;
683c7dac04cSDimitry Andric case MCCFIInstruction::OpOffset:
684c7dac04cSDimitry Andric OS << "offset ";
685c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
686c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
687c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
688c7dac04cSDimitry Andric OS << ", " << CFI.getOffset();
689c7dac04cSDimitry Andric break;
690c7dac04cSDimitry Andric case MCCFIInstruction::OpDefCfaRegister:
691c7dac04cSDimitry Andric OS << "def_cfa_register ";
692c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
693c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
694c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
695c7dac04cSDimitry Andric break;
696c7dac04cSDimitry Andric case MCCFIInstruction::OpDefCfaOffset:
697c7dac04cSDimitry Andric OS << "def_cfa_offset ";
698c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
699c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
700c7dac04cSDimitry Andric OS << CFI.getOffset();
701c7dac04cSDimitry Andric break;
702c7dac04cSDimitry Andric case MCCFIInstruction::OpDefCfa:
703c7dac04cSDimitry Andric OS << "def_cfa ";
704c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
705c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
706c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
707c7dac04cSDimitry Andric OS << ", " << CFI.getOffset();
708c7dac04cSDimitry Andric break;
709344a3780SDimitry Andric case MCCFIInstruction::OpLLVMDefAspaceCfa:
710344a3780SDimitry Andric OS << "llvm_def_aspace_cfa ";
711344a3780SDimitry Andric if (MCSymbol *Label = CFI.getLabel())
712344a3780SDimitry Andric MachineOperand::printSymbol(OS, *Label);
713344a3780SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
714344a3780SDimitry Andric OS << ", " << CFI.getOffset();
715344a3780SDimitry Andric OS << ", " << CFI.getAddressSpace();
716344a3780SDimitry Andric break;
717c7dac04cSDimitry Andric case MCCFIInstruction::OpRelOffset:
718c7dac04cSDimitry Andric OS << "rel_offset ";
719c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
720c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
721c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
722c7dac04cSDimitry Andric OS << ", " << CFI.getOffset();
723c7dac04cSDimitry Andric break;
724c7dac04cSDimitry Andric case MCCFIInstruction::OpAdjustCfaOffset:
725c7dac04cSDimitry Andric OS << "adjust_cfa_offset ";
726c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
727c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
728c7dac04cSDimitry Andric OS << CFI.getOffset();
729c7dac04cSDimitry Andric break;
730c7dac04cSDimitry Andric case MCCFIInstruction::OpRestore:
731c7dac04cSDimitry Andric OS << "restore ";
732c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
733c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
734c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
735c7dac04cSDimitry Andric break;
736c7dac04cSDimitry Andric case MCCFIInstruction::OpEscape: {
737c7dac04cSDimitry Andric OS << "escape ";
738c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
739c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
740c7dac04cSDimitry Andric if (!CFI.getValues().empty()) {
741c7dac04cSDimitry Andric size_t e = CFI.getValues().size() - 1;
742c7dac04cSDimitry Andric for (size_t i = 0; i < e; ++i)
743c7dac04cSDimitry Andric OS << format("0x%02x", uint8_t(CFI.getValues()[i])) << ", ";
744cfca06d7SDimitry Andric OS << format("0x%02x", uint8_t(CFI.getValues()[e]));
745c7dac04cSDimitry Andric }
746c7dac04cSDimitry Andric break;
747c7dac04cSDimitry Andric }
748c7dac04cSDimitry Andric case MCCFIInstruction::OpUndefined:
749c7dac04cSDimitry Andric OS << "undefined ";
750c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
751c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
752c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
753c7dac04cSDimitry Andric break;
754c7dac04cSDimitry Andric case MCCFIInstruction::OpRegister:
755c7dac04cSDimitry Andric OS << "register ";
756c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
757c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
758c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI);
759c7dac04cSDimitry Andric OS << ", ";
760c7dac04cSDimitry Andric printCFIRegister(CFI.getRegister2(), OS, TRI);
761c7dac04cSDimitry Andric break;
762c7dac04cSDimitry Andric case MCCFIInstruction::OpWindowSave:
763c7dac04cSDimitry Andric OS << "window_save ";
764c7dac04cSDimitry Andric if (MCSymbol *Label = CFI.getLabel())
765c7dac04cSDimitry Andric MachineOperand::printSymbol(OS, *Label);
766c7dac04cSDimitry Andric break;
767d8e91e46SDimitry Andric case MCCFIInstruction::OpNegateRAState:
768d8e91e46SDimitry Andric OS << "negate_ra_sign_state ";
769d8e91e46SDimitry Andric if (MCSymbol *Label = CFI.getLabel())
770d8e91e46SDimitry Andric MachineOperand::printSymbol(OS, *Label);
771d8e91e46SDimitry Andric break;
772c7dac04cSDimitry Andric default:
773c7dac04cSDimitry Andric // TODO: Print the other CFI Operations.
774c7dac04cSDimitry Andric OS << "<unserializable cfi directive>";
775c7dac04cSDimitry Andric break;
776c7dac04cSDimitry Andric }
777c7dac04cSDimitry Andric }
778c7dac04cSDimitry Andric
print(raw_ostream & OS,const TargetRegisterInfo * TRI,const TargetIntrinsicInfo * IntrinsicInfo) const779044eb2f6SDimitry Andric void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI,
780044eb2f6SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const {
781eb11fae6SDimitry Andric print(OS, LLT{}, TRI, IntrinsicInfo);
782eb11fae6SDimitry Andric }
783eb11fae6SDimitry Andric
print(raw_ostream & OS,LLT TypeToPrint,const TargetRegisterInfo * TRI,const TargetIntrinsicInfo * IntrinsicInfo) const784eb11fae6SDimitry Andric void MachineOperand::print(raw_ostream &OS, LLT TypeToPrint,
785eb11fae6SDimitry Andric const TargetRegisterInfo *TRI,
786eb11fae6SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const {
787044eb2f6SDimitry Andric tryToGetTargetInfo(*this, TRI, IntrinsicInfo);
788044eb2f6SDimitry Andric ModuleSlotTracker DummyMST(nullptr);
789e3b55780SDimitry Andric print(OS, DummyMST, TypeToPrint, std::nullopt, /*PrintDef=*/false,
790706b4fc4SDimitry Andric /*IsStandalone=*/true,
791044eb2f6SDimitry Andric /*ShouldPrintRegisterTies=*/true,
792044eb2f6SDimitry Andric /*TiedOperandIdx=*/0, TRI, IntrinsicInfo);
793044eb2f6SDimitry Andric }
794044eb2f6SDimitry Andric
print(raw_ostream & OS,ModuleSlotTracker & MST,LLT TypeToPrint,std::optional<unsigned> OpIdx,bool PrintDef,bool IsStandalone,bool ShouldPrintRegisterTies,unsigned TiedOperandIdx,const TargetRegisterInfo * TRI,const TargetIntrinsicInfo * IntrinsicInfo) const795044eb2f6SDimitry Andric void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
796e3b55780SDimitry Andric LLT TypeToPrint, std::optional<unsigned> OpIdx,
797e3b55780SDimitry Andric bool PrintDef, bool IsStandalone,
798e3b55780SDimitry Andric bool ShouldPrintRegisterTies,
799044eb2f6SDimitry Andric unsigned TiedOperandIdx,
800044eb2f6SDimitry Andric const TargetRegisterInfo *TRI,
801044eb2f6SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const {
802044eb2f6SDimitry Andric printTargetFlags(OS, *this);
803044eb2f6SDimitry Andric switch (getType()) {
804044eb2f6SDimitry Andric case MachineOperand::MO_Register: {
8051d5ae102SDimitry Andric Register Reg = getReg();
806044eb2f6SDimitry Andric if (isImplicit())
807044eb2f6SDimitry Andric OS << (isDef() ? "implicit-def " : "implicit ");
808044eb2f6SDimitry Andric else if (PrintDef && isDef())
809044eb2f6SDimitry Andric // Print the 'def' flag only when the operand is defined after '='.
810044eb2f6SDimitry Andric OS << "def ";
811044eb2f6SDimitry Andric if (isInternalRead())
812044eb2f6SDimitry Andric OS << "internal ";
813044eb2f6SDimitry Andric if (isDead())
814044eb2f6SDimitry Andric OS << "dead ";
815044eb2f6SDimitry Andric if (isKill())
816044eb2f6SDimitry Andric OS << "killed ";
817044eb2f6SDimitry Andric if (isUndef())
818044eb2f6SDimitry Andric OS << "undef ";
819044eb2f6SDimitry Andric if (isEarlyClobber())
820044eb2f6SDimitry Andric OS << "early-clobber ";
821e3b55780SDimitry Andric if (getReg().isPhysical() && isRenamable())
822044eb2f6SDimitry Andric OS << "renamable ";
823d8e91e46SDimitry Andric // isDebug() is exactly true for register operands of a DBG_VALUE. So we
824d8e91e46SDimitry Andric // simply infer it when parsing and do not need to print it.
825eb11fae6SDimitry Andric
826eb11fae6SDimitry Andric const MachineRegisterInfo *MRI = nullptr;
827e3b55780SDimitry Andric if (Reg.isVirtual()) {
828eb11fae6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
829eb11fae6SDimitry Andric MRI = &MF->getRegInfo();
830eb11fae6SDimitry Andric }
831eb11fae6SDimitry Andric }
832eb11fae6SDimitry Andric
833eb11fae6SDimitry Andric OS << printReg(Reg, TRI, 0, MRI);
834044eb2f6SDimitry Andric // Print the sub register.
835044eb2f6SDimitry Andric if (unsigned SubReg = getSubReg()) {
836044eb2f6SDimitry Andric if (TRI)
837044eb2f6SDimitry Andric OS << '.' << TRI->getSubRegIndexName(SubReg);
838044eb2f6SDimitry Andric else
839044eb2f6SDimitry Andric OS << ".subreg" << SubReg;
840044eb2f6SDimitry Andric }
841044eb2f6SDimitry Andric // Print the register class / bank.
842e3b55780SDimitry Andric if (Reg.isVirtual()) {
843044eb2f6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
844044eb2f6SDimitry Andric const MachineRegisterInfo &MRI = MF->getRegInfo();
845eb11fae6SDimitry Andric if (IsStandalone || !PrintDef || MRI.def_empty(Reg)) {
846044eb2f6SDimitry Andric OS << ':';
847044eb2f6SDimitry Andric OS << printRegClassOrBank(Reg, MRI, TRI);
848044eb2f6SDimitry Andric }
849044eb2f6SDimitry Andric }
850044eb2f6SDimitry Andric }
851044eb2f6SDimitry Andric // Print ties.
852044eb2f6SDimitry Andric if (ShouldPrintRegisterTies && isTied() && !isDef())
853044eb2f6SDimitry Andric OS << "(tied-def " << TiedOperandIdx << ")";
854044eb2f6SDimitry Andric // Print types.
855044eb2f6SDimitry Andric if (TypeToPrint.isValid())
856044eb2f6SDimitry Andric OS << '(' << TypeToPrint << ')';
857044eb2f6SDimitry Andric break;
858044eb2f6SDimitry Andric }
859706b4fc4SDimitry Andric case MachineOperand::MO_Immediate: {
860706b4fc4SDimitry Andric const MIRFormatter *Formatter = nullptr;
861706b4fc4SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
862706b4fc4SDimitry Andric const auto *TII = MF->getSubtarget().getInstrInfo();
863706b4fc4SDimitry Andric assert(TII && "expected instruction info");
864706b4fc4SDimitry Andric Formatter = TII->getMIRFormatter();
865706b4fc4SDimitry Andric }
866706b4fc4SDimitry Andric if (Formatter)
867706b4fc4SDimitry Andric Formatter->printImm(OS, *getParent(), OpIdx, getImm());
868706b4fc4SDimitry Andric else
869044eb2f6SDimitry Andric OS << getImm();
870044eb2f6SDimitry Andric break;
871706b4fc4SDimitry Andric }
872044eb2f6SDimitry Andric case MachineOperand::MO_CImmediate:
873044eb2f6SDimitry Andric getCImm()->printAsOperand(OS, /*PrintType=*/true, MST);
874044eb2f6SDimitry Andric break;
875044eb2f6SDimitry Andric case MachineOperand::MO_FPImmediate:
876c7dac04cSDimitry Andric getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST);
877044eb2f6SDimitry Andric break;
878044eb2f6SDimitry Andric case MachineOperand::MO_MachineBasicBlock:
879044eb2f6SDimitry Andric OS << printMBBReference(*getMBB());
880044eb2f6SDimitry Andric break;
881044eb2f6SDimitry Andric case MachineOperand::MO_FrameIndex: {
882044eb2f6SDimitry Andric int FrameIndex = getIndex();
883044eb2f6SDimitry Andric bool IsFixed = false;
884eb11fae6SDimitry Andric const MachineFrameInfo *MFI = nullptr;
885eb11fae6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this))
886eb11fae6SDimitry Andric MFI = &MF->getFrameInfo();
887eb11fae6SDimitry Andric printFrameIndex(OS, FrameIndex, IsFixed, MFI);
888044eb2f6SDimitry Andric break;
889044eb2f6SDimitry Andric }
890044eb2f6SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
891044eb2f6SDimitry Andric OS << "%const." << getIndex();
892c7dac04cSDimitry Andric printOperandOffset(OS, getOffset());
893044eb2f6SDimitry Andric break;
894044eb2f6SDimitry Andric case MachineOperand::MO_TargetIndex: {
895044eb2f6SDimitry Andric OS << "target-index(";
896044eb2f6SDimitry Andric const char *Name = "<unknown>";
897044eb2f6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this))
898b60736ecSDimitry Andric if (const auto *TargetIndexName = ::getTargetIndexName(*MF, getIndex()))
899044eb2f6SDimitry Andric Name = TargetIndexName;
900044eb2f6SDimitry Andric OS << Name << ')';
901c7dac04cSDimitry Andric printOperandOffset(OS, getOffset());
902044eb2f6SDimitry Andric break;
903044eb2f6SDimitry Andric }
904044eb2f6SDimitry Andric case MachineOperand::MO_JumpTableIndex:
905044eb2f6SDimitry Andric OS << printJumpTableEntryReference(getIndex());
906044eb2f6SDimitry Andric break;
907044eb2f6SDimitry Andric case MachineOperand::MO_GlobalAddress:
908044eb2f6SDimitry Andric getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
909c7dac04cSDimitry Andric printOperandOffset(OS, getOffset());
910044eb2f6SDimitry Andric break;
911044eb2f6SDimitry Andric case MachineOperand::MO_ExternalSymbol: {
912044eb2f6SDimitry Andric StringRef Name = getSymbolName();
913eb11fae6SDimitry Andric OS << '&';
914044eb2f6SDimitry Andric if (Name.empty()) {
915044eb2f6SDimitry Andric OS << "\"\"";
916044eb2f6SDimitry Andric } else {
917044eb2f6SDimitry Andric printLLVMNameWithoutPrefix(OS, Name);
918044eb2f6SDimitry Andric }
919c7dac04cSDimitry Andric printOperandOffset(OS, getOffset());
920044eb2f6SDimitry Andric break;
921044eb2f6SDimitry Andric }
922c7dac04cSDimitry Andric case MachineOperand::MO_BlockAddress: {
923c7dac04cSDimitry Andric OS << "blockaddress(";
924c7dac04cSDimitry Andric getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false,
925c7dac04cSDimitry Andric MST);
926c7dac04cSDimitry Andric OS << ", ";
927c7dac04cSDimitry Andric printIRBlockReference(OS, *getBlockAddress()->getBasicBlock(), MST);
928c7dac04cSDimitry Andric OS << ')';
929c7dac04cSDimitry Andric MachineOperand::printOperandOffset(OS, getOffset());
930044eb2f6SDimitry Andric break;
931c7dac04cSDimitry Andric }
932044eb2f6SDimitry Andric case MachineOperand::MO_RegisterMask: {
933044eb2f6SDimitry Andric OS << "<regmask";
934044eb2f6SDimitry Andric if (TRI) {
935044eb2f6SDimitry Andric unsigned NumRegsInMask = 0;
936044eb2f6SDimitry Andric unsigned NumRegsEmitted = 0;
937044eb2f6SDimitry Andric for (unsigned i = 0; i < TRI->getNumRegs(); ++i) {
938044eb2f6SDimitry Andric unsigned MaskWord = i / 32;
939044eb2f6SDimitry Andric unsigned MaskBit = i % 32;
940044eb2f6SDimitry Andric if (getRegMask()[MaskWord] & (1 << MaskBit)) {
941044eb2f6SDimitry Andric if (PrintRegMaskNumRegs < 0 ||
942044eb2f6SDimitry Andric NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) {
943044eb2f6SDimitry Andric OS << " " << printReg(i, TRI);
944044eb2f6SDimitry Andric NumRegsEmitted++;
945044eb2f6SDimitry Andric }
946044eb2f6SDimitry Andric NumRegsInMask++;
947044eb2f6SDimitry Andric }
948044eb2f6SDimitry Andric }
949044eb2f6SDimitry Andric if (NumRegsEmitted != NumRegsInMask)
950044eb2f6SDimitry Andric OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more...";
951044eb2f6SDimitry Andric } else {
952044eb2f6SDimitry Andric OS << " ...";
953044eb2f6SDimitry Andric }
954044eb2f6SDimitry Andric OS << ">";
955044eb2f6SDimitry Andric break;
956044eb2f6SDimitry Andric }
957044eb2f6SDimitry Andric case MachineOperand::MO_RegisterLiveOut: {
958044eb2f6SDimitry Andric const uint32_t *RegMask = getRegLiveOut();
959044eb2f6SDimitry Andric OS << "liveout(";
960044eb2f6SDimitry Andric if (!TRI) {
961044eb2f6SDimitry Andric OS << "<unknown>";
962044eb2f6SDimitry Andric } else {
963044eb2f6SDimitry Andric bool IsCommaNeeded = false;
964044eb2f6SDimitry Andric for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) {
965044eb2f6SDimitry Andric if (RegMask[Reg / 32] & (1U << (Reg % 32))) {
966044eb2f6SDimitry Andric if (IsCommaNeeded)
967044eb2f6SDimitry Andric OS << ", ";
968044eb2f6SDimitry Andric OS << printReg(Reg, TRI);
969044eb2f6SDimitry Andric IsCommaNeeded = true;
970044eb2f6SDimitry Andric }
971044eb2f6SDimitry Andric }
972044eb2f6SDimitry Andric }
973044eb2f6SDimitry Andric OS << ")";
974044eb2f6SDimitry Andric break;
975044eb2f6SDimitry Andric }
976044eb2f6SDimitry Andric case MachineOperand::MO_Metadata:
977044eb2f6SDimitry Andric getMetadata()->printAsOperand(OS, MST);
978044eb2f6SDimitry Andric break;
979044eb2f6SDimitry Andric case MachineOperand::MO_MCSymbol:
980044eb2f6SDimitry Andric printSymbol(OS, *getMCSymbol());
981044eb2f6SDimitry Andric break;
982e3b55780SDimitry Andric case MachineOperand::MO_DbgInstrRef: {
983e3b55780SDimitry Andric OS << "dbg-instr-ref(" << getInstrRefInstrIndex() << ", "
984e3b55780SDimitry Andric << getInstrRefOpIndex() << ')';
985e3b55780SDimitry Andric break;
986e3b55780SDimitry Andric }
987c7dac04cSDimitry Andric case MachineOperand::MO_CFIIndex: {
988c7dac04cSDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this))
989c7dac04cSDimitry Andric printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI);
990c7dac04cSDimitry Andric else
991c7dac04cSDimitry Andric OS << "<cfi directive>";
992044eb2f6SDimitry Andric break;
993c7dac04cSDimitry Andric }
994044eb2f6SDimitry Andric case MachineOperand::MO_IntrinsicID: {
995044eb2f6SDimitry Andric Intrinsic::ID ID = getIntrinsicID();
996044eb2f6SDimitry Andric if (ID < Intrinsic::num_intrinsics)
997344a3780SDimitry Andric OS << "intrinsic(@" << Intrinsic::getBaseName(ID) << ')';
998044eb2f6SDimitry Andric else if (IntrinsicInfo)
999c7dac04cSDimitry Andric OS << "intrinsic(@" << IntrinsicInfo->getName(ID) << ')';
1000044eb2f6SDimitry Andric else
1001c7dac04cSDimitry Andric OS << "intrinsic(" << ID << ')';
1002044eb2f6SDimitry Andric break;
1003044eb2f6SDimitry Andric }
1004044eb2f6SDimitry Andric case MachineOperand::MO_Predicate: {
1005044eb2f6SDimitry Andric auto Pred = static_cast<CmpInst::Predicate>(getPredicate());
1006c7dac04cSDimitry Andric OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred("
10077fa27ce4SDimitry Andric << Pred << ')';
1008044eb2f6SDimitry Andric break;
1009044eb2f6SDimitry Andric }
10101d5ae102SDimitry Andric case MachineOperand::MO_ShuffleMask:
10111d5ae102SDimitry Andric OS << "shufflemask(";
1012706b4fc4SDimitry Andric ArrayRef<int> Mask = getShuffleMask();
10131d5ae102SDimitry Andric StringRef Separator;
1014706b4fc4SDimitry Andric for (int Elt : Mask) {
1015706b4fc4SDimitry Andric if (Elt == -1)
1016706b4fc4SDimitry Andric OS << Separator << "undef";
1017706b4fc4SDimitry Andric else
1018706b4fc4SDimitry Andric OS << Separator << Elt;
10191d5ae102SDimitry Andric Separator = ", ";
10201d5ae102SDimitry Andric }
10211d5ae102SDimitry Andric
10221d5ae102SDimitry Andric OS << ')';
10231d5ae102SDimitry Andric break;
1024044eb2f6SDimitry Andric }
1025044eb2f6SDimitry Andric }
1026044eb2f6SDimitry Andric
1027044eb2f6SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1028044eb2f6SDimitry Andric LLVM_DUMP_METHOD void MachineOperand::dump() const { dbgs() << *this << '\n'; }
1029044eb2f6SDimitry Andric #endif
1030044eb2f6SDimitry Andric
1031044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
1032044eb2f6SDimitry Andric // MachineMemOperand Implementation
1033044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
1034044eb2f6SDimitry Andric
1035044eb2f6SDimitry Andric /// getAddrSpace - Return the LLVM IR address space number that this pointer
1036044eb2f6SDimitry Andric /// points into.
getAddrSpace() const1037044eb2f6SDimitry Andric unsigned MachinePointerInfo::getAddrSpace() const { return AddrSpace; }
1038044eb2f6SDimitry Andric
1039044eb2f6SDimitry Andric /// isDereferenceable - Return true if V is always dereferenceable for
1040044eb2f6SDimitry Andric /// Offset + Size byte.
isDereferenceable(unsigned Size,LLVMContext & C,const DataLayout & DL) const1041044eb2f6SDimitry Andric bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C,
1042044eb2f6SDimitry Andric const DataLayout &DL) const {
10437fa27ce4SDimitry Andric if (!isa<const Value *>(V))
1044044eb2f6SDimitry Andric return false;
1045044eb2f6SDimitry Andric
10467fa27ce4SDimitry Andric const Value *BasePtr = cast<const Value *>(V);
1047044eb2f6SDimitry Andric if (BasePtr == nullptr)
1048044eb2f6SDimitry Andric return false;
1049044eb2f6SDimitry Andric
1050044eb2f6SDimitry Andric return isDereferenceableAndAlignedPointer(
1051cfca06d7SDimitry Andric BasePtr, Align(1), APInt(DL.getPointerSizeInBits(), Offset + Size), DL);
1052044eb2f6SDimitry Andric }
1053044eb2f6SDimitry Andric
1054044eb2f6SDimitry Andric /// getConstantPool - Return a MachinePointerInfo record that refers to the
1055044eb2f6SDimitry Andric /// constant pool.
getConstantPool(MachineFunction & MF)1056044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) {
1057044eb2f6SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getConstantPool());
1058044eb2f6SDimitry Andric }
1059044eb2f6SDimitry Andric
1060044eb2f6SDimitry Andric /// getFixedStack - Return a MachinePointerInfo record that refers to the
1061044eb2f6SDimitry Andric /// the specified FrameIndex.
getFixedStack(MachineFunction & MF,int FI,int64_t Offset)1062044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getFixedStack(MachineFunction &MF,
1063044eb2f6SDimitry Andric int FI, int64_t Offset) {
1064044eb2f6SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getFixedStack(FI), Offset);
1065044eb2f6SDimitry Andric }
1066044eb2f6SDimitry Andric
getJumpTable(MachineFunction & MF)1067044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getJumpTable(MachineFunction &MF) {
1068044eb2f6SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getJumpTable());
1069044eb2f6SDimitry Andric }
1070044eb2f6SDimitry Andric
getGOT(MachineFunction & MF)1071044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getGOT(MachineFunction &MF) {
1072044eb2f6SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getGOT());
1073044eb2f6SDimitry Andric }
1074044eb2f6SDimitry Andric
getStack(MachineFunction & MF,int64_t Offset,uint8_t ID)1075044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getStack(MachineFunction &MF,
1076044eb2f6SDimitry Andric int64_t Offset, uint8_t ID) {
1077044eb2f6SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getStack(), Offset, ID);
1078044eb2f6SDimitry Andric }
1079044eb2f6SDimitry Andric
getUnknownStack(MachineFunction & MF)1080044eb2f6SDimitry Andric MachinePointerInfo MachinePointerInfo::getUnknownStack(MachineFunction &MF) {
1081044eb2f6SDimitry Andric return MachinePointerInfo(MF.getDataLayout().getAllocaAddrSpace());
1082044eb2f6SDimitry Andric }
1083044eb2f6SDimitry Andric
MachineMemOperand(MachinePointerInfo ptrinfo,Flags f,LLT type,Align a,const AAMDNodes & AAInfo,const MDNode * Ranges,SyncScope::ID SSID,AtomicOrdering Ordering,AtomicOrdering FailureOrdering)1084044eb2f6SDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f,
1085344a3780SDimitry Andric LLT type, Align a, const AAMDNodes &AAInfo,
1086044eb2f6SDimitry Andric const MDNode *Ranges, SyncScope::ID SSID,
1087044eb2f6SDimitry Andric AtomicOrdering Ordering,
1088044eb2f6SDimitry Andric AtomicOrdering FailureOrdering)
1089344a3780SDimitry Andric : PtrInfo(ptrinfo), MemoryType(type), FlagVals(f), BaseAlign(a),
1090344a3780SDimitry Andric AAInfo(AAInfo), Ranges(Ranges) {
10917fa27ce4SDimitry Andric assert((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) ||
10927fa27ce4SDimitry Andric isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) &&
1093044eb2f6SDimitry Andric "invalid pointer value");
1094044eb2f6SDimitry Andric assert((isLoad() || isStore()) && "Not a load/store!");
1095044eb2f6SDimitry Andric
1096044eb2f6SDimitry Andric AtomicInfo.SSID = static_cast<unsigned>(SSID);
1097044eb2f6SDimitry Andric assert(getSyncScopeID() == SSID && "Value truncated");
1098044eb2f6SDimitry Andric AtomicInfo.Ordering = static_cast<unsigned>(Ordering);
1099344a3780SDimitry Andric assert(getSuccessOrdering() == Ordering && "Value truncated");
1100044eb2f6SDimitry Andric AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering);
1101044eb2f6SDimitry Andric assert(getFailureOrdering() == FailureOrdering && "Value truncated");
1102044eb2f6SDimitry Andric }
1103044eb2f6SDimitry Andric
MachineMemOperand(MachinePointerInfo ptrinfo,Flags F,LocationSize TS,Align BaseAlignment,const AAMDNodes & AAInfo,const MDNode * Ranges,SyncScope::ID SSID,AtomicOrdering Ordering,AtomicOrdering FailureOrdering)1104ac9a064cSDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags F,
1105ac9a064cSDimitry Andric LocationSize TS, Align BaseAlignment,
1106344a3780SDimitry Andric const AAMDNodes &AAInfo,
1107344a3780SDimitry Andric const MDNode *Ranges, SyncScope::ID SSID,
1108344a3780SDimitry Andric AtomicOrdering Ordering,
1109344a3780SDimitry Andric AtomicOrdering FailureOrdering)
1110ac9a064cSDimitry Andric : MachineMemOperand(
1111ac9a064cSDimitry Andric ptrinfo, F,
1112ac9a064cSDimitry Andric !TS.hasValue() ? LLT()
1113ac9a064cSDimitry Andric : TS.isScalable()
1114ac9a064cSDimitry Andric ? LLT::scalable_vector(1, 8 * TS.getValue().getKnownMinValue())
1115ac9a064cSDimitry Andric : LLT::scalar(8 * TS.getValue().getKnownMinValue()),
1116ac9a064cSDimitry Andric BaseAlignment, AAInfo, Ranges, SSID, Ordering, FailureOrdering) {}
1117344a3780SDimitry Andric
refineAlignment(const MachineMemOperand * MMO)1118044eb2f6SDimitry Andric void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) {
1119044eb2f6SDimitry Andric // The Value and Offset may differ due to CSE. But the flags and size
1120044eb2f6SDimitry Andric // should be the same.
1121044eb2f6SDimitry Andric assert(MMO->getFlags() == getFlags() && "Flags mismatch!");
1122ac9a064cSDimitry Andric assert((!MMO->getSize().hasValue() || !getSize().hasValue() ||
1123f65dcba8SDimitry Andric MMO->getSize() == getSize()) &&
1124f65dcba8SDimitry Andric "Size mismatch!");
1125cfca06d7SDimitry Andric if (MMO->getBaseAlign() >= getBaseAlign()) {
1126044eb2f6SDimitry Andric // Update the alignment value.
1127cfca06d7SDimitry Andric BaseAlign = MMO->getBaseAlign();
1128044eb2f6SDimitry Andric // Also update the base and offset, because the new alignment may
1129044eb2f6SDimitry Andric // not be applicable with the old ones.
1130044eb2f6SDimitry Andric PtrInfo = MMO->PtrInfo;
1131044eb2f6SDimitry Andric }
1132044eb2f6SDimitry Andric }
1133044eb2f6SDimitry Andric
1134cfca06d7SDimitry Andric /// getAlign - Return the minimum known alignment in bytes of the
1135cfca06d7SDimitry Andric /// actual memory reference.
getAlign() const1136cfca06d7SDimitry Andric Align MachineMemOperand::getAlign() const {
1137cfca06d7SDimitry Andric return commonAlignment(getBaseAlign(), getOffset());
1138044eb2f6SDimitry Andric }
1139044eb2f6SDimitry Andric
print(raw_ostream & OS,ModuleSlotTracker & MST,SmallVectorImpl<StringRef> & SSNs,const LLVMContext & Context,const MachineFrameInfo * MFI,const TargetInstrInfo * TII) const1140eb11fae6SDimitry Andric void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
1141eb11fae6SDimitry Andric SmallVectorImpl<StringRef> &SSNs,
1142eb11fae6SDimitry Andric const LLVMContext &Context,
1143eb11fae6SDimitry Andric const MachineFrameInfo *MFI,
1144eb11fae6SDimitry Andric const TargetInstrInfo *TII) const {
1145eb11fae6SDimitry Andric OS << '(';
1146044eb2f6SDimitry Andric if (isVolatile())
1147eb11fae6SDimitry Andric OS << "volatile ";
1148eb11fae6SDimitry Andric if (isNonTemporal())
1149eb11fae6SDimitry Andric OS << "non-temporal ";
1150eb11fae6SDimitry Andric if (isDereferenceable())
1151eb11fae6SDimitry Andric OS << "dereferenceable ";
1152eb11fae6SDimitry Andric if (isInvariant())
1153eb11fae6SDimitry Andric OS << "invariant ";
1154e3b55780SDimitry Andric if (TII) {
1155eb11fae6SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag1)
1156eb11fae6SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag1)
1157eb11fae6SDimitry Andric << "\" ";
1158eb11fae6SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag2)
1159eb11fae6SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag2)
1160eb11fae6SDimitry Andric << "\" ";
1161eb11fae6SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag3)
1162eb11fae6SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag3)
1163eb11fae6SDimitry Andric << "\" ";
1164e3b55780SDimitry Andric } else {
1165e3b55780SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag1)
1166e3b55780SDimitry Andric OS << "\"MOTargetFlag1\" ";
1167e3b55780SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag2)
1168e3b55780SDimitry Andric OS << "\"MOTargetFlag2\" ";
1169e3b55780SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag3)
1170e3b55780SDimitry Andric OS << "\"MOTargetFlag3\" ";
1171e3b55780SDimitry Andric }
1172044eb2f6SDimitry Andric
1173eb11fae6SDimitry Andric assert((isLoad() || isStore()) &&
1174eb11fae6SDimitry Andric "machine memory operand must be a load or store (or both)");
1175044eb2f6SDimitry Andric if (isLoad())
1176eb11fae6SDimitry Andric OS << "load ";
1177044eb2f6SDimitry Andric if (isStore())
1178eb11fae6SDimitry Andric OS << "store ";
1179eb11fae6SDimitry Andric
1180eb11fae6SDimitry Andric printSyncScope(OS, Context, getSyncScopeID(), SSNs);
1181eb11fae6SDimitry Andric
1182344a3780SDimitry Andric if (getSuccessOrdering() != AtomicOrdering::NotAtomic)
1183344a3780SDimitry Andric OS << toIRString(getSuccessOrdering()) << ' ';
1184eb11fae6SDimitry Andric if (getFailureOrdering() != AtomicOrdering::NotAtomic)
1185eb11fae6SDimitry Andric OS << toIRString(getFailureOrdering()) << ' ';
1186eb11fae6SDimitry Andric
1187344a3780SDimitry Andric if (getMemoryType().isValid())
1188344a3780SDimitry Andric OS << '(' << getMemoryType() << ')';
1189d8e91e46SDimitry Andric else
1190344a3780SDimitry Andric OS << "unknown-size";
1191d8e91e46SDimitry Andric
1192eb11fae6SDimitry Andric if (const Value *Val = getValue()) {
1193eb11fae6SDimitry Andric OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into ");
1194706b4fc4SDimitry Andric MIRFormatter::printIRValue(OS, *Val, MST);
1195eb11fae6SDimitry Andric } else if (const PseudoSourceValue *PVal = getPseudoValue()) {
1196eb11fae6SDimitry Andric OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into ");
1197eb11fae6SDimitry Andric assert(PVal && "Expected a pseudo source value");
1198eb11fae6SDimitry Andric switch (PVal->kind()) {
1199eb11fae6SDimitry Andric case PseudoSourceValue::Stack:
1200eb11fae6SDimitry Andric OS << "stack";
1201eb11fae6SDimitry Andric break;
1202eb11fae6SDimitry Andric case PseudoSourceValue::GOT:
1203eb11fae6SDimitry Andric OS << "got";
1204eb11fae6SDimitry Andric break;
1205eb11fae6SDimitry Andric case PseudoSourceValue::JumpTable:
1206eb11fae6SDimitry Andric OS << "jump-table";
1207eb11fae6SDimitry Andric break;
1208eb11fae6SDimitry Andric case PseudoSourceValue::ConstantPool:
1209eb11fae6SDimitry Andric OS << "constant-pool";
1210eb11fae6SDimitry Andric break;
1211eb11fae6SDimitry Andric case PseudoSourceValue::FixedStack: {
1212eb11fae6SDimitry Andric int FrameIndex = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
1213eb11fae6SDimitry Andric bool IsFixed = true;
1214eb11fae6SDimitry Andric printFrameIndex(OS, FrameIndex, IsFixed, MFI);
1215eb11fae6SDimitry Andric break;
1216044eb2f6SDimitry Andric }
1217eb11fae6SDimitry Andric case PseudoSourceValue::GlobalValueCallEntry:
1218eb11fae6SDimitry Andric OS << "call-entry ";
1219eb11fae6SDimitry Andric cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand(
1220eb11fae6SDimitry Andric OS, /*PrintType=*/false, MST);
1221eb11fae6SDimitry Andric break;
1222eb11fae6SDimitry Andric case PseudoSourceValue::ExternalSymbolCallEntry:
1223eb11fae6SDimitry Andric OS << "call-entry &";
1224eb11fae6SDimitry Andric printLLVMNameWithoutPrefix(
1225eb11fae6SDimitry Andric OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol());
1226eb11fae6SDimitry Andric break;
1227706b4fc4SDimitry Andric default: {
1228706b4fc4SDimitry Andric const MIRFormatter *Formatter = TII->getMIRFormatter();
1229eb11fae6SDimitry Andric // FIXME: This is not necessarily the correct MIR serialization format for
1230eb11fae6SDimitry Andric // a custom pseudo source value, but at least it allows
1231b60736ecSDimitry Andric // MIR printing to work on a target with custom pseudo source
1232eb11fae6SDimitry Andric // values.
1233706b4fc4SDimitry Andric OS << "custom \"";
1234706b4fc4SDimitry Andric Formatter->printCustomPseudoSourceValue(OS, MST, *PVal);
1235706b4fc4SDimitry Andric OS << '\"';
1236eb11fae6SDimitry Andric break;
1237044eb2f6SDimitry Andric }
1238044eb2f6SDimitry Andric }
1239344a3780SDimitry Andric } else if (getOpaqueValue() == nullptr && getOffset() != 0) {
1240344a3780SDimitry Andric OS << ((isLoad() && isStore()) ? " on "
1241344a3780SDimitry Andric : isLoad() ? " from "
1242344a3780SDimitry Andric : " into ")
1243344a3780SDimitry Andric << "unknown-address";
1244706b4fc4SDimitry Andric }
1245eb11fae6SDimitry Andric MachineOperand::printOperandOffset(OS, getOffset());
1246ac9a064cSDimitry Andric if (!getSize().hasValue() ||
1247ac9a064cSDimitry Andric getAlign() != getSize().getValue().getKnownMinValue())
1248b60736ecSDimitry Andric OS << ", align " << getAlign().value();
1249b60736ecSDimitry Andric if (getAlign() != getBaseAlign())
1250b60736ecSDimitry Andric OS << ", basealign " << getBaseAlign().value();
1251eb11fae6SDimitry Andric auto AAInfo = getAAInfo();
1252eb11fae6SDimitry Andric if (AAInfo.TBAA) {
1253eb11fae6SDimitry Andric OS << ", !tbaa ";
1254eb11fae6SDimitry Andric AAInfo.TBAA->printAsOperand(OS, MST);
1255044eb2f6SDimitry Andric }
1256eb11fae6SDimitry Andric if (AAInfo.Scope) {
1257eb11fae6SDimitry Andric OS << ", !alias.scope ";
1258eb11fae6SDimitry Andric AAInfo.Scope->printAsOperand(OS, MST);
1259044eb2f6SDimitry Andric }
1260eb11fae6SDimitry Andric if (AAInfo.NoAlias) {
1261eb11fae6SDimitry Andric OS << ", !noalias ";
1262eb11fae6SDimitry Andric AAInfo.NoAlias->printAsOperand(OS, MST);
1263044eb2f6SDimitry Andric }
1264eb11fae6SDimitry Andric if (getRanges()) {
1265eb11fae6SDimitry Andric OS << ", !range ";
1266eb11fae6SDimitry Andric getRanges()->printAsOperand(OS, MST);
1267eb11fae6SDimitry Andric }
1268eb11fae6SDimitry Andric // FIXME: Implement addrspace printing/parsing in MIR.
1269eb11fae6SDimitry Andric // For now, print this even though parsing it is not available in MIR.
1270eb11fae6SDimitry Andric if (unsigned AS = getAddrSpace())
1271eb11fae6SDimitry Andric OS << ", addrspace " << AS;
1272044eb2f6SDimitry Andric
1273044eb2f6SDimitry Andric OS << ')';
1274044eb2f6SDimitry Andric }
1275