Files
ispc/llvm_patches/3_5_win_coff_debug_info.patch
2014-10-14 17:17:49 +04:00

154 lines
6.5 KiB
Diff

# This patch allows ISPC code to be debugged in Visual Studio 2012 and above
# Requires LLVM 3.5
Index: include/llvm/Support/COFF.h
===================================================================
--- include/llvm/Support/COFF.h (revision 215535)
+++ include/llvm/Support/COFF.h (working copy)
@@ -642,9 +642,14 @@
enum CodeViewLineTableIdentifiers {
DEBUG_SECTION_MAGIC = 0x4,
+ DEBUG_SYMBOL_SUBSECTION = 0xF1,
DEBUG_LINE_TABLE_SUBSECTION = 0xF2,
DEBUG_STRING_TABLE_SUBSECTION = 0xF3,
- DEBUG_INDEX_SUBSECTION = 0xF4
+ DEBUG_INDEX_SUBSECTION = 0xF4,
+
+ // Symbol subsections are split into subsubsections.
+ DEBUG_SYMBOL_PROC_START_SUBSUBSECTION = 0x1147,
+ DEBUG_SYMBOL_PROC_END_SUBSUBSECTION = 0x114F
};
inline bool isReservedSectionNumber(int N) {
Index: lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp (revision 215535)
+++ lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp (working copy)
@@ -117,14 +117,15 @@
}
static void EmitLabelDiff(MCStreamer &Streamer,
- const MCSymbol *From, const MCSymbol *To) {
+ const MCSymbol *From, const MCSymbol *To,
+ unsigned int Size = 4) {
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
MCContext &Context = Streamer.getContext();
const MCExpr *FromRef = MCSymbolRefExpr::Create(From, Variant, Context),
*ToRef = MCSymbolRefExpr::Create(To, Variant, Context);
const MCExpr *AddrDelta =
MCBinaryExpr::Create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
- Streamer.EmitValue(AddrDelta, 4);
+ Streamer.EmitValue(AddrDelta, Size);
}
void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) {
@@ -132,12 +133,50 @@
// which holds the PC to file:line table.
const MCSymbol *Fn = Asm->getSymbol(GV);
assert(Fn);
+ const StringRef FuncName = Fn->getName();
const FunctionInfo &FI = FnDebugInfo[GV];
if (FI.Instrs.empty())
return;
assert(FI.End && "Don't know where the function ends?");
+ // Emit a symbol subsection, required by VS2012+ to find function boundaries.
+ MCSymbol *SymbolsBegin = Asm->MMI->getContext().CreateTempSymbol(),
+ *SymbolsEnd = Asm->MMI->getContext().CreateTempSymbol();
+ Asm->OutStreamer.AddComment("Symbol subsection for " + Twine(FuncName));
+ Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION);
+ EmitLabelDiff(Asm->OutStreamer, SymbolsBegin, SymbolsEnd);
+ Asm->OutStreamer.EmitLabel(SymbolsBegin);
+ {
+ MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().CreateTempSymbol(),
+ *ProcSegmentEnd = Asm->MMI->getContext().CreateTempSymbol();
+ EmitLabelDiff(Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2);
+ Asm->OutStreamer.EmitLabel(ProcSegmentBegin);
+
+ Asm->EmitInt16(COFF::DEBUG_SYMBOL_PROC_START_SUBSUBSECTION);
+ // Some bytes of this segment don't seem to be required for basic debugging,
+ // so just fill them with zeroes.
+ Asm->OutStreamer.EmitFill(12, 0);
+ // This is the important bit that tells the debugger where the function
+ // code is located:
+ EmitLabelDiff(Asm->OutStreamer, Fn, FI.End);
+ Asm->OutStreamer.EmitFill(12, 0);
+ Asm->OutStreamer.EmitCOFFSecRel32(Fn);
+ Asm->OutStreamer.EmitCOFFSectionIndex(Fn);
+ Asm->EmitInt8(0);
+ // Emit the function name as a null-terminated string.
+ Asm->OutStreamer.EmitBytes(FuncName);
+ Asm->EmitInt8(0);
+ Asm->OutStreamer.EmitLabel(ProcSegmentEnd);
+
+ // We're done with this function.
+ Asm->EmitInt16(0x0002);
+ Asm->EmitInt16(COFF::DEBUG_SYMBOL_PROC_END_SUBSUBSECTION);
+ }
+ Asm->OutStreamer.EmitLabel(SymbolsEnd);
+ // Every subsection must be aligned to a 4-byte boundary.
+ Asm->OutStreamer.EmitFill((-FuncName.size()) % 4, 0);
+
// PCs/Instructions are grouped into segments sharing the same filename.
// Pre-calculate the lengths (in instructions) of these segments and store
// them in a map for convenience. Each index in the map is the sequential
@@ -154,18 +193,18 @@
}
FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
- // Emit the control code of the subsection followed by the payload size.
- Asm->OutStreamer.AddComment(
- "Linetable subsection for " + Twine(Fn->getName()));
+ // Emit a linetable subsection, requred to do PC-to-file:line lookup.
+ Asm->OutStreamer.AddComment("Linetable subsection for " + Twine(FuncName));
Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION);
- MCSymbol *SubsectionBegin = Asm->MMI->getContext().CreateTempSymbol(),
- *SubsectionEnd = Asm->MMI->getContext().CreateTempSymbol();
- EmitLabelDiff(Asm->OutStreamer, SubsectionBegin, SubsectionEnd);
- Asm->OutStreamer.EmitLabel(SubsectionBegin);
+ MCSymbol *LineTableBegin = Asm->MMI->getContext().CreateTempSymbol(),
+ *LineTableEnd = Asm->MMI->getContext().CreateTempSymbol();
+ EmitLabelDiff(Asm->OutStreamer, LineTableBegin, LineTableEnd);
+ Asm->OutStreamer.EmitLabel(LineTableBegin);
// Identify the function this subsection is for.
Asm->OutStreamer.EmitCOFFSecRel32(Fn);
Asm->OutStreamer.EmitCOFFSectionIndex(Fn);
+ Asm->EmitInt16(0);
// Length of the function's code, in bytes.
EmitLabelDiff(Asm->OutStreamer, Fn, FI.End);
@@ -209,7 +248,7 @@
if (FileSegmentEnd)
Asm->OutStreamer.EmitLabel(FileSegmentEnd);
- Asm->OutStreamer.EmitLabel(SubsectionEnd);
+ Asm->OutStreamer.EmitLabel(LineTableEnd);
}
void WinCodeViewLineTables::endModule() {
@@ -254,8 +293,7 @@
Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]);
Asm->EmitInt8(0);
}
-
- // No more subsections. Fill with zeros to align the end of the section by 4.
+ // Every subsection must be aligned to a 4-byte boundary.
Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
clear();
Index: lib/MC/WinCOFFStreamer.cpp
===================================================================
--- lib/MC/WinCOFFStreamer.cpp (revision 215535)
+++ lib/MC/WinCOFFStreamer.cpp (working copy)
@@ -163,7 +163,7 @@
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext());
MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_2);
DF->getFixups().push_back(Fixup);
- DF->getContents().resize(DF->getContents().size() + 4, 0);
+ DF->getContents().resize(DF->getContents().size() + 2, 0);
}
void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {