1//===-- X86ReturnProtectorLowering.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 X86 implementation of ReturnProtectorLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "X86ReturnProtectorLowering.h"
15#include "X86InstrBuilder.h"
16#include "X86InstrInfo.h"
17#include "X86MachineFunctionInfo.h"
18#include "X86Subtarget.h"
19#include "X86TargetMachine.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/MachineModuleInfo.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/IR/Function.h"
25#include "llvm/MC/MCAsmInfo.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 X86ReturnProtectorLowering::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  unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
40
41  BuildMI(MBB, MI, MBBDL, TII->get(X86::MOV64rm), REG)
42      .addReg(X86::RIP)
43      .addImm(0)
44      .addReg(0)
45      .addGlobalAddress(cookie)
46      .addReg(0);
47  addDirectMem(BuildMI(MBB, MI, MBBDL, TII->get(X86::XOR64rm), REG).addReg(REG),
48               X86::RSP);
49}
50
51void X86ReturnProtectorLowering::insertReturnProtectorEpilogue(
52    MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const {
53
54  MachineBasicBlock &MBB = *MI.getParent();
55  DebugLoc MBBDL = MI.getDebugLoc();
56  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
57  unsigned REG = MF.getFrameInfo().getReturnProtectorRegister();
58
59  addDirectMem(BuildMI(MBB, MI, MBBDL, TII->get(X86::XOR64rm), REG).addReg(REG),
60               X86::RSP);
61  BuildMI(MBB, MI, MBBDL, TII->get(X86::CMP64rm))
62      .addReg(REG)
63      .addReg(X86::RIP)
64      .addImm(0)
65      .addReg(0)
66      .addGlobalAddress(cookie)
67      .addReg(0);
68  BuildMI(MBB, MI, MBBDL, TII->get(X86::RETGUARD_JMP_TRAP));
69}
70
71bool X86ReturnProtectorLowering::opcodeIsReturn(unsigned opcode) const {
72  switch (opcode) {
73  case X86::RET:
74  case X86::RET16:
75  case X86::RET32:
76  case X86::RET64:
77  case X86::RETI16:
78  case X86::RETI32:
79  case X86::RETI64:
80  case X86::LRET16:
81  case X86::LRET32:
82  case X86::LRET64:
83  case X86::LRETI16:
84  case X86::LRETI32:
85  case X86::LRETI64:
86    return true;
87  default:
88    return false;
89  }
90}
91
92void X86ReturnProtectorLowering::fillTempRegisters(
93    MachineFunction &MF, std::vector<unsigned> &TempRegs) const {
94
95  TempRegs.push_back(X86::R11);
96  TempRegs.push_back(X86::R10);
97  const Function &F = MF.getFunction();
98  if (!F.isVarArg()) {
99    // We can use any of the caller saved unused arg registers
100    switch (F.arg_size()) {
101    case 0:
102      TempRegs.push_back(X86::RDI);
103      LLVM_FALLTHROUGH;
104    case 1:
105      TempRegs.push_back(X86::RSI);
106      LLVM_FALLTHROUGH;
107    case 2: // RDX is the 2nd return register
108    case 3:
109      TempRegs.push_back(X86::RCX);
110      LLVM_FALLTHROUGH;
111    case 4:
112      TempRegs.push_back(X86::R8);
113      LLVM_FALLTHROUGH;
114    case 5:
115      TempRegs.push_back(X86::R9);
116      LLVM_FALLTHROUGH;
117    default:
118      break;
119    }
120  }
121}
122