Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
Show First 20 Lines • Show All 5,836 Lines • ▼ Show 20 Lines | AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const { | |||||||||
// No suitable register. Return 0. | // No suitable register. Return 0. | |||||||||
return 0u; | return 0u; | |||||||||
} | } | |||||||||
static bool | static bool | |||||||||
outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, | outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, | |||||||||
const outliner::Candidate &b) { | const outliner::Candidate &b) { | |||||||||
const Function &Fa = a.getMF()->getFunction(); | const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>(); | |||||||||
const Function &Fb = b.getMF()->getFunction(); | const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>(); | |||||||||
tellenbach: Is this a typo?
| ||||||||||
D'oh, bloody copy/paste. Good catch, thanks! chill: D'oh, bloody copy/paste. Good catch, thanks! | ||||||||||
// If none of the functions have the "sign-return-address" attribute their | return MFIa->shouldSignReturnAddress(false) == MFIb->shouldSignReturnAddress(false) && | |||||||||
// signing behaviour is equal | MFIa->shouldSignReturnAddress(true) == MFIb->shouldSignReturnAddress(true); | |||||||||
if (!Fa.hasFnAttribute("sign-return-address") && | ||||||||||
!Fb.hasFnAttribute("sign-return-address")) { | ||||||||||
return true; | ||||||||||
} | ||||||||||
// If both functions have the "sign-return-address" attribute their signing | ||||||||||
// behaviour is equal, if the values of the attributes are equal | ||||||||||
if (Fa.hasFnAttribute("sign-return-address") && | ||||||||||
Fb.hasFnAttribute("sign-return-address")) { | ||||||||||
StringRef ScopeA = | ||||||||||
Fa.getFnAttribute("sign-return-address").getValueAsString(); | ||||||||||
StringRef ScopeB = | ||||||||||
Fb.getFnAttribute("sign-return-address").getValueAsString(); | ||||||||||
return ScopeA.equals(ScopeB); | ||||||||||
} | ||||||||||
// If function B doesn't have the "sign-return-address" attribute but A does, | ||||||||||
// the functions' signing behaviour is equal if A's value for | ||||||||||
// "sign-return-address" is "none" and vice versa. | ||||||||||
if (Fa.hasFnAttribute("sign-return-address")) { | ||||||||||
StringRef ScopeA = | ||||||||||
Fa.getFnAttribute("sign-return-address").getValueAsString(); | ||||||||||
return ScopeA.equals("none"); | ||||||||||
} | ||||||||||
if (Fb.hasFnAttribute("sign-return-address")) { | ||||||||||
StringRef ScopeB = | ||||||||||
Fb.getFnAttribute("sign-return-address").getValueAsString(); | ||||||||||
return ScopeB.equals("none"); | ||||||||||
} | ||||||||||
llvm_unreachable("Unkown combination of sign-return-address attributes"); | ||||||||||
} | } | |||||||||
static bool | static bool | |||||||||
outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, | outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, | |||||||||
const outliner::Candidate &b) { | const outliner::Candidate &b) { | |||||||||
const Function &Fa = a.getMF()->getFunction(); | const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>(); | |||||||||
const Function &Fb = b.getMF()->getFunction(); | const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>(); | |||||||||
Same. tellenbach: Same. | ||||||||||
// If none of the functions have the "sign-return-address-key" attribute | ||||||||||
// their keys are equal | ||||||||||
if (!Fa.hasFnAttribute("sign-return-address-key") && | ||||||||||
!Fb.hasFnAttribute("sign-return-address-key")) { | ||||||||||
return true; | ||||||||||
} | ||||||||||
// If both functions have the "sign-return-address-key" attribute their | ||||||||||
// keys are equal if the values of "sign-return-address-key" are equal | ||||||||||
if (Fa.hasFnAttribute("sign-return-address-key") && | ||||||||||
Fb.hasFnAttribute("sign-return-address-key")) { | ||||||||||
StringRef KeyA = | ||||||||||
Fa.getFnAttribute("sign-return-address-key").getValueAsString(); | ||||||||||
StringRef KeyB = | ||||||||||
Fb.getFnAttribute("sign-return-address-key").getValueAsString(); | ||||||||||
return KeyA.equals(KeyB); | ||||||||||
} | ||||||||||
// If B doesn't have the "sign-return-address-key" attribute, both keys are | ||||||||||
// equal, if function a has the default key (a_key) | ||||||||||
if (Fa.hasFnAttribute("sign-return-address-key")) { | ||||||||||
StringRef KeyA = | ||||||||||
Fa.getFnAttribute("sign-return-address-key").getValueAsString(); | ||||||||||
return KeyA.equals_lower("a_key"); | ||||||||||
} | ||||||||||
if (Fb.hasFnAttribute("sign-return-address-key")) { | ||||||||||
StringRef KeyB = | ||||||||||
Fb.getFnAttribute("sign-return-address-key").getValueAsString(); | ||||||||||
return KeyB.equals_lower("a_key"); | ||||||||||
} | ||||||||||
llvm_unreachable("Unkown combination of sign-return-address-key attributes"); | return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey(); | |||||||||
} | } | |||||||||
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, | static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, | |||||||||
const outliner::Candidate &b) { | const outliner::Candidate &b) { | |||||||||
const AArch64Subtarget &SubtargetA = | const AArch64Subtarget &SubtargetA = | |||||||||
a.getMF()->getSubtarget<AArch64Subtarget>(); | a.getMF()->getSubtarget<AArch64Subtarget>(); | |||||||||
const AArch64Subtarget &SubtargetB = | const AArch64Subtarget &SubtargetB = | |||||||||
b.getMF()->getSubtarget<AArch64Subtarget>(); | b.getMF()->getSubtarget<AArch64Subtarget>(); | |||||||||
Show All 39 Lines | outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo( | |||||||||
// the case of "sign-return-address"="non-leaf" this is an assumption: It is | // the case of "sign-return-address"="non-leaf" this is an assumption: It is | |||||||||
// not certainly true that the outlined function will have to sign its return | // not certainly true that the outlined function will have to sign its return | |||||||||
// address but this decision is made later, when the decision to outline | // address but this decision is made later, when the decision to outline | |||||||||
// has already been made. | // has already been made. | |||||||||
// The same holds for the number of additional instructions we need: On | // The same holds for the number of additional instructions we need: On | |||||||||
// v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is | // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is | |||||||||
// necessary. However, at this point we don't know if the outlined function | // necessary. However, at this point we don't know if the outlined function | |||||||||
// will have a RET instruction so we assume the worst. | // will have a RET instruction so we assume the worst. | |||||||||
const Function &FCF = FirstCand.getMF()->getFunction(); | ||||||||||
const TargetRegisterInfo &TRI = getRegisterInfo(); | const TargetRegisterInfo &TRI = getRegisterInfo(); | |||||||||
if (FCF.hasFnAttribute("sign-return-address")) { | if (FirstCand.getMF() | |||||||||
->getInfo<AArch64FunctionInfo>() | ||||||||||
->shouldSignReturnAddress(true)) { | ||||||||||
// One PAC and one AUT instructions | // One PAC and one AUT instructions | |||||||||
NumBytesToCreateFrame += 8; | NumBytesToCreateFrame += 8; | |||||||||
// We have to check if sp modifying instructions would get outlined. | // We have to check if sp modifying instructions would get outlined. | |||||||||
// If so we only allow outlining if sp is unchanged overall, so matching | // If so we only allow outlining if sp is unchanged overall, so matching | |||||||||
// sub and add instructions are okay to outline, all other sp modifications | // sub and add instructions are okay to outline, all other sp modifications | |||||||||
// are not | // are not | |||||||||
auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) { | auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) { | |||||||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | auto SetCandidateCallInfo = | |||||||||
for (outliner::Candidate &C : RepeatedSequenceLocs) | for (outliner::Candidate &C : RepeatedSequenceLocs) | |||||||||
C.setCallInfo(CallID, NumBytesForCall); | C.setCallInfo(CallID, NumBytesForCall); | |||||||||
}; | }; | |||||||||
unsigned FrameID = MachineOutlinerDefault; | unsigned FrameID = MachineOutlinerDefault; | |||||||||
NumBytesToCreateFrame += 4; | NumBytesToCreateFrame += 4; | |||||||||
bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) { | bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) { | |||||||||
return C.getMF()->getFunction().hasFnAttribute("branch-target-enforcement"); | return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement(); | |||||||||
}); | }); | |||||||||
// We check to see if CFI Instructions are present, and if they are | // We check to see if CFI Instructions are present, and if they are | |||||||||
// we find the number of CFI Instructions in the candidates. | // we find the number of CFI Instructions in the candidates. | |||||||||
unsigned CFICount = 0; | unsigned CFICount = 0; | |||||||||
MachineBasicBlock::iterator MBBI = RepeatedSequenceLocs[0].front(); | MachineBasicBlock::iterator MBBI = RepeatedSequenceLocs[0].front(); | |||||||||
for (unsigned Loc = RepeatedSequenceLocs[0].getStartIdx(); | for (unsigned Loc = RepeatedSequenceLocs[0].getStartIdx(); | |||||||||
Loc < RepeatedSequenceLocs[0].getEndIdx() + 1; Loc++) { | Loc < RepeatedSequenceLocs[0].getEndIdx() + 1; Loc++) { | |||||||||
▲ Show 20 Lines • Show All 688 Lines • ▼ Show 20 Lines | MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost)) | |||||||||
.addReg(AArch64::SP) | .addReg(AArch64::SP) | |||||||||
.addImm(16); | .addImm(16); | |||||||||
Et = MBB.insert(Et, LDRXpost); | Et = MBB.insert(Et, LDRXpost); | |||||||||
} | } | |||||||||
// If a bunch of candidates reach this point they must agree on their return | // If a bunch of candidates reach this point they must agree on their return | |||||||||
// address signing. It is therefore enough to just consider the signing | // address signing. It is therefore enough to just consider the signing | |||||||||
// behaviour of one of them | // behaviour of one of them | |||||||||
const Function &CF = OF.Candidates.front().getMF()->getFunction(); | const auto &MFI = *OF.Candidates.front().getMF()->getInfo<AArch64FunctionInfo>(); | |||||||||
bool ShouldSignReturnAddr = false; | bool ShouldSignReturnAddr = MFI.shouldSignReturnAddress(!IsLeafFunction); | |||||||||
if (CF.hasFnAttribute("sign-return-address")) { | ||||||||||
StringRef Scope = | ||||||||||
CF.getFnAttribute("sign-return-address").getValueAsString(); | ||||||||||
if (Scope.equals("all")) | ||||||||||
ShouldSignReturnAddr = true; | ||||||||||
else if (Scope.equals("non-leaf") && !IsLeafFunction) | ||||||||||
ShouldSignReturnAddr = true; | ||||||||||
} | ||||||||||
// a_key is the default | // a_key is the default | |||||||||
bool ShouldSignReturnAddrWithAKey = true; | bool ShouldSignReturnAddrWithAKey = !MFI.shouldSignWithBKey(); | |||||||||
if (CF.hasFnAttribute("sign-return-address-key")) { | ||||||||||
const StringRef Key = | ||||||||||
CF.getFnAttribute("sign-return-address-key").getValueAsString(); | ||||||||||
// Key can either be a_key or b_key | ||||||||||
assert((Key.equals_lower("a_key") || Key.equals_lower("b_key")) && | ||||||||||
"Return address signing key must be either a_key or b_key"); | ||||||||||
ShouldSignReturnAddrWithAKey = Key.equals_lower("a_key"); | ||||||||||
} | ||||||||||
// If this is a tail call outlined function, then there's already a return. | // If this is a tail call outlined function, then there's already a return. | |||||||||
if (OF.FrameConstructionID == MachineOutlinerTailCall || | if (OF.FrameConstructionID == MachineOutlinerTailCall || | |||||||||
OF.FrameConstructionID == MachineOutlinerThunk) { | OF.FrameConstructionID == MachineOutlinerThunk) { | |||||||||
signOutlinedFunction(MF, MBB, ShouldSignReturnAddr, | signOutlinedFunction(MF, MBB, ShouldSignReturnAddr, | |||||||||
ShouldSignReturnAddrWithAKey); | ShouldSignReturnAddrWithAKey); | |||||||||
return; | return; | |||||||||
} | } | |||||||||
▲ Show 20 Lines • Show All 238 Lines • Show Last 20 Lines |
Is this a typo?