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