aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-18 20:30:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-04-06 20:11:55 +0000
commit5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch)
tree1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parent3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff)
parent312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp203
1 files changed, 193 insertions, 10 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 8161de57b58e..dddc08b3bc01 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/contrib/llvm-project/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"
@@ -54,7 +56,6 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
@@ -141,7 +142,7 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
// If this is a Unix-style path, just use it as is. Don't try to canonicalize
// it textually because one of the path components could be a symlink.
- if (Dir.startswith("/") || Filename.startswith("/")) {
+ if (Dir.starts_with("/") || Filename.starts_with("/")) {
if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix))
return Filename;
Filepath = std::string(Dir);
@@ -248,7 +249,10 @@ CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
Site->Inlinee = Inlinee;
InlinedSubprograms.insert(Inlinee);
- getFuncIdForSubprogram(Inlinee);
+ auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
+
+ if (InlinedAt->getInlinedAt() == nullptr)
+ CurFn->Inlinees.insert(InlineeIdx);
}
return *Site;
}
@@ -906,10 +910,10 @@ static std::string flattenCommandLine(ArrayRef<std::string> Args,
i++; // Skip this argument and next one.
continue;
}
- if (Arg.startswith("-object-file-name") || Arg == MainFilename)
+ if (Arg.starts_with("-object-file-name") || Arg == MainFilename)
continue;
// Skip fmessage-length for reproduciability.
- if (Arg.startswith("-fmessage-length"))
+ if (Arg.starts_with("-fmessage-length"))
continue;
if (PrintedOneArg)
OS << " ";
@@ -1192,6 +1196,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.emitInt32(uint32_t(FI.FrameProcOpts));
endSymbolRecord(FrameProcEnd);
+ emitInlinees(FI.Inlinees);
emitLocalVariableList(FI, FI.Locals);
emitGlobalVariableList(FI.Globals);
emitLexicalBlockList(FI.ChildBlocks, FI);
@@ -1243,6 +1248,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);
}
@@ -1390,6 +1397,12 @@ void CodeViewDebug::calculateRanges(
if (Location->Register == 0 || Location->LoadChain.size() > 1)
continue;
+ // Codeview can only express byte-aligned offsets, ensure that we have a
+ // byte-boundaried location.
+ if (Location->FragmentInfo)
+ if (Location->FragmentInfo->OffsetInBits % 8)
+ continue;
+
LocalVarDef DR;
DR.CVRegister = TRI->getCodeViewRegNum(Location->Register);
DR.InMemory = !Location->LoadChain.empty();
@@ -1533,8 +1546,8 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
}
FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedLocalFramePtrReg) << 14U);
FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedParamFramePtrReg) << 16U);
- if (Asm->TM.getOptLevel() != CodeGenOpt::None &&
- !GV.hasOptSize() && !GV.hasOptNone())
+ if (Asm->TM.getOptLevel() != CodeGenOptLevel::None && !GV.hasOptSize() &&
+ !GV.hasOptNone())
FPO |= FrameProcedureOptions::OptimizedForSpeed;
if (GV.hasProfileData()) {
FPO |= FrameProcedureOptions::ValidProfileCounts;
@@ -1578,6 +1591,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) {
@@ -2571,7 +2589,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
// Virtual function pointer member.
if ((Member->getFlags() & DINode::FlagArtificial) &&
- Member->getName().startswith("_vptr$")) {
+ Member->getName().starts_with("_vptr$")) {
VFPtrRecord VFPR(getTypeIndex(Member->getBaseType()));
ContinuationBuilder.writeMemberType(VFPR);
MemberCount++;
@@ -3024,7 +3042,7 @@ void CodeViewDebug::collectLexicalBlockInfo(
if (!BlockInsertion.second)
return;
- // Create a lexical block containing the variables and collect the the
+ // Create a lexical block containing the variables and collect the
// lexical block information for the children.
const InsnRange &Range = Ranges.front();
assert(Range.first && Range.second);
@@ -3083,6 +3101,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();
@@ -3336,7 +3358,7 @@ void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt &Value,
// Encoded integers shouldn't need more than 10 bytes.
uint8_t Data[10];
- BinaryStreamWriter Writer(Data, llvm::support::endianness::little);
+ BinaryStreamWriter Writer(Data, llvm::endianness::little);
CodeViewRecordIO IO(Writer);
cantFail(IO.mapEncodedInteger(Value));
StringRef SRef((char *)Data, Writer.getOffset());
@@ -3442,3 +3464,164 @@ 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:
+ case MachineJumpTableInfo::EK_LabelDifference64:
+ // 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);
+ }
+}
+
+void CodeViewDebug::emitInlinees(
+ const SmallSet<codeview::TypeIndex, 1> &Inlinees) {
+ // Divide the list of inlinees into chunks such that each chunk fits within
+ // one record.
+ constexpr size_t ChunkSize =
+ (MaxRecordLength - sizeof(SymbolKind) - sizeof(uint32_t)) /
+ sizeof(uint32_t);
+
+ SmallVector<TypeIndex> SortedInlinees{Inlinees.begin(), Inlinees.end()};
+ llvm::sort(SortedInlinees);
+
+ size_t CurrentIndex = 0;
+ while (CurrentIndex < SortedInlinees.size()) {
+ auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
+ auto CurrentChunkSize =
+ std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
+ OS.AddComment("Count");
+ OS.emitInt32(CurrentChunkSize);
+
+ const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
+ for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
+ OS.AddComment("Inlinee");
+ OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
+ }
+ endSymbolRecord(Symbol);
+ }
+}