aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 8161de5..47a18ec 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -13,6 +13,7 @@
#include "CodeViewDebug.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
@@ -26,6 +27,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
@@ -1243,6 +1245,8 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
if (SP != nullptr)
emitDebugInfoForUDTs(LocalUDTs);
+ emitDebugInfoForJumpTables(FI);
+
// We're done with this function.
emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
}
@@ -1578,6 +1582,11 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
}
}
}
+
+ // Mark branches that may potentially be using jump tables with labels.
+ bool isThumb = Triple(MMI->getModule()->getTargetTriple()).getArch() ==
+ llvm::Triple::ArchType::thumb;
+ discoverJumpTableBranches(MF, isThumb);
}
static bool shouldEmitUdt(const DIType *T) {
@@ -3083,6 +3092,10 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
}
}
+ bool isThumb = Triple(MMI->getModule()->getTargetTriple()).getArch() ==
+ llvm::Triple::ArchType::thumb;
+ collectDebugInfoForJumpTables(MF, isThumb);
+
CurFn->Annotations = MF->getCodeViewAnnotations();
CurFn->End = Asm->getFunctionEnd();
@@ -3442,3 +3455,135 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
}
}
+
+void forEachJumpTableBranch(
+ const MachineFunction *MF, bool isThumb,
+ const std::function<void(const MachineJumpTableInfo &, const MachineInstr &,
+ int64_t)> &Callback) {
+ auto JTI = MF->getJumpTableInfo();
+ if (JTI && !JTI->isEmpty()) {
+#ifndef NDEBUG
+ auto UsedJTs = llvm::SmallBitVector(JTI->getJumpTables().size());
+#endif
+ for (const auto &MBB : *MF) {
+ // Search for indirect branches...
+ const auto LastMI = MBB.getFirstTerminator();
+ if (LastMI != MBB.end() && LastMI->isIndirectBranch()) {
+ if (isThumb) {
+ // ... that directly use jump table operands.
+ // NOTE: ARM uses pattern matching to lower its BR_JT SDNode to
+ // machine instructions, hence inserting a JUMP_TABLE_DEBUG_INFO node
+ // interferes with this process *but* the resulting pseudo-instruction
+ // uses a Jump Table operand, so extract the jump table index directly
+ // from that.
+ for (const auto &MO : LastMI->operands()) {
+ if (MO.isJTI()) {
+ unsigned Index = MO.getIndex();
+#ifndef NDEBUG
+ UsedJTs.set(Index);
+#endif
+ Callback(*JTI, *LastMI, Index);
+ break;
+ }
+ }
+ } else {
+ // ... that have jump table debug info.
+ // NOTE: The debug info is inserted as a JUMP_TABLE_DEBUG_INFO node
+ // when lowering the BR_JT SDNode to an indirect branch.
+ for (auto I = MBB.instr_rbegin(), E = MBB.instr_rend(); I != E; ++I) {
+ if (I->isJumpTableDebugInfo()) {
+ unsigned Index = I->getOperand(0).getImm();
+#ifndef NDEBUG
+ UsedJTs.set(Index);
+#endif
+ Callback(*JTI, *LastMI, Index);
+ break;
+ }
+ }
+ }
+ }
+ }
+#ifndef NDEBUG
+ assert(UsedJTs.all() &&
+ "Some of jump tables were not used in a debug info instruction");
+#endif
+ }
+}
+
+void CodeViewDebug::discoverJumpTableBranches(const MachineFunction *MF,
+ bool isThumb) {
+ forEachJumpTableBranch(
+ MF, isThumb,
+ [this](const MachineJumpTableInfo &, const MachineInstr &BranchMI,
+ int64_t) { requestLabelBeforeInsn(&BranchMI); });
+}
+
+void CodeViewDebug::collectDebugInfoForJumpTables(const MachineFunction *MF,
+ bool isThumb) {
+ forEachJumpTableBranch(
+ MF, isThumb,
+ [this, MF](const MachineJumpTableInfo &JTI, const MachineInstr &BranchMI,
+ int64_t JumpTableIndex) {
+ // For label-difference jump tables, find the base expression.
+ // Otherwise the jump table uses an absolute address (so no base
+ // is required).
+ const MCSymbol *Base;
+ uint64_t BaseOffset = 0;
+ const MCSymbol *Branch = getLabelBeforeInsn(&BranchMI);
+ JumpTableEntrySize EntrySize;
+ switch (JTI.getEntryKind()) {
+ case MachineJumpTableInfo::EK_Custom32:
+ case MachineJumpTableInfo::EK_GPRel32BlockAddress:
+ case MachineJumpTableInfo::EK_GPRel64BlockAddress:
+ llvm_unreachable(
+ "EK_Custom32, EK_GPRel32BlockAddress, and "
+ "EK_GPRel64BlockAddress should never be emitted for COFF");
+ case MachineJumpTableInfo::EK_BlockAddress:
+ // Each entry is an absolute address.
+ EntrySize = JumpTableEntrySize::Pointer;
+ Base = nullptr;
+ break;
+ case MachineJumpTableInfo::EK_Inline:
+ case MachineJumpTableInfo::EK_LabelDifference32:
+ // Ask the AsmPrinter.
+ std::tie(Base, BaseOffset, Branch, EntrySize) =
+ Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
+ break;
+ }
+
+ CurFn->JumpTables.push_back(
+ {EntrySize, Base, BaseOffset, Branch,
+ MF->getJTISymbol(JumpTableIndex, MMI->getContext()),
+ JTI.getJumpTables()[JumpTableIndex].MBBs.size()});
+ });
+}
+
+void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {
+ for (auto JumpTable : FI.JumpTables) {
+ MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
+ if (JumpTable.Base) {
+ OS.AddComment("Base offset");
+ OS.emitCOFFSecRel32(JumpTable.Base, JumpTable.BaseOffset);
+ OS.AddComment("Base section index");
+ OS.emitCOFFSectionIndex(JumpTable.Base);
+ } else {
+ OS.AddComment("Base offset");
+ OS.emitInt32(0);
+ OS.AddComment("Base section index");
+ OS.emitInt16(0);
+ }
+ OS.AddComment("Switch type");
+ OS.emitInt16(static_cast<uint16_t>(JumpTable.EntrySize));
+ OS.AddComment("Branch offset");
+ OS.emitCOFFSecRel32(JumpTable.Branch, /*Offset=*/0);
+ OS.AddComment("Table offset");
+ OS.emitCOFFSecRel32(JumpTable.Table, /*Offset=*/0);
+ OS.AddComment("Branch section index");
+ OS.emitCOFFSectionIndex(JumpTable.Branch);
+ OS.AddComment("Table section index");
+ OS.emitCOFFSectionIndex(JumpTable.Table);
+ OS.AddComment("Entries count");
+ OS.emitInt32(JumpTable.TableSize);
+ endSymbolRecord(JumpTableEnd);
+ }
+}