109467b48Spatrick //===-- AArch64ReturnProtectorLowering.cpp --------------------------------===//
209467b48Spatrick //
309467b48Spatrick //                     The LLVM Compiler Infrastructure
409467b48Spatrick //
509467b48Spatrick // This file is distributed under the University of Illinois Open Source
609467b48Spatrick // License. See LICENSE.TXT for details.
709467b48Spatrick //
809467b48Spatrick //===----------------------------------------------------------------------===//
909467b48Spatrick //
1009467b48Spatrick // This file contains the AArch64 implementation of ReturnProtectorLowering
1109467b48Spatrick // class.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1509467b48Spatrick #include "AArch64InstrInfo.h"
1609467b48Spatrick #include "AArch64MachineFunctionInfo.h"
1709467b48Spatrick #include "AArch64RegisterInfo.h"
1809467b48Spatrick #include "AArch64ReturnProtectorLowering.h"
1909467b48Spatrick #include "AArch64Subtarget.h"
2009467b48Spatrick #include "AArch64TargetMachine.h"
2109467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
2209467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineModuleInfo.h"
2409467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2509467b48Spatrick #include "llvm/IR/Function.h"
2609467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
2709467b48Spatrick #include "llvm/MC/MCSymbol.h"
2809467b48Spatrick #include "llvm/Support/Debug.h"
2909467b48Spatrick #include "llvm/Target/TargetOptions.h"
3009467b48Spatrick #include <cstdlib>
3109467b48Spatrick 
3209467b48Spatrick using namespace llvm;
3309467b48Spatrick 
insertReturnProtectorPrologue(MachineFunction & MF,MachineBasicBlock & MBB,GlobalVariable * cookie) const3409467b48Spatrick void AArch64ReturnProtectorLowering::insertReturnProtectorPrologue(
3509467b48Spatrick     MachineFunction &MF, MachineBasicBlock &MBB, GlobalVariable *cookie) const {
3609467b48Spatrick 
3709467b48Spatrick   MachineBasicBlock::instr_iterator MI = MBB.instr_begin();
3809467b48Spatrick   DebugLoc MBBDL = MBB.findDebugLoc(MI);
3909467b48Spatrick   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
4009467b48Spatrick   unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
4109467b48Spatrick 
4209467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ADRP), REG)
4309467b48Spatrick       .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE);
4409467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), REG)
4509467b48Spatrick       .addReg(REG)
4609467b48Spatrick       .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4709467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG)
4809467b48Spatrick       .addReg(REG)
4909467b48Spatrick       .addReg(AArch64::LR);
5009467b48Spatrick }
5109467b48Spatrick 
insertReturnProtectorEpilogue(MachineFunction & MF,MachineInstr & MI,GlobalVariable * cookie) const5209467b48Spatrick void AArch64ReturnProtectorLowering::insertReturnProtectorEpilogue(
5309467b48Spatrick     MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const {
5409467b48Spatrick 
5509467b48Spatrick   MachineBasicBlock &MBB = *MI.getParent();
5609467b48Spatrick   DebugLoc MBBDL = MI.getDebugLoc();
5709467b48Spatrick   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
5809467b48Spatrick   unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
5909467b48Spatrick 
6009467b48Spatrick   MBB.addLiveIn(AArch64::X9);
6109467b48Spatrick   // REG holds the cookie we calculated in prologue. We use X9 as a
6209467b48Spatrick   // scratch reg to pull the random data. XOR REG with LR should yield
6309467b48Spatrick   // the random data again. Compare REG with X9 to check.
6409467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::EORXrr), REG)
6509467b48Spatrick       .addReg(REG)
6609467b48Spatrick       .addReg(AArch64::LR);
6709467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ADRP), AArch64::X9)
6809467b48Spatrick       .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE);
6909467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), AArch64::X9)
7009467b48Spatrick       .addReg(AArch64::X9)
7109467b48Spatrick       .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
7209467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::SUBSXrr), REG)
7309467b48Spatrick       .addReg(REG)
7409467b48Spatrick       .addReg(AArch64::X9);
7509467b48Spatrick   BuildMI(MBB, MI, MBBDL, TII->get(AArch64::RETGUARD_JMP_TRAP)).addReg(REG);
7609467b48Spatrick }
7709467b48Spatrick 
opcodeIsReturn(unsigned opcode) const7809467b48Spatrick bool AArch64ReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
7909467b48Spatrick   switch (opcode) {
8009467b48Spatrick   case AArch64::RET:
8109467b48Spatrick   case AArch64::RET_ReallyLR:
8209467b48Spatrick     return true;
8309467b48Spatrick   default:
8409467b48Spatrick     return false;
8509467b48Spatrick   }
8609467b48Spatrick }
8709467b48Spatrick 
fillTempRegisters(MachineFunction & MF,std::vector<unsigned> & TempRegs) const8809467b48Spatrick void AArch64ReturnProtectorLowering::fillTempRegisters(
8909467b48Spatrick     MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
9009467b48Spatrick 
9109467b48Spatrick   TempRegs.push_back(AArch64::X15);
9209467b48Spatrick   TempRegs.push_back(AArch64::X14);
9309467b48Spatrick   TempRegs.push_back(AArch64::X13);
9409467b48Spatrick   TempRegs.push_back(AArch64::X12);
9509467b48Spatrick   TempRegs.push_back(AArch64::X11);
9609467b48Spatrick   TempRegs.push_back(AArch64::X10);
9709467b48Spatrick }
9809467b48Spatrick 
saveReturnProtectorRegister(MachineFunction & MF,std::vector<CalleeSavedInfo> & CSI) const9909467b48Spatrick void AArch64ReturnProtectorLowering::saveReturnProtectorRegister(
10009467b48Spatrick     MachineFunction &MF, std::vector<CalleeSavedInfo> &CSI) const {
10109467b48Spatrick 
10209467b48Spatrick   const MachineFrameInfo &MFI = MF.getFrameInfo();
10309467b48Spatrick   if (!MFI.getReturnProtectorNeeded())
10409467b48Spatrick     return;
10509467b48Spatrick 
10609467b48Spatrick   if (!MFI.hasReturnProtectorRegister())
10709467b48Spatrick     llvm_unreachable("Saving unset return protector register");
10809467b48Spatrick 
10909467b48Spatrick   unsigned Reg = MFI.getReturnProtectorRegister();
11009467b48Spatrick   if (!MFI.getReturnProtectorNeedsStore()) {
11109467b48Spatrick     for (auto &MBB : MF) {
11209467b48Spatrick       if (!MBB.isLiveIn(Reg))
11309467b48Spatrick         MBB.addLiveIn(Reg);
11409467b48Spatrick     }
11509467b48Spatrick     return;
11609467b48Spatrick   }
11709467b48Spatrick 
118*7ad5461fSmortimer   // CSI Reg order is important for pairing registers later.
119*7ad5461fSmortimer   // The expected order of the CSI is given by getCalleeSavedRegs(),
120*7ad5461fSmortimer   // which for us returns a list of GPRs and FPRs in ascending
121*7ad5461fSmortimer   // order. Since our temp regs are all before the usual callee
122*7ad5461fSmortimer   // saved regs, we can just insert our reg first.
123*7ad5461fSmortimer   CSI.insert(CSI.begin(), CalleeSavedInfo(MFI.getReturnProtectorRegister()));
12409467b48Spatrick }
125