Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147429421
MachineOperand.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
43 KB
Referenced Files
None
Subscribers
None
MachineOperand.cpp
View Options
//===- lib/CodeGen/MachineOperand.cpp -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file Methods common to all machine operands.
//
//===----------------------------------------------------------------------===//
#include
"llvm/CodeGen/MachineOperand.h"
#include
"llvm/ADT/StableHashing.h"
#include
"llvm/ADT/StringExtras.h"
#include
"llvm/Analysis/Loads.h"
#include
"llvm/CodeGen/MIRFormatter.h"
#include
"llvm/CodeGen/MachineFrameInfo.h"
#include
"llvm/CodeGen/MachineJumpTableInfo.h"
#include
"llvm/CodeGen/MachineRegisterInfo.h"
#include
"llvm/CodeGen/PseudoSourceValueManager.h"
#include
"llvm/CodeGen/TargetInstrInfo.h"
#include
"llvm/CodeGen/TargetRegisterInfo.h"
#include
"llvm/Config/llvm-config.h"
#include
"llvm/IR/Constants.h"
#include
"llvm/IR/IRPrintingPasses.h"
#include
"llvm/IR/Instructions.h"
#include
"llvm/IR/ModuleSlotTracker.h"
#include
"llvm/MC/MCDwarf.h"
#include
"llvm/Target/TargetMachine.h"
#include
<optional>
using
namespace
llvm
;
static
cl
::
opt
<
int
>
PrintRegMaskNumRegs
(
"print-regmask-num-regs"
,
cl
::
desc
(
"Number of registers to limit to when "
"printing regmask operands in IR dumps. "
"unlimited = -1"
),
cl
::
init
(
32
),
cl
::
Hidden
);
static
const
MachineFunction
*
getMFIfAvailable
(
const
MachineOperand
&
MO
)
{
if
(
const
MachineInstr
*
MI
=
MO
.
getParent
())
if
(
const
MachineBasicBlock
*
MBB
=
MI
->
getParent
())
if
(
const
MachineFunction
*
MF
=
MBB
->
getParent
())
return
MF
;
return
nullptr
;
}
static
MachineFunction
*
getMFIfAvailable
(
MachineOperand
&
MO
)
{
return
const_cast
<
MachineFunction
*>
(
getMFIfAvailable
(
const_cast
<
const
MachineOperand
&>
(
MO
)));
}
unsigned
MachineOperand::getOperandNo
()
const
{
assert
(
getParent
()
&&
"Operand does not belong to any instruction!"
);
return
getParent
()
->
getOperandNo
(
this
);
}
void
MachineOperand::setReg
(
Register
Reg
)
{
if
(
getReg
()
==
Reg
)
return
;
// No change.
// Clear the IsRenamable bit to keep it conservatively correct.
IsRenamable
=
false
;
// Otherwise, we have to change the register. If this operand is embedded
// into a machine function, we need to update the old and new register's
// use/def lists.
if
(
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
MachineRegisterInfo
&
MRI
=
MF
->
getRegInfo
();
MRI
.
removeRegOperandFromUseList
(
this
);
SmallContents
.
RegNo
=
Reg
.
id
();
MRI
.
addRegOperandToUseList
(
this
);
return
;
}
// Otherwise, just change the register, no problem. :)
SmallContents
.
RegNo
=
Reg
.
id
();
}
void
MachineOperand::substVirtReg
(
Register
Reg
,
unsigned
SubIdx
,
const
TargetRegisterInfo
&
TRI
)
{
assert
(
Reg
.
isVirtual
());
if
(
SubIdx
&&
getSubReg
())
SubIdx
=
TRI
.
composeSubRegIndices
(
SubIdx
,
getSubReg
());
setReg
(
Reg
);
if
(
SubIdx
)
setSubReg
(
SubIdx
);
}
void
MachineOperand::substPhysReg
(
MCRegister
Reg
,
const
TargetRegisterInfo
&
TRI
)
{
assert
(
Reg
.
isPhysical
());
if
(
getSubReg
())
{
Reg
=
TRI
.
getSubReg
(
Reg
,
getSubReg
());
// Note that getSubReg() may return 0 if the sub-register doesn't exist.
// That won't happen in legal code.
setSubReg
(
0
);
if
(
isDef
())
setIsUndef
(
false
);
}
setReg
(
Reg
);
}
/// Change a def to a use, or a use to a def.
void
MachineOperand::setIsDef
(
bool
Val
)
{
assert
(
isReg
()
&&
"Wrong MachineOperand accessor"
);
assert
((
!
Val
||
!
isDebug
())
&&
"Marking a debug operation as def"
);
if
(
IsDef
==
Val
)
return
;
assert
(
!
IsDeadOrKill
&&
"Changing def/use with dead/kill set not supported"
);
// MRI may keep uses and defs in different list positions.
if
(
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
MachineRegisterInfo
&
MRI
=
MF
->
getRegInfo
();
MRI
.
removeRegOperandFromUseList
(
this
);
IsDef
=
Val
;
MRI
.
addRegOperandToUseList
(
this
);
return
;
}
IsDef
=
Val
;
}
bool
MachineOperand::isRenamable
()
const
{
assert
(
isReg
()
&&
"Wrong MachineOperand accessor"
);
assert
(
getReg
().
isPhysical
()
&&
"isRenamable should only be checked on physical registers"
);
if
(
!
IsRenamable
)
return
false
;
const
MachineInstr
*
MI
=
getParent
();
if
(
!
MI
)
return
true
;
if
(
isDef
())
return
!
MI
->
hasExtraDefRegAllocReq
(
MachineInstr
::
IgnoreBundle
);
assert
(
isUse
()
&&
"Reg is not def or use"
);
return
!
MI
->
hasExtraSrcRegAllocReq
(
MachineInstr
::
IgnoreBundle
);
}
void
MachineOperand::setIsRenamable
(
bool
Val
)
{
assert
(
isReg
()
&&
"Wrong MachineOperand accessor"
);
assert
(
getReg
().
isPhysical
()
&&
"setIsRenamable should only be called on physical registers"
);
IsRenamable
=
Val
;
}
// If this operand is currently a register operand, and if this is in a
// function, deregister the operand from the register's use/def list.
void
MachineOperand::removeRegFromUses
()
{
if
(
!
isReg
()
||
!
isOnRegUseList
())
return
;
if
(
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
MF
->
getRegInfo
().
removeRegOperandFromUseList
(
this
);
}
/// ChangeToImmediate - Replace this operand with a new immediate operand of
/// the specified value. If an operand is known to be an immediate already,
/// the setImm method should be used.
void
MachineOperand::ChangeToImmediate
(
int64_t
ImmVal
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into an imm"
);
removeRegFromUses
();
OpKind
=
MO_Immediate
;
Contents
.
ImmVal
=
ImmVal
;
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToFPImmediate
(
const
ConstantFP
*
FPImm
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into an imm"
);
removeRegFromUses
();
OpKind
=
MO_FPImmediate
;
Contents
.
CFP
=
FPImm
;
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToES
(
const
char
*
SymName
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into an external symbol"
);
removeRegFromUses
();
OpKind
=
MO_ExternalSymbol
;
Contents
.
OffsetedInfo
.
Val
.
SymbolName
=
SymName
;
setOffset
(
0
);
// Offset is always 0.
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToGA
(
const
GlobalValue
*
GV
,
int64_t
Offset
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a global address"
);
removeRegFromUses
();
OpKind
=
MO_GlobalAddress
;
Contents
.
OffsetedInfo
.
Val
.
GV
=
GV
;
setOffset
(
Offset
);
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToBA
(
const
BlockAddress
*
BA
,
int64_t
Offset
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a block address"
);
removeRegFromUses
();
OpKind
=
MO_BlockAddress
;
Contents
.
OffsetedInfo
.
Val
.
BA
=
BA
;
setOffset
(
Offset
);
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToCPI
(
unsigned
Idx
,
int
Offset
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a constant pool index"
);
removeRegFromUses
();
OpKind
=
MO_ConstantPoolIndex
;
setIndex
(
Idx
);
setOffset
(
Offset
);
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToMCSymbol
(
MCSymbol
*
Sym
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into an MCSymbol"
);
removeRegFromUses
();
OpKind
=
MO_MCSymbol
;
Contents
.
Sym
=
Sym
;
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToFrameIndex
(
int
Idx
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a FrameIndex"
);
removeRegFromUses
();
OpKind
=
MO_FrameIndex
;
setIndex
(
Idx
);
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToTargetIndex
(
unsigned
Idx
,
int64_t
Offset
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a FrameIndex"
);
removeRegFromUses
();
OpKind
=
MO_TargetIndex
;
setIndex
(
Idx
);
setOffset
(
Offset
);
setTargetFlags
(
TargetFlags
);
}
void
MachineOperand::ChangeToDbgInstrRef
(
unsigned
InstrIdx
,
unsigned
OpIdx
,
unsigned
TargetFlags
)
{
assert
((
!
isReg
()
||
!
isTied
())
&&
"Cannot change a tied operand into a DbgInstrRef"
);
removeRegFromUses
();
OpKind
=
MO_DbgInstrRef
;
setInstrRefInstrIndex
(
InstrIdx
);
setInstrRefOpIndex
(
OpIdx
);
setTargetFlags
(
TargetFlags
);
}
/// ChangeToRegister - Replace this operand with a new register operand of
/// the specified value. If an operand is known to be an register already,
/// the setReg method should be used.
void
MachineOperand::ChangeToRegister
(
Register
Reg
,
bool
isDef
,
bool
isImp
,
bool
isKill
,
bool
isDead
,
bool
isUndef
,
bool
isDebug
)
{
MachineRegisterInfo
*
RegInfo
=
nullptr
;
if
(
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
RegInfo
=
&
MF
->
getRegInfo
();
// If this operand is already a register operand, remove it from the
// register's use/def lists.
bool
WasReg
=
isReg
();
if
(
RegInfo
&&
WasReg
)
RegInfo
->
removeRegOperandFromUseList
(
this
);
// Ensure debug instructions set debug flag on register uses.
const
MachineInstr
*
MI
=
getParent
();
if
(
!
isDef
&&
MI
&&
MI
->
isDebugInstr
())
isDebug
=
true
;
// Change this to a register and set the reg#.
assert
(
!
(
isDead
&&
!
isDef
)
&&
"Dead flag on non-def"
);
assert
(
!
(
isKill
&&
isDef
)
&&
"Kill flag on def"
);
OpKind
=
MO_Register
;
SmallContents
.
RegNo
=
Reg
.
id
();
SubReg_TargetFlags
=
0
;
IsDef
=
isDef
;
IsImp
=
isImp
;
IsDeadOrKill
=
isKill
|
isDead
;
IsRenamable
=
false
;
IsUndef
=
isUndef
;
IsInternalRead
=
false
;
IsEarlyClobber
=
false
;
IsDebug
=
isDebug
;
// Ensure isOnRegUseList() returns false.
Contents
.
Reg
.
Prev
=
nullptr
;
// Preserve the tie when the operand was already a register.
if
(
!
WasReg
)
TiedTo
=
0
;
// If this operand is embedded in a function, add the operand to the
// register's use/def list.
if
(
RegInfo
)
RegInfo
->
addRegOperandToUseList
(
this
);
}
/// isIdenticalTo - Return true if this operand is identical to the specified
/// operand. Note that this should stay in sync with the hash_value overload
/// below.
bool
MachineOperand::isIdenticalTo
(
const
MachineOperand
&
Other
)
const
{
if
(
getType
()
!=
Other
.
getType
()
||
getTargetFlags
()
!=
Other
.
getTargetFlags
())
return
false
;
switch
(
getType
())
{
case
MachineOperand
::
MO_Register
:
return
getReg
()
==
Other
.
getReg
()
&&
isDef
()
==
Other
.
isDef
()
&&
getSubReg
()
==
Other
.
getSubReg
();
case
MachineOperand
::
MO_Immediate
:
return
getImm
()
==
Other
.
getImm
();
case
MachineOperand
::
MO_CImmediate
:
return
getCImm
()
==
Other
.
getCImm
();
case
MachineOperand
::
MO_FPImmediate
:
return
getFPImm
()
==
Other
.
getFPImm
();
case
MachineOperand
::
MO_MachineBasicBlock
:
return
getMBB
()
==
Other
.
getMBB
();
case
MachineOperand
::
MO_FrameIndex
:
return
getIndex
()
==
Other
.
getIndex
();
case
MachineOperand
::
MO_ConstantPoolIndex
:
case
MachineOperand
::
MO_TargetIndex
:
return
getIndex
()
==
Other
.
getIndex
()
&&
getOffset
()
==
Other
.
getOffset
();
case
MachineOperand
::
MO_JumpTableIndex
:
return
getIndex
()
==
Other
.
getIndex
();
case
MachineOperand
::
MO_GlobalAddress
:
return
getGlobal
()
==
Other
.
getGlobal
()
&&
getOffset
()
==
Other
.
getOffset
();
case
MachineOperand
::
MO_ExternalSymbol
:
return
strcmp
(
getSymbolName
(),
Other
.
getSymbolName
())
==
0
&&
getOffset
()
==
Other
.
getOffset
();
case
MachineOperand
::
MO_BlockAddress
:
return
getBlockAddress
()
==
Other
.
getBlockAddress
()
&&
getOffset
()
==
Other
.
getOffset
();
case
MachineOperand
::
MO_RegisterMask
:
case
MachineOperand
::
MO_RegisterLiveOut
:
{
// Shallow compare of the two RegMasks
const
uint32_t
*
RegMask
=
getRegMask
();
const
uint32_t
*
OtherRegMask
=
Other
.
getRegMask
();
if
(
RegMask
==
OtherRegMask
)
return
true
;
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
const
TargetRegisterInfo
*
TRI
=
MF
->
getSubtarget
().
getRegisterInfo
();
unsigned
RegMaskSize
=
MachineOperand
::
getRegMaskSize
(
TRI
->
getNumRegs
());
// Deep compare of the two RegMasks
return
std
::
equal
(
RegMask
,
RegMask
+
RegMaskSize
,
OtherRegMask
);
}
// We don't know the size of the RegMask, so we can't deep compare the two
// reg masks.
return
false
;
}
case
MachineOperand
::
MO_MCSymbol
:
return
getMCSymbol
()
==
Other
.
getMCSymbol
();
case
MachineOperand
::
MO_DbgInstrRef
:
return
getInstrRefInstrIndex
()
==
Other
.
getInstrRefInstrIndex
()
&&
getInstrRefOpIndex
()
==
Other
.
getInstrRefOpIndex
();
case
MachineOperand
::
MO_CFIIndex
:
return
getCFIIndex
()
==
Other
.
getCFIIndex
();
case
MachineOperand
::
MO_Metadata
:
return
getMetadata
()
==
Other
.
getMetadata
();
case
MachineOperand
::
MO_IntrinsicID
:
return
getIntrinsicID
()
==
Other
.
getIntrinsicID
();
case
MachineOperand
::
MO_Predicate
:
return
getPredicate
()
==
Other
.
getPredicate
();
case
MachineOperand
::
MO_ShuffleMask
:
return
getShuffleMask
()
==
Other
.
getShuffleMask
();
}
llvm_unreachable
(
"Invalid machine operand type"
);
}
// Note: this must stay exactly in sync with isIdenticalTo above.
hash_code
llvm::hash_value
(
const
MachineOperand
&
MO
)
{
switch
(
MO
.
getType
())
{
case
MachineOperand
::
MO_Register
:
// Register operands don't have target flags.
return
hash_combine
(
MO
.
getType
(),
MO
.
getReg
().
id
(),
MO
.
getSubReg
(),
MO
.
isDef
());
case
MachineOperand
::
MO_Immediate
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getImm
());
case
MachineOperand
::
MO_CImmediate
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getCImm
());
case
MachineOperand
::
MO_FPImmediate
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getFPImm
());
case
MachineOperand
::
MO_MachineBasicBlock
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getMBB
());
case
MachineOperand
::
MO_FrameIndex
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getIndex
());
case
MachineOperand
::
MO_ConstantPoolIndex
:
case
MachineOperand
::
MO_TargetIndex
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getIndex
(),
MO
.
getOffset
());
case
MachineOperand
::
MO_JumpTableIndex
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getIndex
());
case
MachineOperand
::
MO_ExternalSymbol
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getOffset
(),
StringRef
(
MO
.
getSymbolName
()));
case
MachineOperand
::
MO_GlobalAddress
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getGlobal
(),
MO
.
getOffset
());
case
MachineOperand
::
MO_BlockAddress
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getBlockAddress
(),
MO
.
getOffset
());
case
MachineOperand
::
MO_RegisterMask
:
case
MachineOperand
::
MO_RegisterLiveOut
:
{
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
MO
))
{
const
TargetRegisterInfo
*
TRI
=
MF
->
getSubtarget
().
getRegisterInfo
();
unsigned
RegMaskSize
=
MachineOperand
::
getRegMaskSize
(
TRI
->
getNumRegs
());
const
uint32_t
*
RegMask
=
MO
.
getRegMask
();
std
::
vector
<
stable_hash
>
RegMaskHashes
(
RegMask
,
RegMask
+
RegMaskSize
);
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
stable_hash_combine
(
RegMaskHashes
));
}
assert
(
0
&&
"MachineOperand not associated with any MachineFunction"
);
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
());
}
case
MachineOperand
::
MO_Metadata
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getMetadata
());
case
MachineOperand
::
MO_MCSymbol
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getMCSymbol
());
case
MachineOperand
::
MO_DbgInstrRef
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getInstrRefInstrIndex
(),
MO
.
getInstrRefOpIndex
());
case
MachineOperand
::
MO_CFIIndex
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getCFIIndex
());
case
MachineOperand
::
MO_IntrinsicID
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getIntrinsicID
());
case
MachineOperand
::
MO_Predicate
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getPredicate
());
case
MachineOperand
::
MO_ShuffleMask
:
return
hash_combine
(
MO
.
getType
(),
MO
.
getTargetFlags
(),
MO
.
getShuffleMask
());
}
llvm_unreachable
(
"Invalid machine operand type"
);
}
// Try to crawl up to the machine function and get TRI from it.
static
void
tryToGetTargetInfo
(
const
MachineOperand
&
MO
,
const
TargetRegisterInfo
*&
TRI
)
{
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
MO
))
{
TRI
=
MF
->
getSubtarget
().
getRegisterInfo
();
}
}
static
const
char
*
getTargetIndexName
(
const
MachineFunction
&
MF
,
int
Index
)
{
const
auto
*
TII
=
MF
.
getSubtarget
().
getInstrInfo
();
assert
(
TII
&&
"expected instruction info"
);
auto
Indices
=
TII
->
getSerializableTargetIndices
();
auto
Found
=
find_if
(
Indices
,
[
&
](
const
std
::
pair
<
int
,
const
char
*>
&
I
)
{
return
I
.
first
==
Index
;
});
if
(
Found
!=
Indices
.
end
())
return
Found
->
second
;
return
nullptr
;
}
const
char
*
MachineOperand::getTargetIndexName
()
const
{
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
);
return
MF
?
::
getTargetIndexName
(
*
MF
,
this
->
getIndex
())
:
nullptr
;
}
static
const
char
*
getTargetFlagName
(
const
TargetInstrInfo
*
TII
,
unsigned
TF
)
{
auto
Flags
=
TII
->
getSerializableDirectMachineOperandTargetFlags
();
for
(
const
auto
&
I
:
Flags
)
{
if
(
I
.
first
==
TF
)
{
return
I
.
second
;
}
}
return
nullptr
;
}
static
void
printCFIRegister
(
unsigned
DwarfReg
,
raw_ostream
&
OS
,
const
TargetRegisterInfo
*
TRI
)
{
if
(
!
TRI
)
{
OS
<<
"%dwarfreg."
<<
DwarfReg
;
return
;
}
if
(
std
::
optional
<
MCRegister
>
Reg
=
TRI
->
getLLVMRegNum
(
DwarfReg
,
true
))
OS
<<
printReg
(
*
Reg
,
TRI
);
else
OS
<<
"<badreg>"
;
}
static
void
printIRBlockReference
(
raw_ostream
&
OS
,
const
BasicBlock
&
BB
,
ModuleSlotTracker
&
MST
)
{
OS
<<
"%ir-block."
;
if
(
BB
.
hasName
())
{
printLLVMNameWithoutPrefix
(
OS
,
BB
.
getName
());
return
;
}
std
::
optional
<
int
>
Slot
;
if
(
const
Function
*
F
=
BB
.
getParent
())
{
if
(
F
==
MST
.
getCurrentFunction
())
{
Slot
=
MST
.
getLocalSlot
(
&
BB
);
}
else
if
(
const
Module
*
M
=
F
->
getParent
())
{
ModuleSlotTracker
CustomMST
(
M
,
/*ShouldInitializeAllMetadata=*/
false
);
CustomMST
.
incorporateFunction
(
*
F
);
Slot
=
CustomMST
.
getLocalSlot
(
&
BB
);
}
}
if
(
Slot
)
MachineOperand
::
printIRSlotNumber
(
OS
,
*
Slot
);
else
OS
<<
"<unknown>"
;
}
static
void
printSyncScope
(
raw_ostream
&
OS
,
const
LLVMContext
&
Context
,
SyncScope
::
ID
SSID
,
SmallVectorImpl
<
StringRef
>
&
SSNs
)
{
switch
(
SSID
)
{
case
SyncScope
::
System
:
break
;
default
:
if
(
SSNs
.
empty
())
Context
.
getSyncScopeNames
(
SSNs
);
OS
<<
"syncscope(
\"
"
;
printEscapedString
(
SSNs
[
SSID
],
OS
);
OS
<<
"
\"
) "
;
break
;
}
}
static
const
char
*
getTargetMMOFlagName
(
const
TargetInstrInfo
&
TII
,
unsigned
TMMOFlag
)
{
auto
Flags
=
TII
.
getSerializableMachineMemOperandTargetFlags
();
for
(
const
auto
&
I
:
Flags
)
{
if
(
I
.
first
==
TMMOFlag
)
{
return
I
.
second
;
}
}
return
nullptr
;
}
static
void
printFrameIndex
(
raw_ostream
&
OS
,
int
FrameIndex
,
bool
IsFixed
,
const
MachineFrameInfo
*
MFI
)
{
StringRef
Name
;
if
(
MFI
)
{
IsFixed
=
MFI
->
isFixedObjectIndex
(
FrameIndex
);
if
(
const
AllocaInst
*
Alloca
=
MFI
->
getObjectAllocation
(
FrameIndex
))
if
(
Alloca
->
hasName
())
Name
=
Alloca
->
getName
();
if
(
IsFixed
)
FrameIndex
-=
MFI
->
getObjectIndexBegin
();
}
MachineOperand
::
printStackObjectReference
(
OS
,
FrameIndex
,
IsFixed
,
Name
);
}
void
MachineOperand::printSubRegIdx
(
raw_ostream
&
OS
,
uint64_t
Index
,
const
TargetRegisterInfo
*
TRI
)
{
OS
<<
"%subreg."
;
if
(
TRI
&&
Index
!=
0
&&
Index
<
TRI
->
getNumSubRegIndices
())
OS
<<
TRI
->
getSubRegIndexName
(
Index
);
else
OS
<<
Index
;
}
void
MachineOperand::printTargetFlags
(
raw_ostream
&
OS
,
const
MachineOperand
&
Op
)
{
if
(
!
Op
.
getTargetFlags
())
return
;
const
MachineFunction
*
MF
=
getMFIfAvailable
(
Op
);
if
(
!
MF
)
return
;
const
auto
*
TII
=
MF
->
getSubtarget
().
getInstrInfo
();
assert
(
TII
&&
"expected instruction info"
);
auto
Flags
=
TII
->
decomposeMachineOperandsTargetFlags
(
Op
.
getTargetFlags
());
OS
<<
"target-flags("
;
const
bool
HasDirectFlags
=
Flags
.
first
;
const
bool
HasBitmaskFlags
=
Flags
.
second
;
if
(
!
HasDirectFlags
&&
!
HasBitmaskFlags
)
{
OS
<<
"<unknown>) "
;
return
;
}
if
(
HasDirectFlags
)
{
if
(
const
auto
*
Name
=
getTargetFlagName
(
TII
,
Flags
.
first
))
OS
<<
Name
;
else
OS
<<
"<unknown target flag>"
;
}
if
(
!
HasBitmaskFlags
)
{
OS
<<
") "
;
return
;
}
bool
IsCommaNeeded
=
HasDirectFlags
;
unsigned
BitMask
=
Flags
.
second
;
auto
BitMasks
=
TII
->
getSerializableBitmaskMachineOperandTargetFlags
();
for
(
const
auto
&
Mask
:
BitMasks
)
{
// Check if the flag's bitmask has the bits of the current mask set.
if
((
BitMask
&
Mask
.
first
)
==
Mask
.
first
)
{
if
(
IsCommaNeeded
)
OS
<<
", "
;
IsCommaNeeded
=
true
;
OS
<<
Mask
.
second
;
// Clear the bits which were serialized from the flag's bitmask.
BitMask
&=
~
(
Mask
.
first
);
}
}
if
(
BitMask
)
{
// When the resulting flag's bitmask isn't zero, we know that we didn't
// serialize all of the bit flags.
if
(
IsCommaNeeded
)
OS
<<
", "
;
OS
<<
"<unknown bitmask target flag>"
;
}
OS
<<
") "
;
}
void
MachineOperand::printSymbol
(
raw_ostream
&
OS
,
MCSymbol
&
Sym
)
{
OS
<<
"<mcsymbol "
<<
Sym
<<
">"
;
}
void
MachineOperand::printStackObjectReference
(
raw_ostream
&
OS
,
unsigned
FrameIndex
,
bool
IsFixed
,
StringRef
Name
)
{
if
(
IsFixed
)
{
OS
<<
"%fixed-stack."
<<
FrameIndex
;
return
;
}
OS
<<
"%stack."
<<
FrameIndex
;
if
(
!
Name
.
empty
())
OS
<<
'.'
<<
Name
;
}
void
MachineOperand::printOperandOffset
(
raw_ostream
&
OS
,
int64_t
Offset
)
{
if
(
Offset
==
0
)
return
;
if
(
Offset
<
0
)
{
OS
<<
" - "
<<
-
Offset
;
return
;
}
OS
<<
" + "
<<
Offset
;
}
void
MachineOperand::printIRSlotNumber
(
raw_ostream
&
OS
,
int
Slot
)
{
if
(
Slot
==
-1
)
OS
<<
"<badref>"
;
else
OS
<<
Slot
;
}
static
void
printCFI
(
raw_ostream
&
OS
,
const
MCCFIInstruction
&
CFI
,
const
TargetRegisterInfo
*
TRI
)
{
switch
(
CFI
.
getOperation
())
{
case
MCCFIInstruction
::
OpSameValue
:
OS
<<
"same_value "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
break
;
case
MCCFIInstruction
::
OpRememberState
:
OS
<<
"remember_state "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
break
;
case
MCCFIInstruction
::
OpRestoreState
:
OS
<<
"restore_state "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
break
;
case
MCCFIInstruction
::
OpOffset
:
OS
<<
"offset "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
OS
<<
", "
<<
CFI
.
getOffset
();
break
;
case
MCCFIInstruction
::
OpDefCfaRegister
:
OS
<<
"def_cfa_register "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
break
;
case
MCCFIInstruction
::
OpDefCfaOffset
:
OS
<<
"def_cfa_offset "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
OS
<<
CFI
.
getOffset
();
break
;
case
MCCFIInstruction
::
OpDefCfa
:
OS
<<
"def_cfa "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
OS
<<
", "
<<
CFI
.
getOffset
();
break
;
case
MCCFIInstruction
::
OpLLVMDefAspaceCfa
:
OS
<<
"llvm_def_aspace_cfa "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
OS
<<
", "
<<
CFI
.
getOffset
();
OS
<<
", "
<<
CFI
.
getAddressSpace
();
break
;
case
MCCFIInstruction
::
OpRelOffset
:
OS
<<
"rel_offset "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
OS
<<
", "
<<
CFI
.
getOffset
();
break
;
case
MCCFIInstruction
::
OpAdjustCfaOffset
:
OS
<<
"adjust_cfa_offset "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
OS
<<
CFI
.
getOffset
();
break
;
case
MCCFIInstruction
::
OpRestore
:
OS
<<
"restore "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
break
;
case
MCCFIInstruction
::
OpEscape
:
{
OS
<<
"escape "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
if
(
!
CFI
.
getValues
().
empty
())
{
size_t
e
=
CFI
.
getValues
().
size
()
-
1
;
for
(
size_t
i
=
0
;
i
<
e
;
++
i
)
OS
<<
format
(
"0x%02x"
,
uint8_t
(
CFI
.
getValues
()[
i
]))
<<
", "
;
OS
<<
format
(
"0x%02x"
,
uint8_t
(
CFI
.
getValues
()[
e
]));
}
break
;
}
case
MCCFIInstruction
::
OpUndefined
:
OS
<<
"undefined "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
break
;
case
MCCFIInstruction
::
OpRegister
:
OS
<<
"register "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
printCFIRegister
(
CFI
.
getRegister
(),
OS
,
TRI
);
OS
<<
", "
;
printCFIRegister
(
CFI
.
getRegister2
(),
OS
,
TRI
);
break
;
case
MCCFIInstruction
::
OpWindowSave
:
OS
<<
"window_save "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
break
;
case
MCCFIInstruction
::
OpNegateRAState
:
OS
<<
"negate_ra_sign_state "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
break
;
case
MCCFIInstruction
::
OpNegateRAStateWithPC
:
OS
<<
"negate_ra_sign_state_with_pc "
;
if
(
MCSymbol
*
Label
=
CFI
.
getLabel
())
MachineOperand
::
printSymbol
(
OS
,
*
Label
);
break
;
default
:
// TODO: Print the other CFI Operations.
OS
<<
"<unserializable cfi directive>"
;
break
;
}
}
void
MachineOperand::print
(
raw_ostream
&
OS
,
const
TargetRegisterInfo
*
TRI
)
const
{
print
(
OS
,
LLT
{},
TRI
);
}
void
MachineOperand::print
(
raw_ostream
&
OS
,
LLT
TypeToPrint
,
const
TargetRegisterInfo
*
TRI
)
const
{
tryToGetTargetInfo
(
*
this
,
TRI
);
ModuleSlotTracker
DummyMST
(
nullptr
);
print
(
OS
,
DummyMST
,
TypeToPrint
,
std
::
nullopt
,
/*PrintDef=*/
false
,
/*IsStandalone=*/
true
,
/*ShouldPrintRegisterTies=*/
true
,
/*TiedOperandIdx=*/
0
,
TRI
);
}
void
MachineOperand::print
(
raw_ostream
&
OS
,
ModuleSlotTracker
&
MST
,
LLT
TypeToPrint
,
std
::
optional
<
unsigned
>
OpIdx
,
bool
PrintDef
,
bool
IsStandalone
,
bool
ShouldPrintRegisterTies
,
unsigned
TiedOperandIdx
,
const
TargetRegisterInfo
*
TRI
)
const
{
printTargetFlags
(
OS
,
*
this
);
switch
(
getType
())
{
case
MachineOperand
::
MO_Register
:
{
Register
Reg
=
getReg
();
if
(
isImplicit
())
OS
<<
(
isDef
()
?
"implicit-def "
:
"implicit "
);
else
if
(
PrintDef
&&
isDef
())
// Print the 'def' flag only when the operand is defined after '='.
OS
<<
"def "
;
if
(
isInternalRead
())
OS
<<
"internal "
;
if
(
isDead
())
OS
<<
"dead "
;
if
(
isKill
())
OS
<<
"killed "
;
if
(
isUndef
())
OS
<<
"undef "
;
if
(
isEarlyClobber
())
OS
<<
"early-clobber "
;
if
(
getReg
().
isPhysical
()
&&
isRenamable
())
OS
<<
"renamable "
;
// isDebug() is exactly true for register operands of a DBG_VALUE. So we
// simply infer it when parsing and do not need to print it.
const
MachineRegisterInfo
*
MRI
=
nullptr
;
if
(
Reg
.
isVirtual
())
{
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
MRI
=
&
MF
->
getRegInfo
();
}
}
OS
<<
printReg
(
Reg
,
TRI
,
0
,
MRI
);
// Print the sub register.
if
(
unsigned
SubReg
=
getSubReg
())
{
if
(
TRI
)
OS
<<
'.'
<<
TRI
->
getSubRegIndexName
(
SubReg
);
else
OS
<<
".subreg"
<<
SubReg
;
}
// Print the register class / bank.
if
(
Reg
.
isVirtual
())
{
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
const
MachineRegisterInfo
&
MRI
=
MF
->
getRegInfo
();
if
(
IsStandalone
||
!
PrintDef
||
MRI
.
def_empty
(
Reg
))
{
OS
<<
':'
;
OS
<<
printRegClassOrBank
(
Reg
,
MRI
,
TRI
);
}
}
}
// Print ties.
if
(
ShouldPrintRegisterTies
&&
isTied
()
&&
!
isDef
())
OS
<<
"(tied-def "
<<
TiedOperandIdx
<<
")"
;
// Print types.
if
(
TypeToPrint
.
isValid
())
OS
<<
'('
<<
TypeToPrint
<<
')'
;
break
;
}
case
MachineOperand
::
MO_Immediate
:
{
const
MIRFormatter
*
Formatter
=
nullptr
;
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
{
const
auto
*
TII
=
MF
->
getSubtarget
().
getInstrInfo
();
assert
(
TII
&&
"expected instruction info"
);
Formatter
=
TII
->
getMIRFormatter
();
}
if
(
Formatter
)
Formatter
->
printImm
(
OS
,
*
getParent
(),
OpIdx
,
getImm
());
else
OS
<<
getImm
();
break
;
}
case
MachineOperand
::
MO_CImmediate
:
getCImm
()
->
printAsOperand
(
OS
,
/*PrintType=*/
true
,
MST
);
break
;
case
MachineOperand
::
MO_FPImmediate
:
getFPImm
()
->
printAsOperand
(
OS
,
/*PrintType=*/
true
,
MST
);
break
;
case
MachineOperand
::
MO_MachineBasicBlock
:
OS
<<
printMBBReference
(
*
getMBB
());
break
;
case
MachineOperand
::
MO_FrameIndex
:
{
int
FrameIndex
=
getIndex
();
bool
IsFixed
=
false
;
const
MachineFrameInfo
*
MFI
=
nullptr
;
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
MFI
=
&
MF
->
getFrameInfo
();
printFrameIndex
(
OS
,
FrameIndex
,
IsFixed
,
MFI
);
break
;
}
case
MachineOperand
::
MO_ConstantPoolIndex
:
OS
<<
"%const."
<<
getIndex
();
printOperandOffset
(
OS
,
getOffset
());
break
;
case
MachineOperand
::
MO_TargetIndex
:
{
OS
<<
"target-index("
;
const
char
*
Name
=
"<unknown>"
;
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
if
(
const
auto
*
TargetIndexName
=
::
getTargetIndexName
(
*
MF
,
getIndex
()))
Name
=
TargetIndexName
;
OS
<<
Name
<<
')'
;
printOperandOffset
(
OS
,
getOffset
());
break
;
}
case
MachineOperand
::
MO_JumpTableIndex
:
OS
<<
printJumpTableEntryReference
(
getIndex
());
break
;
case
MachineOperand
::
MO_GlobalAddress
:
if
(
auto
*
GV
=
getGlobal
())
GV
->
printAsOperand
(
OS
,
/*PrintType=*/
false
,
MST
);
else
// Invalid, but may appear in debugging scenarios.
OS
<<
"globaladdress(null)"
;
printOperandOffset
(
OS
,
getOffset
());
break
;
case
MachineOperand
::
MO_ExternalSymbol
:
{
StringRef
Name
=
getSymbolName
();
OS
<<
'&'
;
if
(
Name
.
empty
())
{
OS
<<
"
\"\"
"
;
}
else
{
printLLVMNameWithoutPrefix
(
OS
,
Name
);
}
printOperandOffset
(
OS
,
getOffset
());
break
;
}
case
MachineOperand
::
MO_BlockAddress
:
{
OS
<<
"blockaddress("
;
getBlockAddress
()
->
getFunction
()
->
printAsOperand
(
OS
,
/*PrintType=*/
false
,
MST
);
OS
<<
", "
;
printIRBlockReference
(
OS
,
*
getBlockAddress
()
->
getBasicBlock
(),
MST
);
OS
<<
')'
;
MachineOperand
::
printOperandOffset
(
OS
,
getOffset
());
break
;
}
case
MachineOperand
::
MO_RegisterMask
:
{
OS
<<
"<regmask"
;
if
(
TRI
)
{
unsigned
NumRegsInMask
=
0
;
unsigned
NumRegsEmitted
=
0
;
for
(
unsigned
i
=
0
;
i
<
TRI
->
getNumRegs
();
++
i
)
{
unsigned
MaskWord
=
i
/
32
;
unsigned
MaskBit
=
i
%
32
;
if
(
getRegMask
()[
MaskWord
]
&
(
1
<<
MaskBit
))
{
if
(
PrintRegMaskNumRegs
<
0
||
NumRegsEmitted
<=
static_cast
<
unsigned
>
(
PrintRegMaskNumRegs
))
{
OS
<<
" "
<<
printReg
(
i
,
TRI
);
NumRegsEmitted
++
;
}
NumRegsInMask
++
;
}
}
if
(
NumRegsEmitted
!=
NumRegsInMask
)
OS
<<
" and "
<<
(
NumRegsInMask
-
NumRegsEmitted
)
<<
" more..."
;
}
else
{
OS
<<
" ..."
;
}
OS
<<
">"
;
break
;
}
case
MachineOperand
::
MO_RegisterLiveOut
:
{
const
uint32_t
*
RegMask
=
getRegLiveOut
();
OS
<<
"liveout("
;
if
(
!
TRI
)
{
OS
<<
"<unknown>"
;
}
else
{
bool
IsCommaNeeded
=
false
;
for
(
unsigned
Reg
=
0
,
E
=
TRI
->
getNumRegs
();
Reg
<
E
;
++
Reg
)
{
if
(
RegMask
[
Reg
/
32
]
&
(
1U
<<
(
Reg
%
32
)))
{
if
(
IsCommaNeeded
)
OS
<<
", "
;
OS
<<
printReg
(
Reg
,
TRI
);
IsCommaNeeded
=
true
;
}
}
}
OS
<<
")"
;
break
;
}
case
MachineOperand
::
MO_Metadata
:
getMetadata
()
->
printAsOperand
(
OS
,
MST
);
break
;
case
MachineOperand
::
MO_MCSymbol
:
printSymbol
(
OS
,
*
getMCSymbol
());
break
;
case
MachineOperand
::
MO_DbgInstrRef
:
{
OS
<<
"dbg-instr-ref("
<<
getInstrRefInstrIndex
()
<<
", "
<<
getInstrRefOpIndex
()
<<
')'
;
break
;
}
case
MachineOperand
::
MO_CFIIndex
:
{
if
(
const
MachineFunction
*
MF
=
getMFIfAvailable
(
*
this
))
printCFI
(
OS
,
MF
->
getFrameInstructions
()[
getCFIIndex
()],
TRI
);
else
OS
<<
"<cfi directive>"
;
break
;
}
case
MachineOperand
::
MO_IntrinsicID
:
{
Intrinsic
::
ID
ID
=
getIntrinsicID
();
if
(
ID
<
Intrinsic
::
num_intrinsics
)
OS
<<
"intrinsic(@"
<<
Intrinsic
::
getBaseName
(
ID
)
<<
')'
;
else
OS
<<
"intrinsic("
<<
ID
<<
')'
;
break
;
}
case
MachineOperand
::
MO_Predicate
:
{
auto
Pred
=
static_cast
<
CmpInst
::
Predicate
>
(
getPredicate
());
OS
<<
(
CmpInst
::
isIntPredicate
(
Pred
)
?
"int"
:
"float"
)
<<
"pred("
<<
Pred
<<
')'
;
break
;
}
case
MachineOperand
::
MO_ShuffleMask
:
OS
<<
"shufflemask("
;
ArrayRef
<
int
>
Mask
=
getShuffleMask
();
StringRef
Separator
;
for
(
int
Elt
:
Mask
)
{
if
(
Elt
==
-1
)
OS
<<
Separator
<<
"undef"
;
else
OS
<<
Separator
<<
Elt
;
Separator
=
", "
;
}
OS
<<
')'
;
break
;
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD
void
MachineOperand
::
dump
()
const
{
dbgs
()
<<
*
this
<<
'\n'
;
}
#endif
//===----------------------------------------------------------------------===//
// MachineMemOperand Implementation
//===----------------------------------------------------------------------===//
/// getAddrSpace - Return the LLVM IR address space number that this pointer
/// points into.
unsigned
MachinePointerInfo
::
getAddrSpace
()
const
{
return
AddrSpace
;
}
/// isDereferenceable - Return true if V is always dereferenceable for
/// Offset + Size byte.
bool
MachinePointerInfo
::
isDereferenceable
(
unsigned
Size
,
LLVMContext
&
C
,
const
DataLayout
&
DL
)
const
{
if
(
!
isa
<
const
Value
*>
(
V
))
return
false
;
const
Value
*
BasePtr
=
cast
<
const
Value
*>
(
V
);
if
(
BasePtr
==
nullptr
)
return
false
;
return
isDereferenceableAndAlignedPointer
(
BasePtr
,
Align
(
1
),
APInt
(
DL
.
getPointerSizeInBits
(),
Offset
+
Size
),
DL
,
dyn_cast
<
Instruction
>
(
BasePtr
));
}
/// getConstantPool - Return a MachinePointerInfo record that refers to the
/// constant pool.
MachinePointerInfo
MachinePointerInfo
::
getConstantPool
(
MachineFunction
&
MF
)
{
return
MachinePointerInfo
(
MF
.
getPSVManager
().
getConstantPool
());
}
/// getFixedStack - Return a MachinePointerInfo record that refers to the
/// the specified FrameIndex.
MachinePointerInfo
MachinePointerInfo
::
getFixedStack
(
MachineFunction
&
MF
,
int
FI
,
int64_t
Offset
)
{
return
MachinePointerInfo
(
MF
.
getPSVManager
().
getFixedStack
(
FI
),
Offset
);
}
MachinePointerInfo
MachinePointerInfo
::
getJumpTable
(
MachineFunction
&
MF
)
{
return
MachinePointerInfo
(
MF
.
getPSVManager
().
getJumpTable
());
}
MachinePointerInfo
MachinePointerInfo
::
getGOT
(
MachineFunction
&
MF
)
{
return
MachinePointerInfo
(
MF
.
getPSVManager
().
getGOT
());
}
MachinePointerInfo
MachinePointerInfo
::
getStack
(
MachineFunction
&
MF
,
int64_t
Offset
,
uint8_t
ID
)
{
return
MachinePointerInfo
(
MF
.
getPSVManager
().
getStack
(),
Offset
,
ID
);
}
MachinePointerInfo
MachinePointerInfo
::
getUnknownStack
(
MachineFunction
&
MF
)
{
return
MachinePointerInfo
(
MF
.
getDataLayout
().
getAllocaAddrSpace
());
}
MachineMemOperand
::
MachineMemOperand
(
MachinePointerInfo
ptrinfo
,
Flags
f
,
LLT
type
,
Align
a
,
const
AAMDNodes
&
AAInfo
,
const
MDNode
*
Ranges
,
SyncScope
::
ID
SSID
,
AtomicOrdering
Ordering
,
AtomicOrdering
FailureOrdering
)
:
PtrInfo
(
ptrinfo
),
MemoryType
(
type
),
FlagVals
(
f
),
BaseAlign
(
a
),
AAInfo
(
AAInfo
),
Ranges
(
Ranges
)
{
assert
((
PtrInfo
.
V
.
isNull
()
||
isa
<
const
PseudoSourceValue
*>
(
PtrInfo
.
V
)
||
isa
<
PointerType
>
(
cast
<
const
Value
*>
(
PtrInfo
.
V
)
->
getType
()))
&&
"invalid pointer value"
);
assert
((
isLoad
()
||
isStore
())
&&
"Not a load/store!"
);
AtomicInfo
.
SSID
=
static_cast
<
unsigned
>
(
SSID
);
assert
(
getSyncScopeID
()
==
SSID
&&
"Value truncated"
);
AtomicInfo
.
Ordering
=
static_cast
<
unsigned
>
(
Ordering
);
assert
(
getSuccessOrdering
()
==
Ordering
&&
"Value truncated"
);
AtomicInfo
.
FailureOrdering
=
static_cast
<
unsigned
>
(
FailureOrdering
);
assert
(
getFailureOrdering
()
==
FailureOrdering
&&
"Value truncated"
);
}
MachineMemOperand
::
MachineMemOperand
(
MachinePointerInfo
ptrinfo
,
Flags
F
,
LocationSize
TS
,
Align
BaseAlignment
,
const
AAMDNodes
&
AAInfo
,
const
MDNode
*
Ranges
,
SyncScope
::
ID
SSID
,
AtomicOrdering
Ordering
,
AtomicOrdering
FailureOrdering
)
:
MachineMemOperand
(
ptrinfo
,
F
,
!
TS
.
hasValue
()
?
LLT
()
:
TS
.
isScalable
()
?
LLT
::
scalable_vector
(
1
,
8
*
TS
.
getValue
().
getKnownMinValue
())
:
LLT
::
scalar
(
8
*
TS
.
getValue
().
getKnownMinValue
()),
BaseAlignment
,
AAInfo
,
Ranges
,
SSID
,
Ordering
,
FailureOrdering
)
{}
void
MachineMemOperand
::
refineAlignment
(
const
MachineMemOperand
*
MMO
)
{
// The Value and Offset may differ due to CSE. But the flags and size
// should be the same.
assert
(
MMO
->
getFlags
()
==
getFlags
()
&&
"Flags mismatch!"
);
assert
((
!
MMO
->
getSize
().
hasValue
()
||
!
getSize
().
hasValue
()
||
MMO
->
getSize
()
==
getSize
())
&&
"Size mismatch!"
);
if
(
MMO
->
getBaseAlign
()
>=
getBaseAlign
())
{
// Update the alignment value.
BaseAlign
=
MMO
->
getBaseAlign
();
// Also update the base and offset, because the new alignment may
// not be applicable with the old ones.
PtrInfo
=
MMO
->
PtrInfo
;
}
}
/// getAlign - Return the minimum known alignment in bytes of the
/// actual memory reference.
Align
MachineMemOperand
::
getAlign
()
const
{
return
commonAlignment
(
getBaseAlign
(),
getOffset
());
}
void
MachineMemOperand
::
print
(
raw_ostream
&
OS
,
ModuleSlotTracker
&
MST
,
SmallVectorImpl
<
StringRef
>
&
SSNs
,
const
LLVMContext
&
Context
,
const
MachineFrameInfo
*
MFI
,
const
TargetInstrInfo
*
TII
)
const
{
OS
<<
'('
;
if
(
isVolatile
())
OS
<<
"volatile "
;
if
(
isNonTemporal
())
OS
<<
"non-temporal "
;
if
(
isDereferenceable
())
OS
<<
"dereferenceable "
;
if
(
isInvariant
())
OS
<<
"invariant "
;
if
(
TII
)
{
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag1
)
OS
<<
'"'
<<
getTargetMMOFlagName
(
*
TII
,
MachineMemOperand
::
MOTargetFlag1
)
<<
"
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag2
)
OS
<<
'"'
<<
getTargetMMOFlagName
(
*
TII
,
MachineMemOperand
::
MOTargetFlag2
)
<<
"
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag3
)
OS
<<
'"'
<<
getTargetMMOFlagName
(
*
TII
,
MachineMemOperand
::
MOTargetFlag3
)
<<
"
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag4
)
OS
<<
'"'
<<
getTargetMMOFlagName
(
*
TII
,
MachineMemOperand
::
MOTargetFlag4
)
<<
"
\"
"
;
}
else
{
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag1
)
OS
<<
"
\"
MOTargetFlag1
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag2
)
OS
<<
"
\"
MOTargetFlag2
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag3
)
OS
<<
"
\"
MOTargetFlag3
\"
"
;
if
(
getFlags
()
&
MachineMemOperand
::
MOTargetFlag4
)
OS
<<
"
\"
MOTargetFlag4
\"
"
;
}
assert
((
isLoad
()
||
isStore
())
&&
"machine memory operand must be a load or store (or both)"
);
if
(
isLoad
())
OS
<<
"load "
;
if
(
isStore
())
OS
<<
"store "
;
printSyncScope
(
OS
,
Context
,
getSyncScopeID
(),
SSNs
);
if
(
getSuccessOrdering
()
!=
AtomicOrdering
::
NotAtomic
)
OS
<<
toIRString
(
getSuccessOrdering
())
<<
' '
;
if
(
getFailureOrdering
()
!=
AtomicOrdering
::
NotAtomic
)
OS
<<
toIRString
(
getFailureOrdering
())
<<
' '
;
if
(
getMemoryType
().
isValid
())
OS
<<
'('
<<
getMemoryType
()
<<
')'
;
else
OS
<<
"unknown-size"
;
if
(
const
Value
*
Val
=
getValue
())
{
OS
<<
((
isLoad
()
&&
isStore
())
?
" on "
:
isLoad
()
?
" from "
:
" into "
);
MIRFormatter
::
printIRValue
(
OS
,
*
Val
,
MST
);
}
else
if
(
const
PseudoSourceValue
*
PVal
=
getPseudoValue
())
{
OS
<<
((
isLoad
()
&&
isStore
())
?
" on "
:
isLoad
()
?
" from "
:
" into "
);
assert
(
PVal
&&
"Expected a pseudo source value"
);
switch
(
PVal
->
kind
())
{
case
PseudoSourceValue
::
Stack
:
OS
<<
"stack"
;
break
;
case
PseudoSourceValue
::
GOT
:
OS
<<
"got"
;
break
;
case
PseudoSourceValue
::
JumpTable
:
OS
<<
"jump-table"
;
break
;
case
PseudoSourceValue
::
ConstantPool
:
OS
<<
"constant-pool"
;
break
;
case
PseudoSourceValue
::
FixedStack
:
{
int
FrameIndex
=
cast
<
FixedStackPseudoSourceValue
>
(
PVal
)
->
getFrameIndex
();
bool
IsFixed
=
true
;
printFrameIndex
(
OS
,
FrameIndex
,
IsFixed
,
MFI
);
break
;
}
case
PseudoSourceValue
::
GlobalValueCallEntry
:
OS
<<
"call-entry "
;
cast
<
GlobalValuePseudoSourceValue
>
(
PVal
)
->
getValue
()
->
printAsOperand
(
OS
,
/*PrintType=*/
false
,
MST
);
break
;
case
PseudoSourceValue
::
ExternalSymbolCallEntry
:
OS
<<
"call-entry &"
;
printLLVMNameWithoutPrefix
(
OS
,
cast
<
ExternalSymbolPseudoSourceValue
>
(
PVal
)
->
getSymbol
());
break
;
default
:
{
// FIXME: This is not necessarily the correct MIR serialization format for
// a custom pseudo source value, but at least it allows
// MIR printing to work on a target with custom pseudo source
// values.
OS
<<
"custom
\"
"
;
if
(
TII
)
{
const
MIRFormatter
*
Formatter
=
TII
->
getMIRFormatter
();
Formatter
->
printCustomPseudoSourceValue
(
OS
,
MST
,
*
PVal
);
}
else
{
PVal
->
printCustom
(
OS
);
}
OS
<<
'\"'
;
break
;
}
}
}
else
if
(
getOpaqueValue
()
==
nullptr
&&
getOffset
()
!=
0
)
{
OS
<<
((
isLoad
()
&&
isStore
())
?
" on "
:
isLoad
()
?
" from "
:
" into "
)
<<
"unknown-address"
;
}
MachineOperand
::
printOperandOffset
(
OS
,
getOffset
());
if
(
!
getSize
().
hasValue
()
||
(
!
getSize
().
isZero
()
&&
getAlign
()
!=
getSize
().
getValue
().
getKnownMinValue
()))
OS
<<
", align "
<<
getAlign
().
value
();
if
(
getAlign
()
!=
getBaseAlign
())
OS
<<
", basealign "
<<
getBaseAlign
().
value
();
auto
AAInfo
=
getAAInfo
();
if
(
AAInfo
.
TBAA
)
{
OS
<<
", !tbaa "
;
AAInfo
.
TBAA
->
printAsOperand
(
OS
,
MST
);
}
if
(
AAInfo
.
Scope
)
{
OS
<<
", !alias.scope "
;
AAInfo
.
Scope
->
printAsOperand
(
OS
,
MST
);
}
if
(
AAInfo
.
NoAlias
)
{
OS
<<
", !noalias "
;
AAInfo
.
NoAlias
->
printAsOperand
(
OS
,
MST
);
}
if
(
getRanges
())
{
OS
<<
", !range "
;
getRanges
()
->
printAsOperand
(
OS
,
MST
);
}
// FIXME: Implement addrspace printing/parsing in MIR.
// For now, print this even though parsing it is not available in MIR.
if
(
unsigned
AS
=
getAddrSpace
())
OS
<<
", addrspace "
<<
AS
;
OS
<<
')'
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Jul 7, 2:37 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29019889
Default Alt Text
MachineOperand.cpp (43 KB)
Attached To
Mode
rG FreeBSD src repository
Attached
Detach File
Event Timeline
Log In to Comment