21 StringRef WinCodeViewLineTables::getFullFilepath(
const MDNode *S) {
23 assert((isa<DICompileUnit>(S) || isa<DIFile>(S) || isa<DISubprogram>(S) ||
24 isa<DILexicalBlockBase>(S)) &&
25 "Unexpected scope info");
27 auto *Scope = cast<DIScope>(S);
28 StringRef Dir = Scope->getDirectory(),
29 Filename = Scope->getFilename();
30 char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)];
39 if (Filename.find(
':') == 1)
42 Filepath = (Dir +
"\\" + Filename).str();
47 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
51 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
52 Filepath.erase(Cursor, 2);
57 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
62 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
63 if (PrevSlash == std::string::npos)
67 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
74 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
75 Filepath.erase(Cursor, 1);
77 Result = strdup(Filepath.c_str());
78 return StringRef(Result);
81 void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL,
82 const MachineFunction *MF) {
83 const MDNode *Scope = DL.getScope();
86 StringRef Filename = getFullFilepath(Scope);
90 if (!CurFn->Instrs.empty()) {
91 const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()];
92 if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine())
95 FileNameRegistry.add(Filename);
99 CurFn->Instrs.push_back(MCL);
100 InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine(), DL.getCol());
104 :
Asm(nullptr), CurFn(nullptr) {
119 if (FnDebugInfo.
empty())
122 assert(Asm !=
nullptr);
134 for (
size_t I = 0, E = VisitedFunctions.size();
I != E; ++
I)
135 emitDebugInfoForFunction(VisitedFunctions[
I]);
138 Asm->
OutStreamer->AddComment(
"File index to string table offset subsection");
140 size_t NumFilenames = FileNameRegistry.Infos.size();
142 for (
size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++
I) {
143 StringRef Filename = FileNameRegistry.Filenames[
I];
145 Asm->
EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
153 Asm->
EmitInt32(FileNameRegistry.LastOffset);
157 for (
size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++
I) {
159 Asm->
OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
164 Asm->
OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
171 unsigned int Size = 4) {
181 void WinCodeViewLineTables::emitDebugInfoForFunction(
const Function *GV) {
187 const FunctionInfo &FI = FnDebugInfo[GV];
188 if (FI.Instrs.empty())
190 assert(FI.End &&
"Don't know where the function ends?");
192 StringRef GVName = GV->getName();
195 FuncName =
SP->getDisplayName();
201 if (GVName.startswith(
"\01?"))
202 FuncName = GVName.substr(1);
206 Asm->
OutStreamer->AddComment(
"Symbol subsection for " + Twine(FuncName));
238 Asm->
OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
244 DenseMap<size_t, size_t> FilenameSegmentLengths;
245 size_t LastSegmentEnd = 0;
246 StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename;
247 for (
size_t J = 1,
F = FI.Instrs.size(); J !=
F; ++J) {
248 if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename)
250 FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
252 PrevFilename = InstrInfo[FI.Instrs[J]].Filename;
254 FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
257 Asm->
OutStreamer->AddComment(
"Line table subsection for " + Twine(FuncName));
277 size_t LastSegmentStart = 0;
279 auto FinishPreviousChunk = [&] {
282 for (
size_t ColSegI = LastSegmentStart,
283 ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
284 ColSegI != ColSegEnd; ++ColSegI) {
285 unsigned ColumnNumber = InstrInfo[FI.Instrs[ColSegI]].ColumnNumber;
292 for (
size_t J = 0,
F = FI.Instrs.size(); J !=
F; ++J) {
294 assert(InstrInfo.count(Instr));
296 if (FilenameSegmentLengths.count(J)) {
298 FinishPreviousChunk();
299 StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename;
300 assert(FileNameRegistry.Infos.count(CurFilename));
301 size_t IndexInStringTable =
302 FileNameRegistry.Infos[CurFilename].FilenameID;
306 "Segment for file '" + Twine(CurFilename) +
"' begins");
312 size_t SegmentLength = FilenameSegmentLengths[J];
319 LastSegmentStart = J;
324 Asm->
EmitInt32(InstrInfo[Instr].LineNumber);
327 FinishPreviousChunk();
332 assert(!CurFn &&
"Can't process two functions at once!");
338 assert(FnDebugInfo.
count(GV) ==
false);
339 VisitedFunctions.push_back(GV);
340 CurFn = &FnDebugInfo[GV];
346 bool EmptyPrologue =
true;
347 for (
const auto &MBB : *MF) {
350 for (
const auto &
MI : MBB) {
351 if (
MI.isDebugValue())
358 PrologEndLoc =
MI.getDebugLoc();
361 EmptyPrologue =
false;
365 if (PrologEndLoc && !EmptyPrologue) {
367 maybeRecordLocation(FnStartDL, MF);
376 assert(FnDebugInfo.
count(GV));
377 assert(CurFn == &FnDebugInfo[GV]);
379 if (CurFn->Instrs.empty()) {
380 FnDebugInfo.
erase(GV);
381 VisitedFunctions.pop_back();
393 if (DL == PrevInstLoc || !DL)
395 maybeRecordLocation(DL, Asm->
MF);
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
MCSymbol * getSymbol(const GlobalValue *GV) const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
void endFunction(const MachineFunction *) override
Gather post-function debug information.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
void EmitInt8(int Value) const
Emit a byte directive and value.
const MachineFunction * MF
The current machine function.
void EmitInt32(int Value) const
Emit a long directive and value.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Base class for the full range of assembler expressions which are needed for parsing.
const Module * getModule() const
bool hasDebugInfo() const
hasDebugInfo - Returns true if valid debug info is present.
DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
MCContext & getContext() const
Context object for machine code objects.
static cl::opt< std::string > FuncName("cppfname", cl::desc("Specify the name of the generated function"), cl::value_desc("function name"))
void EmitInt16(int Value) const
Emit a short directive and value.
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
bool isDebugValue() const
bool erase(const KeyT &Val)
Streaming machine code generation interface.
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
This class is intended to be used as a driving class for all asm writers.
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
void setDebugInfoAvailability(bool avail)
const MCContext & getContext() const
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
void endModule() override
Emit the COFF section that holds the line table information.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Representation of each machine instruction.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
MCSymbol * getFunctionEnd() const
void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc=SMLoc())
MCSection * getCOFFDebugSymbolsSection() const
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
void beginFunction(const MachineFunction *MF) override
Gather pre-function debug information.
StringRef - Represent a constant reference to a string, i.e.
WinCodeViewLineTables(AsmPrinter *Asm)
MachineModuleInfo - This class contains meta information specific to a module.
static void EmitLabelDiff(MCStreamer &Streamer, const MCSymbol *From, const MCSymbol *To, unsigned int Size=4)