xref: /openbsd-src/gnu/llvm/llvm/lib/Target/X86/X86ReturnProtectorLowering.cpp (revision a96b36398fcfb4953e8190127da8bf074c7552f1)
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 
31 using namespace llvm;
32 
insertReturnProtectorPrologue(MachineFunction & MF,MachineBasicBlock & MBB,GlobalVariable * cookie) const33 void 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 
insertReturnProtectorEpilogue(MachineFunction & MF,MachineInstr & MI,GlobalVariable * cookie) const51 void 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 
opcodeIsReturn(unsigned opcode) const71 bool 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 
fillTempRegisters(MachineFunction & MF,std::vector<unsigned> & TempRegs) const92 void 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