Remove the old disassemble-to-string code

This commit is contained in:
baldurk
2015-07-29 23:47:57 +02:00
parent aec9a3a79f
commit bce7cde005
@@ -1845,598 +1845,7 @@ void DisassembleSPIRV(SPIRVShaderStage shadType, const vector<uint32_t> &spirv,
std::sort(module.globals.begin(), module.globals.end(), SortByVarClass());
///////////////////////////////////////////////////////////////////////////////
// Old direct-to-string (ref) disassembly
vector<string> resultnames;
resultnames.resize(idbound);
vector< pair<uint32_t, const char **> > extensionSets;
extensionSets.reserve(2);
vector< pair<uint32_t, string> > decorations;
// needs to be fleshed out, but this is enough for now
enum BaseType
{
eSPIRVTypeVoid,
eSPIRVTypeBool,
eSPIRVTypeFloat, // assuming floats are all 32-bit
eSPIRVTypeSInt32, // assuming ints are signed or unsigned 32-bit
eSPIRVTypeUInt32,
};
vector<BaseType> typeinfo;
typeinfo.resize(idbound);
vector<uint32_t> values;
values.resize(idbound);
// complete hack
vector<const char *> membernames;
// fetch names and things to be used in the second pass.
// could get away with one pass, just need to detect when function
// declarations/definitions start to fill out unnamed IDs. Or wrap
// it all up and give them anonymous <id> names on the fly (more
// likely).
it = 5;
while(it < spirv.size())
{
uint16_t WordCount = spirv[it]>>16;
spv::Op OpCode = spv::Op(spirv[it]&0xffff);
if(OpCode == spv::OpName)
{
resultnames[ spirv[it+1] ] = (const char *)&spirv[it+2];
}
else if(OpCode == spv::OpLabel)
{
resultnames[spirv[it+1]] = StringFormat::Fmt("Label%u", spirv[it+1]);
}
else if(OpCode == spv::OpMemberName)
{
uint32_t id = spirv[it+1];
uint32_t memberIdx = spirv[it+2];
const char *memberName = (const char *)&spirv[it+3];
// COMPLETE hack
membernames.resize( RDCMAX(membernames.size(), (size_t)memberIdx+1) );
membernames[memberIdx] = memberName;
}
else if(OpCode == spv::OpDecorate)
{
uint32_t target = spirv[it+1];
spv::Decoration decoration = spv::Decoration(spirv[it+2]);
// TODO: decoration parameters here...
decorations.push_back( make_pair(target, ToStr::Get(decoration)) );
}
else if(OpCode == spv::OpTypeVoid)
{
resultnames[ spirv[it+1] ] = "void";
typeinfo[ spirv[it+1] ] = eSPIRVTypeVoid;
}
else if(OpCode == spv::OpTypeBool)
{
resultnames[ spirv[it+1] ] = "bool";
typeinfo[ spirv[it+1] ] = eSPIRVTypeBool;
}
else if(OpCode == spv::OpTypeInt)
{
resultnames[ spirv[it+1] ] = "int";
RDCASSERT( spirv[it+2] == 32 );
typeinfo[ spirv[it+1] ] = spirv[it+3] ? eSPIRVTypeSInt32 : eSPIRVTypeUInt32;
}
else if(OpCode == spv::OpTypeFloat)
{
resultnames[ spirv[it+1] ] = "float";
RDCASSERT( spirv[it+2] == 32 );
typeinfo[ spirv[it+1] ] = eSPIRVTypeFloat;
}
else if(OpCode == spv::OpTypeVector)
{
resultnames[ spirv[it+1] ] = StringFormat::Fmt("%s%u", resultnames[ spirv[it+2] ].c_str(), spirv[it+3]);
typeinfo[ spirv[it+1] ] = typeinfo[ spirv[it+2] ];
}
else if(OpCode == spv::OpTypeArray)
{
resultnames[ spirv[it+1] ] = StringFormat::Fmt("%s[%u]", resultnames[ spirv[it+2] ].c_str(), values[ spirv[it+3] ]);
typeinfo[ spirv[it+1] ] = typeinfo[ spirv[it+2] ];
}
else if(OpCode == spv::OpTypeStruct)
{
resultnames[ spirv[it+1] ] = "struct"; // don't need to decode this at all, we're not going to use the type info
}
else if(OpCode == spv::OpTypePointer)
{
uint32_t id = spirv[it+1];
spv::StorageClass storage = spv::StorageClass(spirv[it+2]);
uint32_t baseType = spirv[it+3];
// bit specific for where we need it (variable declarations), but all this data will be properly parsed & stored
// so each instruction can use it as it wishes
resultnames[id] = resultnames[baseType] + "*";
}
else if(OpCode == spv::OpTypeFunction)
{
// this name will just be used for the arguments in the function definition string, don't need to keep the type info
// or print the return type anywhere (as it must match the return type in the function definition opcode)
string args = "";
for(int i=3; i < WordCount; i++)
{
uint32_t typeId = spirv[it+i];
args += resultnames[typeId];
if(i+1 < WordCount)
args += ", ";
}
if(args.empty()) args = "void";
resultnames[ spirv[it+1] ] = args;
}
else if(OpCode == spv::OpConstant)
{
uint32_t typeId = spirv[it+1];
uint32_t id = spirv[it+2];
// hack - assuming only up to 32-bit values
values[id] = spirv[it+3];
BaseType type = typeinfo[typeId];
string lit = "";
if(type == eSPIRVTypeBool)
lit += values[id] ? "true" : "false";
else if(type == eSPIRVTypeFloat)
lit += StringFormat::Fmt("%f", *(float*)&values[id]);
else if(type == eSPIRVTypeSInt32)
lit += StringFormat::Fmt("%d", *(int32_t*)&values[id]);
else if(type == eSPIRVTypeUInt32)
lit += StringFormat::Fmt("%u", values[id]);
resultnames[id] = StringFormat::Fmt("%s(%s)", resultnames[typeId].c_str(), lit.c_str());
}
else if(OpCode == spv::OpConstantComposite)
{
uint32_t typeId = spirv[it+1];
uint32_t id = spirv[it+2];
BaseType type = typeinfo[typeId];
string lits = "";
for(int i=3; i < WordCount; i++)
{
uint32_t val = spirv[it+i];
if(type == eSPIRVTypeBool)
lits += values[val] ? "true" : "false";
else if(type == eSPIRVTypeFloat)
lits += StringFormat::Fmt("%f", *(float*)&values[val]);
else if(type == eSPIRVTypeSInt32)
lits += StringFormat::Fmt("%d", *(int32_t*)&values[val]);
else if(type == eSPIRVTypeUInt32)
lits += StringFormat::Fmt("%u", values[val]);
if(i+1 < WordCount)
lits += ", ";
}
resultnames[id] = StringFormat::Fmt("%s(%s)", resultnames[typeId].c_str(), lits.c_str());
}
it += WordCount;
}
for(size_t i=0; i < resultnames.size(); i++)
if(resultnames[i].empty())
resultnames[i] = StringFormat::Fmt("{%d}", i);
const size_t tabSize = 2;
string indent;
indent.reserve(tabSize*6);
string funcname;
vector<uint32_t> flowstack;
bool variables = false;
it = 5;
while(it < spirv.size())
{
uint16_t WordCount = spirv[it]>>16;
spv::Op OpCode = spv::Op(spirv[it]&0xffff);
string body;
bool silent = false;
switch(OpCode)
{
case spv::OpSource:
{
body = StringFormat::Fmt("Source %s %d", ToStr::Get(spv::SourceLanguage(spirv[it+1])).c_str(), spirv[it+2]);
break;
}
case spv::OpExtInstImport:
{
resultnames[ spirv[it+1] ] = (char *)&spirv[it+2];
body = StringFormat::Fmt("ExtInstImport %s", (char *)&spirv[it+2]);
if(resultnames[ spirv[it+1] ] == "GLSL.std.450")
{
extensionSets.push_back( make_pair(spirv[it+1], GLSL_STD_450_names) );
if(GLSL_STD_450_names[0] == NULL)
GLSL_STD_450::GetDebugNames(GLSL_STD_450_names);
}
break;
}
case spv::OpMemoryModel:
{
body = StringFormat::Fmt("MemoryModel %s Addressing, %s Memory model",
ToStr::Get(spv::AddressingModel(spirv[it+1])).c_str(),
ToStr::Get(spv::MemoryModel(spirv[it+2])).c_str());
break;
}
case spv::OpEntryPoint:
{
body = StringFormat::Fmt("EntryPoint = %s (%s)",
resultnames[ spirv[it+2] ].c_str(),
ToStr::Get(spv::ExecutionModel(spirv[it+1])).c_str());
break;
}
case spv::OpVariable:
{
if(!variables)
{
variables = true;
disasm += "\n";
}
uint32_t retType = spirv[it+1];
uint32_t resultId = spirv[it+2];
spv::StorageClass control = spv::StorageClass(spirv[it+3]);
uint32_t initializer = ~0U;
if(WordCount > 4)
initializer = spirv[it+4];
string decorationsStr = "";
for(auto it=decorations.begin(); it != decorations.end(); ++it)
{
if(it->first == resultId)
{
decorationsStr += it->second + " ";
}
}
body = StringFormat::Fmt("%s%s %s %s",
decorationsStr.c_str(),
ToStr::Get(control).c_str(),
resultnames[ retType ].c_str(),
resultnames[ resultId ].c_str());
if(initializer < idbound)
body += StringFormat::Fmt(" = %s", resultnames[initializer].c_str());
break;
}
case spv::OpFunction:
{
uint32_t retType = spirv[it+1];
uint32_t resultId = spirv[it+2];
spv::FunctionControlMask control = spv::FunctionControlMask(spirv[it+3]);
uint32_t funcType = spirv[it+4];
// add an extra newline
disasm += "\n";
body = StringFormat::Fmt("%s %s(%s) %s {",
resultnames[retType].c_str(),
resultnames[resultId].c_str(),
resultnames[funcType].c_str(),
OptionalFlagString(control).c_str());
funcname = resultnames[resultId];
break;
}
case spv::OpFunctionEnd:
{
body = StringFormat::Fmt("} // end of %s", funcname.c_str());
funcname = "";
indent.resize(indent.size() - tabSize);
break;
}
case spv::OpAccessChain:
{
uint32_t retType = spirv[it+1];
uint32_t resultId = spirv[it+2];
uint32_t base = spirv[it+3];
body = StringFormat::Fmt("%s %s = %s",
resultnames[retType].c_str(),
resultnames[resultId].c_str(),
resultnames[base].c_str());
// this is a complete and utter hack
for(int i=4; i < WordCount; i++)
{
if(i == 4 && values[spirv[it+4]] < membernames.size())
body += StringFormat::Fmt(".%s", membernames[ values[spirv[it+4]] ]);
else
body += StringFormat::Fmt("[%s]", resultnames[ spirv[it+i] ].c_str());
}
break;
}
case spv::OpLoad:
{
uint32_t retType = spirv[it+1];
uint32_t resultId = spirv[it+2];
uint32_t pointer = spirv[it+3];
spv::MemoryAccessMask access = spv::MemoryAccessMaskNone;
for(int i=4; i < WordCount; i++)
{
if(i == WordCount-1)
{
access = spv::MemoryAccessMask(spirv[it+i]);
}
else
{
uint32_t lit = spirv[it+i];
// don't understand what these literals are - seems like OpAccessChain handles
// struct member/array access so it doesn't seem to be for array indices
RDCBREAK();
}
}
body = StringFormat::Fmt("%s %s = Load(%s) %s",
resultnames[retType].c_str(),
resultnames[resultId].c_str(),
resultnames[pointer].c_str(),
OptionalFlagString(access).c_str());
break;
}
case spv::OpStore:
case spv::OpCopyMemory:
{
uint32_t pointer = spirv[it+1];
uint32_t object = spirv[it+2];
spv::MemoryAccessMask access = spv::MemoryAccessMaskNone;
for(int i=3; i < WordCount; i++)
{
if(i == WordCount-1)
{
access = spv::MemoryAccessMask(spirv[it+i]);
}
else
{
uint32_t lit = spirv[it+i];
// don't understand what these literals are - seems like OpAccessChain handles
// struct member/array access so it doesn't seem to be for array indices
RDCBREAK();
}
}
if(OpCode == spv::OpStore)
body = StringFormat::Fmt("Store(%s) = %s %s",
resultnames[ pointer ].c_str(),
resultnames[ object ].c_str(),
OptionalFlagString(access).c_str());
if(OpCode == spv::OpCopyMemory)
body = StringFormat::Fmt("Copy(%s) = Load(%s) %s",
resultnames[ pointer ].c_str(),
resultnames[ object ].c_str(),
OptionalFlagString(access).c_str());
break;
}
case spv::OpName:
case spv::OpMemberName:
case spv::OpDecorate:
case spv::OpConstant:
case spv::OpConstantComposite:
case spv::OpTypeVoid:
case spv::OpTypeBool:
case spv::OpTypeInt:
case spv::OpTypeFloat:
case spv::OpTypeVector:
case spv::OpTypePointer:
case spv::OpTypeArray:
case spv::OpTypeStruct:
case spv::OpTypeFunction:
{
silent = true;
break;
}
case spv::OpIAdd:
case spv::OpIMul:
case spv::OpFAdd:
case spv::OpFMul:
case spv::OpSLessThan:
{
char op = '?';
switch(OpCode)
{
case spv::OpIAdd:
case spv::OpFAdd:
op = '+';
break;
case spv::OpIMul:
case spv::OpFMul:
op = '*';
break;
case spv::OpSLessThan:
op = '<';
break;
default:
break;
}
uint32_t retType = spirv[it+1];
uint32_t result = spirv[it+2];
uint32_t a = spirv[it+3];
uint32_t b = spirv[it+4];
body = StringFormat::Fmt("%s %s = %s %c %s",
resultnames[ retType ].c_str(),
resultnames[ result ].c_str(),
resultnames[ a ].c_str(),
op,
resultnames[ b ].c_str());
break;
}
case spv::OpExtInst:
{
uint32_t retType = spirv[it+1];
uint32_t result = spirv[it+2];
uint32_t extset = spirv[it+3];
uint32_t instruction = spirv[it+4];
string instructionName = "";
for(auto ext = extensionSets.begin(); ext != extensionSets.end(); ++ext)
if(ext->first == extset)
instructionName = ext->second[instruction];
if(instructionName.empty())
instructionName = StringFormat::Fmt("Unknown%u", instruction);
string args = "";
for(int i=5; i < WordCount; i++)
{
args += resultnames[ spirv[it+i] ];
if(i+1 < WordCount)
args += ", ";
}
body = StringFormat::Fmt("%s %s = %s::%s(%s)",
resultnames[ retType ].c_str(),
resultnames[ result ].c_str(),
resultnames[ extset ].c_str(),
instructionName.c_str(),
args.c_str());
break;
}
case spv::OpReturn:
{
body = "Return";
break;
}
case spv::OpSelectionMerge:
{
uint32_t mergeLabel = spirv[it+1];
spv::SelectionControlMask control = spv::SelectionControlMask(spirv[it+2]);
flowstack.push_back(mergeLabel);
body = StringFormat::Fmt("SelectionMerge %s %s", resultnames[ mergeLabel ].c_str(), OptionalFlagString(control).c_str());
break;
}
case spv::OpLoopMerge:
{
uint32_t mergeLabel = spirv[it+1];
spv::LoopControlMask control = spv::LoopControlMask(spirv[it+2]);
flowstack.push_back(mergeLabel);
body = StringFormat::Fmt("LoopMerge %s %s", resultnames[ mergeLabel ].c_str(), OptionalFlagString(control).c_str());
break;
}
case spv::OpBranch:
{
body = StringFormat::Fmt("goto %s", resultnames[ spirv[it+1] ].c_str());
break;
}
case spv::OpBranchConditional:
{
uint32_t condition = spirv[it+1];
uint32_t truelabel = spirv[it+2];
uint32_t falselabel = spirv[it+3];
if(WordCount == 4)
{
body = StringFormat::Fmt("if(%s) goto %s, else goto %s",
resultnames[condition].c_str(),
resultnames[truelabel].c_str(),
resultnames[falselabel].c_str());
}
else
{
uint32_t weightA = spirv[it+4];
uint32_t weightB = spirv[it+5];
float a = float(weightA)/float(weightA+weightB);
float b = float(weightB)/float(weightA+weightB);
a *= 100.0f;
b *= 100.0f;
body = StringFormat::Fmt("if(%s) goto %.2f%% %s, else goto %.2f%% %s",
a,
resultnames[condition].c_str(),
resultnames[truelabel].c_str(),
b,
resultnames[falselabel].c_str());
}
break;
}
case spv::OpLabel:
{
body = resultnames[spirv[it+1]] + ":";
if(!flowstack.empty() && flowstack.back() == spirv[it+1])
indent.resize(indent.size() - tabSize);
break;
}
default:
{
body = "!" + ToStr::Get(OpCode);
for(uint16_t i=1; i < WordCount; i++)
{
if(spirv[it+i] <= idbound)
body += StringFormat::Fmt(" %u%s", spirv[it+i], i+1 < WordCount ? "," : "");
else
body += StringFormat::Fmt(" %#x%s", spirv[it+i], i+1 < WordCount ? "," : "");
}
break;
}
}
if(!silent)
disasm += StringFormat::Fmt("%s%s\n", indent.c_str(), body.c_str());
// post printing operations
switch(OpCode)
{
case spv::OpFunction:
indent.insert(indent.end(), tabSize, ' ');
break;
case spv::OpSelectionMerge:
case spv::OpLoopMerge:
indent.insert(indent.end(), tabSize, ' ');
break;
default:
break;
}
it += WordCount;
}
disasm += "\n\n--------------\n\n" + module.Disassemble();
disasm = module.Disassemble();
return;
#endif