[PATCH] D35844: Correct dwarf unwind information in function epilogue
Matthias Braun via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 3 11:50:41 PDT 2017
MatzeB added a comment.
Thanks @violetav this looks a lot better as a self-contained pass!
================
Comment at: include/llvm/CodeGen/MachineInstr.h:795
+ bool isDirective() const { return isDebugValue() || isCFIInstruction(); }
bool isPHI() const {
----------------
This name is unintuitive to me. And it feels like this isn't really a category of machine instructions but rather just a combination that `BranchFolding` is able to deal with after this patch.
Maybe it would be better to move this into BranchFolding.cpp then in the form of
`static bool isDirective(const MachineInstr &MI) { return MI.isDebugValue() || MI.isCFIInstruction(); }`.
================
Comment at: include/llvm/CodeGen/Passes.h:420-424
+ /// This pass verifies that outgoing cfa offset and register of predecessor
+ /// blocks match incoming cfa offset and register of their successors. Then it
+ /// checks if blocks have correct CFA calculation rule set and inserts
+ /// required CFI instruction at their beginnings if they don't (due to
+ /// non-linear block layout).
----------------
Even though there is a lot of precedent in this file, I'm starting to wonder how useful it is to have a description of a pass at the beginning of the passes implementation file and another one in front of the corresponding function in Passes.h. Maybe it would be best to shorten this to:
```
/// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp
```
so we only have to maintain one description of the passes details.
================
Comment at: include/llvm/Target/TargetFrameLowering.h:345-347
+ // Return initial CFA offset value i.e. the one valid at the beginning of the
+ // function (before any stack operations).
+ virtual int getInitialCFAOffset(MachineFunction &MF) const;
----------------
- Use doxygen `///` comments.
- I guess `const MachineFunction &MF` should work as well?
================
Comment at: include/llvm/Target/TargetFrameLowering.h:349-351
+ // Return initial CFA register value i.e. the one valid at the beginning of
+ // the function (before any stack operations).
+ virtual unsigned getInitialCFARegister(MachineFunction &MF) const;
----------------
ditto
================
Comment at: include/llvm/Target/TargetMachine.h:268-272
+
+ /// Check whether CFA info is maintained for this target. If not, it shouldn't
+ /// be verified for consistency and additional CFI instructions should not be
+ /// inserted to correct CFA calculation rule.
+ virtual bool maintainsCFAInfo() const { return false; }
----------------
I think we should rather add a TargetPassConfig method instead of another TargetMachine callback (see below).
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:10-18
+// This pass verifies incoming and outgoing CFA information of basic blocks. CFA
+// information is information about offset and register set by CFI directives,
+// valid at the start and end of a basic block. This pass checks that outgoing
+// information of predecessors matches incoming information of their successors.
+// Then it checks if blocks have correct CFA calculation rule set and inserts
+// additional CFI instruction at their beginnings if they don't. CFI
+// instructions are inserted if basic blocks have incorrect offset or register
----------------
Use doxygen comments:
```
/// \file This pass verifies ...
```
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:35
+ static char ID;
+ int ErrorNum;
+
----------------
This feels slightly out of place as a member variable. Why not make it a return value of `verify()`?
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:53
+ calculateCFAInfo(MF);
+ verify(MF);
+ if (ErrorNum)
----------------
thegameg wrote:
> Should this be guarded by the `EXPENSIVE_CHECKS` macro?
I wouldn't go as far as EXPENSIVE_CHECKS. But I think `#ifndef NDEBUG` would be good to skip the verification in release builds.
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:77-79
+ // Contains cfa offset and register values valid at entry and exit of basic
+ // blocks.
+ std::map<unsigned, MBBCFAInfo> MBBMap;
----------------
MachineBasicBlocks have a dense numbering, so you can use a more efficient std::vector of length `MachineFunction::getNumBlockIDs()` instead. (See MachineTraceMetrics::BlockInfo for an example)
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:114
+char CFIInstrInserter::ID = 0;
+INITIALIZE_PASS(CFIInstrInserter, "CFIInstrInserter",
+ "Check CFA info and insert CFI instructions if needed", false,
----------------
We tend to use lowercase pass names here. So maybe `"cfi-instr-inserter"`?
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:130
+ // Initialize MBBMap.
+ for (auto &MBB : MF) {
+ struct MBBCFAInfo MBBInfo;
----------------
Please avoid `auto` in cases where the actual type is only slightly longer. I think that is friendlier to readers of the code. (same for a number of other loops below).
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:164-165
+ // Determine cfa offset and register set by the block.
+ for (MachineBasicBlock::instr_iterator MI = MBBInfo->MBB->instr_begin();
+ MI != MBBInfo->MBB->instr_end(); ++MI) {
+ if (MI->isCFIInstruction()) {
----------------
You could use `for (MachineInstr &MI : make_range(MBBInfo->MBB->instr_begin(), MBBInfo->MBB->instr_end()) { ... }` here.
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:205
+ MBBCFAInfo PrevMBBInfo = MBBMap[MF.front().getNumber()];
+ MBBCFAInfo MBBInfo;
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
----------------
You could move this declaration down to the use (and combine it with the first assignment).
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:254
+void CFIInstrInserter::report(const char *msg, MachineBasicBlock &MBB) {
+ assert(&MBB);
+ ErrorNum++;
----------------
thegameg wrote:
> I think you can assume the reference is always non-null here, right?
References must be non-null otherwise it's undefined behavior. This means the compiler will most likely optimize this assert away and it won't do anything even if the reference happened to illegally be nullptr.
================
Comment at: lib/CodeGen/CFIInstrInserter.cpp:266
+ ErrorNum = 0;
+ MBBCFAInfo CurrMBBInfo, PredMBBInfo, SuccMBBInfo;
+ for (auto &CurrMBB : MF) {
----------------
The declarations could be move downwards to their first use.
================
Comment at: lib/CodeGen/MachineInstr.cpp:331-347
+ if (op != OtherInst.getOperation()) return false;
+ if (op == MCCFIInstruction::OpDefCfa || op == MCCFIInstruction::OpOffset ||
+ op == MCCFIInstruction::OpRestore ||
+ op == MCCFIInstruction::OpUndefined ||
+ op == MCCFIInstruction::OpSameValue ||
+ op == MCCFIInstruction::OpDefCfaRegister ||
+ op == MCCFIInstruction::OpRelOffset ||
----------------
This looks like a good candidate for a `switch()`.
================
Comment at: lib/CodeGen/TargetFrameLoweringImpl.cpp:109-112
+ assert(!MF.getTarget().maintainsCFAInfo() &&
+ "Must implement getInitialCFAOffset() if target maintains CFA "
+ "information!");
+ return -1;
----------------
I'd simply use `llvm_unreachable("getInitialCFAOffset not implemented!");` and don't even bother checking the flag. Same in the next function.
================
Comment at: lib/CodeGen/TargetPassConfig.cpp:877-881
+ // Verify basic block incoming and outgoing cfa offset and register values and
+ // correct CFA calculation rule where needed by inserting appropriate CFI
+ // instructions.
+ if (TM->maintainsCFAInfo())
+ addPass(createCFIInstrInserter(), false);
----------------
- I'd vote to remove the `maintainsCFAInfo()` flag and simply let the targets that need it add the pass as part of `addPreEmitPass()`.
- Is the `, false` really necessary? I wouldn't expect the pass to produce anything that fails the machine verifier.
Repository:
rL LLVM
https://reviews.llvm.org/D35844
More information about the llvm-commits
mailing list