From 340bf9f805812aa583b35f4d266ab20091fa4516 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 9 Jun 2020 16:47:32 +0100 Subject: [PATCH] Add handling for branching and phi nodes --- .../driver/shaders/dxil/dxil_bytecode.cpp | 97 ++++++++++++++++++- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 8 ++ .../driver/shaders/dxil/dxil_disassemble.cpp | 79 +++++++++++++++ 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 056063040..000bfe986 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -855,6 +855,7 @@ Program::Program(const byte *bytes, size_t length) case SymbolType::Instruction: case SymbolType::Metadata: case SymbolType::Literal: + case SymbolType::BasicBlock: RDCERR("Unexpected global symbol referring to %d", m_Symbols[s].type); break; case SymbolType::GlobalVar: @@ -970,6 +971,8 @@ Program::Program(const byte *bytes, size_t length) size_t prevNumSymbols = m_Symbols.size(); size_t instrSymbolStart = 0; + rdcarray forwardRefInstructions; + for(size_t i = 0; i < f.funcType->members.size(); i++) { Instruction arg; @@ -984,7 +987,7 @@ Program::Program(const byte *bytes, size_t length) return id < m_Symbols.size() ? m_Symbols[id] : Symbol(SymbolType::Unknown, id); }; - Block *curBlock = NULL; + size_t curBlock = 0; int32_t debugLocIndex = -1; for(const LLVMBC::BlockOrRecord &funcChild : rootchild.children) @@ -1104,6 +1107,7 @@ Program::Program(const byte *bytes, size_t length) case SymbolType::Instruction: f.instructions[s.idx].name = symtab.getString(1); break; + case SymbolType::BasicBlock: f.blocks[s.idx].name = symtab.getString(1); break; case SymbolType::GlobalVar: case SymbolType::Function: case SymbolType::Alias: @@ -1159,7 +1163,7 @@ Program::Program(const byte *bytes, size_t length) { f.blocks.resize(op.ops[0]); - curBlock = &f.blocks[0]; + curBlock = 0; } else if(IS_KNOWN(op.id, FunctionRecord::DEBUG_LOC)) { @@ -1602,6 +1606,70 @@ Program::Program(const byte *bytes, size_t length) f.instructions.push_back(inst); } + else if(IS_KNOWN(op.id, FunctionRecord::INST_BR)) + { + Instruction inst; + + inst.op = Instruction::Branch; + + inst.type = GetVoidType(); + + // true destination + inst.args.push_back(Symbol(SymbolType::BasicBlock, op.ops[0])); + + f.blocks[op.ops[0]].preds.insert(0, &f.blocks[curBlock]); + + if(op.ops.size() > 1) + { + // false destination + inst.args.push_back(Symbol(SymbolType::BasicBlock, op.ops[1])); + + f.blocks[op.ops[1]].preds.insert(0, &f.blocks[curBlock]); + + // predicate + inst.args.push_back(getSymbol(op.ops[2])); + } + + curBlock++; + + f.instructions.push_back(inst); + } + else if(IS_KNOWN(op.id, FunctionRecord::INST_PHI)) + { + Instruction inst; + + inst.op = Instruction::Phi; + + inst.type = &m_Types[op.ops[0]]; + + bool fwdRef = false; + + for(size_t idx = 1; idx < op.ops.size(); idx += 2) + { + int64_t valSrc = LLVMBC::BitReader::svbr(op.ops[idx]); + uint64_t blockSrc = op.ops[idx + 1]; + + if(valSrc < 0) + { + inst.args.push_back(Symbol(SymbolType::Unknown, m_Symbols.size() - valSrc)); + fwdRef = true; + } + else + { + inst.args.push_back(getSymbol((uint64_t)valSrc)); + } + inst.args.push_back(Symbol(SymbolType::BasicBlock, blockSrc)); + } + + // forward references can't be resolved until we know the symbols lookup (because void + // instructions are skipped) + if(fwdRef) + forwardRefInstructions.push_back(f.instructions.size()); + + m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); + + f.instructions.push_back(inst); + } else if(IS_KNOWN(op.id, FunctionRecord::INST_EXTRACTELT)) { // DXIL claims to be scalarised so should this appear? @@ -1728,8 +1796,20 @@ Program::Program(const byte *bytes, size_t length) } } + f.blocks[0].resultID = 0; + + curBlock = 0; for(size_t i = 0, resultID = 1; i < f.instructions.size(); i++) { + if(f.instructions[i].op == Instruction::Branch || + f.instructions[i].op == Instruction::Unreachable) + { + curBlock++; + if(f.blocks[curBlock].name.empty()) + f.blocks[curBlock].resultID = (uint32_t)resultID++; + continue; + } + if(f.instructions[i].type->isVoid()) continue; @@ -1745,6 +1825,18 @@ Program::Program(const byte *bytes, size_t length) if(m.func) m.instruction = m_Symbols[instrSymbolStart + m.instruction].idx; + for(size_t fwdRefInst : forwardRefInstructions) + { + for(Symbol &s : f.instructions[fwdRefInst].args) + { + if(s.type == SymbolType::Unknown) + { + s = m_Symbols[s.idx]; + RDCASSERT(s.type == SymbolType::Instruction); + } + } + } + m_Symbols.resize(prevNumSymbols); } else @@ -1830,6 +1922,7 @@ const Type *Program::GetSymbolType(const Function &f, Symbol s) case SymbolType::Unknown: case SymbolType::Alias: case SymbolType::Metadata: + case SymbolType::BasicBlock: case SymbolType::Literal: RDCERR("Unexpected symbol to get type for %d", s.type); break; } return ret; diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 46b14a400..d33d35f94 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -89,6 +89,7 @@ enum class SymbolType Instruction, Metadata, Literal, + BasicBlock, }; struct Symbol @@ -308,6 +309,8 @@ BITMASK_OPERATORS(InstructionFlags); typedef rdcarray> AttachedMetadata; +struct Block; + struct Instruction { enum @@ -383,6 +386,8 @@ struct Instruction InsertElement, ShuffleVector, InsertValue, + Branch, + Phi, } op = Unknown; InstructionFlags opFlags = InstructionFlags::NoFlags; @@ -404,6 +409,9 @@ struct Instruction struct Block { + uint32_t resultID = ~0U; + rdcstr name; + rdcarray preds; }; struct Function diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index 75dcc7e1c..77802c848 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -438,6 +438,16 @@ void Program::MakeDisassemblyString() ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(refinst.name).c_str()); break; } + case SymbolType::BasicBlock: + { + const Block &block = func.blocks[s.idx]; + if(withTypes) + ret = "label "; + if(block.name.empty()) + ret += StringFormat::Fmt("%%%u", block.resultID); + else + ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(block.name).c_str()); + } } return ret; }; @@ -459,6 +469,8 @@ void Program::MakeDisassemblyString() m_Disassembly += " {\n"; instructionLine++; + size_t curBlock = 0; + for(Instruction &inst : func.instructions) { inst.disassemblyLine = instructionLine; @@ -792,6 +804,37 @@ void Program::MakeDisassemblyString() } break; } + case Instruction::Branch: + { + m_Disassembly += "br "; + if(inst.args.size() > 1) + { + m_Disassembly += argToString(inst.args[2], true); + m_Disassembly += StringFormat::Fmt(", %s", argToString(inst.args[0], true).c_str()); + m_Disassembly += StringFormat::Fmt(", %s", argToString(inst.args[1], true).c_str()); + } + else + { + m_Disassembly += argToString(inst.args[0], true); + } + break; + } + case Instruction::Phi: + { + m_Disassembly += "phi "; + m_Disassembly += inst.type->toString(); + for(size_t a = 0; a < inst.args.size(); a += 2) + { + if(a == 0) + m_Disassembly += " "; + else + m_Disassembly += ", "; + m_Disassembly += + StringFormat::Fmt("[ %s, %s ]", argToString(inst.args[a], false).c_str(), + argToString(inst.args[a + 1], false).c_str()); + } + break; + } } if(inst.debugLoc != ~0U) @@ -861,6 +904,42 @@ void Program::MakeDisassemblyString() m_Disassembly += "\n"; instructionLine++; + + if(inst.op == Instruction::Branch || inst.op == Instruction::Unreachable) + { + m_Disassembly += "\n"; + instructionLine++; + + curBlock++; + + rdcstr labelName; + + if(func.blocks[curBlock].name.empty()) + labelName = StringFormat::Fmt(";