154 lines
6.5 KiB
Diff
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) {
|