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