Perform #line pre-processing earlier, so it's picked up when reflecting

* If we only do this preprocessing when generating a disassembly string, it's
  not done when the files in the shader reflection are fetched.
This commit is contained in:
baldurk
2018-06-04 13:58:11 +01:00
parent 9b9451971a
commit 77ee70c2d2
2 changed files with 211 additions and 203 deletions
@@ -463,212 +463,21 @@ void DXBCFile::MakeDisassemblyString()
size_t d = 0;
vector<vector<string> > fileLines;
if(m_DebugInfo)
{
vector<string> fileNames;
fileLines.resize(m_DebugInfo->Files.size());
fileNames.resize(m_DebugInfo->Files.size());
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
fileNames[i] = m_DebugInfo->Files[i].first;
// we essentially do a copy-paste out of m_DebugInfo->Files into fileLines,
// by doing a mini-preprocess to handle #line directives. This means that
// any lines that our source file declares to be in another filename via a #line
// get put in the right place for what the debug information hopefully matches.
// We also concatenate duplicate lines and display them all, to handle edge
// cases where #lines declare duplicates.
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
{
vector<string> srclines;
vector<string> *dstFile =
&fileLines[i]; // start off writing to the corresponding output file.
size_t dstLine = 0;
split(m_DebugInfo->Files[i].second, srclines, '\n');
srclines.push_back("");
// handle #line directives by inserting empty lines or erasing as necessary
for(size_t srcLine = 0; srcLine < srclines.size(); srcLine++)
{
if(srclines[srcLine].empty())
{
dstLine++;
continue;
}
char *c = &srclines[srcLine][0];
char *end = c + srclines[srcLine].size();
while(*c == '\t' || *c == ' ' || *c == '\r')
c++;
if(c == end)
{
// blank line, just advance line counter
dstLine++;
continue;
}
if(c + 5 > end || strncmp(c, "#line", 5))
{
// resize up to account for the current line, if necessary
dstFile->resize(RDCMAX(dstLine + 1, dstFile->size()));
// if non-empty, append this line (to allow multiple lines on the same line
// number to be concatenated)
if((*dstFile)[dstLine].empty())
(*dstFile)[dstLine] = srclines[srcLine];
else
(*dstFile)[dstLine] += "\n" + srclines[srcLine];
// advance line counter
dstLine++;
continue;
}
// we have a #line directive
c += 5;
if(c >= end)
{
// invalid #line, just advance line counter
dstLine++;
continue;
}
while(*c == '\t' || *c == ' ')
c++;
if(c >= end)
{
// invalid #line, just advance line counter
dstLine++;
continue;
}
// invalid #line, no line number. Skip/ignore and just advance line counter
if(*c < '0' || *c > '9')
{
dstLine++;
continue;
}
size_t newLineNum = 0;
while(*c >= '0' && *c <= '9')
{
newLineNum *= 10;
newLineNum += int((*c) - '0');
c++;
}
// convert to 0-indexed line number
if(newLineNum > 0)
newLineNum--;
while(*c == '\t' || *c == ' ')
c++;
// no filename
if(*c == 0)
{
// set the next line number, and continue processing
dstLine = newLineNum;
continue;
}
else if(*c == '"')
{
c++;
char *filename = c;
// parse out filename
while(*c != '"' && *c != 0)
{
if(*c == '\\')
{
// skip escaped characters
c += 2;
}
else
{
c++;
}
}
// parsed filename successfully
if(*c == '"')
{
*c = 0;
// find the new destination file
bool found = false;
size_t dstFileIdx = 0;
for(size_t f = 0; f < fileNames.size(); f++)
{
if(fileNames[f] == filename)
{
found = true;
dstFileIdx = f;
break;
}
}
if(found)
{
dstFile = &fileLines[dstFileIdx];
}
else
{
RDCWARN("Couldn't find filename '%s' in #line directive in debug info", filename);
// make a dummy file to write into that won't be used.
fileNames.push_back(filename);
fileLines.push_back(vector<string>());
dstFile = &fileLines.back();
}
// set the next line number, and continue processing
dstLine = newLineNum;
continue;
}
else
{
// invalid #line, ignore
continue;
}
}
else
{
// invalid #line, ignore
continue;
}
}
}
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
{
if(m_DebugInfo->Files[i].second.empty())
{
merge(fileLines[i], m_DebugInfo->Files[i].second, '\n');
}
}
}
LineColumnInfo prevLineInfo;
size_t debugInst = 0;
std::vector<std::vector<std::string>> fileLines;
// generate fileLines by splitting each file in the debug info
if(m_DebugInfo)
{
fileLines.resize(m_DebugInfo->Files.size());
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
split(m_DebugInfo->Files[i].second, fileLines[i], '\n');
}
for(size_t i = 0; i < m_Instructions.size(); i++)
{
for(; d < m_Declarations.size(); d++)
@@ -3209,4 +3018,4 @@ char *SystemValueToString(SVSemantic name)
return "";
}
}; // namespace DXBC
}; // namespace DXBC
@@ -1069,6 +1069,205 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength)
else if(*fourcc == FOURCC_SPDB)
{
m_DebugInfo = new SPDBChunk(fourcc);
// we do a mini-preprocess of the files from the debug info to handle #line directives.
// This means that any lines that our source file declares to be in another filename via a #line
// get put in the right place for what the debug information hopefully matches.
// We also concatenate duplicate lines and display them all, to handle edge cases where #lines
// declare duplicates.
if(m_DebugInfo)
{
std::vector<std::vector<std::string>> fileLines;
std::vector<std::string> fileNames;
fileLines.resize(m_DebugInfo->Files.size());
fileNames.resize(m_DebugInfo->Files.size());
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
fileNames[i] = m_DebugInfo->Files[i].first;
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
{
std::vector<std::string> srclines;
std::vector<std::string> *dstFile =
&fileLines[i]; // start off writing to the corresponding output file.
size_t dstLine = 0;
split(m_DebugInfo->Files[i].second, srclines, '\n');
srclines.push_back("");
// handle #line directives by inserting empty lines or erasing as necessary
for(size_t srcLine = 0; srcLine < srclines.size(); srcLine++)
{
if(srclines[srcLine].empty())
{
dstLine++;
continue;
}
char *c = &srclines[srcLine][0];
char *end = c + srclines[srcLine].size();
while(*c == '\t' || *c == ' ' || *c == '\r')
c++;
if(c == end)
{
// blank line, just advance line counter
dstLine++;
continue;
}
if(c + 5 > end || strncmp(c, "#line", 5))
{
// resize up to account for the current line, if necessary
dstFile->resize(RDCMAX(dstLine + 1, dstFile->size()));
// if non-empty, append this line (to allow multiple lines on the same line
// number to be concatenated). To avoid screwing up line numbers we have to append with a
// comment and not a newline.
if((*dstFile)[dstLine].empty())
(*dstFile)[dstLine] = srclines[srcLine];
else
(*dstFile)[dstLine] += " /* multiple #lines overlapping */ " + srclines[srcLine];
// advance line counter
dstLine++;
continue;
}
// we have a #line directive
c += 5;
if(c >= end)
{
// invalid #line, just advance line counter
dstLine++;
continue;
}
while(*c == '\t' || *c == ' ')
c++;
if(c >= end)
{
// invalid #line, just advance line counter
dstLine++;
continue;
}
// invalid #line, no line number. Skip/ignore and just advance line counter
if(*c < '0' || *c > '9')
{
dstLine++;
continue;
}
size_t newLineNum = 0;
while(*c >= '0' && *c <= '9')
{
newLineNum *= 10;
newLineNum += int((*c) - '0');
c++;
}
// convert to 0-indexed line number
if(newLineNum > 0)
newLineNum--;
while(*c == '\t' || *c == ' ')
c++;
// no filename
if(*c == 0)
{
// set the next line number, and continue processing
dstLine = newLineNum;
continue;
}
else if(*c == '"')
{
c++;
char *filename = c;
// parse out filename
while(*c != '"' && *c != 0)
{
if(*c == '\\')
{
// skip escaped characters
c += 2;
}
else
{
c++;
}
}
// parsed filename successfully
if(*c == '"')
{
*c = 0;
// find the new destination file
bool found = false;
size_t dstFileIdx = 0;
for(size_t f = 0; f < fileNames.size(); f++)
{
if(fileNames[f] == filename)
{
found = true;
dstFileIdx = f;
break;
}
}
if(found)
{
dstFile = &fileLines[dstFileIdx];
}
else
{
RDCWARN("Couldn't find filename '%s' in #line directive in debug info", filename);
// make a dummy file to write into that won't be used.
fileNames.push_back(filename);
fileLines.push_back(vector<string>());
dstFile = &fileLines.back();
}
// set the next line number, and continue processing
dstLine = newLineNum;
continue;
}
else
{
// invalid #line, ignore
continue;
}
}
else
{
// invalid #line, ignore
continue;
}
}
}
for(size_t i = 0; i < m_DebugInfo->Files.size(); i++)
{
if(m_DebugInfo->Files[i].second.empty())
{
merge(fileLines[i], m_DebugInfo->Files[i].second, '\n');
}
}
}
}