@@ -131,6 +131,13 @@ class AArch64AsmPrinter : public AsmPrinter {
131
131
unsigned emitPtrauthDiscriminator (uint16_t Disc, unsigned AddrDisc,
132
132
unsigned &InstsEmitted);
133
133
134
+ // Emit the sequence for LOADauthptrstatic
135
+ void LowerLOADauthptrstatic (const MachineInstr &MI);
136
+
137
+ // Emit the sequence for LOADgotPAC/MOVaddrPAC (either GOT adrp-ldr or
138
+ // adrp-add followed by PAC sign)
139
+ void LowerMOVaddrPAC (const MachineInstr &MI);
140
+
134
141
// / tblgen'erated driver function for lowering simple MI->MC
135
142
// / pseudo instructions.
136
143
bool emitPseudoExpansionLowering (MCStreamer &OutStreamer,
@@ -1575,6 +1582,173 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) {
1575
1582
assert (STI->getInstrInfo ()->getInstSizeInBytes (*MI) >= InstsEmitted * 4 );
1576
1583
}
1577
1584
1585
+ void AArch64AsmPrinter::LowerLOADauthptrstatic (const MachineInstr &MI) {
1586
+ unsigned DstReg = MI.getOperand (0 ).getReg ();
1587
+ MachineOperand GAOp = MI.getOperand (1 );
1588
+ uint64_t KeyC = MI.getOperand (2 ).getImm ();
1589
+ assert (KeyC <= AArch64PACKey::LAST && " Key is out of range" );
1590
+ auto Key = (AArch64PACKey::ID)KeyC;
1591
+ uint64_t Disc = MI.getOperand (3 ).getImm ();
1592
+ assert (isUInt<16 >(Disc) && " Constant discriminator is too wide" );
1593
+
1594
+ const MCSymbol *GASym = TM.getSymbol (GAOp.getGlobal ());
1595
+ uint64_t Offset = GAOp.getOffset ();
1596
+
1597
+ // Emit instruction sequence like the following:
1598
+ // ADRP x16, symbol$auth_ptr$key$disc
1599
+ // LDR x16, [x16, :lo12:symbol$auth_ptr$key$disc]
1600
+ //
1601
+ // Where the $auth_ptr$ symbol is the stub slot containing the signed pointer
1602
+ // to symbol.
1603
+ assert (TM.getTargetTriple ().isOSBinFormatELF () &&
1604
+ " LOADauthptrstatic only implemented on ELF" );
1605
+ assert (Offset == 0 &&
1606
+ " Non-zero offset for $auth_ptr$ stub slots is not supported" );
1607
+
1608
+ const auto &TLOF =
1609
+ static_cast <const AArch64_ELFTargetObjectFile &>(getObjFileLowering ());
1610
+ MCSymbol *AuthPtrStubSym =
1611
+ TLOF.getAuthPtrSlotSymbol (TM, &MF->getMMI (), GASym, Key, Disc);
1612
+
1613
+ MachineOperand StubMOHi =
1614
+ MachineOperand::CreateMCSymbol (AuthPtrStubSym, AArch64II::MO_PAGE);
1615
+ MachineOperand StubMOLo = MachineOperand::CreateMCSymbol (
1616
+ AuthPtrStubSym, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
1617
+ MCOperand StubMCHi, StubMCLo;
1618
+
1619
+ MCInstLowering.lowerOperand (StubMOHi, StubMCHi);
1620
+ MCInstLowering.lowerOperand (StubMOLo, StubMCLo);
1621
+
1622
+ EmitToStreamer (
1623
+ *OutStreamer,
1624
+ MCInstBuilder (AArch64::ADRP).addReg (DstReg).addOperand (StubMCHi));
1625
+
1626
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::LDRXui)
1627
+ .addReg (DstReg)
1628
+ .addReg (DstReg)
1629
+ .addOperand (StubMCLo));
1630
+ }
1631
+
1632
+ void AArch64AsmPrinter::LowerMOVaddrPAC (const MachineInstr &MI) {
1633
+ unsigned InstsEmitted = 0 ;
1634
+
1635
+ const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
1636
+ MachineOperand GAOp = MI.getOperand (0 );
1637
+ uint64_t KeyC = MI.getOperand (1 ).getImm ();
1638
+ assert (KeyC <= AArch64PACKey::LAST && " Key is out of range" );
1639
+ auto Key = (AArch64PACKey::ID)KeyC;
1640
+ unsigned AddrDisc = MI.getOperand (2 ).getReg ();
1641
+ uint64_t Disc = MI.getOperand (3 ).getImm ();
1642
+ assert (isUInt<16 >(Disc) && " Constant discriminator is too wide" );
1643
+
1644
+ uint64_t Offset = GAOp.getOffset ();
1645
+ GAOp.setOffset (0 );
1646
+
1647
+ // Emit:
1648
+ // target materialization:
1649
+ // via GOT:
1650
+ // adrp x16, :got:target
1651
+ // ldr x16, [x16, :got_lo12:target]
1652
+ // add x16, x16, #<offset> ; if offset != 0; up to 3 depending on width
1653
+ //
1654
+ // direct:
1655
+ // adrp x16, target
1656
+ // add x16, x16, :lo12:target
1657
+ // add x16, x16, #<offset> ; if offset != 0; up to 3 depending on width
1658
+ //
1659
+ // signing:
1660
+ // - 0 discriminator:
1661
+ // paciza x16
1662
+ // - Non-0 discriminator, no address discriminator:
1663
+ // mov x17, #Disc
1664
+ // pacia x16, x17
1665
+ // - address discriminator (with potentially folded immediate discriminator):
1666
+ // pacia x16, xAddrDisc
1667
+
1668
+ MachineOperand GAMOHi (GAOp), GAMOLo (GAOp);
1669
+ MCOperand GAMCHi, GAMCLo;
1670
+
1671
+ GAMOHi.setTargetFlags (AArch64II::MO_PAGE);
1672
+ GAMOLo.setTargetFlags (AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
1673
+ if (IsGOTLoad) {
1674
+ GAMOHi.addTargetFlag (AArch64II::MO_GOT);
1675
+ GAMOLo.addTargetFlag (AArch64II::MO_GOT);
1676
+ }
1677
+
1678
+ MCInstLowering.lowerOperand (GAMOHi, GAMCHi);
1679
+ MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
1680
+
1681
+ EmitToStreamer (
1682
+ *OutStreamer,
1683
+ MCInstBuilder (AArch64::ADRP).addReg (AArch64::X16).addOperand (GAMCHi));
1684
+ ++InstsEmitted;
1685
+
1686
+ if (IsGOTLoad) {
1687
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::LDRXui)
1688
+ .addReg (AArch64::X16)
1689
+ .addReg (AArch64::X16)
1690
+ .addOperand (GAMCLo));
1691
+ ++InstsEmitted;
1692
+ } else {
1693
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::ADDXri)
1694
+ .addReg (AArch64::X16)
1695
+ .addReg (AArch64::X16)
1696
+ .addOperand (GAMCLo)
1697
+ .addImm (0 ));
1698
+ ++InstsEmitted;
1699
+ }
1700
+
1701
+ if (Offset) {
1702
+ if (!isUInt<32 >(Offset))
1703
+ report_fatal_error (" ptrauth global offset too large, 32bit max encoding" );
1704
+
1705
+ for (int BitPos = 0 ; BitPos < 32 && (Offset >> BitPos); BitPos += 12 ) {
1706
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::ADDXri)
1707
+ .addReg (AArch64::X16)
1708
+ .addReg (AArch64::X16)
1709
+ .addImm ((Offset >> BitPos) & 0xfff )
1710
+ .addImm (AArch64_AM::getShifterImm (
1711
+ AArch64_AM::LSL, BitPos)));
1712
+ ++InstsEmitted;
1713
+ }
1714
+ }
1715
+
1716
+ unsigned DiscReg = AddrDisc;
1717
+ if (Disc) {
1718
+ if (AddrDisc != AArch64::XZR) {
1719
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::ORRXrs)
1720
+ .addReg (AArch64::X17)
1721
+ .addReg (AArch64::XZR)
1722
+ .addReg (AddrDisc)
1723
+ .addImm (0 ));
1724
+ ++InstsEmitted;
1725
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::MOVKXi)
1726
+ .addReg (AArch64::X17)
1727
+ .addReg (AArch64::X17)
1728
+ .addImm (Disc)
1729
+ .addImm (/* shift=*/ 48 ));
1730
+ ++InstsEmitted;
1731
+ } else {
1732
+ EmitToStreamer (*OutStreamer, MCInstBuilder (AArch64::MOVZXi)
1733
+ .addReg (AArch64::X17)
1734
+ .addImm (Disc)
1735
+ .addImm (/* shift=*/ 0 ));
1736
+ ++InstsEmitted;
1737
+ }
1738
+ DiscReg = AArch64::X17;
1739
+ }
1740
+
1741
+ auto MIB = MCInstBuilder (getPACOpcodeForKey (Key, DiscReg == AArch64::XZR))
1742
+ .addReg (AArch64::X16)
1743
+ .addReg (AArch64::X16);
1744
+ if (DiscReg != AArch64::XZR)
1745
+ MIB.addReg (DiscReg);
1746
+ EmitToStreamer (*OutStreamer, MIB);
1747
+ ++InstsEmitted;
1748
+
1749
+ assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
1750
+ }
1751
+
1578
1752
// Simple pseudo-instructions have their lowering (with expansion to real
1579
1753
// instructions) auto-generated.
1580
1754
#include " AArch64GenMCPseudoLowering.inc"
@@ -1710,6 +1884,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
1710
1884
return ;
1711
1885
}
1712
1886
1887
+ case AArch64::LOADauthptrstatic:
1888
+ LowerLOADauthptrstatic (*MI);
1889
+ return ;
1890
+
1891
+ case AArch64::LOADgotPAC:
1892
+ case AArch64::MOVaddrPAC:
1893
+ LowerMOVaddrPAC (*MI);
1894
+ return ;
1895
+
1713
1896
case AArch64::BLRA:
1714
1897
emitPtrauthBranch (MI);
1715
1898
return ;
0 commit comments