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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
// slang-serialize-source-loc.h
#ifndef SLANG_SERIALIZE_SOURCE_LOC_H
#define SLANG_SERIALIZE_SOURCE_LOC_H
#include "../core/slang-riff.h"
#include "../core/slang-string-slice-pool.h"
#include "../core/slang-array-view.h"
#include "slang-serialize-types.h"
#include "../compiler-core/slang-name.h"
#include "../compiler-core/slang-source-loc.h"
namespace Slang {
class SerialSourceLocData
{
public:
typedef SerialSourceLocData ThisType;
typedef uint32_t SourceLoc;
typedef SerialStringData::StringIndex StringIndex;
// The list that contains all the subsequent modules
static const FourCC kDebugFourCc = SLANG_FOUR_CC('S', 'd', 'e', 'b');
static const FourCC kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't');
static const FourCC kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n');
static const FourCC kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l');
static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o');
struct SourceRange
{
typedef SourceRange ThisType;
bool operator==(const ThisType& rhs) const { return m_start == rhs.m_start && m_end == rhs.m_end; }
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
Slang::SourceLoc getSourceLoc(SourceLoc loc, SourceView* view) const
{
return (loc && contains(loc)) ? Slang::SourceLoc::fromRaw((loc - m_start) + SourceLoc(view->getRange().begin.getRaw())) : Slang::SourceLoc();
}
SourceLoc getCount() const { return m_end - m_start; }
bool contains(SourceLoc loc) const { return loc >= m_start && loc <= m_end; }
/// Set up a range that can't occur in practice
static SourceRange getInvalid() { return SourceRange{ ~SourceLoc(0), ~SourceLoc(0) }; }
SourceLoc m_start; ///< The offset to the source
SourceLoc m_end; ///< The number of bytes in the source
};
struct SourceInfo
{
typedef SourceInfo ThisType;
bool operator==(const ThisType& rhs) const
{
return m_pathIndex == rhs.m_pathIndex &&
m_range == rhs.m_range &&
m_numLineInfos == rhs.m_numLineInfos &&
m_lineInfosStartIndex == rhs.m_lineInfosStartIndex &&
m_numLineInfos == rhs.m_numLineInfos;
}
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
StringIndex m_pathIndex; ///< Index to the string table
SourceRange m_range; ///< The range of locations
uint32_t m_numLines; ///< Total number of lines in source file
uint32_t m_lineInfosStartIndex; ///< Index into m_debugLineInfos
uint32_t m_numLineInfos; ///< The number of line infos
uint32_t m_adjustedLineInfosStartIndex; ///< Adjusted start index
uint32_t m_numAdjustedLineInfos; ///< The number of line infos
};
struct LineInfo
{
typedef LineInfo ThisType;
bool operator<(const ThisType& rhs) const { return m_lineStartOffset < rhs.m_lineStartOffset; }
bool operator==(const ThisType& rhs) const
{
return m_lineStartOffset == rhs.m_lineStartOffset &&
m_lineIndex == rhs.m_lineIndex;
}
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
uint32_t m_lineStartOffset; ///< The offset into the source file
uint32_t m_lineIndex; ///< Original line index
};
struct AdjustedLineInfo
{
typedef AdjustedLineInfo ThisType;
bool operator==(const ThisType& rhs) const
{
return m_lineInfo == rhs.m_lineInfo &&
m_adjustedLineIndex == rhs.m_adjustedLineIndex &&
m_pathStringIndex == rhs.m_pathStringIndex;
}
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
bool operator<(const ThisType& rhs) const { return m_lineInfo < rhs.m_lineInfo; }
LineInfo m_lineInfo;
uint32_t m_adjustedLineIndex; ///< The line index with the adjustment (if there is any). Is 0 if m_pathStringIndex is 0.
StringIndex m_pathStringIndex; ///< The path as an index
};
size_t calcSizeInBytes() const;
void clear();
Index findSourceInfoIndex(SourceLoc sourceLoc) const
{
const Index numInfos = m_sourceInfos.getCount();
for (Index i = 0; i < numInfos; ++i)
{
if (m_sourceInfos[i].m_range.contains(sourceLoc))
{
return i;
}
}
return -1;
}
bool operator==(const ThisType& rhs) const;
Result writeContainer(SerialCompressionType moduleCompressionType, RiffContainer* container);
Result readContainer(SerialCompressionType moduleCompressionType, RiffContainer::ListChunk* listChunk);
List<char> m_stringTable; ///< String table for debug use only
List<LineInfo> m_lineInfos; ///< Line information
List<AdjustedLineInfo> m_adjustedLineInfos; ///< Adjusted line infos
List<SourceInfo> m_sourceInfos; ///< Source infos
};
class SerialSourceLocReader : public RefObject
{
public:
static const SerialExtraType kExtraType = SerialExtraType::SourceLocReader;
Index findViewIndex(SerialSourceLocData::SourceLoc loc);
SourceLoc getSourceLoc(SerialSourceLocData::SourceLoc loc);
/// Works out the amount to fix an input source loc to get a regular Slang::SourceLoc
int calcFixSourceLoc(SerialSourceLocData::SourceLoc loc, SerialSourceLocData::SourceRange& outRange);
/// Calc the loc
static SourceLoc calcFixedLoc(SerialSourceLocData::SourceLoc loc, int fix, const SerialSourceLocData::SourceRange& range) { SLANG_ASSERT(range.contains(loc)); SLANG_UNUSED(range); return SourceLoc::fromRaw(SourceLoc::RawValue(loc + fix)); }
SlangResult read(const SerialSourceLocData* serialData, SourceManager* sourceManager);
protected:
struct View
{
SerialSourceLocData::SourceRange m_range;
SourceView* m_sourceView;
};
List<View> m_views; ///< All the views
Index m_lastViewIndex = -1; ///< Caches last lookup
};
/// Used to write serialized SourceLoc information
class SerialSourceLocWriter : public RefObject
{
public:
static const SerialExtraType kExtraType = SerialExtraType::SourceLocWriter;
class Source : public RefObject
{
public:
Source(SourceFile* sourceFile, SourceLoc::RawValue baseSourceLoc) :
m_sourceFile(sourceFile),
m_baseSourceLoc(baseSourceLoc)
{
// Need to know how many lines there are
const List<uint32_t>& lineOffsets = sourceFile->getLineBreakOffsets();
const auto numLineIndices = lineOffsets.getCount();
// Set none as being used initially
m_lineIndexUsed.setCount(numLineIndices);
::memset(m_lineIndexUsed.begin(), 0, numLineIndices * sizeof(uint8_t));
}
/// True if we have information on that line index
bool hasLineIndex(int lineIndex) const { return m_lineIndexUsed[lineIndex] != 0; }
void setHasLineIndex(int lineIndex) { m_lineIndexUsed[lineIndex] = 1; }
SourceLoc::RawValue m_baseSourceLoc; ///< The base source location
SourceFile* m_sourceFile; ///< The source file
List<uint8_t> m_lineIndexUsed; ///< Has 1 if the line is used
List<uint32_t> m_usedLineIndices; ///< Holds the lines that have been hit
List<SerialSourceLocData::LineInfo> m_lineInfos; ///< The line infos
List<SerialSourceLocData::AdjustedLineInfo> m_adjustedLineInfos; ///< The adjusted line infos
};
/// Add a source location. Returns the location that can be serialized.
SerialSourceLocData::SourceLoc addSourceLoc(SourceLoc sourceLoc);
/// Write into outDebugData
void write(SerialSourceLocData* outSourceLocData);
SerialSourceLocWriter(SourceManager* sourceManager):
m_sourceManager(sourceManager),
m_stringSlicePool(StringSlicePool::Style::Default),
m_freeSourceLoc(1)
{
}
SourceManager* m_sourceManager;
StringSlicePool m_stringSlicePool; ///< Slices held just for debug usage
SourceLoc::RawValue m_freeSourceLoc; ///< Locations greater than this are free
Dictionary<SourceFile*, RefPtr<Source> > m_sourceFileMap;
};
} // namespace Slang
#endif
|