xref: /openbsd-src/gnu/llvm/llvm/lib/Target/PowerPC/PPCReturnProtectorLowering.cpp (revision 281fc861f1643ad20868f1a996ca9689e28c0b9d)
1 //===-- PPCReturnProtectorLowering.cpp --------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the PPC implementation of ReturnProtectorLowering
11 // class.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "PPC.h"
16 #include "PPCInstrInfo.h"
17 #include "PPCMachineFunctionInfo.h"
18 #include "PPCReturnProtectorLowering.h"
19 #include "PPCTargetMachine.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Target/TargetOptions.h"
29 #include <cstdlib>
30 
31 using namespace llvm;
32 
insertReturnProtectorPrologue(MachineFunction & MF,MachineBasicBlock & MBB,GlobalVariable * cookie) const33 void PPCReturnProtectorLowering::insertReturnProtectorPrologue(
34     MachineFunction &MF, MachineBasicBlock &MBB, GlobalVariable *cookie) const {
35 
36   MachineBasicBlock::instr_iterator MI = MBB.instr_begin();
37   DebugLoc MBBDL = MBB.findDebugLoc(MI);
38   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
39   const TargetMachine &TM = MF.getTarget();
40   unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
41   bool is64bit = MF.getSubtarget<PPCSubtarget>().isPPC64();
42   bool isELFv2 = MF.getSubtarget<PPCSubtarget>().isELFv2ABI();
43 
44   unsigned LRReg = PPC::R0;
45   unsigned TOCReg = PPC::R2;
46   unsigned XOR = PPC::XOR;
47   unsigned LWZ = PPC::LWZ;
48   unsigned MFLR = PPC::MFLR;
49   if (is64bit) {
50     LRReg = PPC::X0;
51     TOCReg = PPC::X2;
52     XOR = PPC::XOR8;
53     LWZ = PPC::LWZ8;
54     MFLR = PPC::MFLR8;
55   }
56 
57   if (!MBB.isLiveIn(LRReg))
58     MBB.addLiveIn(LRReg);
59 
60   if (is64bit) {
61     // PIC and non-PIC is the same
62     if (!isELFv2)
63       llvm_unreachable("ppc64 retguard requires ELFv2");
64     // Get the return address into LRReg
65     BuildMI(MBB, MI, MBBDL, TII->get(MFLR), LRReg);
66     // Load the random cookie value into REG
67     BuildMI(MBB, MI, MBBDL, TII->get(PPC::ADDIStocHA8), REG)
68       .addReg(TOCReg)
69       .addGlobalAddress(cookie);
70     BuildMI(MBB, MI, MBBDL, TII->get(PPC::LD), REG)
71       .addGlobalAddress(cookie, 0, PPCII::MO_TOC_LO)
72       .addReg(REG);
73     // XOR cookie ^ random = retguard cookie
74     BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
75       .addReg(REG)
76       .addReg(LRReg);
77   } else {
78     // 32 bit
79     if (TM.isPositionIndependent()) {
80       MCSymbol *HereSym = MF.getContext().createTempSymbol();
81       // Get LR into a register, and get PC into another register
82       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_PC), REG)
83         .addReg(LRReg, RegState::Define)
84         .addSym(HereSym);
85       // Get the random cookie address into REG
86       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_GOT), REG)
87         .addReg(REG)
88         .addSym(HereSym);
89       BuildMI(MBB, MI, MBBDL, TII->get(PPC::LWZtoc), REG)
90         .addGlobalAddress(cookie, 0, 0)
91         .addReg(REG);
92       // Now load the random cookie value
93       BuildMI(MBB, MI, MBBDL, TII->get(PPC::LWZ), REG)
94         .addImm(0)
95         .addReg(REG);
96       // XOR cookie ^ random = retguard cookie
97       BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
98         .addReg(REG)
99         .addReg(LRReg);
100     } else {
101       // Non-PIC prologue
102       // Load LR into a register
103       BuildMI(MBB, MI, MBBDL, TII->get(MFLR), LRReg);
104       // Load random cookie into another register
105       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_COOKIE), REG)
106         .addGlobalAddress(cookie);
107       // XOR cookie ^ random = retguard cookie
108       BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
109         .addReg(REG)
110         .addReg(LRReg);
111     }
112   }
113 }
114 
insertReturnProtectorEpilogue(MachineFunction & MF,MachineInstr & MI,GlobalVariable * cookie) const115 void PPCReturnProtectorLowering::insertReturnProtectorEpilogue(
116     MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const {
117 
118   MachineBasicBlock &MBB = *MI.getParent();
119   DebugLoc MBBDL = MI.getDebugLoc();
120   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
121   const TargetMachine &TM = MF.getTarget();
122   unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
123   bool is64bit = MF.getSubtarget<PPCSubtarget>().isPPC64();
124   bool isELFv2 = MF.getSubtarget<PPCSubtarget>().isELFv2ABI();
125 
126   unsigned LRReg = PPC::R0;
127   unsigned TOCReg = PPC::R2;
128   unsigned RGReg = PPC::R12;
129   unsigned TRAP = PPC::TW;
130   unsigned XOR = PPC::XOR;
131   unsigned LWZ = PPC::LWZ;
132   unsigned MFLR = PPC::MFLR;
133   if (is64bit) {
134     LRReg = PPC::X0;
135     TOCReg = PPC::X2;
136     RGReg = PPC::X12;
137     TRAP = PPC::TD;
138     XOR = PPC::XOR8;
139     LWZ = PPC::LWZ8;
140     MFLR = PPC::MFLR8;
141   }
142 
143   if (!MBB.isLiveIn(LRReg))
144     MBB.addLiveIn(LRReg);
145   if (!MBB.isLiveIn(RGReg))
146     MBB.addLiveIn(RGReg);
147 
148   if (is64bit) {
149     // PIC and non-PIC is the same
150     if (!isELFv2)
151       llvm_unreachable("ppc64 retguard requires ELFv2");
152     // Get the return address into LRReg
153     BuildMI(MBB, MI, MBBDL, TII->get(MFLR), LRReg);
154     // XOR the LRReg with the retguard cookie value
155     BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
156       .addReg(REG)
157       .addReg(LRReg);
158     // Load the random cookie value into RGReg
159     BuildMI(MBB, MI, MBBDL, TII->get(PPC::ADDIStocHA8), RGReg)
160       .addReg(TOCReg)
161       .addGlobalAddress(cookie);
162     BuildMI(MBB, MI, MBBDL, TII->get(PPC::LD), RGReg)
163       .addGlobalAddress(cookie, 0, PPCII::MO_TOC_LO)
164       .addReg(RGReg);
165     // Trap if they don't compare
166     BuildMI(MBB, MI, MBBDL, TII->get(TRAP))
167       .addImm(24)
168       .addReg(REG)
169       .addReg(RGReg);
170   } else {
171     // 32 bit
172     if (TM.isPositionIndependent()) {
173       // Get the PC into RGReg and the LR value into LRReg
174       MCSymbol *HereSym = MF.getContext().createTempSymbol();
175       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_PC), RGReg)
176         .addReg(LRReg, RegState::Define)
177         .addSym(HereSym);
178       // XOR the LRReg with the retguard cookie value
179       BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
180         .addReg(REG)
181         .addReg(LRReg);
182       // Get the random cookie address into RGReg
183       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_GOT), RGReg)
184         .addReg(RGReg)
185         .addSym(HereSym);
186       BuildMI(MBB, MI, MBBDL, TII->get(PPC::LWZtoc), RGReg)
187         .addGlobalAddress(cookie, 0, 0)
188         .addReg(RGReg);
189       // Load the cookie random balue
190       BuildMI(MBB, MI, MBBDL, TII->get(PPC::LWZ), RGReg)
191         .addImm(0)
192         .addReg(RGReg);
193       // Trap if they don't compare
194       BuildMI(MBB, MI, MBBDL, TII->get(TRAP))
195         .addImm(24)
196         .addReg(REG)
197         .addReg(RGReg);
198     } else {
199       // Get LR into a register
200       BuildMI(MBB, MI, MBBDL, TII->get(MFLR), LRReg);
201       // XOR the LR Reg with the retguard cookie value
202       BuildMI(MBB, MI, MBBDL, TII->get(XOR), REG)
203         .addReg(REG)
204         .addReg(LRReg);
205       BuildMI(MBB, MI, MBBDL, TII->get(PPC::RETGUARD_LOAD_COOKIE), RGReg)
206         .addGlobalAddress(cookie);
207       // Trap if they don't compare
208       BuildMI(MBB, MI, MBBDL, TII->get(TRAP))
209         .addImm(24)
210         .addReg(REG)
211         .addReg(RGReg);
212     }
213   }
214 }
215 
opcodeIsReturn(unsigned opcode) const216 bool PPCReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
217   switch (opcode) {
218     case PPC::BLR:
219     case PPC::BCCLR:
220     case PPC::BCLR:
221     case PPC::BCLRn:
222     case PPC::BDZLR:
223     case PPC::BDNZLR:
224     case PPC::BDZLRp:
225     case PPC::BDNZLRp:
226     case PPC::BDZLRm:
227     case PPC::BDNZLRm:
228     case PPC::BLR8:
229     case PPC::BDZLR8:
230     case PPC::BDNZLR8:
231       return true;
232     default:
233       return false;
234   }
235 }
236 
fillTempRegisters(MachineFunction & MF,std::vector<unsigned> & TempRegs) const237 void PPCReturnProtectorLowering::fillTempRegisters(
238     MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
239 
240   const Function &F = MF.getFunction();
241 
242   bool is64bit = MF.getSubtarget<PPCSubtarget>().isPPC64();
243 
244   // R0/R12 are also the hardcoded temp regs for the rest of
245   // frame lowering, so leave them alone.
246   //TempRegs.push_back(is64bit ? PPC::X0  : PPC::R0);
247   //TempRegs.push_back(is64bit ? PPC::X12 : PPC::R12);
248   // X11 is also the 'nest' param or environment pointer
249   TempRegs.push_back(is64bit ? PPC::X11 : PPC::R11);
250 
251   if (!F.isVarArg()) {
252     // We can use any of the caller saved unused arg registers
253     switch (F.arg_size()) {
254       case 0: // X3/R3 are used to return
255       case 1: // X4/R4 are used to return
256       case 2:
257         TempRegs.push_back(is64bit ? PPC::X5 : PPC::R5);
258         LLVM_FALLTHROUGH;
259       case 3:
260         TempRegs.push_back(is64bit ? PPC::X6 : PPC::R6);
261         LLVM_FALLTHROUGH;
262       case 4:
263         TempRegs.push_back(is64bit ? PPC::X7 : PPC::R7);
264         LLVM_FALLTHROUGH;
265       case 5:
266         TempRegs.push_back(is64bit ? PPC::X8 : PPC::R8);
267         LLVM_FALLTHROUGH;
268       case 6:
269         TempRegs.push_back(is64bit ? PPC::X9 : PPC::R9);
270         LLVM_FALLTHROUGH;
271       case 7:
272         TempRegs.push_back(is64bit ? PPC::X10 : PPC::R10);
273         LLVM_FALLTHROUGH;
274       default:
275         break;
276     }
277   }
278 }
279