@@ -163,8 +163,15 @@ class AArch64AsmPrinter : public AsmPrinter {
163
163
// Emit the sequence for AUT or AUTPAC.
164
164
void emitPtrauthAuthResign (const MachineInstr *MI);
165
165
166
- // Emit the sequence to compute a discriminator into x17, or reuse AddrDisc.
167
- unsigned emitPtrauthDiscriminator (uint16_t Disc, unsigned AddrDisc);
166
+ // Emit the sequence to compute the discriminator.
167
+ // ScratchReg should be x16/x17.
168
+ // The returned register is either unmodified AddrDisc or x16/x17.
169
+ // If the expanded pseudo is allowed to clobber AddrDisc register, setting
170
+ // MayUseAddrAsScratch may save one MOV instruction, provided the address
171
+ // is already in x16/x17.
172
+ Register emitPtrauthDiscriminator (uint16_t Disc, Register AddrDisc,
173
+ Register ScratchReg,
174
+ bool MayUseAddrAsScratch = false );
168
175
169
176
// Emit the sequence for LOADauthptrstatic
170
177
void LowerLOADauthptrstatic (const MachineInstr &MI);
@@ -1727,8 +1734,10 @@ void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) {
1727
1734
}
1728
1735
}
1729
1736
1730
- unsigned AArch64AsmPrinter::emitPtrauthDiscriminator (uint16_t Disc,
1731
- unsigned AddrDisc) {
1737
+ Register AArch64AsmPrinter::emitPtrauthDiscriminator (uint16_t Disc,
1738
+ Register AddrDisc,
1739
+ Register ScratchReg,
1740
+ bool MayUseAddrAsScratch) {
1732
1741
// So far we've used NoRegister in pseudos. Now we need real encodings.
1733
1742
if (AddrDisc == AArch64::NoRegister)
1734
1743
AddrDisc = AArch64::XZR;
@@ -1738,16 +1747,24 @@ unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
1738
1747
if (!Disc)
1739
1748
return AddrDisc;
1740
1749
1741
- // If there's only a constant discriminator, MOV it into x17 .
1750
+ // If there's only a constant discriminator, MOV it into the scratch register .
1742
1751
if (AddrDisc == AArch64::XZR) {
1743
- emitMOVZ (AArch64::X17 , Disc, 0 );
1744
- return AArch64::X17 ;
1752
+ emitMOVZ (ScratchReg , Disc, 0 );
1753
+ return ScratchReg ;
1745
1754
}
1746
1755
1747
- // If there are both, emit a blend into x17.
1748
- emitMovXReg (AArch64::X17, AddrDisc);
1749
- emitMOVK (AArch64::X17, Disc, 48 );
1750
- return AArch64::X17;
1756
+ // If there are both, emit a blend into the scratch register.
1757
+
1758
+ // Check if we can save one MOV instruction.
1759
+ assert (MayUseAddrAsScratch || ScratchReg != AddrDisc);
1760
+ bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
1761
+ if (MayUseAddrAsScratch && AddrDiscIsSafe)
1762
+ ScratchReg = AddrDisc;
1763
+ else
1764
+ emitMovXReg (ScratchReg, AddrDisc);
1765
+
1766
+ emitMOVK (ScratchReg, Disc, 48 );
1767
+ return ScratchReg;
1751
1768
}
1752
1769
1753
1770
// / Emits a code sequence to check an authenticated pointer value.
@@ -1964,7 +1981,8 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
1964
1981
1965
1982
// Compute aut discriminator into x17
1966
1983
assert (isUInt<16 >(AUTDisc));
1967
- unsigned AUTDiscReg = emitPtrauthDiscriminator (AUTDisc, AUTAddrDisc);
1984
+ Register AUTDiscReg =
1985
+ emitPtrauthDiscriminator (AUTDisc, AUTAddrDisc, AArch64::X17);
1968
1986
bool AUTZero = AUTDiscReg == AArch64::XZR;
1969
1987
unsigned AUTOpc = getAUTOpcodeForKey (AUTKey, AUTZero);
1970
1988
@@ -2005,7 +2023,8 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
2005
2023
2006
2024
// Compute pac discriminator into x17
2007
2025
assert (isUInt<16 >(PACDisc));
2008
- unsigned PACDiscReg = emitPtrauthDiscriminator (PACDisc, PACAddrDisc);
2026
+ Register PACDiscReg =
2027
+ emitPtrauthDiscriminator (PACDisc, PACAddrDisc, AArch64::X17);
2009
2028
bool PACZero = PACDiscReg == AArch64::XZR;
2010
2029
unsigned PACOpc = getPACOpcodeForKey (PACKey, PACZero);
2011
2030
@@ -2037,8 +2056,17 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
2037
2056
2038
2057
unsigned AddrDisc = MI->getOperand (3 ).getReg ();
2039
2058
2040
- // Compute discriminator into x17
2041
- unsigned DiscReg = emitPtrauthDiscriminator (Disc, AddrDisc);
2059
+ // Make sure AddrDisc is solely used to compute the discriminator.
2060
+ // While hardly meaningful, it is still possible to describe an authentication
2061
+ // of a pointer against its own value (instead of storage address) with
2062
+ // intrinsics, so use report_fatal_error instead of assert.
2063
+ if (BrTarget == AddrDisc)
2064
+ report_fatal_error (" Branch target is signed with its own value" );
2065
+
2066
+ // x16 and x17 are implicit-def'ed by MI, and AddrDisc is not used as any
2067
+ // other input, so try to save one MOV by setting MayUseAddrAsScratch.
2068
+ Register DiscReg = emitPtrauthDiscriminator (Disc, AddrDisc, AArch64::X17,
2069
+ /* MayUseAddrAsScratch=*/ true );
2042
2070
bool IsZeroDisc = DiscReg == AArch64::XZR;
2043
2071
2044
2072
unsigned Opc;
@@ -2332,16 +2360,7 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2332
2360
}
2333
2361
}
2334
2362
2335
- unsigned DiscReg = AddrDisc;
2336
- if (Disc != 0 ) {
2337
- if (AddrDisc != AArch64::XZR) {
2338
- emitMovXReg (AArch64::X17, AddrDisc);
2339
- emitMOVK (AArch64::X17, Disc, 48 );
2340
- } else {
2341
- emitMOVZ (AArch64::X17, Disc, 0 );
2342
- }
2343
- DiscReg = AArch64::X17;
2344
- }
2363
+ Register DiscReg = emitPtrauthDiscriminator (Disc, AddrDisc, AArch64::X17);
2345
2364
2346
2365
auto MIB = MCInstBuilder (getPACOpcodeForKey (Key, DiscReg == AArch64::XZR))
2347
2366
.addReg (AArch64::X16)
@@ -2609,6 +2628,7 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
2609
2628
// instruction here.
2610
2629
case AArch64::AUTH_TCRETURN:
2611
2630
case AArch64::AUTH_TCRETURN_BTI: {
2631
+ Register Callee = MI->getOperand (0 ).getReg ();
2612
2632
const uint64_t Key = MI->getOperand (2 ).getImm ();
2613
2633
assert ((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) &&
2614
2634
" Invalid auth key for tail-call return" );
@@ -2618,31 +2638,23 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
2618
2638
2619
2639
Register AddrDisc = MI->getOperand (4 ).getReg ();
2620
2640
2621
- Register ScratchReg = MI->getOperand (0 ).getReg () == AArch64::X16
2622
- ? AArch64::X17
2623
- : AArch64::X16;
2641
+ Register ScratchReg = Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2624
2642
2625
2643
emitPtrauthTailCallHardening (MI);
2626
2644
2627
- unsigned DiscReg = AddrDisc;
2628
- if (Disc) {
2629
- if (AddrDisc != AArch64::NoRegister) {
2630
- if (ScratchReg != AddrDisc)
2631
- emitMovXReg (ScratchReg, AddrDisc);
2632
- emitMOVK (ScratchReg, Disc, 48 );
2633
- } else {
2634
- emitMOVZ (ScratchReg, Disc, 0 );
2635
- }
2636
- DiscReg = ScratchReg;
2637
- }
2645
+ // See the comments in emitPtrauthBranch.
2646
+ if (Callee == AddrDisc)
2647
+ report_fatal_error (" Call target is signed with its own value" );
2648
+ Register DiscReg = emitPtrauthDiscriminator (Disc, AddrDisc, ScratchReg,
2649
+ /* MayUseAddrAsScratch=*/ true );
2638
2650
2639
- const bool IsZero = DiscReg == AArch64::NoRegister ;
2651
+ const bool IsZero = DiscReg == AArch64::XZR ;
2640
2652
const unsigned Opcodes[2 ][2 ] = {{AArch64::BRAA, AArch64::BRAAZ},
2641
2653
{AArch64::BRAB, AArch64::BRABZ}};
2642
2654
2643
2655
MCInst TmpInst;
2644
2656
TmpInst.setOpcode (Opcodes[Key][IsZero]);
2645
- TmpInst.addOperand (MCOperand::createReg (MI-> getOperand ( 0 ). getReg () ));
2657
+ TmpInst.addOperand (MCOperand::createReg (Callee ));
2646
2658
if (!IsZero)
2647
2659
TmpInst.addOperand (MCOperand::createReg (DiscReg));
2648
2660
EmitToStreamer (*OutStreamer, TmpInst);
0 commit comments