blob: b83c957d7c47095e0222435de5c03781782ab113 [file] [log] [blame]
Petar Jovanovic7b3a38e2017-06-28 10:21:17 +00001//===------ CFIInstrInserter.cpp - Insert additional CFI instructions -----===//
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// Insert CFI instructions at the beginnings of basic blocks if needed. CFI
11// instructions are inserted if basic blocks have incorrect offset or register
12// set by prevoius blocks.
13//
14//===----------------------------------------------------------------------===//
15#include "llvm/CodeGen/MachineFunctionPass.h"
16#include "llvm/CodeGen/MachineInstrBuilder.h"
17#include "llvm/CodeGen/MachineModuleInfo.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/Target/TargetInstrInfo.h"
20#include "llvm/Target/TargetMachine.h"
21#include "llvm/Target/TargetSubtargetInfo.h"
22using namespace llvm;
23
24namespace {
25class CFIInstrInserter : public MachineFunctionPass {
26 public:
27 CFIInstrInserter() : MachineFunctionPass(ID) {
28 initializeCFIInstrInserterPass(*PassRegistry::getPassRegistry());
29 }
30 bool runOnMachineFunction(MachineFunction &MF) override;
31 static char ID;
32
33 private:
34 StringRef getPassName() const override { return "CFI Instruction Inserter"; }
35
36 // Check if incoming CFI information of a basic block matches outgoing CFI
37 // information of the previous block. If it doesn't, insert CFI instruction at
38 // the beginning of the block that corrects the CFA calculation rule for that
39 // block.
40 void CorrectCFA(MachineFunction &MF);
41
42 // Return the cfa offset value that should be set at the beginning of MBB if
43 // needed. The negated value is needed when creating CFI instructions that set
44 // absolute offset.
45 int getCorrectCFAOffset(MachineBasicBlock &MBB) {
46 return -MBB.getIncomingCFAOffset();
47 }
48
49 // Were any CFI instructions inserted
50 bool InsertedCFIInstr = false;
51};
52}
53
54char CFIInstrInserter::ID = 0;
55INITIALIZE_PASS(CFIInstrInserter, "cfiinstrinserter",
56 "Check CFI info and insert CFI instructions if needed", false,
57 false)
58
59FunctionPass *llvm::createCFIInstrInserter() { return new CFIInstrInserter(); }
60
61bool CFIInstrInserter::runOnMachineFunction(MachineFunction &MF) {
62 bool NeedsDwarfCFI = (MF.getMMI().hasDebugInfo() ||
63 MF.getFunction()->needsUnwindTableEntry()) &&
64 (!MF.getTarget().getTargetTriple().isOSDarwin() &&
65 !MF.getTarget().getTargetTriple().isOSWindows());
66
67 if (!NeedsDwarfCFI) return false;
68
69 // Insert appropriate CFI instructions for each MBB if CFA calculation rule
70 // needs to be corrected for that MBB.
71 CorrectCFA(MF);
72
73 return InsertedCFIInstr;
74}
75
76void CFIInstrInserter::CorrectCFA(MachineFunction &MF) {
77
78 MachineBasicBlock &FirstMBB = MF.front();
79 MachineBasicBlock *PrevMBB = &FirstMBB;
80 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
81 InsertedCFIInstr = false;
82
83 for (auto &MBB : MF) {
84 // Skip the first MBB in a function
85 if (MBB.getNumber() == FirstMBB.getNumber()) continue;
86
87 auto MBBI = MBB.begin();
88 DebugLoc DL = MBB.findDebugLoc(MBBI);
89
90 if (PrevMBB->getOutgoingCFAOffset() != MBB.getIncomingCFAOffset()) {
91 // If both outgoing offset and register of a previous block don't match
92 // incoming offset and register of this block, add a def_cfa instruction
93 // with the correct offset and register for this block.
94 if (PrevMBB->getOutgoingCFARegister() != MBB.getIncomingCFARegister()) {
95 unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
96 nullptr, MBB.getIncomingCFARegister(), getCorrectCFAOffset(MBB)));
97 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
98 .addCFIIndex(CFIIndex);
99 // If outgoing offset of a previous block doesn't match incoming offset
100 // of this block, add a def_cfa_offset instruction with the correct
101 // offset for this block.
102 } else {
103 unsigned CFIIndex =
104 MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(
105 nullptr, getCorrectCFAOffset(MBB)));
106 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
107 .addCFIIndex(CFIIndex);
108 }
109 InsertedCFIInstr = true;
110 // If outgoing register of a previous block doesn't match incoming
111 // register of this block, add a def_cfa_register instruction with the
112 // correct register for this block.
113 } else if (PrevMBB->getOutgoingCFARegister() !=
114 MBB.getIncomingCFARegister()) {
115 unsigned CFIIndex =
116 MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
117 nullptr, MBB.getIncomingCFARegister()));
118 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
119 .addCFIIndex(CFIIndex);
120 InsertedCFIInstr = true;
121 }
122 PrevMBB = &MBB;
123 }
124}