PPCReturnProtectorLowering.cpp revision 1.2
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
31using namespace llvm;
32
33void 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
115void 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
216bool 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
237void 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