Skip to content

Commit 4b5db1c

Browse files
authored
PIX: Fix scope ascension for variable lookup (microsoft#6091)
In DxcPixLiveVariables.cpp, UniqueScopeForInlinedFunctions::AscendScopeHierarchy tries to keep track of a variable's scope and the scope at which its containing function was inlined, if any. This scope duo has to be the same in two places for things to work out: the scopes inferred from dbg.declare, and then again when the scope hierarchy is ascended in order to discover all variables accessible from a given point in the program. AscendScopeHierarchy was forgetting to update the inlined part of the scope, resulting in, for example, PIX's debugger losing track of variables outside of, for example, a for loop, even though the code can see those variables at that point. Just setting the inlined scope to be the same as the function scope fixes this problem. (In addition to these new tests, existing PIX tests exercise this situation happily)
1 parent 0abe45d commit 4b5db1c

File tree

6 files changed

+366
-30
lines changed

6 files changed

+366
-30
lines changed

include/dxc/Test/HlslTestUtils.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ using namespace std;
115115
#endif // VERIFY_ARE_EQUAL
116116

117117
static constexpr char whitespaceChars[] = " \t\r\n";
118+
static constexpr wchar_t wideWhitespaceChars[] = L" \t\r\n";
118119

119120
inline std::string strltrim(const std::string &value) {
120121
size_t first = value.find_first_not_of(whitespaceChars);
@@ -157,6 +158,25 @@ strtok(const std::string &value, const char *delimiters = whitespaceChars) {
157158
return tokens;
158159
}
159160

161+
inline std::vector<std::wstring>
162+
strtok(const std::wstring &value,
163+
const wchar_t *delimiters = wideWhitespaceChars) {
164+
size_t searchOffset = 0;
165+
std::vector<std::wstring> tokens;
166+
while (searchOffset != value.size()) {
167+
size_t tokenStartIndex = value.find_first_not_of(delimiters, searchOffset);
168+
if (tokenStartIndex == std::string::npos)
169+
break;
170+
size_t tokenEndIndex = value.find_first_of(delimiters, tokenStartIndex);
171+
if (tokenEndIndex == std::string::npos)
172+
tokenEndIndex = value.size();
173+
tokens.emplace_back(
174+
value.substr(tokenStartIndex, tokenEndIndex - tokenStartIndex));
175+
searchOffset = tokenEndIndex;
176+
}
177+
return tokens;
178+
}
179+
160180
// strreplace will replace all instances of lookFors with replacements at the
161181
// same index. Will log an error if the string is not found, unless the first
162182
// character is ? marking it optional.

include/dxc/WinAdapter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,11 @@ class CComBSTR {
10151015
m_str = NULL;
10161016
return s;
10171017
}
1018+
1019+
void Empty() throw() {
1020+
SysFreeString(m_str);
1021+
m_str = NULL;
1022+
}
10181023
};
10191024

10201025
//===--------- Convert argv to wchar ----------------===//

lib/DxilDia/DxcPixLiveVariables.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,19 @@ class UniqueScopeForInlinedFunctions {
4949
// is at file-level scope, it will return nullptr.
5050
if (auto Namespace = llvm::dyn_cast<llvm::DINamespace>(FunctionScope)) {
5151
if (auto *ContainingScope = Namespace->getScope()) {
52-
FunctionScope = ContainingScope;
52+
if (FunctionScope == InlinedAtScope)
53+
InlinedAtScope = FunctionScope = ContainingScope;
54+
else
55+
FunctionScope = ContainingScope;
5356
return;
5457
}
5558
}
5659
const llvm::DITypeIdentifierMap EmptyMap;
57-
FunctionScope = FunctionScope->getScope().resolve(EmptyMap);
60+
if (FunctionScope == InlinedAtScope)
61+
InlinedAtScope = FunctionScope =
62+
FunctionScope->getScope().resolve(EmptyMap);
63+
else
64+
FunctionScope = FunctionScope->getScope().resolve(EmptyMap);
5865
}
5966

6067
static UniqueScopeForInlinedFunctions Create(llvm::DebugLoc const &DbgLoc,

0 commit comments

Comments
 (0)