@@ -5037,147 +5037,15 @@ AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const {
5037
5037
return 0u ;
5038
5038
}
5039
5039
5040
- static bool
5041
- outliningCandidatesSigningScopeConsensus (const outliner::Candidate &a,
5042
- const outliner::Candidate &b) {
5043
- const Function &Fa = a.getMF ()->getFunction ();
5044
- const Function &Fb = b.getMF ()->getFunction ();
5045
-
5046
- // If none of the functions have the "sign-return-address" attribute their
5047
- // signing behaviour is equal
5048
- if (!Fa.hasFnAttribute (" sign-return-address" ) &&
5049
- !Fb.hasFnAttribute (" sign-return-address" )) {
5050
- return true ;
5051
- }
5052
-
5053
- // If both functions have the "sign-return-address" attribute their signing
5054
- // behaviour is equal, if the values of the attributes are equal
5055
- if (Fa.hasFnAttribute (" sign-return-address" ) &&
5056
- Fb.hasFnAttribute (" sign-return-address" )) {
5057
- StringRef ScopeA =
5058
- Fa.getFnAttribute (" sign-return-address" ).getValueAsString ();
5059
- StringRef ScopeB =
5060
- Fb.getFnAttribute (" sign-return-address" ).getValueAsString ();
5061
- return ScopeA.equals (ScopeB);
5062
- }
5063
-
5064
- // If function B doesn't have the "sign-return-address" attribute but A does,
5065
- // the functions' signing behaviour is equal if A's value for
5066
- // "sign-return-address" is "none" and vice versa.
5067
- if (Fa.hasFnAttribute (" sign-return-address" )) {
5068
- StringRef ScopeA =
5069
- Fa.getFnAttribute (" sign-return-address" ).getValueAsString ();
5070
- return ScopeA.equals (" none" );
5071
- }
5072
-
5073
- if (Fb.hasFnAttribute (" sign-return-address" )) {
5074
- StringRef ScopeB =
5075
- Fb.getFnAttribute (" sign-return-address" ).getValueAsString ();
5076
- return ScopeB.equals (" none" );
5077
- }
5078
-
5079
- llvm_unreachable (" Unkown combination of sign-return-address attributes" );
5080
- }
5081
-
5082
- static bool
5083
- outliningCandidatesSigningKeyConsensus (const outliner::Candidate &a,
5084
- const outliner::Candidate &b) {
5085
- const Function &Fa = a.getMF ()->getFunction ();
5086
- const Function &Fb = b.getMF ()->getFunction ();
5087
-
5088
- // If none of the functions have the "sign-return-address-key" attribute
5089
- // their keys are equal
5090
- if (!Fa.hasFnAttribute (" sign-return-address-key" ) &&
5091
- !Fb.hasFnAttribute (" sign-return-address-key" )) {
5092
- return true ;
5093
- }
5094
-
5095
- // If both functions have the "sign-return-address-key" attribute their
5096
- // keys are equal if the values of "sign-return-address-key" are equal
5097
- if (Fa.hasFnAttribute (" sign-return-address-key" ) &&
5098
- Fb.hasFnAttribute (" sign-return-address-key" )) {
5099
- StringRef KeyA =
5100
- Fa.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5101
- StringRef KeyB =
5102
- Fb.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5103
- return KeyA.equals (KeyB);
5104
- }
5105
-
5106
- // If B doesn't have the "sign-return-address-key" attribute, both keys are
5107
- // equal, if function a has the default key (a_key)
5108
- if (Fa.hasFnAttribute (" sign-return-address-key" )) {
5109
- StringRef KeyA =
5110
- Fa.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5111
- return KeyA.equals_lower (" a_key" );
5112
- }
5113
-
5114
- if (Fb.hasFnAttribute (" sign-return-address-key" )) {
5115
- StringRef KeyB =
5116
- Fb.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5117
- return KeyB.equals_lower (" a_key" );
5118
- }
5119
-
5120
- llvm_unreachable (" Unkown combination of sign-return-address-key attributes" );
5121
- }
5122
-
5123
- static bool outliningCandidatesV8_3OpsConsensus (const outliner::Candidate &a,
5124
- const outliner::Candidate &b) {
5125
- const AArch64Subtarget &SubtargetA =
5126
- a.getMF ()->getSubtarget <AArch64Subtarget>();
5127
- const AArch64Subtarget &SubtargetB =
5128
- b.getMF ()->getSubtarget <AArch64Subtarget>();
5129
- return SubtargetA.hasV8_3aOps () == SubtargetB.hasV8_3aOps ();
5130
- }
5131
-
5132
- outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo (
5040
+ outliner::OutlinedFunction
5041
+ AArch64InstrInfo::getOutliningCandidateInfo (
5133
5042
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
5134
5043
outliner::Candidate &FirstCand = RepeatedSequenceLocs[0 ];
5135
5044
unsigned SequenceSize =
5136
5045
std::accumulate (FirstCand.front (), std::next (FirstCand.back ()), 0 ,
5137
5046
[this ](unsigned Sum, const MachineInstr &MI) {
5138
5047
return Sum + getInstSizeInBytes (MI);
5139
5048
});
5140
- unsigned NumBytesToCreateFrame = 0 ;
5141
-
5142
- // We only allow outlining for functions having exactly matching return
5143
- // address signing attributes, i.e., all share the same value for the
5144
- // attribute "sign-return-address" and all share the same type of key they
5145
- // are signed with.
5146
- // Additionally we require all functions to simultaniously either support
5147
- // v8.3a features or not. Otherwise an outlined function could get signed
5148
- // using dedicated v8.3 instructions and a call from a function that doesn't
5149
- // support v8.3 instructions would therefore be invalid.
5150
- if (std::adjacent_find (
5151
- RepeatedSequenceLocs.begin (), RepeatedSequenceLocs.end (),
5152
-
5153
- [](const outliner::Candidate &a, const outliner::Candidate &b) {
5154
- // Return true if a and b are non-equal w.r.t. return address
5155
- // signing or support of v8.3a features
5156
- if (outliningCandidatesSigningScopeConsensus (a, b) &&
5157
- outliningCandidatesSigningKeyConsensus (a, b) &&
5158
- outliningCandidatesV8_3OpsConsensus (a, b)) {
5159
- return false ;
5160
- }
5161
- return true ;
5162
- }) != RepeatedSequenceLocs.end ()) {
5163
- return outliner::OutlinedFunction ();
5164
- }
5165
-
5166
- // Since at this point all candidates agree on their return address signing
5167
- // picking just one is fine. If the candidate functions potentially sign their
5168
- // return addresses, the outlined function should do the same. Note that in
5169
- // the case of "sign-return-address"="non-leaf" this is an assumption: It is
5170
- // not certainly true that the outlined function will have to sign its return
5171
- // address but this decision is made later, when the decision to outline
5172
- // has already been made.
5173
- // The same holds for the number of additional instructions we need: On
5174
- // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
5175
- // necessary. However, at this point we don't know if the outlined function
5176
- // will have a RET instruction so we assume the worst.
5177
- const Function &FCF = FirstCand.getMF ()->getFunction ();
5178
- if (FCF.hasFnAttribute (" sign-return-address" ))
5179
- // One PAC and one AUT instructions
5180
- NumBytesToCreateFrame += 8 ;
5181
5049
5182
5050
// Properties about candidate MBBs that hold for all of them.
5183
5051
unsigned FlagsSetInAll = 0xF ;
@@ -5239,7 +5107,7 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo(
5239
5107
};
5240
5108
5241
5109
unsigned FrameID = MachineOutlinerDefault;
5242
- NumBytesToCreateFrame + = 4 ;
5110
+ unsigned NumBytesToCreateFrame = 4 ;
5243
5111
5244
5112
bool HasBTI = any_of (RepeatedSequenceLocs, [](outliner::Candidate &C) {
5245
5113
return C.getMF ()->getFunction ().hasFnAttribute (" branch-target-enforcement" );
@@ -5508,19 +5376,6 @@ AArch64InstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT,
5508
5376
MachineFunction *MF = MBB->getParent ();
5509
5377
AArch64FunctionInfo *FuncInfo = MF->getInfo <AArch64FunctionInfo>();
5510
5378
5511
- // Don't outline anything used for return address signing. The outlined
5512
- // function will get signed later if needed
5513
- switch (MI.getOpcode ()) {
5514
- case AArch64::PACIASP:
5515
- case AArch64::PACIBSP:
5516
- case AArch64::AUTIASP:
5517
- case AArch64::AUTIBSP:
5518
- case AArch64::RETAA:
5519
- case AArch64::RETAB:
5520
- case AArch64::EMITBKEY:
5521
- return outliner::InstrType::Illegal;
5522
- }
5523
-
5524
5379
// Don't outline LOHs.
5525
5380
if (FuncInfo->getLOHRelated ().count (&MI))
5526
5381
return outliner::InstrType::Illegal;
@@ -5673,59 +5528,6 @@ void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
5673
5528
}
5674
5529
}
5675
5530
5676
- static void signOutlinedFunction (MachineFunction &MF, MachineBasicBlock &MBB,
5677
- bool ShouldSignReturnAddr,
5678
- bool ShouldSignReturnAddrWithAKey) {
5679
- if (ShouldSignReturnAddr) {
5680
- MachineBasicBlock::iterator MBBPAC = MBB.begin ();
5681
- MachineBasicBlock::iterator MBBAUT = MBB.getFirstTerminator ();
5682
- const AArch64Subtarget &Subtarget = MF.getSubtarget <AArch64Subtarget>();
5683
- const TargetInstrInfo *TII = Subtarget.getInstrInfo ();
5684
- DebugLoc DL;
5685
-
5686
- if (MBBAUT != MBB.end ())
5687
- DL = MBBAUT->getDebugLoc ();
5688
-
5689
- // At the very beginning of the basic block we insert the following
5690
- // depending on the key type
5691
- //
5692
- // a_key: b_key:
5693
- // PACIASP EMITBKEY
5694
- // CFI_INSTRUCTION PACIBSP
5695
- // CFI_INSTRUCTION
5696
- if (ShouldSignReturnAddrWithAKey) {
5697
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::PACIASP))
5698
- .setMIFlag (MachineInstr::FrameSetup);
5699
- } else {
5700
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::EMITBKEY))
5701
- .setMIFlag (MachineInstr::FrameSetup);
5702
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::PACIBSP))
5703
- .setMIFlag (MachineInstr::FrameSetup);
5704
- }
5705
- unsigned CFIIndex =
5706
- MF.addFrameInst (MCCFIInstruction::createNegateRAState (nullptr ));
5707
- BuildMI (MBB, MBBPAC, DebugLoc (), TII->get (AArch64::CFI_INSTRUCTION))
5708
- .addCFIIndex (CFIIndex)
5709
- .setMIFlags (MachineInstr::FrameSetup);
5710
-
5711
- // If v8.3a features are available we can replace a RET instruction by
5712
- // RETAA or RETAB and omit the AUT instructions
5713
- if (Subtarget.hasV8_3aOps () && MBBAUT != MBB.end () &&
5714
- MBBAUT->getOpcode () == AArch64::RET) {
5715
- BuildMI (MBB, MBBAUT, DL,
5716
- TII->get (ShouldSignReturnAddrWithAKey ? AArch64::RETAA
5717
- : AArch64::RETAB))
5718
- .copyImplicitOps (*MBBAUT);
5719
- MBB.erase (MBBAUT);
5720
- } else {
5721
- BuildMI (MBB, MBBAUT, DL,
5722
- TII->get (ShouldSignReturnAddrWithAKey ? AArch64::AUTIASP
5723
- : AArch64::AUTIBSP))
5724
- .setMIFlag (MachineInstr::FrameDestroy);
5725
- }
5726
- }
5727
- }
5728
-
5729
5531
void AArch64InstrInfo::buildOutlinedFrame (
5730
5532
MachineBasicBlock &MBB, MachineFunction &MF,
5731
5533
const outliner::OutlinedFunction &OF) const {
@@ -5741,28 +5543,23 @@ void AArch64InstrInfo::buildOutlinedFrame(
5741
5543
TailOpcode = AArch64::TCRETURNriALL;
5742
5544
}
5743
5545
MachineInstr *TC = BuildMI (MF, DebugLoc (), get (TailOpcode))
5744
- .add (Call->getOperand (0 ))
5745
- .addImm (0 );
5546
+ .add (Call->getOperand (0 ))
5547
+ .addImm (0 );
5746
5548
MBB.insert (MBB.end (), TC);
5747
5549
Call->eraseFromParent ();
5748
5550
}
5749
5551
5750
- bool IsLeafFunction = true ;
5751
-
5752
5552
// Is there a call in the outlined range?
5753
- auto IsNonTailCall = [](const MachineInstr &MI) {
5553
+ auto IsNonTailCall = [](MachineInstr &MI) {
5754
5554
return MI.isCall () && !MI.isReturn ();
5755
5555
};
5756
-
5757
5556
if (std::any_of (MBB.instr_begin (), MBB.instr_end (), IsNonTailCall)) {
5758
5557
// Fix up the instructions in the range, since we're going to modify the
5759
5558
// stack.
5760
5559
assert (OF.FrameConstructionID != MachineOutlinerDefault &&
5761
5560
" Can only fix up stack references once" );
5762
5561
fixupPostOutline (MBB);
5763
5562
5764
- IsLeafFunction = false ;
5765
-
5766
5563
// LR has to be a live in so that we can save it.
5767
5564
MBB.addLiveIn (AArch64::LR);
5768
5565
@@ -5809,47 +5606,16 @@ void AArch64InstrInfo::buildOutlinedFrame(
5809
5606
Et = MBB.insert (Et, LDRXpost);
5810
5607
}
5811
5608
5812
- // If a bunch of candidates reach this point they must agree on their return
5813
- // address signing. It is therefore enough to just consider the signing
5814
- // behaviour of one of them
5815
- const Function &CF = OF.Candidates .front ().getMF ()->getFunction ();
5816
- bool ShouldSignReturnAddr = false ;
5817
- if (CF.hasFnAttribute (" sign-return-address" )) {
5818
- StringRef Scope =
5819
- CF.getFnAttribute (" sign-return-address" ).getValueAsString ();
5820
- if (Scope.equals (" all" ))
5821
- ShouldSignReturnAddr = true ;
5822
- else if (Scope.equals (" non-leaf" ) && !IsLeafFunction)
5823
- ShouldSignReturnAddr = true ;
5824
- }
5825
-
5826
- // a_key is the default
5827
- bool ShouldSignReturnAddrWithAKey = true ;
5828
- if (CF.hasFnAttribute (" sign-return-address-key" )) {
5829
- const StringRef Key =
5830
- CF.getFnAttribute (" sign-return-address-key" ).getValueAsString ();
5831
- // Key can either be a_key or b_key
5832
- assert ((Key.equals_lower (" a_key" ) || Key.equals_lower (" b_key" )) &&
5833
- " Return address signing key must be either a_key or b_key" );
5834
- ShouldSignReturnAddrWithAKey = Key.equals_lower (" a_key" );
5835
- }
5836
-
5837
5609
// If this is a tail call outlined function, then there's already a return.
5838
5610
if (OF.FrameConstructionID == MachineOutlinerTailCall ||
5839
- OF.FrameConstructionID == MachineOutlinerThunk) {
5840
- signOutlinedFunction (MF, MBB, ShouldSignReturnAddr,
5841
- ShouldSignReturnAddrWithAKey);
5611
+ OF.FrameConstructionID == MachineOutlinerThunk)
5842
5612
return ;
5843
- }
5844
5613
5845
5614
// It's not a tail call, so we have to insert the return ourselves.
5846
5615
MachineInstr *ret = BuildMI (MF, DebugLoc (), get (AArch64::RET))
5847
5616
.addReg (AArch64::LR, RegState::Undef);
5848
5617
MBB.insert (MBB.end (), ret);
5849
5618
5850
- signOutlinedFunction (MF, MBB, ShouldSignReturnAddr,
5851
- ShouldSignReturnAddrWithAKey);
5852
-
5853
5619
// Did we have to modify the stack by saving the link register?
5854
5620
if (OF.FrameConstructionID != MachineOutlinerDefault)
5855
5621
return ;
0 commit comments