aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
blob: 8492eacb7ff723f6453b80d66bfdd30230b18d59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h ----*- C++ -*--===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing line tables info into COFF files.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H

#include "AsmPrinterHandler.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/TargetLoweringObjectFile.h"

namespace llvm {
/// \brief Collects and handles line tables information in a CodeView format.
class WinCodeViewLineTables : public AsmPrinterHandler {
  AsmPrinter *Asm;
  DebugLoc PrevInstLoc;

  // For each function, store a vector of labels to its instructions, as well as
  // to the end of the function.
  struct FunctionInfo {
    SmallVector<MCSymbol *, 10> Instrs;
    MCSymbol *End;
    FunctionInfo() : End(nullptr) {}
  } *CurFn;

  typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
  FnDebugInfoTy FnDebugInfo;
  // Store the functions we've visited in a vector so we can maintain a stable
  // order while emitting subsections.
  SmallVector<const Function *, 10> VisitedFunctions;

  // InstrInfoTy - Holds the Filename:LineNumber information for every
  // instruction with a unique debug location.
  struct InstrInfoTy {
    StringRef Filename;
    unsigned LineNumber;

    InstrInfoTy() : LineNumber(0) {}

    InstrInfoTy(StringRef Filename, unsigned LineNumber)
        : Filename(Filename), LineNumber(LineNumber) {}
  };
  DenseMap<MCSymbol *, InstrInfoTy> InstrInfo;

  // FileNameRegistry - Manages filenames observed while generating debug info
  // by filtering out duplicates and bookkeeping the offsets in the string
  // table to be generated.
  struct FileNameRegistryTy {
    SmallVector<StringRef, 10> Filenames;
    struct PerFileInfo {
      size_t FilenameID, StartOffset;
    };
    StringMap<PerFileInfo> Infos;

    // The offset in the string table where we'll write the next unique
    // filename.
    size_t LastOffset;

    FileNameRegistryTy() {
      clear();
    }

    // Add Filename to the registry, if it was not observed before.
    void add(StringRef Filename) {
      if (Infos.count(Filename))
        return;
      size_t OldSize = Infos.size();
      Infos[Filename].FilenameID = OldSize;
      Infos[Filename].StartOffset = LastOffset;
      LastOffset += Filename.size() + 1;
      Filenames.push_back(Filename);
    }

    void clear() {
      LastOffset = 1;
      Infos.clear();
      Filenames.clear();
    }
  } FileNameRegistry;

  typedef std::map<std::pair<StringRef, StringRef>, char *>
      DirAndFilenameToFilepathMapTy;
  DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap;
  StringRef getFullFilepath(const MDNode *S);

  void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);

  void clear() {
    assert(CurFn == nullptr);
    FileNameRegistry.clear();
    InstrInfo.clear();
  }

  void emitDebugInfoForFunction(const Function *GV);

public:
  WinCodeViewLineTables(AsmPrinter *Asm);

  ~WinCodeViewLineTables() {
    for (DirAndFilenameToFilepathMapTy::iterator
             I = DirAndFilenameToFilepathMap.begin(),
             E = DirAndFilenameToFilepathMap.end();
         I != E; ++I)
      free(I->second);
  }

  void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {}

  /// \brief Emit the COFF section that holds the line table information.
  void endModule() override;

  /// \brief Gather pre-function debug information.
  void beginFunction(const MachineFunction *MF) override;

  /// \brief Gather post-function debug information.
  void endFunction(const MachineFunction *) override;

  /// \brief Process beginning of an instruction.
  void beginInstruction(const MachineInstr *MI) override;

  /// \brief Process end of an instruction.
  void endInstruction() override {}
};
} // End of namespace llvm

#endif