Skip to content

Commit

Permalink
PIX: Fix scope ascension for variable lookup (microsoft#6091)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
jeffnn authored Dec 6, 2023
1 parent 0abe45d commit 4b5db1c
Show file tree
Hide file tree
Showing 6 changed files with 366 additions and 30 deletions.
20 changes: 20 additions & 0 deletions include/dxc/Test/HlslTestUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ using namespace std;
#endif // VERIFY_ARE_EQUAL

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

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

inline std::vector<std::wstring>
strtok(const std::wstring &value,
const wchar_t *delimiters = wideWhitespaceChars) {
size_t searchOffset = 0;
std::vector<std::wstring> tokens;
while (searchOffset != value.size()) {
size_t tokenStartIndex = value.find_first_not_of(delimiters, searchOffset);
if (tokenStartIndex == std::string::npos)
break;
size_t tokenEndIndex = value.find_first_of(delimiters, tokenStartIndex);
if (tokenEndIndex == std::string::npos)
tokenEndIndex = value.size();
tokens.emplace_back(
value.substr(tokenStartIndex, tokenEndIndex - tokenStartIndex));
searchOffset = tokenEndIndex;
}
return tokens;
}

// strreplace will replace all instances of lookFors with replacements at the
// same index. Will log an error if the string is not found, unless the first
// character is ? marking it optional.
Expand Down
5 changes: 5 additions & 0 deletions include/dxc/WinAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,11 @@ class CComBSTR {
m_str = NULL;
return s;
}

void Empty() throw() {
SysFreeString(m_str);
m_str = NULL;
}
};

//===--------- Convert argv to wchar ----------------===//
Expand Down
11 changes: 9 additions & 2 deletions lib/DxilDia/DxcPixLiveVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,19 @@ class UniqueScopeForInlinedFunctions {
// is at file-level scope, it will return nullptr.
if (auto Namespace = llvm::dyn_cast<llvm::DINamespace>(FunctionScope)) {
if (auto *ContainingScope = Namespace->getScope()) {
FunctionScope = ContainingScope;
if (FunctionScope == InlinedAtScope)
InlinedAtScope = FunctionScope = ContainingScope;
else
FunctionScope = ContainingScope;
return;
}
}
const llvm::DITypeIdentifierMap EmptyMap;
FunctionScope = FunctionScope->getScope().resolve(EmptyMap);
if (FunctionScope == InlinedAtScope)
InlinedAtScope = FunctionScope =
FunctionScope->getScope().resolve(EmptyMap);
else
FunctionScope = FunctionScope->getScope().resolve(EmptyMap);
}

static UniqueScopeForInlinedFunctions Create(llvm::DebugLoc const &DbgLoc,
Expand Down
Loading

0 comments on commit 4b5db1c

Please sign in to comment.