Go to the documentation of this file.
29 #define DEBUG_TYPE "arm-sls-hardening"
31 #define ARM_SLS_HARDENING_NAME "ARM sls hardening pass"
76 "Must not insert SpeculationBarrierEndBB as only instruction in MBB.");
78 "SpeculationBarrierEndBB must only follow unconditional control flow "
81 "SpeculationBarrierEndBB must only follow terminators.");
86 ProduceSB ? (
ST->isThumb() ? ARM::t2SpeculationBarrierSBEndBB
87 : ARM::SpeculationBarrierSBEndBB)
88 : (
ST->isThumb() ? ARM::t2SpeculationBarrierISBDSBEndBB
89 : ARM::SpeculationBarrierISBDSBEndBB);
99 for (
auto &
MBB : MF) {
108 if (!
ST->hardenSlsRetBr())
116 NextMBBI = std::next(
MBBI);
120 insertSpeculationBarrier(
ST,
MBB, std::next(
MBBI),
MI.getDebugLoc());
127 static const char SLSBLRNamePrefix[] =
"__llvm_slsblr_thunk_";
134 {
"__llvm_slsblr_thunk_arm_r0", ARM::R0,
false},
135 {
"__llvm_slsblr_thunk_arm_r1", ARM::R1,
false},
136 {
"__llvm_slsblr_thunk_arm_r2",
ARM::R2,
false},
137 {
"__llvm_slsblr_thunk_arm_r3", ARM::R3,
false},
138 {
"__llvm_slsblr_thunk_arm_r4",
ARM::R4,
false},
139 {
"__llvm_slsblr_thunk_arm_r5", ARM::R5,
false},
140 {
"__llvm_slsblr_thunk_arm_r6",
ARM::R6,
false},
141 {
"__llvm_slsblr_thunk_arm_r7", ARM::R7,
false},
142 {
"__llvm_slsblr_thunk_arm_r8", ARM::R8,
false},
143 {
"__llvm_slsblr_thunk_arm_r9", ARM::R9,
false},
144 {
"__llvm_slsblr_thunk_arm_r10", ARM::R10,
false},
145 {
"__llvm_slsblr_thunk_arm_r11", ARM::R11,
false},
146 {
"__llvm_slsblr_thunk_arm_sp", ARM::SP,
false},
147 {
"__llvm_slsblr_thunk_arm_pc", ARM::PC,
false},
148 {
"__llvm_slsblr_thunk_thumb_r0", ARM::R0,
true},
149 {
"__llvm_slsblr_thunk_thumb_r1", ARM::R1,
true},
150 {
"__llvm_slsblr_thunk_thumb_r2",
ARM::R2,
true},
151 {
"__llvm_slsblr_thunk_thumb_r3", ARM::R3,
true},
152 {
"__llvm_slsblr_thunk_thumb_r4",
ARM::R4,
true},
153 {
"__llvm_slsblr_thunk_thumb_r5", ARM::R5,
true},
154 {
"__llvm_slsblr_thunk_thumb_r6",
ARM::R6,
true},
155 {
"__llvm_slsblr_thunk_thumb_r7", ARM::R7,
true},
156 {
"__llvm_slsblr_thunk_thumb_r8", ARM::R8,
true},
157 {
"__llvm_slsblr_thunk_thumb_r9", ARM::R9,
true},
158 {
"__llvm_slsblr_thunk_thumb_r10", ARM::R10,
true},
159 {
"__llvm_slsblr_thunk_thumb_r11", ARM::R11,
true},
160 {
"__llvm_slsblr_thunk_thumb_sp", ARM::SP,
true},
161 {
"__llvm_slsblr_thunk_thumb_pc", ARM::PC,
true},
165 struct SLSBLRThunkInserter :
ThunkInserter<SLSBLRThunkInserter> {
166 const char *getThunkPrefix() {
return SLSBLRNamePrefix; }
177 bool ComdatThunks =
true;
186 createThunkFunction(MMI,
T.Name, ComdatThunks);
197 bool isThumb = ThunkIt->isThumb;
207 Entry->addLiveIn(ThunkReg);
257 int RegOpIdxOnIndirectCall = -1;
263 RegOpIdxOnIndirectCall = 0;
266 case ARM::tBLXr_noip:
268 RegOpIdxOnIndirectCall = 2;
282 bool RegIsKilled =
IndirectCall.getOperand(RegOpIdxOnIndirectCall).isKill();
292 const GlobalValue *GV = cast<GlobalValue>(
M->getNamedValue(ThunkIt->Name));
311 for (
unsigned OpIdx =
BL->getNumExplicitOperands();
312 OpIdx < BL->getNumOperands(); OpIdx++) {
316 if (
Op.getReg() == ARM::LR &&
Op.isDef())
318 if (
Op.getReg() == ARM::SP && !
Op.isDef())
323 int FirstOpIdxToRemove =
std::max(ImpLROpIdx, ImpSPOpIdx);
324 int SecondOpIdxToRemove =
std::min(ImpLROpIdx, ImpSPOpIdx);
325 BL->removeOperand(FirstOpIdxToRemove);
326 BL->removeOperand(SecondOpIdxToRemove);
328 BL->copyImplicitOps(MF, IndirectCall);
340 if (!
ST->hardenSlsBlr())
347 NextMBBI = std::next(
MBBI);
352 ConvertIndirectCallToIndirectJump(
MBB,
MBBI);
362 return new ARMSLSHardening();
372 StringRef getPassName()
const override {
return "ARM Indirect Thunks"; }
374 bool doInitialization(
Module &M)
override;
384 std::tuple<SLSBLRThunkInserter> TIs;
387 template <
typename... ThunkInserterT>
388 static void initTIs(
Module &M,
389 std::tuple<ThunkInserterT...> &ThunkInserters) {
390 (void)std::initializer_list<int>{
391 (std::get<ThunkInserterT>(ThunkInserters).init(M), 0)...};
393 template <
typename... ThunkInserterT>
395 std::tuple<ThunkInserterT...> &ThunkInserters) {
397 (void)std::initializer_list<int>{
398 Modified |= std::get<ThunkInserterT>(ThunkInserters).run(MMI, MF)...};
408 return new ARMIndirectThunks();
411 bool ARMIndirectThunks::doInitialization(
Module &M) {
418 auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
419 return runTIs(MMI, MF, TIs);
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
MachineBasicBlock MachineBasicBlock::iterator DebugLoc bool AlwaysUseISBDSB
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
const MachineInstrBuilder & add(const MachineOperand &MO) const
virtual const TargetInstrInfo * getInstrInfo() const
Reg
All possible values of the reg field in the ModR/M byte.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const_iterator end(StringRef path)
Get end iterator over path.
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const MachineBasicBlock & front() const
TargetInstrInfo - Interface to description of machine instruction set.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void initializeARMSLSHardeningPass(PassRegistry &)
Represent the analysis usage information of a pass.
const HexagonInstrInfo * TII
MachineOperand class - Representation of each machine instruction operand.
This class contains meta information specific to a module.
static bool isThumb(const MCSubtargetInfo &STI)
INITIALIZE_PASS(ARMSLSHardening, "arm-sls-hardening", ARM_SLS_HARDENING_NAME, false, false) static void insertSpeculationBarrier(const ARMSubtarget *ST
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
#define ARM_SLS_HARDENING_NAME
Representation of each machine instruction.
Module * getParent()
Get the module that this global value is contained inside of...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
A Module instance is used to store all the information related to an LLVM module.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
FunctionPass * createARMSLSHardeningPass()
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static bool isIndirectCall(const MachineInstr &MI)
FunctionPass * createARMIndirectThunks()
Wrapper class representing virtual and physical registers.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)
static const struct ThunkNameRegMode SLSBLRThunks[]
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineBasicBlock MachineBasicBlock::iterator MBBI
FunctionPass class - This class is used to implement most global optimizations.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
AnalysisUsage & addRequired()
static bool isSpeculationBarrierEndBBOpcode(int Opc)