summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorPetar Jovanovic <petar.jovanovic@imgtec.com>2017-06-28 10:21:17 +0000
committerPetar Jovanovic <petar.jovanovic@imgtec.com>2017-06-28 10:21:17 +0000
commit7b3a38ec306c49861869dc9d2a2bd99af82b3280 (patch)
tree91bea90da1471b702f66e72f4ea3baf16e3a5329 /llvm/include
parent77b5536e4e7612c2a47e1f56253a0fc84f1beef9 (diff)
downloadbcm5719-llvm-7b3a38ec306c49861869dc9d2a2bd99af82b3280.tar.gz
bcm5719-llvm-7b3a38ec306c49861869dc9d2a2bd99af82b3280.zip
[X86] Correct dwarf unwind information in function epilogue
CFI instructions that set appropriate cfa offset and cfa register are now inserted in emitEpilogue() in X86FrameLowering. Majority of the changes in this patch: 1. Ensure that CFI instructions do not affect code generation. 2. Enable maintaining correct information about cfa offset and cfa register in a function when basic blocks are reordered, merged, split, duplicated. These changes are target independent and described below. Changed CFI instructions so that they: 1. are duplicable 2. are not counted as instructions when tail duplicating or tail merging 3. can be compared as equal Add information to each MachineBasicBlock about cfa offset and cfa register that are valid at its entry and exit (incoming and outgoing CFI info). Add support for updating this information when basic blocks are merged, split, duplicated, created. Add a verification pass (CFIInfoVerifier) that checks that outgoing cfa offset and register of predecessor blocks match incoming values of their successors. Incoming and outgoing CFI information is used by a late pass (CFIInstrInserter) that corrects CFA calculation rule for a basic block if needed. That means that additional CFI instructions get inserted at basic block beginning to correct the rule for calculating CFA. Having CFI instructions in function epilogue can cause incorrect CFA calculation rule for some basic blocks. This can happen if, due to basic block reordering, or the existence of multiple epilogue blocks, some of the blocks have wrong cfa offset and register values set by the epilogue block above them. Patch by Violeta Vukobrat. Differential Revision: https://reviews.llvm.org/D18046 llvm-svn: 306529
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/CodeGen/MachineBasicBlock.h47
-rw-r--r--llvm/include/llvm/CodeGen/MachineInstr.h1
-rw-r--r--llvm/include/llvm/CodeGen/Passes.h8
-rw-r--r--llvm/include/llvm/InitializePasses.h2
-rw-r--r--llvm/include/llvm/Target/Target.td2
-rw-r--r--llvm/include/llvm/Target/TargetFrameLowering.h13
6 files changed, 72 insertions, 1 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 97a49ce4dc4..a4ccc29c56e 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/LaneBitmask.h"
+#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/BranchProbability.h"
#include <cassert>
@@ -757,6 +758,52 @@ private:
/// unless you know what you're doing, because it doesn't update Pred's
/// successors list. Use Pred->removeSuccessor instead.
void removePredecessor(MachineBasicBlock *Pred);
+
+ // Value of cfa offset valid at basic block entry.
+ int IncomingCFAOffset = -1;
+ // Value of cfa offset valid at basic block exit.
+ int OutgoingCFAOffset = -1;
+ // Value of cfa register valid at basic block entry.
+ unsigned IncomingCFARegister = 0;
+ // Value of cfa register valid at basic block exit.
+ unsigned OutgoingCFARegister = 0;
+ // If a block contains a def_cfa_offset or def_cfa directive.
+ bool DefOffset = false;
+ // If a block contains a def_cfa_register or def_cfa directive.
+ bool DefRegister = false;
+
+ public:
+ int getIncomingCFAOffset() { return IncomingCFAOffset; }
+ void setIncomingCFAOffset(int Offset) { IncomingCFAOffset = Offset; }
+ int getOutgoingCFAOffset() { return OutgoingCFAOffset; }
+ void setOutgoingCFAOffset(int Offset) { OutgoingCFAOffset = Offset; }
+ unsigned getIncomingCFARegister() { return IncomingCFARegister; }
+ void setIncomingCFARegister(unsigned Register) {
+ IncomingCFARegister = Register;
+ }
+ unsigned getOutgoingCFARegister() { return OutgoingCFARegister; }
+ void setOutgoingCFARegister(unsigned Register) {
+ OutgoingCFARegister = Register;
+ }
+
+ bool hasDefOffset() { return DefOffset; }
+ bool hasDefRegister() { return DefRegister; }
+ void setDefOffset(bool SetsOffset) { DefOffset = SetsOffset; }
+ void setDefRegister(bool SetsRegister) { DefRegister = SetsRegister; }
+
+ // Update the outgoing cfa offset and register for this block based on the CFI
+ // instruction inserted at Pos.
+ void updateCFIInfo(MachineBasicBlock::iterator Pos);
+ // Update the cfa offset and register values for all successors of this block.
+ void updateCFIInfoSucc();
+ // Recalculate outgoing cfa offset and register. Use existing incoming offset
+ // and register values if UseExistingIncoming is set to true. If it is false,
+ // use new values passed as arguments.
+ void recalculateCFIInfo(bool UseExistingIncoming, int NewIncomingOffset = -1,
+ unsigned NewIncomingRegister = 0);
+ // Update outgoing cfa offset and register of the block after it is merged
+ // with MBB.
+ void mergeCFIInfo(MachineBasicBlock *MBB);
};
raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB);
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 95401e98b29..15ea29f369d 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -789,6 +789,7 @@ public:
&& getOperand(1).isImm();
}
+ bool isDirective() const { return isDebugValue() || isCFIInstruction(); }
bool isPHI() const { return getOpcode() == TargetOpcode::PHI; }
bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 96cfce5b84d..ca54c8e25a5 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -420,6 +420,14 @@ namespace llvm {
/// shuffles.
FunctionPass *createExpandReductionsPass();
+ /// This pass verifies that outgoing cfa offset and register of predecessor
+ /// blocks match incoming cfa offset and register of their successors.
+ FunctionPass *createCFIInfoVerifier();
+
+ /// This pass inserts required CFI instruction at basic block beginning to
+ /// correct the CFA calculation rule for that block if necessary.
+ FunctionPass *createCFIInstrInserter();
+
} // End llvm namespace
#endif
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index a52fa3b542a..01c91f28874 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -87,6 +87,8 @@ void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&);
void initializeCFGPrinterLegacyPassPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
void initializeCFGViewerLegacyPassPass(PassRegistry&);
+void initializeCFIInfoVerifierPass(PassRegistry&);
+void initializeCFIInstrInserterPass(PassRegistry&);
void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
void initializeCallGraphDOTPrinterPass(PassRegistry&);
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 6f44292c47e..3657f7fc828 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -824,7 +824,7 @@ def CFI_INSTRUCTION : Instruction {
let InOperandList = (ins i32imm:$id);
let AsmString = "";
let hasCtrlDep = 1;
- let isNotDuplicable = 1;
+ let isNotDuplicable = 0;
}
def EH_LABEL : Instruction {
let OutOperandList = (outs);
diff --git a/llvm/include/llvm/Target/TargetFrameLowering.h b/llvm/include/llvm/Target/TargetFrameLowering.h
index 4576f8c7582..7e6e40f0892 100644
--- a/llvm/include/llvm/Target/TargetFrameLowering.h
+++ b/llvm/include/llvm/Target/TargetFrameLowering.h
@@ -339,6 +339,19 @@ public:
return false;
return true;
}
+
+ // Set initial incoming and outgoing cfa offset and register values for basic
+ // blocks. Initial values are the ones valid at the beginning of the function
+ // (before any stack operations). Incoming and outgoing cfa offset and
+ // register values are used to keep track of offset and register that are
+ // valid at basic block entry and exit. This information is used by a late
+ // pass that corrects the CFA calculation rule for a basic block if needed.
+ // Having CFI instructions in function epilogue can cause incorrect CFA
+ // calculation rule for some basic blocks. This can happen if, due to basic
+ // block reordering, or the existence of multiple epilogue blocks, some of the
+ // blocks have wrong cfa offset and register values set by the epilogue block
+ // above them.
+ virtual void initializeCFIInfo(MachineFunction & MF) const {}
};
} // End llvm namespace
OpenPOWER on IntegriCloud